summaryrefslogtreecommitdiffhomepage
path: root/runsc/specutils
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/specutils
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/specutils')
-rw-r--r--runsc/specutils/namespace.go12
-rw-r--r--runsc/specutils/specutils.go41
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
+}