From 6f9467ccc92db4526340fed5e0401119a8951f19 Mon Sep 17 00:00:00 2001 From: zbarsky-openai Date: Mon, 24 Aug 2026 05:23:40 -0400 Subject: [PATCH] executor: mount isolated POSIX shared memory per action Python multiprocessing fails inside an action sandbox while creating a POSIX named semaphore: ```text executor = ProcessPoolExecutor(max_workers=5, mp_context=multiprocessing.get_context("spawn")) ... self._semlock = _multiprocessing.SemLock(...) FileNotFoundError: [Errno 2] No such file or directory ``` Create `/dev/shm` alongside each action's existing base directories and mount a private 64 MiB tmpfs after entering its mount namespace. Keep the mount `nosuid,nodev,noexec`, give it the standard sticky world-writable mode, and perform the mount before dropping sandbox privileges. Extend the existing base directory test to cover the new mount point. The failure was reproduced remotely with `//project/oai_sandbox:pytest -k test_get_minijail_concurrent_calls_only_one_download` using Bazel `9.3.0-actiond-dzbarsky14`. --- src/action_executor.zig | 3 ++- src/action_runner.zig | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/action_executor.zig b/src/action_executor.zig index 29a208f..06d8ace 100644 --- a/src/action_executor.zig +++ b/src/action_executor.zig @@ -2109,7 +2109,7 @@ fn createOutputParent(io: std.Io, work_root: std.Io.Dir, path: []const u8) !void } fn prepareChrootBaseDirs(io: std.Io, chroot_root: std.Io.Dir) !void { - try chroot_root.createDirPath(io, "dev"); + try chroot_root.createDirPath(io, "dev/shm"); try chroot_root.createDirPath(io, "proc"); try chroot_root.createDirPath(io, "tmp"); try chroot_root.createDirPath(io, "var/tmp"); @@ -3641,6 +3641,7 @@ test "prepareChrootBaseDirs creates temporary directories" { defer work_dir.close(std.testing.io); try prepareChrootBaseDirs(std.testing.io, work_dir); + try work_dir.access(std.testing.io, "dev/shm", .{}); try work_dir.access(std.testing.io, "tmp", .{}); try work_dir.access(std.testing.io, "var/tmp", .{}); } diff --git a/src/action_runner.zig b/src/action_runner.zig index 0ecbb14..36c2ee7 100644 --- a/src/action_runner.zig +++ b/src/action_runner.zig @@ -648,6 +648,14 @@ fn forkAction(action: ForkAction) !std.os.linux.pid_t { childSyscallName(linux.chroot(action.chroot_dir.ptr), "chroot"); childSyscallName(linux.chdir("/"), "chdir_root"); childSyscallName(linux.mount("proc", "/proc", "proc", linux.MS.NOSUID | linux.MS.NODEV | linux.MS.NOEXEC, 0), "mount_proc"); + const shared_memory_mount_data: [:0]const u8 = "mode=1777,size=64m"; + childSyscallName(linux.mount( + "tmpfs", + "/dev/shm", + "tmpfs", + linux.MS.NOSUID | linux.MS.NODEV | linux.MS.NOEXEC, + @intFromPtr(shared_memory_mount_data.ptr), + ), "mount_shm"); childDropPrivileges(action.sandbox_uid, action.sandbox_gid); childSyscallName(linux.chdir(action.cwd.ptr), "chdir"); childInstallSocketFilter();