mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[codex] Allow socketpair in proxy-routed Linux sandbox (#26625)
## Summary - allow `socketpair(AF_UNIX, ...)` in the proxy-routed Linux seccomp mode - continue denying `socket(AF_UNIX, ...)` so user commands cannot create pathname or abstract Unix sockets - extend the managed-proxy integration test to verify both behaviors ## Root cause `NetworkSeccompMode::ProxyRouted` treated anonymous Unix socket pairs like externally addressable Unix sockets and returned `EPERM`. This breaks tools that use socket pairs for local child-process IPC even though a socket pair cannot connect outside the sandbox or bypass the routed proxy. `dangerously_allow_all_unix_sockets` controls Unix-socket requests forwarded by the managed network proxy; it does not currently configure the Linux seccomp filter. Socket pairs should not require that dangerous setting because they are unnamed, process-local IPC. Related but independent: #26553 fixes host proxy bridge socket path length handling. --------- Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
40c8f1a007
commit
d40454522e
@@ -217,10 +217,11 @@ fn install_network_seccomp_filter_on_current_thread(
|
||||
}
|
||||
NetworkSeccompMode::ProxyRouted => {
|
||||
// In proxy-routed mode we allow IP sockets in the isolated
|
||||
// namespace (used to reach the local TCP bridge) but deny all
|
||||
// other socket families, including AF_UNIX. This prevents
|
||||
// bypassing the routed bridge via new Unix sockets and narrows the
|
||||
// socket surface in proxy-only mode.
|
||||
// namespace (used to reach the local TCP bridge) but deny socket()
|
||||
// for all other families, including AF_UNIX. Only AF_UNIX
|
||||
// socketpair() remains available for process-local IPC because it
|
||||
// cannot connect to a socket outside the sandbox or bypass the
|
||||
// bridge.
|
||||
let deny_non_ip_socket = SeccompRule::new(vec![
|
||||
SeccompCondition::new(
|
||||
0,
|
||||
@@ -235,14 +236,14 @@ fn install_network_seccomp_filter_on_current_thread(
|
||||
libc::AF_INET6 as u64,
|
||||
)?,
|
||||
])?;
|
||||
let deny_unix_socketpair = SeccompRule::new(vec![SeccompCondition::new(
|
||||
let deny_non_unix_socketpair = SeccompRule::new(vec![SeccompCondition::new(
|
||||
0,
|
||||
SeccompCmpArgLen::Dword,
|
||||
SeccompCmpOp::Eq,
|
||||
SeccompCmpOp::Ne,
|
||||
libc::AF_UNIX as u64,
|
||||
)?])?;
|
||||
rules.insert(libc::SYS_socket, vec![deny_non_ip_socket]);
|
||||
rules.insert(libc::SYS_socketpair, vec![deny_unix_socketpair]);
|
||||
rules.insert(libc::SYS_socketpair, vec![deny_non_unix_socketpair]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -266,7 +266,7 @@ async fn managed_proxy_mode_routes_through_bridge_and_blocks_direct_egress() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn managed_proxy_mode_denies_af_unix_creation_for_user_command() {
|
||||
async fn managed_proxy_mode_denies_af_unix_socket_but_allows_socketpair() {
|
||||
if let Some(skip_reason) = managed_proxy_skip_reason().await {
|
||||
eprintln!("skipping managed proxy test: {skip_reason}");
|
||||
return;
|
||||
@@ -292,7 +292,7 @@ async fn managed_proxy_mode_denies_af_unix_creation_for_user_command() {
|
||||
&[
|
||||
"python3",
|
||||
"-c",
|
||||
"import socket,sys\ntry:\n socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)\nexcept PermissionError:\n sys.exit(0)\nexcept OSError:\n sys.exit(2)\nsys.exit(1)\n",
|
||||
"import socket,sys\ntry:\n socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)\nexcept PermissionError:\n pass\nexcept OSError:\n sys.exit(2)\nelse:\n sys.exit(1)\nleft,right = socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM)\nleft.sendall(b'ok')\nif right.recv(2) != b'ok':\n sys.exit(3)\n",
|
||||
],
|
||||
&PermissionProfile::Disabled,
|
||||
/*allow_network_for_proxy*/ true,
|
||||
@@ -304,7 +304,7 @@ async fn managed_proxy_mode_denies_af_unix_creation_for_user_command() {
|
||||
assert_eq!(
|
||||
output.status.code(),
|
||||
Some(0),
|
||||
"expected AF_UNIX creation to be denied cleanly for user command; status={:?}; stdout={}; stderr={}",
|
||||
"expected AF_UNIX socket creation to be denied and socketpair to work; status={:?}; stdout={}; stderr={}",
|
||||
output.status.code(),
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
|
||||
Reference in New Issue
Block a user