diff options
Diffstat (limited to 'runsc')
-rw-r--r-- | runsc/boot/config.go | 9 | ||||
-rw-r--r-- | runsc/boot/fs.go | 62 | ||||
-rw-r--r-- | runsc/boot/loader_test.go | 36 | ||||
-rw-r--r-- | runsc/container/container_test.go | 207 | ||||
-rw-r--r-- | runsc/main.go | 6 | ||||
-rw-r--r-- | runsc/sandbox/sandbox.go | 8 | ||||
-rw-r--r-- | runsc/test/testutil/testutil.go | 1 |
7 files changed, 258 insertions, 71 deletions
diff --git a/runsc/boot/config.go b/runsc/boot/config.go index 074cd6a63..6c69a7c38 100644 --- a/runsc/boot/config.go +++ b/runsc/boot/config.go @@ -64,6 +64,11 @@ const ( // requests and forwards them to the host. FileAccessProxy FileAccessType = iota + // FileAccessProxyExclusive is the same as FileAccessProxy, but enables + // extra caching for improved performance. It should only be used if + // the sandbox has exclusive access to the filesystem. + FileAccessProxyExclusive + // FileAccessDirect connects the sandbox directly to the host filesystem. FileAccessDirect ) @@ -73,6 +78,8 @@ func MakeFileAccessType(s string) (FileAccessType, error) { switch s { case "proxy": return FileAccessProxy, nil + case "proxy-exclusive": + return FileAccessProxyExclusive, nil case "direct": return FileAccessDirect, nil default: @@ -84,6 +91,8 @@ func (f FileAccessType) String() string { switch f { case FileAccessProxy: return "proxy" + case FileAccessProxyExclusive: + return "proxy-exclusive" case FileAccessDirect: return "direct" default: diff --git a/runsc/boot/fs.go b/runsc/boot/fs.go index e596c739f..eea2ec1f5 100644 --- a/runsc/boot/fs.go +++ b/runsc/boot/fs.go @@ -17,6 +17,7 @@ package boot import ( "fmt" "path/filepath" + "strconv" "strings" // Include filesystem types that OCI spec might mount. @@ -54,6 +55,9 @@ type fdDispenser struct { } func (f *fdDispenser) remove() int { + if f.empty() { + panic("fdDispenser out of fds") + } rv := f.fds[0] f.fds = f.fds[1:] return rv @@ -160,8 +164,6 @@ func compileMounts(spec *specs.Spec) []specs.Mount { // setMounts iterates over mounts and mounts them in the specified // mount namespace. func setMounts(ctx context.Context, conf *Config, mns *fs.MountNamespace, fds *fdDispenser, mounts []specs.Mount) error { - - // Mount all submounts from mounts. for _, m := range mounts { if err := mountSubmount(ctx, conf, mns, fds, m, mounts); err != nil { return err @@ -181,11 +183,12 @@ func createRootMount(ctx context.Context, spec *specs.Spec, conf *Config, fds *f ) switch conf.FileAccess { - case FileAccessProxy: + case FileAccessProxy, FileAccessProxyExclusive: fd := fds.remove() log.Infof("Mounting root over 9P, ioFD: %d", fd) hostFS := mustFindFilesystem("9p") - rootInode, err = hostFS.Mount(ctx, rootDevice, mf, fmt.Sprintf("trans=fd,rfdno=%d,wfdno=%d,privateunixsocket=true", fd, fd)) + opts := p9MountOptions(conf, fd) + rootInode, err = hostFS.Mount(ctx, rootDevice, mf, strings.Join(opts, ",")) if err != nil { return nil, fmt.Errorf("failed to generate root mount point: %v", err) } @@ -242,13 +245,16 @@ func addOverlay(ctx context.Context, conf *Config, lower *fs.Inode, name string, return fs.NewOverlayRoot(ctx, upper, lower, lowerFlags) } -// getMountNameAndOptions retrieves the fsName, data, and useOverlay values +// getMountNameAndOptions retrieves the fsName, opts, and useOverlay values // used for mounts. func getMountNameAndOptions(conf *Config, m specs.Mount, fds *fdDispenser) (string, []string, bool, error) { - var fsName string - var data []string - var useOverlay bool - var err error + var ( + fsName string + opts []string + useOverlay bool + err error + ) + switch m.Type { case "devpts", "devtmpfs", "proc", "sysfs": fsName = m.Type @@ -258,17 +264,17 @@ func getMountNameAndOptions(conf *Config, m specs.Mount, fds *fdDispenser) (stri fsName = m.Type // tmpfs has some extra supported options that we must pass through. - data, err = parseAndFilterOptions(m.Options, "mode", "uid", "gid") + opts, err = parseAndFilterOptions(m.Options, "mode", "uid", "gid") case "bind": switch conf.FileAccess { - case FileAccessProxy: + case FileAccessProxy, FileAccessProxyExclusive: fd := fds.remove() fsName = "9p" - data = []string{"trans=fd", fmt.Sprintf("rfdno=%d", fd), fmt.Sprintf("wfdno=%d", fd), "privateunixsocket=true"} + opts = p9MountOptions(conf, fd) case FileAccessDirect: fsName = "whitelistfs" - data = []string{"root=" + m.Source, "dont_translate_ownership=true"} + opts = []string{"root=" + m.Source, "dont_translate_ownership=true"} default: err = fmt.Errorf("invalid file access type: %v", conf.FileAccess) } @@ -282,13 +288,13 @@ func getMountNameAndOptions(conf *Config, m specs.Mount, fds *fdDispenser) (stri // we do not support. log.Warningf("ignoring unknown filesystem type %q", m.Type) } - return fsName, data, useOverlay, err + return fsName, opts, useOverlay, err } func mountSubmount(ctx context.Context, conf *Config, mns *fs.MountNamespace, fds *fdDispenser, m specs.Mount, mounts []specs.Mount) error { // Map mount type to filesystem name, and parse out the options that we are // capable of dealing with. - fsName, data, useOverlay, err := getMountNameAndOptions(conf, m, fds) + fsName, opts, useOverlay, err := getMountNameAndOptions(conf, m, fds) // Return the error or nil that corresponds to the default case in getMountNameAndOptions. if err != nil { @@ -307,7 +313,7 @@ func mountSubmount(ctx context.Context, conf *Config, mns *fs.MountNamespace, fd mf.ReadOnly = true } - inode, err := filesystem.Mount(ctx, mountDevice(m), mf, strings.Join(data, ",")) + inode, err := filesystem.Mount(ctx, mountDevice(m), mf, strings.Join(opts, ",")) if err != nil { return fmt.Errorf("failed to create mount with source %q: %v", m.Source, err) } @@ -387,6 +393,20 @@ func mkdirAll(ctx context.Context, mns *fs.MountNamespace, path string) error { return nil } +// p9MountOptions creates a slice of options for a p9 mount. +func p9MountOptions(conf *Config, fd int) []string { + opts := []string{ + "trans=fd", + "rfdno=" + strconv.Itoa(fd), + "wfdno=" + strconv.Itoa(fd), + "privateunixsocket=true", + } + if conf.FileAccess == FileAccessProxy { + opts = append(opts, "cache=remote_revalidating") + } + return opts +} + // parseAndFilterOptions parses a MountOptions slice and filters by the allowed // keys. func parseAndFilterOptions(opts []string, allowedKeys ...string) ([]string, error) { @@ -436,8 +456,7 @@ func mountDevice(m specs.Mount) string { // addRestoreMount adds a mount to the MountSources map used for restoring a // checkpointed container. func addRestoreMount(conf *Config, renv *fs.RestoreEnvironment, m specs.Mount, fds *fdDispenser) error { - fsName, data, _, err := getMountNameAndOptions(conf, m, fds) - dataString := strings.Join(data, ",") + fsName, opts, _, err := getMountNameAndOptions(conf, m, fds) // Return the error or nil that corresponds to the default case in getMountNameAndOptions. if err != nil { @@ -452,7 +471,7 @@ func addRestoreMount(conf *Config, renv *fs.RestoreEnvironment, m specs.Mount, f newMount := fs.MountArgs{ Dev: mountDevice(m), Flags: mountFlags(m.Options), - Data: dataString, + Data: strings.Join(opts, ","), } renv.MountSources[fsName] = append(renv.MountSources[fsName], newMount) log.Infof("Added mount at %q: %+v", fsName, newMount) @@ -473,7 +492,8 @@ func createRestoreEnvironment(spec *specs.Spec, conf *Config, fds *fdDispenser) // Add root mount. fd := fds.remove() - dataString := strings.Join([]string{"trans=fd", fmt.Sprintf("rfdno=%d", fd), fmt.Sprintf("wfdno=%d", fd), "privateunixsocket=true"}, ",") + opts := p9MountOptions(conf, fd) + mf := fs.MountSourceFlags{} if spec.Root.Readonly { mf.ReadOnly = true @@ -482,7 +502,7 @@ func createRestoreEnvironment(spec *specs.Spec, conf *Config, fds *fdDispenser) rootMount := fs.MountArgs{ Dev: rootDevice, Flags: mf, - Data: dataString, + Data: strings.Join(opts, ","), } renv.MountSources[rootFsName] = append(renv.MountSources[rootFsName], rootMount) diff --git a/runsc/boot/loader_test.go b/runsc/boot/loader_test.go index 7ea2e1ee5..f2f690b5d 100644 --- a/runsc/boot/loader_test.go +++ b/runsc/boot/loader_test.go @@ -398,7 +398,7 @@ func TestRestoreEnvironment(t *testing.T) { { Dev: "9pfs-/", Flags: fs.MountSourceFlags{ReadOnly: true}, - Data: "trans=fd,rfdno=0,wfdno=0,privateunixsocket=true", + Data: "trans=fd,rfdno=0,wfdno=0,privateunixsocket=true,cache=remote_revalidating", }, }, "tmpfs": { @@ -458,11 +458,11 @@ func TestRestoreEnvironment(t *testing.T) { { Dev: "9pfs-/", Flags: fs.MountSourceFlags{ReadOnly: true}, - Data: "trans=fd,rfdno=0,wfdno=0,privateunixsocket=true", + Data: "trans=fd,rfdno=0,wfdno=0,privateunixsocket=true,cache=remote_revalidating", }, { Dev: "9pfs-/dev/fd-foo", - Data: "trans=fd,rfdno=1,wfdno=1,privateunixsocket=true", + Data: "trans=fd,rfdno=1,wfdno=1,privateunixsocket=true,cache=remote_revalidating", }, }, "tmpfs": { @@ -522,7 +522,7 @@ func TestRestoreEnvironment(t *testing.T) { { Dev: "9pfs-/", Flags: fs.MountSourceFlags{ReadOnly: true}, - Data: "trans=fd,rfdno=0,wfdno=0,privateunixsocket=true", + Data: "trans=fd,rfdno=0,wfdno=0,privateunixsocket=true,cache=remote_revalidating", }, }, "tmpfs": { @@ -606,21 +606,21 @@ func TestRestoreEnvironment(t *testing.T) { errorExpected: true, }, } - for _, tc := range testCases { - fds := &fdDispenser{fds: tc.ioFDs} - - actualRenv, err := createRestoreEnvironment(tc.spec, tc.conf, fds) - if !tc.errorExpected && err != nil { - t.Fatalf("could not create restore environment for test:%s", tc.name) - } else if tc.errorExpected { - if err == nil { - t.Fatalf("expected an error, but no error occurred.") + t.Run(tc.name, func(t *testing.T) { + fds := &fdDispenser{fds: tc.ioFDs} + actualRenv, err := createRestoreEnvironment(tc.spec, tc.conf, fds) + if !tc.errorExpected && err != nil { + t.Fatalf("could not create restore environment for test:%s", tc.name) + } else if tc.errorExpected { + if err == nil { + t.Errorf("expected an error, but no error occurred.") + } + } else { + if !reflect.DeepEqual(*actualRenv, tc.expectedRenv) { + t.Errorf("restore environments did not match for test:%s\ngot:%+v\nwant:%+v\n", tc.name, *actualRenv, tc.expectedRenv) + } } - } else { - if !reflect.DeepEqual(*actualRenv, tc.expectedRenv) { - t.Fatalf("restore environments did not match for test:%s\ngot:%+v\nwant:%+v\n", tc.name, *actualRenv, tc.expectedRenv) - } - } + }) } } diff --git a/runsc/container/container_test.go b/runsc/container/container_test.go index 11edcd615..33c53e189 100644 --- a/runsc/container/container_test.go +++ b/runsc/container/container_test.go @@ -227,33 +227,43 @@ func findUDSApp() (string, error) { return matches[0], nil } -type configOptions int +type configOption int const ( - overlay configOptions = 1 << iota + overlay configOption = iota kvm + nonExclusiveFS ) -const all = overlay | kvm + +var all = []configOption{overlay, kvm, nonExclusiveFS} // configs generates different configurations to run tests. -func configs(opts configOptions) []*boot.Config { - cs := []*boot.Config{testutil.TestConfig(), testutil.TestConfig()} - return cs +func configs(opts ...configOption) []*boot.Config { + // Always load the default config. + cs := []*boot.Config{testutil.TestConfig()} - if opts&overlay != 0 { + for _, o := range opts { c := testutil.TestConfig() - c.Overlay = true + switch o { + case overlay: + c.Overlay = true + case kvm: + // TODO: KVM tests are flaky. Disable until fixed. + continue + + // TODO: KVM doesn't work with --race. + if testutil.RaceEnabled { + continue + } + c.Platform = boot.PlatformKVM + case nonExclusiveFS: + c.FileAccess = boot.FileAccessProxy + default: + panic(fmt.Sprintf("unknown config option %v", o)) + + } cs = append(cs, c) } - - // TODO: KVM tests are flaky. Disable until fixed. - // // TODO: KVM doesn't work with --race. - // if !testutil.RaceEnabled && opts&kvm != 0 { - // c := testutil.TestConfig() - // c.Platform = boot.PlatformKVM - // cs = append(cs, c) - // } - return cs } @@ -261,7 +271,7 @@ func configs(opts configOptions) []*boot.Config { // It verifies after each step that the container can be loaded from disk, and // has the correct status. func TestLifecycle(t *testing.T) { - for _, conf := range configs(all) { + for _, conf := range configs(all...) { t.Logf("Running test with conf: %+v", conf) // The container will just sleep for a long time. We will kill it before // it finishes sleeping. @@ -1049,10 +1059,11 @@ func TestPauseResumeStatus(t *testing.T) { // - Running exec as non-root with CAP_DAC_OVERRIDE succeeds because it skips // this check. func TestCapabilities(t *testing.T) { - const uid = 343 - const gid = 2401 + // Pick uid/gid different than ours. + uid := auth.KUID(os.Getuid() + 1) + gid := auth.KGID(os.Getgid() + 1) - for _, conf := range configs(all) { + for _, conf := range configs(all...) { t.Logf("Running test with conf: %+v", conf) spec := testutil.NewSpecWithArgs("sleep", "100") @@ -1142,7 +1153,7 @@ func TestCapabilities(t *testing.T) { // Test that an tty FD is sent over the console socket if one is provided. func TestConsoleSocket(t *testing.T) { - for _, conf := range configs(all) { + for _, conf := range configs(all...) { t.Logf("Running test with conf: %+v", conf) spec := testutil.NewSpecWithArgs("true") rootDir, bundleDir, err := testutil.SetupContainer(spec, conf) @@ -1303,8 +1314,6 @@ func TestReadonlyRoot(t *testing.T) { defer os.RemoveAll(rootDir) defer os.RemoveAll(bundleDir) - conf.Overlay = true - // Create, start and wait for the container. s, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "") if err != nil { @@ -1348,8 +1357,6 @@ func TestReadonlyMount(t *testing.T) { defer os.RemoveAll(rootDir) defer os.RemoveAll(bundleDir) - conf.Overlay = true - // Create, start and wait for the container. s, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "") if err != nil { @@ -1430,7 +1437,7 @@ func TestAbbreviatedIDs(t *testing.T) { // TestMultiContainerSanity checks that it is possible to run 2 dead-simple // containers in the same sandbox. func TestMultiContainerSanity(t *testing.T) { - for _, conf := range configs(all) { + for _, conf := range configs(all...) { t.Logf("Running test with conf: %+v", conf) containerIDs := []string{ @@ -1619,3 +1626,149 @@ func TestMultiContainerWait(t *testing.T) { wg.Wait() } + +// Check that modifications to a volume mount are propigated into and out of +// the sandbox. +func TestContainerVolumeContentsShared(t *testing.T) { + // Only run this test with shared proxy, since that is the only + // behavior it is testing. + conf := testutil.TestConfig() + conf.FileAccess = boot.FileAccessProxy + t.Logf("Running test with conf: %+v", conf) + + // Main process just sleeps. We will use "exec" to probe the state of + // the filesystem. + spec := testutil.NewSpecWithArgs("sleep", "1000") + + // Mount host temp dir inside the sandbox at '/tmp2'. + hostTmpDir, err := ioutil.TempDir("", "root-fs-test") + sandboxTmpDir := "/tmp2" + if err != nil { + t.Fatalf("TempDir failed: %v", err) + } + spec.Mounts = append(spec.Mounts, specs.Mount{ + Type: "bind", + Destination: sandboxTmpDir, + Source: hostTmpDir, + }) + + rootDir, bundleDir, err := testutil.SetupContainer(spec, conf) + if err != nil { + t.Fatalf("error setting up container: %v", err) + } + defer os.RemoveAll(rootDir) + defer os.RemoveAll(bundleDir) + + // Create and start the container. + c, err := container.Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "") + 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) + } + + // File that will be used to check consistency inside/outside sandbox. + hostFilename := filepath.Join(hostTmpDir, "file") + sandboxFilename := filepath.Join(sandboxTmpDir, "file") + + // File does not exist yet. Reading from the sandbox should fail. + execArgsTestFile := control.ExecArgs{ + Filename: "/usr/bin/test", + Argv: []string{"test", "-f", sandboxFilename}, + } + if ws, err := c.Execute(&execArgsTestFile); err != nil { + t.Fatalf("unexpected error testing file %q: %v", sandboxFilename, err) + } else if ws.ExitStatus() == 0 { + t.Errorf("test %q exited with code %v, wanted not zero", ws.ExitStatus(), err) + } + + // Create the file from outside of the sandbox. + if err := ioutil.WriteFile(hostFilename, []byte("foobar"), 0777); err != nil { + t.Fatalf("error writing to file %q: %v", hostFilename, err) + } + + // Now we should be able to test the file from within the sandbox. + if ws, err := c.Execute(&execArgsTestFile); err != nil { + t.Fatalf("unexpected error testing file %q: %v", sandboxFilename, err) + } else if ws.ExitStatus() != 0 { + t.Errorf("test %q exited with code %v, wanted zero", sandboxFilename, ws.ExitStatus()) + } + + // Rename the file from outside of the sandbox. + newHostFilename := filepath.Join(hostTmpDir, "newfile") + newSandboxFilename := filepath.Join(sandboxTmpDir, "newfile") + if err := os.Rename(hostFilename, newHostFilename); err != nil { + t.Fatalf("os.Rename(%q, %q) failed: %v", hostFilename, newHostFilename, err) + } + + // File should no longer exist at the old path within the sandbox. + if ws, err := c.Execute(&execArgsTestFile); err != nil { + t.Fatalf("unexpected error testing file %q: %v", sandboxFilename, err) + } else if ws.ExitStatus() == 0 { + t.Errorf("test %q exited with code %v, wanted not zero", sandboxFilename, ws.ExitStatus()) + } + + // We should be able to test the new filename from within the sandbox. + execArgsTestNewFile := control.ExecArgs{ + Filename: "/usr/bin/test", + Argv: []string{"test", "-f", newSandboxFilename}, + } + if ws, err := c.Execute(&execArgsTestNewFile); err != nil { + t.Fatalf("unexpected error testing file %q: %v", newSandboxFilename, err) + } else if ws.ExitStatus() != 0 { + t.Errorf("test %q exited with code %v, wanted zero", newSandboxFilename, ws.ExitStatus()) + } + + // Delete the renamed file from outside of the sandbox. + if err := os.Remove(newHostFilename); err != nil { + t.Fatalf("error removing file %q: %v", hostFilename, err) + } + + // Renamed file should no longer exist at the old path within the sandbox. + if ws, err := c.Execute(&execArgsTestNewFile); err != nil { + t.Fatalf("unexpected error testing file %q: %v", newSandboxFilename, err) + } else if ws.ExitStatus() == 0 { + t.Errorf("test %q exited with code %v, wanted not zero", newSandboxFilename, ws.ExitStatus()) + } + + // Now create the file from WITHIN the sandbox. + execArgsTouch := control.ExecArgs{ + Filename: "/usr/bin/touch", + Argv: []string{"touch", sandboxFilename}, + KUID: auth.KUID(os.Getuid()), + KGID: auth.KGID(os.Getgid()), + } + if ws, err := c.Execute(&execArgsTouch); err != nil { + t.Fatalf("unexpected error touching file %q: %v", sandboxFilename, err) + } else if ws.ExitStatus() != 0 { + t.Errorf("touch %q exited with code %v, wanted zero", sandboxFilename, ws.ExitStatus()) + } + + // File should exist outside the sandbox. + if _, err := os.Stat(hostFilename); err != nil { + t.Errorf("stat %q got error %v, wanted nil", hostFilename, err) + } + + // File should exist outside the sandbox. + if _, err := os.Stat(hostFilename); err != nil { + t.Errorf("stat %q got error %v, wanted nil", hostFilename, err) + } + + // Delete the file from within the sandbox. + execArgsRemove := control.ExecArgs{ + Filename: "/bin/rm", + Argv: []string{"rm", sandboxFilename}, + } + if ws, err := c.Execute(&execArgsRemove); err != nil { + t.Fatalf("unexpected error removing file %q: %v", sandboxFilename, err) + } else if ws.ExitStatus() != 0 { + t.Errorf("remove %q exited with code %v, wanted zero", sandboxFilename, ws.ExitStatus()) + } + + // File should not exist outside the sandbox. + if _, err := os.Stat(hostFilename); !os.IsNotExist(err) { + t.Errorf("stat %q got error %v, wanted ErrNotExist", hostFilename, err) + } +} diff --git a/runsc/main.go b/runsc/main.go index 10ae44b5e..b36100cca 100644 --- a/runsc/main.go +++ b/runsc/main.go @@ -57,7 +57,7 @@ var ( // Flags that control sandbox runtime behavior. platform = flag.String("platform", "ptrace", "specifies which platform to use: ptrace (default), kvm") network = flag.String("network", "sandbox", "specifies which network to use: sandbox (default), host, none. Using network inside the sandbox is more secure because it's isolated from the host network.") - fileAccess = flag.String("file-access", "proxy", "specifies which filesystem to use: proxy (default), direct. Using a proxy is more secure because it disallows the sandbox from opennig files directly in the host.") + fileAccess = flag.String("file-access", "proxy-exclusive", "specifies which filesystem to use: proxy-exclusive (default), proxy-shared, or direct. Using a proxy is more secure because it disallows the sandbox from opening files directly in the host. Setting 'proxy-shared' will disable caches and should be used if external modifications to the filesystem are expected.") overlay = flag.Bool("overlay", false, "wrap filesystem mounts with writable overlay. All modifications are stored in memory inside the sandbox.") multiContainer = flag.Bool("multi-container", false, "enable *experimental* multi-container support.") watchdogAction = flag.String("watchdog-action", "log", "sets what action the watchdog takes when triggered: log (default), panic.") @@ -119,6 +119,10 @@ func main() { cmd.Fatalf("%v", err) } + if *fileAccess == "proxy" && *overlay { + cmd.Fatalf("overlay flag is incompatible with file-access=proxy") + } + // Create a new Config from the flags. conf := &boot.Config{ RootDir: *rootDir, diff --git a/runsc/sandbox/sandbox.go b/runsc/sandbox/sandbox.go index 196949f11..2b043d412 100644 --- a/runsc/sandbox/sandbox.go +++ b/runsc/sandbox/sandbox.go @@ -233,7 +233,7 @@ func (s *Sandbox) connError(err error) error { } func (s *Sandbox) createGoferProcess(spec *specs.Spec, conf *boot.Config, bundleDir, binPath string) ([]*os.File, error) { - if conf.FileAccess != boot.FileAccessProxy { + if conf.FileAccess == boot.FileAccessDirect { // Don't start a gofer. The sandbox will access host FS directly. return nil, nil } @@ -369,11 +369,11 @@ func (s *Sandbox) createSandboxProcess(spec *specs.Spec, conf *boot.Config, bund nss = append(nss, specs.LinuxNamespace{Type: specs.PIDNamespace}) } - if conf.FileAccess == boot.FileAccessProxy { + if conf.FileAccess == boot.FileAccessDirect { + log.Infof("Sandbox will be started in the current mount namespace") + } else { log.Infof("Sandbox will be started in new mount namespace") nss = append(nss, specs.LinuxNamespace{Type: specs.MountNamespace}) - } else { - log.Infof("Sandbox will be started in the current mount namespace") } // Joins the network namespace if network is enabled. the sandbox talks diff --git a/runsc/test/testutil/testutil.go b/runsc/test/testutil/testutil.go index 4e7ab3760..d2b39b58c 100644 --- a/runsc/test/testutil/testutil.go +++ b/runsc/test/testutil/testutil.go @@ -81,6 +81,7 @@ func TestConfig() *boot.Config { Network: boot.NetworkNone, Strace: true, MultiContainer: true, + FileAccess: boot.FileAccessProxyExclusive, } } |