runtime, syscall: workaround for bug in Linux's execve

Linux's execve has (at the time of writing, and since v2.6.30) a bug when it ran
concurrently with clone, in that it would fail to set up some datastructures if
the thread count before and after some steps differed. This is described better
and in more detail by Colin King in Launchpad¹ and kernel² bugs. When a program
written in Go runtime.Exec's a setuid binary, this issue may cause the resulting
process to not have the expected uid. This patch works around the issue by using
a mutex to serialize exec and clone.

1. https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1672819
2. https://bugzilla.kernel.org/show_bug.cgi?id=195453

Fixes #19546

Change-Id: I126e87d1d9ce3be5ea4ec9c7ffe13f92e087903d
Reviewed-on: https://go-review.googlesource.com/43713
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:
John R. Lenton 2017-05-20 17:22:36 +01:00 committed by Ian Lance Taylor
parent 3ca8ee14d1
commit 91139b87f7
2 changed files with 28 additions and 0 deletions

View file

@ -242,6 +242,10 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
return pid, 0, err
}
// Implemented in runtime package.
func runtime_BeforeExec()
func runtime_AfterExec()
// Exec invokes the execve(2) system call.
func Exec(argv0 string, argv []string, envv []string) (err error) {
argv0p, err := BytePtrFromString(argv0)
@ -256,9 +260,11 @@ func Exec(argv0 string, argv []string, envv []string) (err error) {
if err != nil {
return err
}
runtime_BeforeExec()
_, _, err1 := RawSyscall(SYS_EXECVE,
uintptr(unsafe.Pointer(argv0p)),
uintptr(unsafe.Pointer(&argvp[0])),
uintptr(unsafe.Pointer(&envvp[0])))
runtime_AfterExec()
return Errno(err1)
}