aboutsummaryrefslogtreecommitdiff
path: root/compiler_wrapper
diff options
context:
space:
mode:
authorTobias Bosch <tbosch@google.com>2019-09-06 10:19:51 -0700
committerTobias Bosch <tbosch@google.com>2019-09-06 23:11:42 +0000
commit7d811f440f3dc7de8ae7f0faa8044fe6751f4944 (patch)
tree091ff6fe39e8b3a6161c705cc7e59f90581f207f /compiler_wrapper
parent367e8a932d78a4037bf0acdbc62fae8f3f46be99 (diff)
downloadtoolchain-utils-7d811f440f3dc7de8ae7f0faa8044fe6751f4944.tar.gz
Use libc execve instead of syscall.Execve
Also create a dynamically linked binary. BUG=chromium:1000863 TEST=manual test against portage sandbox Change-Id: I36db7eac14466f41fbc1f0a41979039d8eaa1d83 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/1789670 Tested-by: Tobias Bosch <tbosch@google.com> Reviewed-by: George Burgess <gbiv@chromium.org>
Diffstat (limited to 'compiler_wrapper')
-rwxr-xr-xcompiler_wrapper/build.py17
-rw-r--r--compiler_wrapper/env.go3
-rw-r--r--compiler_wrapper/libc_execve.go63
3 files changed, 73 insertions, 10 deletions
diff --git a/compiler_wrapper/build.py b/compiler_wrapper/build.py
index 9d3384d1..6cbfa893 100755
--- a/compiler_wrapper/build.py
+++ b/compiler_wrapper/build.py
@@ -27,18 +27,19 @@ def parse_args():
def calc_go_args(args, version):
- # See https://github.com/golang/go/issues/26492 for how to
- # build a fully static binary in go.
ldFlags = [
- '-X', 'main.ConfigName=' + args.config, '-X',
- 'main.UseCCache=' + args.use_ccache, '-X',
- 'main.OldWrapperPath=' + args.old_wrapper_path, '-X',
- 'main.Version=' + version, "-extldflags '-static'"
+ '-X',
+ 'main.ConfigName=' + args.config,
+ '-X',
+ 'main.UseCCache=' + args.use_ccache,
+ '-X',
+ 'main.OldWrapperPath=' + args.old_wrapper_path,
+ '-X',
+ 'main.Version=' + version,
]
return [
'go', 'build', '-o',
- os.path.abspath(args.output_file), '-ldflags', ' '.join(ldFlags), '-tags',
- 'osusergo netgo static_build'
+ os.path.abspath(args.output_file), '-ldflags', ' '.join(ldFlags)
]
diff --git a/compiler_wrapper/env.go b/compiler_wrapper/env.go
index 399ba354..71e4c7ef 100644
--- a/compiler_wrapper/env.go
+++ b/compiler_wrapper/env.go
@@ -10,7 +10,6 @@ import (
"io"
"os"
"strings"
- "syscall"
)
type env interface {
@@ -73,7 +72,7 @@ func (env *processEnv) stderr() io.Writer {
func (env *processEnv) exec(cmd *command) error {
execCmd := newExecCmd(env, cmd)
- return syscall.Exec(execCmd.Path, execCmd.Args, execCmd.Env)
+ return libcExecve(execCmd.Path, execCmd.Args, execCmd.Env)
}
func (env *processEnv) run(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error {
diff --git a/compiler_wrapper/libc_execve.go b/compiler_wrapper/libc_execve.go
new file mode 100644
index 00000000..53160695
--- /dev/null
+++ b/compiler_wrapper/libc_execve.go
@@ -0,0 +1,63 @@
+// Copyright 2019 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package main
+
+// #include <stdlib.h>
+// #include <unistd.h>
+// #include <errno.h>
+// int libc_execve(const char *pathname, char *const argv[],
+// char *const envp[]) {
+// if (execve(pathname, argv, envp) != 0) {
+// return errno;
+// }
+// return 0;
+// }
+import "C"
+import (
+ "unsafe"
+)
+
+// Replacement for syscall.Execve that uses the libc.
+// This allows tools that rely on intercepting syscalls via
+// LD_PRELOAD to work properly (e.g. gentoo sandbox).
+// Note that this changes the go binary to be a dynamically linked one.
+// See crbug.com/1000863 for details.
+func libcExecve(argv0 string, argv []string, envv []string) error {
+ freeList := []unsafe.Pointer{}
+ defer func() {
+ for _, ptr := range freeList {
+ C.free(ptr)
+ }
+ }()
+
+ goStrToC := func(goStr string) *C.char {
+ cstr := C.CString(goStr)
+ freeList = append(freeList, unsafe.Pointer(cstr))
+ return cstr
+ }
+
+ goSliceToC := func(goSlice []string) **C.char {
+ // len(goSlice)+1 as the c array needs to be null terminated.
+ cArray := C.malloc(C.size_t(len(goSlice)+1) * C.size_t(unsafe.Sizeof(uintptr(0))))
+ freeList = append(freeList, cArray)
+
+ // Convert the C array to a Go Array so we can index it.
+ // Note: Storing pointers to the c heap in go pointer types is ok
+ // (see https://golang.org/cmd/cgo/).
+ cArrayForIndex := (*[1<<30 - 1]*C.char)(cArray)
+ for i, str := range goSlice {
+ cArrayForIndex[i] = goStrToC(str)
+ }
+ cArrayForIndex[len(goSlice)] = nil
+
+ return (**C.char)(cArray)
+ }
+
+ if errno := C.libc_execve(goStrToC(argv0), goSliceToC(argv), goSliceToC(envv)); errno != 0 {
+ return newErrorwithSourceLocf("exec error: %d", errno)
+ }
+
+ return nil
+}