diff options
Diffstat (limited to 'runsc/cmd')
-rw-r--r-- | runsc/cmd/BUILD | 98 | ||||
-rw-r--r-- | runsc/cmd/capability_test.go | 127 | ||||
-rw-r--r-- | runsc/cmd/cmd_state_autogen.go | 3 | ||||
-rw-r--r-- | runsc/cmd/delete_test.go | 41 | ||||
-rw-r--r-- | runsc/cmd/exec_test.go | 154 | ||||
-rw-r--r-- | runsc/cmd/gofer_test.go | 164 |
6 files changed, 3 insertions, 584 deletions
diff --git a/runsc/cmd/BUILD b/runsc/cmd/BUILD deleted file mode 100644 index 19520d7ab..000000000 --- a/runsc/cmd/BUILD +++ /dev/null @@ -1,98 +0,0 @@ -load("//tools:defs.bzl", "go_library", "go_test") - -package(licenses = ["notice"]) - -go_library( - name = "cmd", - srcs = [ - "boot.go", - "capability.go", - "checkpoint.go", - "chroot.go", - "cmd.go", - "create.go", - "debug.go", - "delete.go", - "do.go", - "error.go", - "events.go", - "exec.go", - "gofer.go", - "help.go", - "install.go", - "kill.go", - "list.go", - "path.go", - "pause.go", - "ps.go", - "restore.go", - "resume.go", - "run.go", - "spec.go", - "start.go", - "state.go", - "statefile.go", - "symbolize.go", - "syscalls.go", - "wait.go", - ], - visibility = [ - "//runsc:__subpackages__", - ], - deps = [ - "//pkg/coverage", - "//pkg/log", - "//pkg/p9", - "//pkg/sentry/control", - "//pkg/sentry/kernel", - "//pkg/sentry/kernel/auth", - "//pkg/sentry/platform", - "//pkg/state/pretty", - "//pkg/state/statefile", - "//pkg/sync", - "//pkg/unet", - "//pkg/urpc", - "//runsc/boot", - "//runsc/config", - "//runsc/console", - "//runsc/container", - "//runsc/flag", - "//runsc/fsgofer", - "//runsc/fsgofer/filter", - "//runsc/specutils", - "@com_github_google_subcommands//:go_default_library", - "@com_github_opencontainers_runtime_spec//specs-go:go_default_library", - "@com_github_syndtr_gocapability//capability:go_default_library", - "@org_golang_x_sys//unix:go_default_library", - ], -) - -go_test( - name = "cmd_test", - size = "small", - srcs = [ - "capability_test.go", - "delete_test.go", - "exec_test.go", - "gofer_test.go", - ], - data = [ - "//runsc", - ], - library = ":cmd", - deps = [ - "//pkg/abi/linux", - "//pkg/log", - "//pkg/sentry/control", - "//pkg/sentry/kernel/auth", - "//pkg/test/testutil", - "//pkg/urpc", - "//runsc/config", - "//runsc/container", - "//runsc/specutils", - "@com_github_google_go_cmp//cmp:go_default_library", - "@com_github_google_go_cmp//cmp/cmpopts: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/cmd/capability_test.go b/runsc/cmd/capability_test.go deleted file mode 100644 index e13a94486..000000000 --- a/runsc/cmd/capability_test.go +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2018 The gVisor Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cmd - -import ( - "flag" - "fmt" - "os" - "testing" - - specs "github.com/opencontainers/runtime-spec/specs-go" - "github.com/syndtr/gocapability/capability" - "gvisor.dev/gvisor/pkg/log" - "gvisor.dev/gvisor/pkg/test/testutil" - "gvisor.dev/gvisor/runsc/config" - "gvisor.dev/gvisor/runsc/container" - "gvisor.dev/gvisor/runsc/specutils" -) - -func init() { - log.SetLevel(log.Debug) - if err := testutil.ConfigureExePath(); err != nil { - panic(err.Error()) - } -} - -func checkProcessCaps(pid int, wantCaps *specs.LinuxCapabilities) error { - curCaps, err := capability.NewPid2(pid) - if err != nil { - return fmt.Errorf("capability.NewPid2(%d) failed: %v", pid, err) - } - if err := curCaps.Load(); err != nil { - return fmt.Errorf("unable to load capabilities: %v", err) - } - fmt.Printf("Capabilities (PID: %d): %v\n", pid, curCaps) - - for _, c := range allCapTypes { - if err := checkCaps(c, curCaps, wantCaps); err != nil { - return err - } - } - return nil -} - -func checkCaps(which capability.CapType, curCaps capability.Capabilities, wantCaps *specs.LinuxCapabilities) error { - wantNames := getCaps(which, wantCaps) - for name, c := range capFromName { - want := specutils.ContainsStr(wantNames, name) - got := curCaps.Get(which, c) - if want != got { - if want { - return fmt.Errorf("capability %v:%s should be set", which, name) - } - return fmt.Errorf("capability %v:%s should NOT be set", which, name) - } - } - return nil -} - -func TestCapabilities(t *testing.T) { - stop := testutil.StartReaper() - defer stop() - - spec := testutil.NewSpecWithArgs("/bin/sleep", "10000") - caps := []string{ - "CAP_CHOWN", - "CAP_SYS_PTRACE", // ptrace is added due to the platform choice. - } - spec.Process.Capabilities = &specs.LinuxCapabilities{ - Permitted: caps, - Bounding: caps, - Effective: caps, - Inheritable: caps, - } - - conf := testutil.TestConfig(t) - - // Use --network=host to make sandbox use spec's capabilities. - conf.Network = config.NetworkHost - - _, bundleDir, cleanup, err := testutil.SetupContainer(spec, conf) - if err != nil { - t.Fatalf("error setting up container: %v", err) - } - defer cleanup() - - // Create and start the container. - args := container.Args{ - ID: testutil.RandomContainerID(), - Spec: spec, - BundleDir: bundleDir, - } - c, err := container.New(conf, args) - if err != nil { - t.Fatalf("error creating container: %v", err) - } - defer c.Destroy() - if err := c.Start(conf); err != nil { - t.Fatalf("error starting container: %v", err) - } - - // Check that sandbox and gofer have the proper capabilities. - if err := checkProcessCaps(c.Sandbox.Pid, spec.Process.Capabilities); err != nil { - t.Error(err) - } - if err := checkProcessCaps(c.GoferPid, goferCaps); err != nil { - t.Error(err) - } -} - -func TestMain(m *testing.M) { - flag.Parse() - specutils.MaybeRunAsRoot() - os.Exit(m.Run()) -} diff --git a/runsc/cmd/cmd_state_autogen.go b/runsc/cmd/cmd_state_autogen.go new file mode 100644 index 000000000..de8aa267b --- /dev/null +++ b/runsc/cmd/cmd_state_autogen.go @@ -0,0 +1,3 @@ +// automatically generated by stateify. + +package cmd diff --git a/runsc/cmd/delete_test.go b/runsc/cmd/delete_test.go deleted file mode 100644 index e2d994a05..000000000 --- a/runsc/cmd/delete_test.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2018 The gVisor Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cmd - -import ( - "io/ioutil" - "testing" - - "gvisor.dev/gvisor/runsc/config" -) - -func TestNotFound(t *testing.T) { - ids := []string{"123"} - dir, err := ioutil.TempDir("", "metadata") - if err != nil { - t.Fatalf("error creating dir: %v", err) - } - conf := &config.Config{RootDir: dir} - - d := Delete{} - if err := d.execute(ids, conf); err == nil { - t.Error("Deleting non-existent container should have failed") - } - - d = Delete{force: true} - if err := d.execute(ids, conf); err != nil { - t.Errorf("Deleting non-existent container with --force should NOT have failed: %v", err) - } -} diff --git a/runsc/cmd/exec_test.go b/runsc/cmd/exec_test.go deleted file mode 100644 index a1e980d08..000000000 --- a/runsc/cmd/exec_test.go +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2018 The gVisor Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cmd - -import ( - "os" - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - specs "github.com/opencontainers/runtime-spec/specs-go" - "gvisor.dev/gvisor/pkg/abi/linux" - "gvisor.dev/gvisor/pkg/sentry/control" - "gvisor.dev/gvisor/pkg/sentry/kernel/auth" - "gvisor.dev/gvisor/pkg/urpc" -) - -func TestUser(t *testing.T) { - testCases := []struct { - input string - want user - wantErr bool - }{ - {input: "0", want: user{kuid: 0, kgid: 0}}, - {input: "7", want: user{kuid: 7, kgid: 0}}, - {input: "49:343", want: user{kuid: 49, kgid: 343}}, - {input: "0:2401", want: user{kuid: 0, kgid: 2401}}, - {input: "", wantErr: true}, - {input: "foo", wantErr: true}, - {input: ":123", wantErr: true}, - {input: "1:2:3", wantErr: true}, - } - - for _, tc := range testCases { - var u user - if err := u.Set(tc.input); err != nil && tc.wantErr { - // We got an error and wanted one. - continue - } else if err == nil && tc.wantErr { - t.Errorf("user.Set(%s): got no error, but wanted one", tc.input) - } else if err != nil && !tc.wantErr { - t.Errorf("user.Set(%s): got error %v, but wanted none", tc.input, err) - } else if u != tc.want { - t.Errorf("user.Set(%s): got %+v, but wanted %+v", tc.input, u, tc.want) - } - } -} - -func TestCLIArgs(t *testing.T) { - testCases := []struct { - ex Exec - argv []string - expected control.ExecArgs - }{ - { - ex: Exec{ - cwd: "/foo/bar", - user: user{kuid: 0, kgid: 0}, - extraKGIDs: []string{"1", "2", "3"}, - caps: []string{"CAP_DAC_OVERRIDE"}, - processPath: "", - }, - argv: []string{"ls", "/"}, - expected: control.ExecArgs{ - Argv: []string{"ls", "/"}, - WorkingDirectory: "/foo/bar", - FilePayload: urpc.FilePayload{Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}}, - KUID: 0, - KGID: 0, - ExtraKGIDs: []auth.KGID{1, 2, 3}, - Capabilities: &auth.TaskCapabilities{ - BoundingCaps: auth.CapabilitySetOf(linux.CAP_DAC_OVERRIDE), - EffectiveCaps: auth.CapabilitySetOf(linux.CAP_DAC_OVERRIDE), - InheritableCaps: auth.CapabilitySetOf(linux.CAP_DAC_OVERRIDE), - PermittedCaps: auth.CapabilitySetOf(linux.CAP_DAC_OVERRIDE), - }, - }, - }, - } - - for _, tc := range testCases { - e, err := tc.ex.argsFromCLI(tc.argv, true) - if err != nil { - t.Errorf("argsFromCLI(%+v): got error: %+v", tc.ex, err) - } else if !cmp.Equal(*e, tc.expected, cmpopts.IgnoreUnexported(os.File{})) { - t.Errorf("argsFromCLI(%+v): got %+v, but expected %+v", tc.ex, *e, tc.expected) - } - } -} - -func TestJSONArgs(t *testing.T) { - testCases := []struct { - // ex is provided to make sure it is overridden by p. - ex Exec - p specs.Process - expected control.ExecArgs - }{ - { - ex: Exec{ - cwd: "/baz/quux", - user: user{kuid: 1, kgid: 1}, - extraKGIDs: []string{"4", "5", "6"}, - caps: []string{"CAP_SETGID"}, - processPath: "/bin/foo", - }, - p: specs.Process{ - User: specs.User{UID: 0, GID: 0, AdditionalGids: []uint32{1, 2, 3}}, - Args: []string{"ls", "/"}, - Cwd: "/foo/bar", - Capabilities: &specs.LinuxCapabilities{ - Bounding: []string{"CAP_DAC_OVERRIDE"}, - Effective: []string{"CAP_DAC_OVERRIDE"}, - Inheritable: []string{"CAP_DAC_OVERRIDE"}, - Permitted: []string{"CAP_DAC_OVERRIDE"}, - }, - }, - expected: control.ExecArgs{ - Argv: []string{"ls", "/"}, - WorkingDirectory: "/foo/bar", - FilePayload: urpc.FilePayload{Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}}, - KUID: 0, - KGID: 0, - ExtraKGIDs: []auth.KGID{1, 2, 3}, - Capabilities: &auth.TaskCapabilities{ - BoundingCaps: auth.CapabilitySetOf(linux.CAP_DAC_OVERRIDE), - EffectiveCaps: auth.CapabilitySetOf(linux.CAP_DAC_OVERRIDE), - InheritableCaps: auth.CapabilitySetOf(linux.CAP_DAC_OVERRIDE), - PermittedCaps: auth.CapabilitySetOf(linux.CAP_DAC_OVERRIDE), - }, - }, - }, - } - - for _, tc := range testCases { - e, err := argsFromProcess(&tc.p, true) - if err != nil { - t.Errorf("argsFromProcess(%+v): got error: %+v", tc.p, err) - } else if !cmp.Equal(*e, tc.expected, cmpopts.IgnoreUnexported(os.File{})) { - t.Errorf("argsFromProcess(%+v): got %+v, but expected %+v", tc.p, *e, tc.expected) - } - } -} diff --git a/runsc/cmd/gofer_test.go b/runsc/cmd/gofer_test.go deleted file mode 100644 index cbea7f127..000000000 --- a/runsc/cmd/gofer_test.go +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2018 The gVisor Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cmd - -import ( - "fmt" - "io/ioutil" - "os" - "path" - "path/filepath" - "testing" -) - -func tmpDir() string { - dir := os.Getenv("TEST_TMPDIR") - if dir == "" { - dir = "/tmp" - } - return dir -} - -type dir struct { - rel string - link string -} - -func construct(root string, dirs []dir) error { - for _, d := range dirs { - p := path.Join(root, d.rel) - if d.link == "" { - if err := os.MkdirAll(p, 0755); err != nil { - return fmt.Errorf("error creating dir: %v", err) - } - } else { - if err := os.MkdirAll(path.Dir(p), 0755); err != nil { - return fmt.Errorf("error creating dir: %v", err) - } - if err := os.Symlink(d.link, p); err != nil { - return fmt.Errorf("error creating symlink: %v", err) - } - } - } - return nil -} - -func TestResolveSymlinks(t *testing.T) { - root, err := ioutil.TempDir(tmpDir(), "root") - if err != nil { - t.Fatal("ioutil.TempDir() failed:", err) - } - dirs := []dir{ - {"dir1/dir11/dir111/dir1111", ""}, // Just a boring dir - {"dir1/lnk12", "dir11"}, // Link to sibling - {"dir1/lnk13", "./dir11"}, // Link to sibling through self - {"dir1/lnk14", "../dir1/dir11"}, // Link to sibling through parent - {"dir1/dir15/lnk151", ".."}, // Link to parent - {"dir1/lnk16", "dir11/dir111"}, // Link to child - {"dir1/lnk17", "."}, // Link to self - {"dir1/lnk18", "lnk13"}, // Link to link - {"lnk2", "dir1/lnk13"}, // Link to link to link - {"dir3/dir21/lnk211", "../.."}, // Link to root relative - {"dir3/lnk22", "/"}, // Link to root absolute - {"dir3/lnk23", "/dir1"}, // Link to dir absolute - {"dir3/lnk24", "/dir1/lnk12"}, // Link to link absolute - {"lnk5", "../../.."}, // Link outside root - } - if err := construct(root, dirs); err != nil { - t.Fatal("construct failed:", err) - } - - tests := []struct { - name string - rel string - want string - compareHost bool - }{ - {name: "root", rel: "/", want: "/", compareHost: true}, - {name: "basic dir", rel: "/dir1/dir11/dir111", want: "/dir1/dir11/dir111", compareHost: true}, - {name: "dot 1", rel: "/dir1/dir11/./dir111", want: "/dir1/dir11/dir111", compareHost: true}, - {name: "dot 2", rel: "/dir1/././dir11/./././././dir111/.", want: "/dir1/dir11/dir111", compareHost: true}, - {name: "dotdot 1", rel: "/dir1/dir11/../dir15", want: "/dir1/dir15", compareHost: true}, - {name: "dotdot 2", rel: "/dir1/dir11/dir1111/../..", want: "/dir1", compareHost: true}, - - {name: "link sibling", rel: "/dir1/lnk12", want: "/dir1/dir11", compareHost: true}, - {name: "link sibling + dir", rel: "/dir1/lnk12/dir111", want: "/dir1/dir11/dir111", compareHost: true}, - {name: "link sibling through self", rel: "/dir1/lnk13", want: "/dir1/dir11", compareHost: true}, - {name: "link sibling through parent", rel: "/dir1/lnk14", want: "/dir1/dir11", compareHost: true}, - - {name: "link parent", rel: "/dir1/dir15/lnk151", want: "/dir1", compareHost: true}, - {name: "link parent + dir", rel: "/dir1/dir15/lnk151/dir11", want: "/dir1/dir11", compareHost: true}, - {name: "link child", rel: "/dir1/lnk16", want: "/dir1/dir11/dir111", compareHost: true}, - {name: "link child + dir", rel: "/dir1/lnk16/dir1111", want: "/dir1/dir11/dir111/dir1111", compareHost: true}, - {name: "link self", rel: "/dir1/lnk17", want: "/dir1", compareHost: true}, - {name: "link self + dir", rel: "/dir1/lnk17/dir11", want: "/dir1/dir11", compareHost: true}, - - {name: "link^2", rel: "/dir1/lnk18", want: "/dir1/dir11", compareHost: true}, - {name: "link^2 + dir", rel: "/dir1/lnk18/dir111", want: "/dir1/dir11/dir111", compareHost: true}, - {name: "link^3", rel: "/lnk2", want: "/dir1/dir11", compareHost: true}, - {name: "link^3 + dir", rel: "/lnk2/dir111", want: "/dir1/dir11/dir111", compareHost: true}, - - {name: "link abs", rel: "/dir3/lnk23", want: "/dir1"}, - {name: "link abs + dir", rel: "/dir3/lnk23/dir11", want: "/dir1/dir11"}, - {name: "link^2 abs", rel: "/dir3/lnk24", want: "/dir1/dir11"}, - {name: "link^2 abs + dir", rel: "/dir3/lnk24/dir111", want: "/dir1/dir11/dir111"}, - - {name: "root link rel", rel: "/dir3/dir21/lnk211", want: "/", compareHost: true}, - {name: "root link abs", rel: "/dir3/lnk22", want: "/"}, - {name: "root contain link", rel: "/lnk5/dir1", want: "/dir1"}, - {name: "root contain dotdot", rel: "/dir1/dir11/../../../../../../../..", want: "/"}, - - {name: "crazy", rel: "/dir3/dir21/lnk211/dir3/lnk22/dir1/dir11/../../lnk5/dir3/../dir3/lnk24/dir111/dir1111/..", want: "/dir1/dir11/dir111"}, - } - for _, tst := range tests { - t.Run(tst.name, func(t *testing.T) { - got, err := resolveSymlinks(root, tst.rel) - if err != nil { - t.Errorf("resolveSymlinks(root, %q) failed: %v", tst.rel, err) - } - want := path.Join(root, tst.want) - if got != want { - t.Errorf("resolveSymlinks(root, %q) got: %q, want: %q", tst.rel, got, want) - } - if tst.compareHost { - // Check that host got to the same end result. - host, err := filepath.EvalSymlinks(path.Join(root, tst.rel)) - if err != nil { - t.Errorf("path.EvalSymlinks(root, %q) failed: %v", tst.rel, err) - } - if host != got { - t.Errorf("resolveSymlinks(root, %q) got: %q, want: %q", tst.rel, host, got) - } - } - }) - } -} - -func TestResolveSymlinksLoop(t *testing.T) { - root, err := ioutil.TempDir(tmpDir(), "root") - if err != nil { - t.Fatal("ioutil.TempDir() failed:", err) - } - dirs := []dir{ - {"loop1", "loop2"}, - {"loop2", "loop1"}, - } - if err := construct(root, dirs); err != nil { - t.Fatal("construct failed:", err) - } - if _, err := resolveSymlinks(root, "loop1"); err == nil { - t.Errorf("resolveSymlinks() should have failed") - } -} |