diff options
Diffstat (limited to 'src/syscall/exec_linux.go')
| -rw-r--r-- | src/syscall/exec_linux.go | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go index 1ed10dd915..e35ac25580 100644 --- a/src/syscall/exec_linux.go +++ b/src/syscall/exec_linux.go @@ -42,6 +42,11 @@ type SysProcAttr struct { GidMappingsEnableSetgroups bool } +var ( + none = [...]byte{'n', 'o', 'n', 'e', 0} + slash = [...]byte{'/', 0} +) + // Implemented in runtime package. func runtime_BeforeFork() func runtime_AfterFork() @@ -204,6 +209,19 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr if err1 != 0 { goto childerror } + // The unshare system call in Linux doesn't unshare mount points + // mounted with --shared. Systemd mounts / with --shared. For a + // long discussion of the pros and cons of this see debian bug 739593. + // The Go model of unsharing is more like Plan 9, where you ask + // to unshare and the namespaces are unconditionally unshared. + // To make this model work we must further mark / as MS_PRIVATE. + // This is what the standard unshare command does. + if sys.Unshareflags&CLONE_NEWNS == CLONE_NEWNS { + _, _, err1 = RawSyscall6(SYS_MOUNT, uintptr(unsafe.Pointer(&none[0])), uintptr(unsafe.Pointer(&slash[0])), 0, MS_REC|MS_PRIVATE, 0, 0) + if err1 != 0 { + goto childerror + } + } } // User and groups |
