diff options
author | Fabricio Voznika <fvoznika@google.com> | 2018-05-24 14:27:05 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-05-24 14:27:57 -0700 |
commit | e48f7078761b00552ac74068c184ee4fb90fe9aa (patch) | |
tree | 8cb4ff41119d6fa8c28ed11d33f350bae4321ad1 /runsc/container | |
parent | 7996ae7ccf284718fc98f5ba34c94b044b858ec2 (diff) |
Configure sandbox as superuser
Container user might not have enough priviledge to walk directories and
mount filesystems. Instead, create superuser to perform these steps of
the configuration.
PiperOrigin-RevId: 197953667
Change-Id: I643650ab654e665408e2af1b8e2f2aa12d58d4fb
Diffstat (limited to 'runsc/container')
-rw-r--r-- | runsc/container/container_test.go | 106 |
1 files changed, 73 insertions, 33 deletions
diff --git a/runsc/container/container_test.go b/runsc/container/container_test.go index e1674d631..24e9de3ce 100644 --- a/runsc/container/container_test.go +++ b/runsc/container/container_test.go @@ -20,6 +20,7 @@ import ( "io" "io/ioutil" "os" + "path" "path/filepath" "reflect" "strings" @@ -132,6 +133,34 @@ func waitForProcessList(s *container.Container, expected []*control.Process) err return fmt.Errorf("container got process list: %s, want: %s", procListToString(got), procListToString(expected)) } +// procListsEqual is used to check whether 2 Process lists are equal for all +// implemented fields. +func procListsEqual(got, want []*control.Process) bool { + if len(got) != len(want) { + return false + } + for i := range got { + pd1 := got[i] + pd2 := want[i] + // Zero out unimplemented and timing dependant fields. + pd1.Time, pd2.Time = "", "" + pd1.STime, pd2.STime = "", "" + pd1.C, pd2.C = 0, 0 + if *pd1 != *pd2 { + return false + } + } + return true +} + +func procListToString(pl []*control.Process) string { + strs := make([]string, 0, len(pl)) + for _, p := range pl { + strs = append(strs, fmt.Sprintf("%+v", p)) + } + return fmt.Sprintf("[%s]", strings.Join(strs, ",")) +} + // TestLifecycle tests the basic Create/Start/Signal/Destroy container lifecycle. // It verifies after each step that the container can be loaded from disk, and // has the correct status. @@ -434,17 +463,6 @@ func TestCapabilities(t *testing.T) { Type: "bind", }) - // Capability below is needed to mount TempDir above in case the user doesn't - // have access to all parents that lead to TempDir. - caps := []string{"CAP_DAC_OVERRIDE"} - spec.Process.Capabilities = &specs.LinuxCapabilities{ - Bounding: caps, - Effective: caps, - Inheritable: caps, - Permitted: caps, - Ambient: caps, - } - rootDir, bundleDir, conf, err := setupContainer(spec) if err != nil { t.Fatalf("error setting up container: %v", err) @@ -621,32 +639,54 @@ func TestSpecUnsupported(t *testing.T) { } } -// procListsEqual is used to check whether 2 Process lists are equal for all -// implemented fields. -func procListsEqual(got, want []*control.Process) bool { - if len(got) != len(want) { - return false +// TestRunNonRoot checks that sandbox can be configured when running as +// non-priviledged user. +func TestRunNonRoot(t *testing.T) { + spec := newSpecWithArgs("/bin/true") + spec.Process.User.UID = 343 + spec.Process.User.GID = 2401 + + // User that container runs as can't list '$TMP/blocked' and would fail to + // mount it. + dir := path.Join(os.TempDir(), "blocked") + if err := os.Mkdir(dir, 0700); err != nil { + t.Fatalf("os.MkDir(%q) failed: %v", dir, err) } - for i := range got { - pd1 := got[i] - pd2 := want[i] - // Zero out unimplemented and timing dependant fields. - pd1.Time, pd2.Time = "", "" - pd1.STime, pd2.STime = "", "" - pd1.C, pd2.C = 0, 0 - if *pd1 != *pd2 { - return false - } + dir = path.Join(dir, "test") + if err := os.Mkdir(dir, 0755); err != nil { + t.Fatalf("os.MkDir(%q) failed: %v", dir, err) } - return true -} -func procListToString(pl []*control.Process) string { - strs := make([]string, 0, len(pl)) - for _, p := range pl { - strs = append(strs, fmt.Sprintf("%+v", p)) + // We generate files in the host temporary directory. + spec.Mounts = append(spec.Mounts, specs.Mount{ + Destination: dir, + Source: dir, + Type: "bind", + }) + + rootDir, bundleDir, conf, err := setupContainer(spec) + if err != nil { + t.Fatalf("error setting up container: %v", err) + } + defer os.RemoveAll(rootDir) + defer os.RemoveAll(bundleDir) + + // Create, start and wait for the container. + s, err := container.Create(uniqueContainerID(), spec, conf, bundleDir, "", "") + if err != nil { + t.Fatalf("error creating container: %v", err) + } + defer s.Destroy() + if err := s.Start(conf); err != nil { + t.Fatalf("error starting container: %v", err) + } + ws, err := s.Wait() + if err != nil { + t.Errorf("error waiting on container: %v", err) + } + if !ws.Exited() || ws.ExitStatus() != 0 { + t.Errorf("container failed, waitStatus: %v", ws) } - return fmt.Sprintf("[%s]", strings.Join(strs, ",")) } // TestMain acts like runsc if it is called with the "boot" argument, otherwise |