From 2eb4c8b22956135cae37770634621632aff7ac53 Mon Sep 17 00:00:00 2001 From: danbugs Date: Sun, 17 May 2026 06:59:04 +0000 Subject: [PATCH 1/2] fix: set default 30s timeout on guest-created sockets Adds SOCKET_TIMEOUT (30s) applied to all sockets at creation time via set_read_timeout/set_write_timeout. Also uses connect_timeout in handle_net_connect, releasing the SocketTable lock before the blocking connect call to avoid stalling concurrent socket operations. Includes a unit test that verifies the timeout is actually set. Signed-off-by: danbugs --- host/src/lib.rs | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/host/src/lib.rs b/host/src/lib.rs index b893ff3..328b7af 100644 --- a/host/src/lib.rs +++ b/host/src/lib.rs @@ -99,6 +99,9 @@ const MAX_NET_SEND: usize = 1024 * 1024; /// Cap for `__hl_sleep` duration to prevent unbounded host-thread blocking (60 s). const MAX_SLEEP_NS: u64 = 60_000_000_000; +/// Default socket timeout for read/write/connect operations (30 s). +const SOCKET_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(30); + /// A preopened host directory exposed to the guest. /// /// Semantics mirror Wasmtime's `preopened_dir`: `host_dir` is canonicalised @@ -1192,6 +1195,8 @@ fn handle_net_socket( Some(Protocol::from(protocol)) }; let sock = Socket::new(domain, stype, proto)?; + sock.set_read_timeout(Some(SOCKET_TIMEOUT))?; + sock.set_write_timeout(Some(SOCKET_TIMEOUT))?; let fd = table.lock().unwrap().insert(HostSocket { socket: sock, sock_type, @@ -1210,9 +1215,11 @@ fn handle_net_connect( let addr = parse_sockaddr(args)?; policy.check(&addr)?; let sa: SockAddr = addr.into(); - let tbl = table.lock().unwrap(); - let sock = tbl.get_socket(fd)?; - sock.connect(&sa)?; + let sock = { + let tbl = table.lock().unwrap(); + tbl.get_socket(fd)?.try_clone()? + }; + sock.connect_timeout(&sa, SOCKET_TIMEOUT)?; Ok(json!({})) } @@ -3389,4 +3396,27 @@ mod tests { al.learn_ip(IpAddr::V4(Ipv4Addr::new(10, 1, 0, 1))); assert_eq!(al.learned_ips.lock().unwrap().len(), MAX_LEARNED_IPS); } + + #[test] + fn net_socket_has_default_timeout() { + let mut tools = ToolRegistry::new(); + let exit_code = Arc::new(AtomicI32::new(0)); + let table = + register_internal_tools(&mut tools, &exit_code, Some(&NetworkPolicy::AllowAll), None) + .expect("network tools should be registered"); + + let req = br#"{"name":"net_socket","args":{"family":2,"type":1}}"#; + let resp = tools.dispatch(req); + let s = std::str::from_utf8(&resp).unwrap(); + assert!(!s.contains("error"), "socket creation should succeed: {s}"); + + let v: serde_json::Value = serde_json::from_str(s).unwrap(); + let fd = v["result"]["fd"].as_u64().unwrap(); + assert!(fd > 0); + + let tbl = table.lock().unwrap(); + let sock = tbl.get_socket(fd).unwrap(); + assert_eq!(sock.read_timeout().unwrap(), Some(SOCKET_TIMEOUT)); + assert_eq!(sock.write_timeout().unwrap(), Some(SOCKET_TIMEOUT)); + } } From 5af8e1f294458ed0219ef1f67effc2b3b1450174 Mon Sep 17 00:00:00 2001 From: danbugs Date: Sun, 17 May 2026 07:31:16 +0000 Subject: [PATCH 2/2] ci: trigger fresh CI run on different runner Signed-off-by: danbugs