aboutsummaryrefslogtreecommitdiff
path: root/src/syscall/exec_linux.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/syscall/exec_linux.go')
-rw-r--r--src/syscall/exec_linux.go18
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