Skip to content
This repository was archived by the owner on Feb 1, 2020. It is now read-only.

Commit cf226d4

Browse files
fvoznikashentubot
authored andcommitted
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
1 parent 6779bd1 commit cf226d4

File tree

7 files changed

+24
-25
lines changed

7 files changed

+24
-25
lines changed

runsc/cmd/capability.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,11 @@ func applyCaps(caps *specs.LinuxCapabilities) error {
6060
newCaps.Set(c, set...)
6161
}
6262

63-
return newCaps.Apply(capability.CAPS | capability.BOUNDS | capability.AMBS)
63+
if err := newCaps.Apply(capability.CAPS | capability.BOUNDS | capability.AMBS); err != nil {
64+
return err
65+
}
66+
log.Infof("Capabilities applied: %+v", newCaps)
67+
return nil
6468
}
6569

6670
func getCaps(which capability.CapType, caps *specs.LinuxCapabilities) []string {

runsc/cmd/cmd.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ func setCapsAndCallSelf(args []string, caps *specs.LinuxCapabilities) error {
8585
return err
8686
}
8787

88-
log.Infof("Capabilities applied: %+v", caps)
8988
log.Infof("Execve %q again, bye!", binPath)
9089
syscall.Exec(binPath, args, []string{})
9190
panic("unreachable")

runsc/sandbox/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ go_library(
2525
"//runsc/specutils",
2626
"@com_github_cenkalti_backoff//:go_default_library",
2727
"@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
28+
"@com_github_syndtr_gocapability//capability:go_default_library",
2829
"@com_github_vishvananda_netlink//:go_default_library",
2930
],
3031
)

runsc/sandbox/sandbox.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626

2727
"github.com/cenkalti/backoff"
2828
specs "github.com/opencontainers/runtime-spec/specs-go"
29+
"github.com/syndtr/gocapability/capability"
2930
"gvisor.googlesource.com/gvisor/pkg/control/client"
3031
"gvisor.googlesource.com/gvisor/pkg/control/server"
3132
"gvisor.googlesource.com/gvisor/pkg/log"
@@ -415,7 +416,7 @@ func (s *Sandbox) createSandboxProcess(spec *specs.Spec, conf *boot.Config, bund
415416
// as user nobody.
416417
if conf.TestOnlyAllowRunAsCurrentUserWithoutChroot {
417418
log.Warningf("Running sandbox in test mode as current user (uid=%d gid=%d). This is only safe in tests!", os.Getuid(), os.Getgid())
418-
} else if specutils.CanSetUIDGID() {
419+
} else if specutils.HasCapabilities(capability.CAP_SETUID, capability.CAP_SETGID) {
419420
// Map nobody in the new namespace to nobody in the parent namespace.
420421
const nobody = 65534
421422
cmd.SysProcAttr.UidMappings = []syscall.SysProcIDMap{{
@@ -442,7 +443,7 @@ func (s *Sandbox) createSandboxProcess(spec *specs.Spec, conf *boot.Config, bund
442443
// bind-mount the executable inside it.
443444
if conf.TestOnlyAllowRunAsCurrentUserWithoutChroot {
444445
log.Warningf("Running sandbox in test mode without chroot. This is only safe in tests!")
445-
} else if specutils.HasCapSysAdmin() {
446+
} else if specutils.HasCapabilities(capability.CAP_SYS_ADMIN, capability.CAP_SYS_CHROOT) {
446447
log.Infof("Sandbox will be started in minimal chroot")
447448
chroot, err := setUpChroot()
448449
if err != nil {
@@ -453,7 +454,7 @@ func (s *Sandbox) createSandboxProcess(spec *specs.Spec, conf *boot.Config, bund
453454
cmd.Args[0] = "/runsc"
454455
cmd.Path = "/runsc"
455456
} else {
456-
return fmt.Errorf("can't run sandbox process in minimal chroot since we don't have CAP_SYS_ADMIN")
457+
return fmt.Errorf("can't run sandbox process in minimal chroot since we don't have CAP_SYS_ADMIN and CAP_SYS_CHROOT")
457458
}
458459
}
459460

runsc/specutils/namespace.go

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -204,27 +204,19 @@ func SetUIDGIDMappings(cmd *exec.Cmd, s *specs.Spec) {
204204
}
205205
}
206206

207-
// CanSetUIDGID returns true if the user has SETUID and SETGID capabilities.
208-
func CanSetUIDGID() bool {
207+
// HasCapabilities returns true if the user has all capabilties in 'cs'.
208+
func HasCapabilities(cs ...capability.Cap) bool {
209209
caps, err := capability.NewPid2(os.Getpid())
210210
if err != nil {
211211
return false
212212
}
213213
if err := caps.Load(); err != nil {
214214
return false
215215
}
216-
return caps.Get(capability.EFFECTIVE, capability.CAP_SETUID) &&
217-
caps.Get(capability.EFFECTIVE, capability.CAP_SETGID)
218-
}
219-
220-
// HasCapSysAdmin returns true if the user has CAP_SYS_ADMIN capability.
221-
func HasCapSysAdmin() bool {
222-
caps, err := capability.NewPid2(os.Getpid())
223-
if err != nil {
224-
return false
225-
}
226-
if err := caps.Load(); err != nil {
227-
return false
216+
for _, c := range cs {
217+
if !caps.Get(capability.EFFECTIVE, c) {
218+
return false
219+
}
228220
}
229-
return caps.Get(capability.EFFECTIVE, capability.CAP_SYS_ADMIN)
221+
return true
230222
}

runsc/test/testutil/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ go_library(
1818
"//runsc/specutils",
1919
"@com_github_cenkalti_backoff//:go_default_library",
2020
"@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
21+
"@com_github_syndtr_gocapability//capability:go_default_library",
2122
],
2223
)

runsc/test/testutil/testutil.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232

3333
"github.com/cenkalti/backoff"
3434
specs "github.com/opencontainers/runtime-spec/specs-go"
35+
"github.com/syndtr/gocapability/capability"
3536
"gvisor.googlesource.com/gvisor/runsc/boot"
3637
"gvisor.googlesource.com/gvisor/runsc/specutils"
3738
)
@@ -234,12 +235,12 @@ func WaitForHTTP(port int, timeout time.Duration) error {
234235
return Poll(cb, timeout)
235236
}
236237

237-
// RunAsRoot ensures the test runs with CAP_SYS_ADMIN. If need it will create
238-
// a new user namespace and reexecute the test as root inside of the namespace.
239-
// This functionr returns when it's running as root. If it needs to create
240-
// another process, it will exit from there and not return.
238+
// RunAsRoot ensures the test runs with CAP_SYS_ADMIN and CAP_SYS_CHROOT. If
239+
// need it will create a new user namespace and reexecute the test as root
240+
// inside of the namespace. This functionr returns when it's running as root. If
241+
// it needs to create another process, it will exit from there and not return.
241242
func RunAsRoot() {
242-
if specutils.HasCapSysAdmin() {
243+
if specutils.HasCapabilities(capability.CAP_SYS_ADMIN, capability.CAP_SYS_CHROOT) {
243244
return
244245
}
245246

0 commit comments

Comments
 (0)