diff options
author | Tobias Bosch <tbosch@google.com> | 2019-09-06 10:19:51 -0700 |
---|---|---|
committer | Tobias Bosch <tbosch@google.com> | 2019-09-06 23:11:42 +0000 |
commit | 7d811f440f3dc7de8ae7f0faa8044fe6751f4944 (patch) | |
tree | 091ff6fe39e8b3a6161c705cc7e59f90581f207f /compiler_wrapper | |
parent | 367e8a932d78a4037bf0acdbc62fae8f3f46be99 (diff) | |
download | toolchain-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-x | compiler_wrapper/build.py | 17 | ||||
-rw-r--r-- | compiler_wrapper/env.go | 3 | ||||
-rw-r--r-- | compiler_wrapper/libc_execve.go | 63 |
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 +} |