From 960155cdaad49ccea07e45152f124beeb7e7fdcc Mon Sep 17 00:00:00 2001 From: Fabricio Voznika Date: Tue, 23 Mar 2021 16:19:02 -0700 Subject: Add --file-access-mounts flag --file-access-mounts flag is similar to --file-access, but controls non-root mounts that were previously mounted in shared mode only. This gives more flexibility to control how mounts are shared within a container. PiperOrigin-RevId: 364669882 --- runsc/boot/fs.go | 7 +++---- runsc/boot/fs_test.go | 3 ++- runsc/boot/vfs.go | 2 +- runsc/config/config.go | 21 +++++++++++++++------ runsc/config/flags.go | 3 ++- 5 files changed, 23 insertions(+), 13 deletions(-) (limited to 'runsc') diff --git a/runsc/boot/fs.go b/runsc/boot/fs.go index d1dacee03..32adde643 100644 --- a/runsc/boot/fs.go +++ b/runsc/boot/fs.go @@ -792,7 +792,7 @@ func (c *containerMounter) getMountNameAndOptions(conf *config.Config, m specs.M case bind: fd := c.fds.remove() fsName = gofervfs2.Name - opts = p9MountData(fd, c.getMountAccessType(m), conf.VFS2) + opts = p9MountData(fd, c.getMountAccessType(conf, m), conf.VFS2) // If configured, add overlay to all writable mounts. useOverlay = conf.Overlay && !mountFlags(m.Options).ReadOnly @@ -802,12 +802,11 @@ func (c *containerMounter) getMountNameAndOptions(conf *config.Config, m specs.M return fsName, opts, useOverlay, nil } -func (c *containerMounter) getMountAccessType(mount specs.Mount) config.FileAccessType { +func (c *containerMounter) getMountAccessType(conf *config.Config, mount specs.Mount) config.FileAccessType { if hint := c.hints.findMount(mount); hint != nil { return hint.fileAccessType() } - // Non-root bind mounts are always shared if no hints were provided. - return config.FileAccessShared + return conf.FileAccessMounts } // mountSubmount mounts volumes inside the container's root. Because mounts may diff --git a/runsc/boot/fs_test.go b/runsc/boot/fs_test.go index e986231e5..b4f12d034 100644 --- a/runsc/boot/fs_test.go +++ b/runsc/boot/fs_test.go @@ -243,7 +243,8 @@ func TestGetMountAccessType(t *testing.T) { t.Fatalf("newPodMountHints failed: %v", err) } mounter := containerMounter{hints: podHints} - if got := mounter.getMountAccessType(specs.Mount{Source: source}); got != tst.want { + conf := &config.Config{FileAccessMounts: config.FileAccessShared} + if got := mounter.getMountAccessType(conf, specs.Mount{Source: source}); got != tst.want { t.Errorf("getMountAccessType(), want: %v, got: %v", tst.want, got) } }) diff --git a/runsc/boot/vfs.go b/runsc/boot/vfs.go index 3fd28e516..9b3dacf46 100644 --- a/runsc/boot/vfs.go +++ b/runsc/boot/vfs.go @@ -494,7 +494,7 @@ func (c *containerMounter) getMountNameAndOptionsVFS2(conf *config.Config, m *mo // but unlikely to be correct in this context. return "", nil, false, fmt.Errorf("9P mount requires a connection FD") } - data = p9MountData(m.fd, c.getMountAccessType(m.Mount), true /* vfs2 */) + data = p9MountData(m.fd, c.getMountAccessType(conf, m.Mount), true /* vfs2 */) iopts = gofer.InternalFilesystemOptions{ UniqueID: m.Destination, } diff --git a/runsc/config/config.go b/runsc/config/config.go index 34ef48825..1e5858837 100644 --- a/runsc/config/config.go +++ b/runsc/config/config.go @@ -58,9 +58,12 @@ type Config struct { // DebugLogFormat is the log format for debug. DebugLogFormat string `flag:"debug-log-format"` - // FileAccess indicates how the filesystem is accessed. + // FileAccess indicates how the root filesystem is accessed. FileAccess FileAccessType `flag:"file-access"` + // FileAccessMounts indicates how non-root volumes are accessed. + FileAccessMounts FileAccessType `flag:"file-access-mounts"` + // Overlay is whether to wrap the root filesystem in an overlay. Overlay bool `flag:"overlay"` @@ -197,13 +200,19 @@ func (c *Config) validate() error { type FileAccessType int const ( - // FileAccessExclusive is the same as FileAccessShared, but enables - // extra caching for improved performance. It should only be used if - // the sandbox has exclusive access to the filesystem. + // FileAccessExclusive gives the sandbox exclusive access over files and + // directories in the filesystem. No external modifications are permitted and + // can lead to undefined behavior. + // + // Exclusive filesystem access enables more aggressive caching and offers + // significantly better performance. This is the default mode for the root + // volume. FileAccessExclusive FileAccessType = iota - // FileAccessShared sends IO requests to a Gofer process that validates the - // requests and forwards them to the host. + // FileAccessShared is used for volumes that can have external changes. It + // requires revalidation on every filesystem access to detect external + // changes, and reduces the amount of caching that can be done. This is the + // default mode for non-root volumes. FileAccessShared ) diff --git a/runsc/config/flags.go b/runsc/config/flags.go index adbee506c..1d996c841 100644 --- a/runsc/config/flags.go +++ b/runsc/config/flags.go @@ -67,7 +67,8 @@ func RegisterFlags() { flag.Bool("oci-seccomp", false, "Enables loading OCI seccomp filters inside the sandbox.") // Flags that control sandbox runtime behavior: FS related. - flag.Var(fileAccessTypePtr(FileAccessExclusive), "file-access", "specifies which filesystem to use for the root mount: exclusive (default), shared. Volume mounts are always shared.") + flag.Var(fileAccessTypePtr(FileAccessExclusive), "file-access", "specifies which filesystem validation to use for the root mount: exclusive (default), shared.") + flag.Var(fileAccessTypePtr(FileAccessShared), "file-access-mounts", "specifies which filesystem validation to use for volumes other than the root mount: shared (default), exclusive.") flag.Bool("overlay", false, "wrap filesystem mounts with writable overlay. All modifications are stored in memory inside the sandbox.") flag.Bool("verity", false, "specifies whether a verity file system will be mounted.") flag.Bool("overlayfs-stale-read", true, "assume root mount is an overlay filesystem") -- cgit v1.2.3