Skip to content

Restricted Linux sandbox breaks connected Unix socket sends and asyncio wakeups #33793

Description

@everySympathy

Summary

The restricted Linux network seccomp filter unconditionally denies sendto(2). On Linux, send(2) is implemented as sendto(..., dest_addr = NULL), so this also breaks writes to already-connected Unix-domain sockets.

One visible consequence is that Python asyncio cross-thread wakeups stop working inside the default Codex workspace sandbox. loop.call_soon_threadsafe() writes to asyncio's AF_UNIX wakeup socket; the write receives EPERM, asyncio suppresses that OSError, and the event loop remains asleep.

Reproduction

On current main (315195492c), build Codex and run:

./target/debug/codex sandbox -P :workspace -C /tmp /usr/bin/python3 -c 'import asyncio, threading; loop=asyncio.new_event_loop(); threading.Thread(target=loop.run_forever, daemon=True).start(); print(asyncio.run_coroutine_threadsafe(asyncio.sleep(0, result=42), loop).result(timeout=2))'

Expected:

42

Actual:

TimeoutError

This also causes Daft's native runner to hang on a simple collect() operation.

Isolation

  • The same program succeeds outside the Codex sandbox.
  • It succeeds with the same bubblewrap filesystem isolation and a full-network Codex profile.
  • It succeeds with plain bubblewrap plus --unshare-net.
  • It fails only when Codex's restricted network seccomp filter is installed.

Root cause and possible fix

In codex-rs/linux-sandbox/src/landlock.rs, restricted mode unconditionally denies SYS_sendto.

A narrowly scoped fix is to deny sendto only when its fifth argument (dest_addr) is non-null. This permits send() on an already-connected socket, including AF_UNIX socketpairs used for local IPC, while continuing to deny sends to explicit destinations such as unconnected Unix datagram socket paths.

I have a tested patch with regression coverage for both sides of this boundary:

  • connected AF_UNIX socket send() succeeds;
  • sendto() with an explicit destination still returns EPERM.

The codex-linux-sandbox test suite passes (120/120), and both the minimal asyncio reproducer and the original Daft collect() scenario pass with the patched binary.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    CLIIssues related to the Codex CLIbugSomething isn't workingsandboxIssues related to permissions or sandboxing

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions