Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions internal/sandboxrun/bwrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
// - system baseline as --ro-bind
// - fresh --proc /proc and --dev /dev, --tmpfs /tmp unless granted
// - --unshare-pid --unshare-ipc --unshare-uts (NOT --unshare-net)
// - --die-with-parent --new-session
// - --die-with-parent (NOT --new-session, see below)
// - protected paths inside granted trees masked with --tmpfs (dirs)
// or --ro-bind /dev/null (files), honoring override_deny
//
Expand All @@ -34,7 +34,15 @@ func BuildBwrapArgv(g *Grants, stage2Argv []string) ([]string, error) {
argv := []string{
"bwrap",
"--die-with-parent",
"--new-session",
// Deliberately NOT --new-session. setsid(2) detaches the inner
// process tree from the controlling terminal, which stops the
// kernel from delivering SIGWINCH on window resize — so an inner
// TUI (e.g. opencode) renders once and never reflows. --new-session
// exists only to block TIOCSTI terminal-input injection; that
// vector is gated off by the kernel on Linux >= 6.2 via the
// dev.tty.legacy_tiocsti sysctl (default 0). We keep the real
// terminal so resize works; filesystem/network/PID isolation is
// unaffected (it comes from the binds, Landlock, and --unshare-*).
"--unshare-pid",
"--unshare-ipc",
"--unshare-uts",
Expand Down
6 changes: 5 additions & 1 deletion internal/sandboxrun/bwrap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ func TestBwrapArgvStructure(t *testing.T) {
for _, want := range []string{
"bwrap",
"--die-with-parent",
"--new-session",
"--unshare-pid",
"--unshare-ipc",
"--unshare-uts",
Expand All @@ -57,6 +56,11 @@ func TestBwrapArgvStructure(t *testing.T) {
if strings.Contains(joined, "--unshare-net") {
t.Error("network namespace must NOT be unshared")
}
// --new-session detaches the controlling terminal and breaks SIGWINCH
// resize propagation into the inner TUI; it must stay out.
if strings.Contains(joined, "--new-session") {
t.Error("must NOT use --new-session (breaks terminal resize/SIGWINCH)")
}
}

func TestBwrapNoTmpfsWhenTmpGranted(t *testing.T) {
Expand Down
Loading