syscall: fix ordering of Unshare and chroot on Linux

When unshare specifies a new namespace, the syscall
package changes / to make namespace changes private.

If a chroot is specified, the unshare must be done first.
If the chroot is done first then the unshare will
not specify the correct /.

A new test is included which test combining chroot
and CLONE_NEWNS; it fails without the patch and works with
it.

Fixes #20103

Change-Id: I86022803c784bd418a30383321f3d64103d95c62
Reviewed-on: https://go-review.googlesource.com/41626
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:
Ronald G. Minnich 2017-04-24 16:09:24 -07:00 committed by Ian Lance Taylor
parent cf3a28124b
commit 67399c6279
2 changed files with 71 additions and 9 deletions

View file

@ -195,14 +195,6 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
}
}
// Chroot
if chroot != nil {
_, _, err1 = RawSyscall(SYS_CHROOT, uintptr(unsafe.Pointer(chroot)), 0, 0)
if err1 != 0 {
goto childerror
}
}
// Unshare
if sys.Unshareflags != 0 {
_, _, err1 = RawSyscall(SYS_UNSHARE, sys.Unshareflags, 0, 0)
@ -224,6 +216,14 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
}
}
// Chroot
if chroot != nil {
_, _, err1 = RawSyscall(SYS_CHROOT, uintptr(unsafe.Pointer(chroot)), 0, 0)
if err1 != 0 {
goto childerror
}
}
// User and groups
if cred := sys.Credential; cred != nil {
ngroups := uintptr(len(cred.Groups))