summaryrefslogtreecommitdiffhomepage
path: root/runsc/sandbox/sandbox.go
diff options
context:
space:
mode:
authorNicolas Lacasse <nlacasse@google.com>2018-09-07 10:15:34 -0700
committerShentubot <shentubot@google.com>2018-09-07 10:16:39 -0700
commit210c2520890ea48d551c0c9fffe890a7c60fb802 (patch)
tree4f431b5737cd9e6a7c8c33e459242c3404eab7c0 /runsc/sandbox/sandbox.go
parent590d8320992d74e54e2c095c68c49abc2b23dcbe (diff)
runsc: Run sandbox process inside minimal chroot.
We construct a dir with the executable bind-mounted at /exe, and proc mounted at /proc. Runsc now executes the sandbox process inside this chroot, thus limiting access to the host filesystem. The mounts and chroot dir are removed when the sandbox is destroyed. Because this requires bind-mounts, we can only do the chroot if we have CAP_SYS_ADMIN. PiperOrigin-RevId: 211994001 Change-Id: Ia71c515e26085e0b69b833e71691830148bc70d1
Diffstat (limited to 'runsc/sandbox/sandbox.go')
-rw-r--r--runsc/sandbox/sandbox.go33
1 files changed, 29 insertions, 4 deletions
diff --git a/runsc/sandbox/sandbox.go b/runsc/sandbox/sandbox.go
index dd5a0aa56..f6264d5b2 100644
--- a/runsc/sandbox/sandbox.go
+++ b/runsc/sandbox/sandbox.go
@@ -51,6 +51,10 @@ type Sandbox struct {
// Pid is the pid of the running sandbox (immutable). May be 0 is the sandbox
// is not running.
Pid int `json:"pid"`
+
+ // Chroot is the path to the chroot directory that the sandbox process
+ // is running in.
+ Chroot string `json:"chroot"`
}
// Create creates the sandbox process.
@@ -392,12 +396,11 @@ func (s *Sandbox) createSandboxProcess(spec *specs.Spec, conf *boot.Config, bund
log.Infof("Sandbox will be started in new user namespace")
nss = append(nss, specs.LinuxNamespace{Type: specs.UserNamespace})
- if conf.TestOnlyAllowRunAsCurrentUser {
+ // If we have CAP_SETUID and CAP_SETGID, then we can also run
+ // as user nobody.
+ if conf.TestOnlyAllowRunAsCurrentUserWithoutChroot {
log.Warningf("Running sandbox in test mode as current user (uid=%d gid=%d). This is only safe in tests!", os.Getuid(), os.Getgid())
} else if specutils.CanSetUIDGID() {
- // If we have CAP_SETUID and CAP_SETGID, then we can also run
- // as user nobody.
-
// Map nobody in the new namespace to nobody in the parent namespace.
const nobody = 65534
cmd.SysProcAttr.UidMappings = []syscall.SysProcIDMap{{
@@ -419,6 +422,23 @@ func (s *Sandbox) createSandboxProcess(spec *specs.Spec, conf *boot.Config, bund
} else {
return fmt.Errorf("can't run sandbox process as user nobody since we don't have CAP_SETUID or CAP_SETGID")
}
+
+ // If we have CAP_SYS_ADMIN, we can create an empty chroot and
+ // bind-mount the executable inside it.
+ if conf.TestOnlyAllowRunAsCurrentUserWithoutChroot {
+ log.Warningf("Running sandbox in test mode without chroot. This is only safe in tests!")
+ } else if specutils.HasCapSysAdmin() {
+ log.Infof("Sandbox will be started in minimal chroot")
+ chroot, err := setUpChroot(conf.Platform)
+ if err != nil {
+ return fmt.Errorf("error setting up chroot: %v", err)
+ }
+ cmd.SysProcAttr.Chroot = chroot
+ cmd.Args[0] = "/runsc"
+ cmd.Path = "/runsc"
+ } else {
+ return fmt.Errorf("can't run sandbox process in minimal chroot since we don't have CAP_SYS_ADMIN")
+ }
}
// Log the fds we are donating to the sandbox process.
@@ -525,6 +545,11 @@ func (s *Sandbox) Destroy() error {
log.Debugf("Killing sandbox %q", s.ID)
signalProcess(s.Pid, unix.SIGKILL)
}
+
+ if s.Chroot != "" {
+ return tearDownChroot(s.Chroot)
+ }
+
return nil
}