diff options
author | Fabricio Voznika <fvoznika@google.com> | 2018-09-28 09:43:13 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-09-28 09:44:13 -0700 |
commit | cf226d48ce8c49409049e03ed405366db9fc2a04 (patch) | |
tree | 293d892446f0b03179757ab8a45ae032ccb534aa /runsc | |
parent | 6779bd1187e2b0f8692ab8a16d8d1681f0e674c5 (diff) |
Switch to root in userns when CAP_SYS_CHROOT is also missing
Some tests check current capabilities and re-run the tests as root inside
userns if required capabibilities are missing. It was checking for
CAP_SYS_ADMIN only, CAP_SYS_CHROOT is also required now.
PiperOrigin-RevId: 214949226
Change-Id: Ic81363969fa76c04da408fae8ea7520653266312
Diffstat (limited to 'runsc')
-rw-r--r-- | runsc/cmd/capability.go | 6 | ||||
-rw-r--r-- | runsc/cmd/cmd.go | 1 | ||||
-rw-r--r-- | runsc/sandbox/BUILD | 1 | ||||
-rw-r--r-- | runsc/sandbox/sandbox.go | 7 | ||||
-rw-r--r-- | runsc/specutils/namespace.go | 22 | ||||
-rw-r--r-- | runsc/test/testutil/BUILD | 1 | ||||
-rw-r--r-- | runsc/test/testutil/testutil.go | 11 |
7 files changed, 24 insertions, 25 deletions
diff --git a/runsc/cmd/capability.go b/runsc/cmd/capability.go index affbb7ce3..0b18c5481 100644 --- a/runsc/cmd/capability.go +++ b/runsc/cmd/capability.go @@ -60,7 +60,11 @@ func applyCaps(caps *specs.LinuxCapabilities) error { newCaps.Set(c, set...) } - return newCaps.Apply(capability.CAPS | capability.BOUNDS | capability.AMBS) + if err := newCaps.Apply(capability.CAPS | capability.BOUNDS | capability.AMBS); err != nil { + return err + } + log.Infof("Capabilities applied: %+v", newCaps) + return nil } func getCaps(which capability.CapType, caps *specs.LinuxCapabilities) []string { diff --git a/runsc/cmd/cmd.go b/runsc/cmd/cmd.go index 44ebd7165..2937ae1c4 100644 --- a/runsc/cmd/cmd.go +++ b/runsc/cmd/cmd.go @@ -85,7 +85,6 @@ func setCapsAndCallSelf(args []string, caps *specs.LinuxCapabilities) error { return err } - log.Infof("Capabilities applied: %+v", caps) log.Infof("Execve %q again, bye!", binPath) syscall.Exec(binPath, args, []string{}) panic("unreachable") diff --git a/runsc/sandbox/BUILD b/runsc/sandbox/BUILD index 7ae19ff35..09965dcc0 100644 --- a/runsc/sandbox/BUILD +++ b/runsc/sandbox/BUILD @@ -25,6 +25,7 @@ go_library( "//runsc/specutils", "@com_github_cenkalti_backoff//:go_default_library", "@com_github_opencontainers_runtime-spec//specs-go:go_default_library", + "@com_github_syndtr_gocapability//capability:go_default_library", "@com_github_vishvananda_netlink//:go_default_library", ], ) diff --git a/runsc/sandbox/sandbox.go b/runsc/sandbox/sandbox.go index ef85f175f..d288be1d2 100644 --- a/runsc/sandbox/sandbox.go +++ b/runsc/sandbox/sandbox.go @@ -26,6 +26,7 @@ import ( "github.com/cenkalti/backoff" specs "github.com/opencontainers/runtime-spec/specs-go" + "github.com/syndtr/gocapability/capability" "gvisor.googlesource.com/gvisor/pkg/control/client" "gvisor.googlesource.com/gvisor/pkg/control/server" "gvisor.googlesource.com/gvisor/pkg/log" @@ -415,7 +416,7 @@ func (s *Sandbox) createSandboxProcess(spec *specs.Spec, conf *boot.Config, bund // 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() { + } else if specutils.HasCapabilities(capability.CAP_SETUID, capability.CAP_SETGID) { // Map nobody in the new namespace to nobody in the parent namespace. const nobody = 65534 cmd.SysProcAttr.UidMappings = []syscall.SysProcIDMap{{ @@ -442,7 +443,7 @@ func (s *Sandbox) createSandboxProcess(spec *specs.Spec, conf *boot.Config, bund // 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() { + } else if specutils.HasCapabilities(capability.CAP_SYS_ADMIN, capability.CAP_SYS_CHROOT) { log.Infof("Sandbox will be started in minimal chroot") chroot, err := setUpChroot() if err != nil { @@ -453,7 +454,7 @@ func (s *Sandbox) createSandboxProcess(spec *specs.Spec, conf *boot.Config, bund 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") + return fmt.Errorf("can't run sandbox process in minimal chroot since we don't have CAP_SYS_ADMIN and CAP_SYS_CHROOT") } } diff --git a/runsc/specutils/namespace.go b/runsc/specutils/namespace.go index 48a199a77..00293d45b 100644 --- a/runsc/specutils/namespace.go +++ b/runsc/specutils/namespace.go @@ -204,8 +204,8 @@ func SetUIDGIDMappings(cmd *exec.Cmd, s *specs.Spec) { } } -// CanSetUIDGID returns true if the user has SETUID and SETGID capabilities. -func CanSetUIDGID() bool { +// HasCapabilities returns true if the user has all capabilties in 'cs'. +func HasCapabilities(cs ...capability.Cap) bool { caps, err := capability.NewPid2(os.Getpid()) if err != nil { return false @@ -213,18 +213,10 @@ func CanSetUIDGID() bool { if err := caps.Load(); err != nil { return false } - 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 + for _, c := range cs { + if !caps.Get(capability.EFFECTIVE, c) { + return false + } } - return caps.Get(capability.EFFECTIVE, capability.CAP_SYS_ADMIN) + return true } diff --git a/runsc/test/testutil/BUILD b/runsc/test/testutil/BUILD index 03ab3c4ac..ca91e07ff 100644 --- a/runsc/test/testutil/BUILD +++ b/runsc/test/testutil/BUILD @@ -18,5 +18,6 @@ go_library( "//runsc/specutils", "@com_github_cenkalti_backoff//:go_default_library", "@com_github_opencontainers_runtime-spec//specs-go:go_default_library", + "@com_github_syndtr_gocapability//capability:go_default_library", ], ) diff --git a/runsc/test/testutil/testutil.go b/runsc/test/testutil/testutil.go index 37927f395..706db74a7 100644 --- a/runsc/test/testutil/testutil.go +++ b/runsc/test/testutil/testutil.go @@ -32,6 +32,7 @@ import ( "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" ) @@ -234,12 +235,12 @@ 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. -// This functionr returns when it's running as root. If it needs to create -// another process, it will exit from there and not return. +// RunAsRoot ensures the test runs with CAP_SYS_ADMIN and CAP_SYS_CHROOT. If +// need it will create a new user namespace and reexecute the test as root +// inside of the namespace. This functionr returns when it's running as root. If +// it needs to create another process, it will exit from there and not return. func RunAsRoot() { - if specutils.HasCapSysAdmin() { + if specutils.HasCapabilities(capability.CAP_SYS_ADMIN, capability.CAP_SYS_CHROOT) { return } |