Connect a TCP stream to `addr` inside the sandbox network namespace. The SSH supervisor runs in the host network namespace while sandbox child processes run in an isolated network namespace (with their own loopback). A plain `TcpStream::connect("127.0.0.1:port")` from the supervisor would hit the host loopback, not the sandbox loopback where services are listening. On Linux, we spawn a dedicated
(
addr: &str,
netns_fd: Option<RawFd>,
)
| 603 | /// thread could be reused for unrelated tasks and must not be contaminated. |
| 604 | /// On non-Linux platforms (no network namespace support), we connect directly. |
| 605 | pub async fn connect_in_netns( |
| 606 | addr: &str, |
| 607 | netns_fd: Option<RawFd>, |
| 608 | ) -> std::io::Result<tokio::net::TcpStream> { |
| 609 | #[cfg(target_os = "linux")] |
| 610 | if let Some(fd) = netns_fd { |
| 611 | let addr = addr.to_string(); |
| 612 | let (tx, rx) = tokio::sync::oneshot::channel(); |
| 613 | std::thread::spawn(move || { |
| 614 | let result = (|| -> std::io::Result<std::net::TcpStream> { |
| 615 | // Enter the sandbox network namespace on this dedicated thread. |
| 616 | // SAFETY: setns is safe to call; this is a dedicated thread that |
| 617 | // will exit after the connection is established. |
| 618 | #[allow(unsafe_code)] |
| 619 | let rc = unsafe { libc::setns(fd, libc::CLONE_NEWNET) }; |
| 620 | if rc != 0 { |
| 621 | return Err(std::io::Error::last_os_error()); |
| 622 | } |
| 623 | std::net::TcpStream::connect(&addr) |
| 624 | })(); |
| 625 | let _ = tx.send(result); |
| 626 | }); |
| 627 | |
| 628 | let std_stream = rx |
| 629 | .await |
| 630 | .map_err(|_| std::io::Error::other("netns connect thread panicked"))??; |
| 631 | std_stream.set_nonblocking(true)?; |
| 632 | return tokio::net::TcpStream::from_std(std_stream); |
| 633 | } |
| 634 | |
| 635 | #[cfg(not(target_os = "linux"))] |
| 636 | let _ = netns_fd; |
| 637 | |
| 638 | tokio::net::TcpStream::connect(addr).await |
| 639 | } |
| 640 | |
| 641 | #[derive(Clone)] |
| 642 | struct PtyRequest { |
no test coverage detected