From 3f46f2e5017106d1569f759b8d19aee6e9827c58 Mon Sep 17 00:00:00 2001 From: Fabricio Voznika Date: Wed, 3 Oct 2018 20:43:18 -0700 Subject: Fix sandbox chroot Sandbox was setting chroot, but was not chaging the working dir. Added test to ensure this doesn't happen in the future. PiperOrigin-RevId: 215676270 Change-Id: I14352d3de64a4dcb90e50948119dc8328c9c15e1 --- runsc/test/root/BUILD | 27 +++++++++++ runsc/test/root/chroot_test.go | 103 +++++++++++++++++++++++++++++++++++++++++ runsc/test/root/root.go | 16 +++++++ 3 files changed, 146 insertions(+) create mode 100644 runsc/test/root/BUILD create mode 100644 runsc/test/root/chroot_test.go create mode 100644 runsc/test/root/root.go (limited to 'runsc/test/root') diff --git a/runsc/test/root/BUILD b/runsc/test/root/BUILD new file mode 100644 index 000000000..dbc0f1d26 --- /dev/null +++ b/runsc/test/root/BUILD @@ -0,0 +1,27 @@ +package(licenses = ["notice"]) # Apache 2.0 + +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "root", + srcs = ["root.go"], + importpath = "gvisor.googlesource.com/gvisor/runsc/test/root", +) + +go_test( + name = "root_test", + size = "small", + srcs = ["chroot_test.go"], + embed = [":root"], + tags = [ + # Requires docker and runsc to be configured before the test runs. + # Also test only runs as root. + "manual", + "local", + ], + deps = [ + "//runsc/specutils", + "//runsc/test/testutil", + "@com_github_syndtr_gocapability//capability:go_default_library", + ], +) diff --git a/runsc/test/root/chroot_test.go b/runsc/test/root/chroot_test.go new file mode 100644 index 000000000..5c59e7451 --- /dev/null +++ b/runsc/test/root/chroot_test.go @@ -0,0 +1,103 @@ +// Copyright 2018 Google Inc. +// +// 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 root is used for tests that requires sysadmin privileges run. First, +// follow the setup instruction in runsc/test/README.md. To run these test: +// +// bazel build //runsc/test/root:root_test +// root_test=$(find -L ./bazel-bin/ -executable -type f -name root_test | grep __main__) +// sudo RUNSC_RUNTIME=runsc-test ${root_test} +package root + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "reflect" + "sort" + "strconv" + "strings" + "testing" + + "github.com/syndtr/gocapability/capability" + "gvisor.googlesource.com/gvisor/runsc/specutils" + "gvisor.googlesource.com/gvisor/runsc/test/testutil" +) + +// TestChroot verifies that the sandbox is chroot'd and that mounts are cleaned +// up after the sandbox is destroyed. +func TestChroot(t *testing.T) { + d := testutil.MakeDocker("chroot-test") + if err := d.Run("alpine", "sleep", "10000"); err != nil { + t.Fatalf("docker run failed: %v", err) + } + defer d.CleanUp() + + pid, err := d.SandboxPid() + if err != nil { + t.Fatalf("Docker.SandboxPid(): %v", err) + } + + // Check that sandbox is chroot'ed. + chroot, err := filepath.EvalSymlinks(filepath.Join("/proc", strconv.Itoa(pid), "root")) + if err != nil { + t.Fatalf("error resolving /proc//root symlink: %v", err) + } + if want := "/tmp/runsc-sandbox-chroot-"; !strings.HasPrefix(chroot, want) { + t.Errorf("sandbox is not chroot'd, it should be inside: %q, got: %q", want, chroot) + } + + path, err := filepath.EvalSymlinks(filepath.Join("/proc", strconv.Itoa(pid), "cwd")) + if err != nil { + t.Fatalf("error resolving /proc//cwd symlink: %v", err) + } + if chroot != path { + t.Errorf("sandbox current dir is wrong, want: %q, got: %q", chroot, path) + } + + fi, err := ioutil.ReadDir(chroot) + if err != nil { + t.Fatalf("error listing %q: %v", chroot, err) + } + if want, got := 2, len(fi); want != got { + t.Fatalf("chroot dir got %d entries, want %d", want, got) + } + + // chroot dir is prepared by runsc and should contains only the executable + // and /proc. + files := []string{fi[0].Name(), fi[1].Name()} + sort.Strings(files) + if want := []string{"proc", "runsc"}; !reflect.DeepEqual(files, want) { + t.Errorf("chroot got children %v, want %v", files, want) + } + + d.CleanUp() + + // Check that chroot directory was cleaned up. + if _, err := os.Stat(chroot); err == nil || !os.IsNotExist(err) { + t.Errorf("chroot directory %q was not deleted: %v", chroot, err) + } +} + +func TestMain(m *testing.M) { + testutil.EnsureSupportedDockerVersion() + + if !specutils.HasCapabilities(capability.CAP_SYS_ADMIN, capability.CAP_DAC_OVERRIDE) { + fmt.Println("Test requires sysadmin privileges to run. Try again with sudo.") + os.Exit(1) + } + + os.Exit(m.Run()) +} diff --git a/runsc/test/root/root.go b/runsc/test/root/root.go new file mode 100644 index 000000000..790f62c29 --- /dev/null +++ b/runsc/test/root/root.go @@ -0,0 +1,16 @@ +// Copyright 2018 Google Inc. +// +// 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 root is empty. See chroot_test.go for description. +package root -- cgit v1.2.3