From bf10e2c3682e75c53f6109d758737dcb9fc01482 Mon Sep 17 00:00:00 2001 From: zbarsky-openai Date: Mon, 24 Aug 2026 11:48:16 -0400 Subject: [PATCH] vm: enable isolated System V IPC for sandboxed actions PostgreSQL initialization inside an actiond action currently fails with: ```text FATAL: could not create shared memory segment: Function not implemented DETAIL: Failed system call was shmget(key=4140, size=56, 03600). ``` Enable System V IPC and IPC namespaces in both supported guest-kernel configurations, and give every action its own IPC namespace. Isolating IPC at the action boundary prevents shared-memory segments, semaphore sets, and message queues from leaking between unrelated executions. Extend the existing clone-flags test to cover IPC namespace isolation. Both architecture configurations resolve through the real Linux Kconfig parser. The ARM64 guest kernel and initramfs build through actiond, and the original PostgreSQL/pgvector integration test passes against the rebuilt guest. --- src/action_runner.zig | 5 +++-- vm/linux.config | 2 ++ vm/linux_x86_64.config | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/action_runner.zig b/src/action_runner.zig index 0ecbb14..8bc0ebd 100644 --- a/src/action_runner.zig +++ b/src/action_runner.zig @@ -45,7 +45,7 @@ inline fn runnerTimingNow(io: std.Io) std.Io.Timestamp { fn actionNamespaceFlags() usize { const linux = std.os.linux; - return linux.CLONE.NEWNS | linux.CLONE.NEWNET | linux.CLONE.NEWPID; + return linux.CLONE.NEWNS | linux.CLONE.NEWNET | linux.CLONE.NEWPID | linux.CLONE.NEWIPC; } fn actionCloneFlags() u32 { @@ -1637,12 +1637,13 @@ test "ExecutionControl rejects a cancelled action" { try std.testing.expectError(error.ExecutionCancelled, execution_control.check(std.testing.io)); } -test "action clone flags isolate mounts, networking, and action process IDs" { +test "action clone flags isolate mounts, networking, process IDs, and IPC" { const linux = std.os.linux; const flags = actionCloneFlags(); try std.testing.expect((flags & linux.CLONE.NEWNS) != 0); try std.testing.expect((flags & linux.CLONE.NEWNET) != 0); try std.testing.expect((flags & linux.CLONE.NEWPID) != 0); + try std.testing.expect((flags & linux.CLONE.NEWIPC) != 0); try std.testing.expectEqual(@as(u32, @intFromEnum(linux.SIG.CHLD)), flags & linux.CSIGNAL); } diff --git a/vm/linux.config b/vm/linux.config index 69abcd9..34de9d5 100644 --- a/vm/linux.config +++ b/vm/linux.config @@ -36,6 +36,7 @@ CONFIG_HYPERV_STORAGE=y CONFIG_HYPERV_VMBUS=y CONFIG_HYPERV_VSOCKETS=y CONFIG_INET=y +CONFIG_IPC_NS=y CONFIG_JBD2=y CONFIG_KALLSYMS=y CONFIG_MEMCG=y @@ -61,6 +62,7 @@ CONFIG_SCSI_COMMON=y CONFIG_SCSI_LOWLEVEL=y CONFIG_SIGNALFD=y CONFIG_SYSFS=y +CONFIG_SYSVIPC=y CONFIG_SQUASHFS=y CONFIG_SQUASHFS_ZSTD=y CONFIG_TMPFS=y diff --git a/vm/linux_x86_64.config b/vm/linux_x86_64.config index 278a71f..f6b17d4 100644 --- a/vm/linux_x86_64.config +++ b/vm/linux_x86_64.config @@ -33,6 +33,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_FUSE_FS is not set CONFIG_FUTEX=y CONFIG_INET=y +CONFIG_IPC_NS=y CONFIG_JBD2=y CONFIG_KALLSYMS=y CONFIG_KERNEL_LZ4=y @@ -54,6 +55,7 @@ CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SIGNALFD=y CONFIG_SYSFS=y +CONFIG_SYSVIPC=y CONFIG_SQUASHFS=y CONFIG_SQUASHFS_ZSTD=y CONFIG_TMPFS=y