mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
os/exec: handle Unshareflags with CLONE_NEWNS
In some newer Linux distros, systemd forces
all mount namespaces to be shared, starting
at /. This disables the CLONE_NEWNS
flag in unshare(2) and clone(2).
While this problem is most commonly seen
on systems with systemd, it can happen anywhere,
due to how Linux namespaces now work.
Hence, to create a private mount namespace,
it is not sufficient to just set
CLONE_NEWS; you have to call mount(2) to change
the behavior of namespaces, i.e.
mount("none", "/", NULL, MS_REC|MS_PRIVATE, NULL)
This is tested and working and we can now correctly
start child process with private namespaces on Linux
distros that use systemd.
The new test works correctly on Ubuntu 16.04.2 LTS.
It fails if I comment out the new Mount, and
succeeds otherwise. In each case it correctly
cleans up after itself.
Fixes #19661
Change-Id: I52240b59628e3772b529d9bbef7166606b0c157d
Reviewed-on: https://go-review.googlesource.com/38471
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
9ecfd177cf
commit
d8ed449d8e
2 changed files with 80 additions and 0 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue