summaryrefslogtreecommitdiffhomepage
path: root/runsc/test/testutil/testutil.go
diff options
context:
space:
mode:
authorFabricio Voznika <fvoznika@google.com>2018-08-27 11:09:06 -0700
committerShentubot <shentubot@google.com>2018-08-27 11:10:14 -0700
commitdb81c0b02f2f947ae837a3e16471a148a66436eb (patch)
treed91ef12da80b0a76ef1c69db290665e31cc59860 /runsc/test/testutil/testutil.go
parent2524111fc63343fd7372f5ea0266130adea778a5 (diff)
Put fsgofer inside chroot
Now each container gets its own dedicated gofer that is chroot'd to the rootfs path. This is done to add an extra layer of security in case the gofer gets compromised. PiperOrigin-RevId: 210396476 Change-Id: Iba21360a59dfe90875d61000db103f8609157ca0
Diffstat (limited to 'runsc/test/testutil/testutil.go')
-rw-r--r--runsc/test/testutil/testutil.go57
1 files changed, 57 insertions, 0 deletions
diff --git a/runsc/test/testutil/testutil.go b/runsc/test/testutil/testutil.go
index fc3d61e52..e90ab5ad5 100644
--- a/runsc/test/testutil/testutil.go
+++ b/runsc/test/testutil/testutil.go
@@ -23,11 +23,16 @@ import (
"io/ioutil"
"net/http"
"os"
+ "os/exec"
"path/filepath"
+ "runtime"
+ "syscall"
+ "testing"
"time"
"github.com/cenkalti/backoff"
specs "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/syndtr/gocapability/capability"
"gvisor.googlesource.com/gvisor/runsc/boot"
"gvisor.googlesource.com/gvisor/runsc/specutils"
)
@@ -227,3 +232,55 @@ func WaitForHTTP(port int, timeout time.Duration) error {
}
return Poll(cb, timeout)
}
+
+// RunAsRoot ensures the test runs with CAP_SYS_ADMIN. If need it will create
+// a new user namespace and reexecute the test as root inside of the namespace.
+func RunAsRoot(m *testing.M) {
+ caps, err := capability.NewPid2(os.Getpid())
+ if err != nil {
+ panic(err.Error())
+ }
+ if err := caps.Load(); err != nil {
+ panic(err.Error())
+ }
+ if caps.Get(capability.EFFECTIVE, capability.CAP_SYS_ADMIN) {
+ // Capability: check! Good to run.
+ os.Exit(m.Run())
+ }
+
+ // Current process doesn't have CAP_SYS_ADMIN, create user namespace and run
+ // as root inside that namespace to get it.
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ cmd := exec.Command("/proc/self/exe", os.Args...)
+ cmd.SysProcAttr = &syscall.SysProcAttr{
+ Cloneflags: syscall.CLONE_NEWUSER | syscall.CLONE_NEWNS,
+ // Set current user/group as root inside the namespace.
+ UidMappings: []syscall.SysProcIDMap{
+ {ContainerID: 0, HostID: os.Getuid(), Size: 1},
+ },
+ GidMappings: []syscall.SysProcIDMap{
+ {ContainerID: 0, HostID: os.Getgid(), Size: 1},
+ },
+ GidMappingsEnableSetgroups: false,
+ Credential: &syscall.Credential{
+ Uid: 0,
+ Gid: 0,
+ },
+ }
+ cmd.Env = os.Environ()
+ cmd.Stdin = os.Stdin
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ if err := cmd.Run(); err != nil {
+ if exit, ok := err.(*exec.ExitError); ok {
+ if ws, ok := exit.Sys().(syscall.WaitStatus); ok {
+ os.Exit(ws.ExitStatus())
+ }
+ os.Exit(-1)
+ }
+ panic(fmt.Sprint("error running child process:", err.Error()))
+ }
+ os.Exit(0)
+}