diff options
author | Nicolas Lacasse <nlacasse@google.com> | 2018-09-07 10:15:34 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-09-07 10:16:39 -0700 |
commit | 210c2520890ea48d551c0c9fffe890a7c60fb802 (patch) | |
tree | 4f431b5737cd9e6a7c8c33e459242c3404eab7c0 /runsc/specutils | |
parent | 590d8320992d74e54e2c095c68c49abc2b23dcbe (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/specutils')
-rw-r--r-- | runsc/specutils/namespace.go | 12 | ||||
-rw-r--r-- | runsc/specutils/specutils.go | 41 |
2 files changed, 53 insertions, 0 deletions
diff --git a/runsc/specutils/namespace.go b/runsc/specutils/namespace.go index 356943a65..48a199a77 100644 --- a/runsc/specutils/namespace.go +++ b/runsc/specutils/namespace.go @@ -216,3 +216,15 @@ func CanSetUIDGID() bool { return caps.Get(capability.EFFECTIVE, capability.CAP_SETUID) && caps.Get(capability.EFFECTIVE, capability.CAP_SETGID) } + +// HasCapSysAdmin returns true if the user has CAP_SYS_ADMIN capability. +func HasCapSysAdmin() bool { + caps, err := capability.NewPid2(os.Getpid()) + if err != nil { + return false + } + if err := caps.Load(); err != nil { + return false + } + return caps.Get(capability.EFFECTIVE, capability.CAP_SYS_ADMIN) +} diff --git a/runsc/specutils/specutils.go b/runsc/specutils/specutils.go index 551718e9a..f3fa8d129 100644 --- a/runsc/specutils/specutils.go +++ b/runsc/specutils/specutils.go @@ -363,3 +363,44 @@ func DebugLogFile(logDir, subcommand string) (*os.File, error) { filename := fmt.Sprintf("runsc.log.%s.%s", time.Now().Format("20060102-150405.000000"), subcommand) return os.OpenFile(filepath.Join(logDir, filename), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0664) } + +// Mount creates the mount point and calls Mount with the given flags. +func Mount(src, dst, typ string, flags uint32) error { + // Create the mount point inside. The type must be the same as the + // source (file or directory). + var isDir bool + if typ == "proc" { + // Special case, as there is no source directory for proc + // mounts. + isDir = true + } else if fi, err := os.Stat(src); err != nil { + return fmt.Errorf("Stat(%q) failed: %v", src, err) + } else { + isDir = fi.IsDir() + } + + if isDir { + // Create the destination directory. + if err := os.MkdirAll(dst, 0777); err != nil { + return fmt.Errorf("Mkdir(%q) failed: %v", dst, err) + } + } else { + // Create the parent destination directory. + parent := path.Dir(dst) + if err := os.MkdirAll(parent, 0777); err != nil { + return fmt.Errorf("Mkdir(%q) failed: %v", parent, err) + } + // Create the destination file if it does not exist. + f, err := os.OpenFile(dst, syscall.O_CREAT, 0777) + if err != nil { + return fmt.Errorf("Open(%q) failed: %v", dst, err) + } + f.Close() + } + + // Do the mount. + if err := syscall.Mount(src, dst, typ, uintptr(flags), ""); err != nil { + return fmt.Errorf("Mount(%q, %q, %d) failed: %v", src, dst, flags, err) + } + return nil +} |