openai/codex · critical

failed to place bubblewrap child in its own process group: {

Error message

failed to place bubblewrap child in its own process group: {err}

What it means

The forked child that will exec bubblewrap calls libc::setpgid(0, 0) to move itself into a fresh process group; the parent relies on this to forward signals to the whole sandbox tree via kill(-pid, ...) (send_signal_to_bwrap_child, linux_run_main.rs:912). Linux guarantees setpgid(0,0) succeeds on a just-forked child, so this panic means the environment broke that invariant: an outer seccomp/LSM policy denies setpgid, or an exotic runtime (gVisor, a nested sandbox) restricts process-group changes. The child dies before exec, so every sandboxed run fails.

Source

Thrown at codex-rs/linux-sandbox/src/linux_run_main.rs:593

    let setup_signal_mask = ForwardedSignalMask::block();
    let synthetic_mount_registrations = register_synthetic_mount_targets(&synthetic_mount_targets);
    let protected_create_registrations =
        register_protected_create_targets(&protected_create_targets);
    let exec_start_pipe = create_exec_start_pipe(!protected_create_targets.is_empty());
    let parent_pid = unsafe { libc::getpid() };
    let pid = unsafe { libc::fork() };
    if pid < 0 {
        let err = std::io::Error::last_os_error();
        panic!("failed to fork for bubblewrap: {err}");
    }

    if pid == 0 {
        reset_forwarded_signal_handlers_to_default();
        setup_signal_mask.restore();
        let setpgid_res = unsafe { libc::setpgid(0, 0) };
        if setpgid_res < 0 {
            let err = std::io::Error::last_os_error();
            panic!("failed to place bubblewrap child in its own process group: {err}");
        }
        terminate_with_parent(parent_pid);
        wait_for_parent_exec_start(exec_start_pipe[0], exec_start_pipe[1]);
        exec_bwrap(args, preserved_files);
    }

    close_child_exec_start_read(exec_start_pipe[0]);
    let protected_create_monitor = ProtectedCreateMonitor::start(&protected_create_targets);
    let signal_forwarders = install_bwrap_signal_forwarders(pid);
    release_child_exec_start(exec_start_pipe[1]);
    setup_signal_mask.restore();
    let status = wait_for_bwrap_child(pid);
    let cleanup_signal_mask = ForwardedSignalMask::block();
    BWRAP_CHILD_PID.store(0, Ordering::SeqCst);
    let protected_create_monitor_violation = protected_create_monitor
        .map(ProtectedCreateMonitor::stop)
        .unwrap_or(false);
    cleanup_synthetic_mount_targets(&synthetic_mount_registrations);

View on GitHub (pinned to 339751715c)

Solutions

  1. Stop nesting sandboxes, or run the launcher outside the restrictive wrapper.
  2. If you own the outer seccomp policy, allow the setpgid syscall (syscall 109, @process group).
  3. Reproduce with strace -f -e setpgid to capture the exact errno printed in the panic.
  4. If the errno is unexpected on a stock kernel, report it against codex-rs/linux-sandbox with the trace.

Example fix

# before: outer unit filters process-management calls
SystemCallFilter=~@process

# after: allow setpgid for the nested sandbox launcher
SystemCallFilter=add setpgid
Defensive patterns

Strategy: validation

Validate before calling

fn process_group_creation_works() -> bool {
    match unsafe { libc::fork() } {
        0 => unsafe { libc::_exit(if libc::setpgid(0, 0) == 0 { 0 } else { 1 }) },
        pid if pid > 0 => {
            let mut status = 0;
            unsafe { libc::waitpid(pid, &mut status, 0) };
            libc::WIFEXITED(status) && libc::WEXITSTATUS(status) == 0
        }
        _ => false,
    }
}

Prevention

When it happens

Trigger: Any sandboxed command whose BwrapArgs carry synthetic mount targets or protected-create targets, forcing the fork path in run_or_exec_bwrap (linux_run_main.rs:568-598), executed under a wrapper whose seccomp filter blocks setpgid (EPERM) or denies it through policy.

Common situations: Nesting the linux-sandbox launcher inside another sandbox or container with a restrictive seccomp profile; hardened CI runners; gVisor-based runtimes; kernel hardening modules denying process-group manipulation.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/cc212cc451999bf3. Report an issue: GitHub.