Start deletion of VFS1 from runsc config

Updates #1624

PiperOrigin-RevId: 450708193
This commit is contained in:
Fabricio Voznika
2022-05-24 10:04:59 -07:00
committed by gVisor bot
parent a6fbca2eec
commit adff8e5863
12 changed files with 53 additions and 1012 deletions
-5
View File
@@ -54,10 +54,8 @@ go_library(
"//pkg/sentry/fdimport",
"//pkg/sentry/fs",
"//pkg/sentry/fs/dev",
"//pkg/sentry/fs/gofer",
"//pkg/sentry/fs/host",
"//pkg/sentry/fs/proc",
"//pkg/sentry/fs/ramfs",
"//pkg/sentry/fs/sys",
"//pkg/sentry/fs/tmpfs",
"//pkg/sentry/fs/tty",
@@ -143,12 +141,9 @@ go_test(
library = ":boot",
deps = [
"//pkg/control/server",
"//pkg/fd",
"//pkg/fspath",
"//pkg/log",
"//pkg/p9",
"//pkg/sentry/contexttest",
"//pkg/sentry/fs",
"//pkg/sentry/vfs",
"//pkg/sync",
"//pkg/unet",
+4 -13
View File
@@ -27,7 +27,6 @@ import (
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/control"
controlpb "gvisor.dev/gvisor/pkg/sentry/control/control_go_proto"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/seccheck"
"gvisor.dev/gvisor/pkg/sentry/socket/netstack"
@@ -446,18 +445,10 @@ func (cm *containerManager) Restore(o *RestoreOpts, _ *struct{}) error {
// Set up the restore environment.
ctx := k.SupervisorContext()
mntr := newContainerMounter(&cm.l.root, cm.l.k, cm.l.mountHints, kernel.VFS2Enabled, cm.l.productName)
if kernel.VFS2Enabled {
ctx, err = mntr.configureRestore(ctx)
if err != nil {
return fmt.Errorf("configuring filesystem restore: %v", err)
}
} else {
renv, err := mntr.createRestoreEnvironment(cm.l.root.conf)
if err != nil {
return fmt.Errorf("creating RestoreEnvironment: %v", err)
}
fs.SetRestoreEnvironment(*renv)
mntr := newContainerMounter(&cm.l.root, cm.l.k, cm.l.mountHints, cm.l.productName)
ctx, err = mntr.configureRestore(ctx)
if err != nil {
return fmt.Errorf("configuring filesystem restore: %v", err)
}
// Prepare to load from the state file.
+5 -596
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -243,7 +243,7 @@ func TestGetMountAccessType(t *testing.T) {
t.Fatalf("newPodMountHints failed: %v", err)
}
mounter := containerMounter{hints: podHints}
conf := &config.Config{VFS2: true, FileAccessMounts: config.FileAccessShared}
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)
}
+25 -70
View File
@@ -253,13 +253,10 @@ func New(args Args) (*Loader, error) {
return nil, fmt.Errorf("setting up memory usage: %w", err)
}
// Is this a VFSv2 kernel?
if args.Conf.VFS2 {
kernel.VFS2Enabled = true
kernel.FUSEEnabled = args.Conf.FUSE
kernel.LISAFSEnabled = args.Conf.Lisafs
vfs2.Override()
}
kernel.VFS2Enabled = true
kernel.FUSEEnabled = args.Conf.FUSE
kernel.LISAFSEnabled = args.Conf.Lisafs
vfs2.Override()
// Make host FDs stable between invocations. Host FDs must map to the exact
// same number when the sandbox is restored. Otherwise the wrong FD will be
@@ -377,14 +374,8 @@ func New(args Args) (*Loader, error) {
return nil, fmt.Errorf("initializing kernel: %w", err)
}
if kernel.VFS2Enabled {
if err := registerFilesystems(k); err != nil {
return nil, fmt.Errorf("registering filesystems: %w", err)
}
}
if err := adjustDirentCache(k); err != nil {
return nil, err
if err := registerFilesystems(k); err != nil {
return nil, fmt.Errorf("registering filesystems: %w", err)
}
// Turn on packet logging if enabled.
@@ -419,15 +410,13 @@ func New(args Args) (*Loader, error) {
info.conf = args.Conf
info.spec = args.Spec
if kernel.VFS2Enabled {
// Set up host mount that will be used for imported fds.
hostFilesystem, err := hostvfs2.NewFilesystem(k.VFS())
if err != nil {
return nil, fmt.Errorf("failed to create hostfs filesystem: %w", err)
}
defer hostFilesystem.DecRef(k.SupervisorContext())
k.SetHostMount(k.VFS().NewDisconnectedMount(hostFilesystem, nil, &vfs.MountOptions{}))
// Set up host mount that will be used for imported fds.
hostFilesystem, err := hostvfs2.NewFilesystem(k.VFS())
if err != nil {
return nil, fmt.Errorf("failed to create hostfs filesystem: %w", err)
}
defer hostFilesystem.DecRef(k.SupervisorContext())
k.SetHostMount(k.VFS().NewDisconnectedMount(hostFilesystem, nil, &vfs.MountOptions{}))
if args.PodInitConfigFD >= 0 {
if err := setupSeccheck(args.PodInitConfigFD, args.SinkFDs); err != nil {
@@ -837,30 +826,22 @@ func (l *Loader) createContainerProcess(root bool, cid string, info *containerIn
}
l.startGoferMonitor(cid, int32(info.goferFDs[0].FD()))
mntr := newContainerMounter(info, l.k, l.mountHints, kernel.VFS2Enabled, l.productName)
mntr := newContainerMounter(info, l.k, l.mountHints, l.productName)
if root {
if err := mntr.processHints(info.conf, info.procArgs.Credentials); err != nil {
return nil, nil, nil, err
}
}
if err := setupContainerFS(ctx, info.conf, mntr, &info.procArgs); err != nil {
if err := setupContainerVFS(ctx, info.conf, mntr, &info.procArgs); err != nil {
return nil, nil, nil, err
}
// Add the HOME environment variable if it is not already set.
var envv []string
if kernel.VFS2Enabled {
envv, err = user.MaybeAddExecUserHomeVFS2(ctx, info.procArgs.MountNamespaceVFS2,
info.procArgs.Credentials.RealKUID, info.procArgs.Envv)
} else {
envv, err = user.MaybeAddExecUserHome(ctx, info.procArgs.MountNamespace,
info.procArgs.Credentials.RealKUID, info.procArgs.Envv)
}
info.procArgs.Envv, err = user.MaybeAddExecUserHomeVFS2(ctx, info.procArgs.MountNamespaceVFS2,
info.procArgs.Credentials.RealKUID, info.procArgs.Envv)
if err != nil {
return nil, nil, nil, err
}
info.procArgs.Envv = envv
// Create and start the new process.
tg, _, err := l.k.CreateProcess(info.procArgs)
@@ -1012,22 +993,10 @@ func (l *Loader) executeAsync(args *control.ExecArgs) (kernel.ThreadID, error) {
// Get the container MountNamespace from the Task. Try to acquire ref may fail
// in case it raced with task exit.
if kernel.VFS2Enabled {
// task.MountNamespaceVFS2() does not take a ref, so we must do so ourselves.
args.MountNamespaceVFS2 = tg.Leader().MountNamespaceVFS2()
if args.MountNamespaceVFS2 == nil || !args.MountNamespaceVFS2.TryIncRef() {
return 0, fmt.Errorf("container %q has stopped", args.ContainerID)
}
} else {
var reffed bool
tg.Leader().WithMuLocked(func(t *kernel.Task) {
// task.MountNamespace() does not take a ref, so we must do so ourselves.
args.MountNamespace = t.MountNamespace()
reffed = args.MountNamespace.TryIncRef()
})
if !reffed {
return 0, fmt.Errorf("container %q has stopped", args.ContainerID)
}
// task.MountNamespaceVFS2() does not take a ref, so we must do so ourselves.
args.MountNamespaceVFS2 = tg.Leader().MountNamespaceVFS2()
if args.MountNamespaceVFS2 == nil || !args.MountNamespaceVFS2.TryIncRef() {
return 0, fmt.Errorf("container %q has stopped", args.ContainerID)
}
args.Envv, err = specutils.ResolveEnvs(args.Envv)
@@ -1036,25 +1005,11 @@ func (l *Loader) executeAsync(args *control.ExecArgs) (kernel.ThreadID, error) {
}
// Add the HOME environment variable if it is not already set.
if kernel.VFS2Enabled {
root := args.MountNamespaceVFS2.Root()
ctx := vfs.WithRoot(l.k.SupervisorContext(), root)
defer args.MountNamespaceVFS2.DecRef(ctx)
envv, err := user.MaybeAddExecUserHomeVFS2(ctx, args.MountNamespaceVFS2, args.KUID, args.Envv)
if err != nil {
return 0, err
}
args.Envv = envv
} else {
root := args.MountNamespace.Root()
ctx := fs.WithRoot(l.k.SupervisorContext(), root)
defer args.MountNamespace.DecRef(ctx)
defer root.DecRef(ctx)
envv, err := user.MaybeAddExecUserHome(ctx, args.MountNamespace, args.KUID, args.Envv)
if err != nil {
return 0, err
}
args.Envv = envv
ctx := vfs.WithRoot(l.k.SupervisorContext(), args.MountNamespaceVFS2.Root())
defer args.MountNamespaceVFS2.DecRef(ctx)
args.Envv, err = user.MaybeAddExecUserHomeVFS2(ctx, args.MountNamespaceVFS2, args.KUID, args.Envv)
if err != nil {
return 0, err
}
args.PIDNamespace = tg.PIDNamespace()
+5 -288
View File
@@ -18,19 +18,15 @@ import (
"fmt"
"math/rand"
"os"
"reflect"
"testing"
"time"
specs "github.com/opencontainers/runtime-spec/specs-go"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/control/server"
"gvisor.dev/gvisor/pkg/fd"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/p9"
"gvisor.dev/gvisor/pkg/sentry/contexttest"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/sync"
"gvisor.dev/gvisor/pkg/unet"
@@ -110,14 +106,12 @@ func startGofer(root string) (int, func(), error) {
return sandboxEnd, cleanup, nil
}
func createLoader(vfsEnabled bool, spec *specs.Spec) (*Loader, func(), error) {
func createLoader(spec *specs.Spec) (*Loader, func(), error) {
fd, err := server.CreateSocket(ControlSocketAddr(fmt.Sprintf("%010d", rand.Int())[:10]))
if err != nil {
return nil, nil, err
}
conf := testConfig()
conf.VFS2 = vfsEnabled
sandEnd, cleanup, err := startGofer(spec.Root.Path)
if err != nil {
return nil, nil, err
@@ -152,16 +146,7 @@ func createLoader(vfsEnabled bool, spec *specs.Spec) (*Loader, func(), error) {
// TestRun runs a simple application in a sandbox and checks that it succeeds.
func TestRun(t *testing.T) {
doRun(t, false)
}
// TestRunVFS2 runs TestRun in VFSv2.
func TestRunVFS2(t *testing.T) {
doRun(t, true)
}
func doRun(t *testing.T, vfsEnabled bool) {
l, cleanup, err := createLoader(vfsEnabled, testSpec())
l, cleanup, err := createLoader(testSpec())
if err != nil {
t.Fatalf("error creating loader: %v", err)
}
@@ -199,16 +184,7 @@ func doRun(t *testing.T, vfsEnabled bool) {
// TestStartSignal tests that the controller Start message will cause
// WaitForStartSignal to return.
func TestStartSignal(t *testing.T) {
doStartSignal(t, false)
}
// TestStartSignalVFS2 does TestStartSignal with VFS2.
func TestStartSignalVFS2(t *testing.T) {
doStartSignal(t, true)
}
func doStartSignal(t *testing.T, vfsEnabled bool) {
l, cleanup, err := createLoader(vfsEnabled, testSpec())
l, cleanup, err := createLoader(testSpec())
if err != nil {
t.Fatalf("error creating loader: %v", err)
}
@@ -253,7 +229,6 @@ func doStartSignal(t *testing.T, vfsEnabled bool) {
case <-time.After(50 * time.Millisecond):
t.Errorf("WaitForStartSignal did not complete but it should have")
}
}
type CreateMountTestcase struct {
@@ -431,49 +406,6 @@ func createMountTestcases() []*CreateMountTestcase {
// Test that MountNamespace can be created with various specs.
func TestCreateMountNamespace(t *testing.T) {
for _, tc := range createMountTestcases() {
t.Run(tc.name, func(t *testing.T) {
conf := testConfig()
ctx := contexttest.Context(t)
sandEnd, cleanup, err := startGofer(tc.spec.Root.Path)
if err != nil {
t.Fatalf("failed to create gofer: %v", err)
}
defer cleanup()
info := containerInfo{
conf: conf,
spec: &tc.spec,
goferFDs: []*fd.FD{fd.New(sandEnd)},
}
mntr := newContainerMounter(&info, nil, &podMountHints{}, false /* vfs2Enabled */, "")
mns, err := mntr.createMountNamespace(ctx, conf)
if err != nil {
t.Fatalf("failed to create mount namespace: %v", err)
}
ctx = fs.WithRoot(ctx, mns.Root())
if err := mntr.mountSubmounts(ctx, conf, mns); err != nil {
t.Fatalf("failed to create mount namespace: %v", err)
}
root := mns.Root()
defer root.DecRef(ctx)
for _, p := range tc.expectedPaths {
maxTraversals := uint(0)
if d, err := mns.FindInode(ctx, root, root, p, &maxTraversals); err != nil {
t.Errorf("expected path %v to exist with spec %v, but got error %v", p, tc.spec, err)
} else {
d.DecRef(ctx)
}
}
})
}
}
// Test that MountNamespace can be created with various specs.
func TestCreateMountNamespaceVFS2(t *testing.T) {
for _, tc := range createMountTestcases() {
t.Run(tc.name, func(t *testing.T) {
spec := testSpec()
@@ -481,14 +413,14 @@ func TestCreateMountNamespaceVFS2(t *testing.T) {
spec.Root = tc.spec.Root
t.Logf("Using root: %q", spec.Root.Path)
l, loaderCleanup, err := createLoader(true /* VFS2 Enabled */, spec)
l, loaderCleanup, err := createLoader(spec)
if err != nil {
t.Fatalf("failed to create loader: %v", err)
}
defer l.Destroy()
defer loaderCleanup()
mntr := newContainerMounter(&l.root, l.k, l.mountHints, true /* vfs2Enabled */, "")
mntr := newContainerMounter(&l.root, l.k, l.mountHints, "")
if err := mntr.processHints(l.root.conf, l.root.procArgs.Credentials); err != nil {
t.Fatalf("failed process hints: %v", err)
}
@@ -518,218 +450,3 @@ func TestCreateMountNamespaceVFS2(t *testing.T) {
})
}
}
// TestRestoreEnvironment tests that the correct mounts are collected from the spec and config
// in order to build the environment for restoring.
func TestRestoreEnvironment(t *testing.T) {
testCases := []struct {
name string
spec *specs.Spec
ioFDs []int
errorExpected bool
expectedRenv fs.RestoreEnvironment
}{
{
name: "basic spec test",
spec: &specs.Spec{
Root: &specs.Root{
Path: os.TempDir(),
Readonly: true,
},
Mounts: []specs.Mount{
{
Destination: "/some/very/very/deep/path",
Type: "tmpfs",
},
{
Destination: "/proc",
Type: "tmpfs",
},
},
},
ioFDs: []int{0},
errorExpected: false,
expectedRenv: fs.RestoreEnvironment{
MountSources: map[string][]fs.MountArgs{
"9p": {
{
Dev: "9pfs-/",
Flags: fs.MountSourceFlags{ReadOnly: true},
DataString: "trans=fd,rfdno=0,wfdno=0",
},
},
"tmpfs": {
{
Dev: "none",
},
{
Dev: "none",
},
{
Dev: "none",
},
},
"devtmpfs": {
{
Dev: "none",
},
},
"devpts": {
{
Dev: "none",
},
},
"sysfs": {
{
Dev: "none",
},
},
},
},
},
{
name: "bind type test",
spec: &specs.Spec{
Root: &specs.Root{
Path: os.TempDir(),
Readonly: true,
},
Mounts: []specs.Mount{
{
Destination: "/dev/fd-foo",
Type: "bind",
},
},
},
ioFDs: []int{0, 1},
errorExpected: false,
expectedRenv: fs.RestoreEnvironment{
MountSources: map[string][]fs.MountArgs{
"9p": {
{
Dev: "9pfs-/",
Flags: fs.MountSourceFlags{ReadOnly: true},
DataString: "trans=fd,rfdno=0,wfdno=0",
},
{
Dev: "9pfs-/dev/fd-foo",
DataString: "trans=fd,rfdno=1,wfdno=1,cache=remote_revalidating",
},
},
"tmpfs": {
{
Dev: "none",
},
},
"devtmpfs": {
{
Dev: "none",
},
},
"devpts": {
{
Dev: "none",
},
},
"proc": {
{
Dev: "none",
},
},
"sysfs": {
{
Dev: "none",
},
},
},
},
},
{
name: "options test",
spec: &specs.Spec{
Root: &specs.Root{
Path: os.TempDir(),
Readonly: true,
},
Mounts: []specs.Mount{
{
Destination: "/dev/fd-foo",
Type: "tmpfs",
Options: []string{"uid=1022", "noatime"},
},
},
},
ioFDs: []int{0},
errorExpected: false,
expectedRenv: fs.RestoreEnvironment{
MountSources: map[string][]fs.MountArgs{
"9p": {
{
Dev: "9pfs-/",
Flags: fs.MountSourceFlags{ReadOnly: true},
DataString: "trans=fd,rfdno=0,wfdno=0",
},
},
"tmpfs": {
{
Dev: "none",
Flags: fs.MountSourceFlags{NoAtime: true},
DataString: "uid=1022",
},
{
Dev: "none",
},
},
"devtmpfs": {
{
Dev: "none",
},
},
"devpts": {
{
Dev: "none",
},
},
"proc": {
{
Dev: "none",
},
},
"sysfs": {
{
Dev: "none",
},
},
},
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
conf := testConfig()
conf.VFS2 = true
var ioFDs []*fd.FD
for _, ioFD := range tc.ioFDs {
ioFDs = append(ioFDs, fd.New(ioFD))
}
info := containerInfo{
conf: conf,
spec: tc.spec,
goferFDs: ioFDs,
}
mntr := newContainerMounter(&info, nil, &podMountHints{}, conf.VFS2, "")
actualRenv, err := mntr.createRestoreEnvironment(conf)
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)
}
}
})
}
}
+5 -5
View File
@@ -151,7 +151,7 @@ func registerFilesystems(k *kernel.Kernel) error {
return nil
}
func setupContainerVFS2(ctx context.Context, conf *config.Config, mntr *containerMounter, procArgs *kernel.CreateProcessArgs) error {
func setupContainerVFS(ctx context.Context, conf *config.Config, mntr *containerMounter, procArgs *kernel.CreateProcessArgs) error {
mns, err := mntr.mountAll(conf, procArgs)
if err != nil {
return fmt.Errorf("failed to setupFS: %w", err)
@@ -213,7 +213,7 @@ func (c *containerMounter) mountAll(conf *config.Config, procArgs *kernel.Create
// createMountNamespaceVFS2 creates the container's root mount and namespace.
func (c *containerMounter) createMountNamespaceVFS2(ctx context.Context, conf *config.Config, creds *auth.Credentials) (*vfs.MountNamespace, error) {
fd := c.fds.remove()
data := goferMountData(fd, conf.FileAccess, true /* vfs2 */, conf.Lisafs)
data := goferMountData(fd, conf.FileAccess, conf.Lisafs)
// We can't check for overlayfs here because sandbox is chroot'ed and gofer
// can only send mount options for specs.Mounts (specs.Root is missing
@@ -525,7 +525,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 = goferMountData(m.fd, c.getMountAccessType(conf, m.mount), true /* vfs2 */, conf.Lisafs)
data = goferMountData(m.fd, c.getMountAccessType(conf, m.mount), conf.Lisafs)
internalData = gofer.InternalFilesystemOptions{
UniqueID: m.mount.Destination,
}
@@ -718,10 +718,10 @@ func (c *containerMounter) mountTmpVFS2(ctx context.Context, conf *config.Config
}
}
// processHintsVFS2 processes annotations that container hints about how volumes
// processHints processes annotations that container hints about how volumes
// should be mounted (e.g. a volume shared between containers). It must be
// called for the root container only.
func (c *containerMounter) processHintsVFS2(conf *config.Config, creds *auth.Credentials) error {
func (c *containerMounter) processHints(conf *config.Config, creds *auth.Credentials) error {
ctx := c.k.SupervisorContext()
for _, hint := range c.hints.mounts {
// TODO(b/142076984): Only support tmpfs for now. Bind mounts require a
+4 -4
View File
@@ -218,7 +218,7 @@ func (g *Gofer) serveLisafs(spec *specs.Spec, conf *config.Config, root string)
mountIdx := 1 // first one is the root
for _, m := range spec.Mounts {
if !specutils.IsGoferMount(m, conf.VFS2) {
if !specutils.IsGoferMount(m) {
continue
}
@@ -273,7 +273,7 @@ func (g *Gofer) serve9P(spec *specs.Spec, conf *config.Config, root string) subc
mountIdx := 1 // first one is the root
for _, m := range spec.Mounts {
if specutils.IsGoferMount(m, conf.VFS2) {
if specutils.IsGoferMount(m) {
cfg := fsgofer.Config{
ROMount: isReadonlyMount(m.Options) || conf.Overlay,
HostUDS: conf.FSGoferHostUDS,
@@ -445,7 +445,7 @@ func setupRootFS(spec *specs.Spec, conf *config.Config) error {
// creates directories as needed.
func setupMounts(conf *config.Config, mounts []specs.Mount, root, procPath string) error {
for _, m := range mounts {
if !specutils.IsGoferMount(m, conf.VFS2) {
if !specutils.IsGoferMount(m) {
continue
}
@@ -485,7 +485,7 @@ func setupMounts(conf *config.Config, mounts []specs.Mount, root, procPath strin
func resolveMounts(conf *config.Config, mounts []specs.Mount, root string) ([]specs.Mount, error) {
cleanMounts := make([]specs.Mount, 0, len(mounts))
for _, m := range mounts {
if !specutils.IsGoferMount(m, conf.VFS2) {
if !specutils.IsGoferMount(m) {
cleanMounts = append(cleanMounts, m)
continue
}
-3
View File
@@ -204,9 +204,6 @@ type Config struct {
// E.g. 0.2 CPU quota will result in 1, and 1.9 in 2.
CPUNumFromQuota bool `flag:"cpu-num-from-quota"`
// DEPRECATED: VFS2 is always enabled and cannot be disabled.
VFS2 bool
// Enable lisafs.
Lisafs bool `flag:"lisafs"`
+1 -1
View File
@@ -131,7 +131,7 @@ func checkOciSeccomp(name string, value string) error {
// NewFromFlags creates a new Config with values coming from command line flags.
func NewFromFlags(flagSet *flag.FlagSet) (*Config, error) {
conf := &Config{VFS2: true}
conf := &Config{}
obj := reflect.ValueOf(conf).Elem()
st := obj.Type()
+1 -1
View File
@@ -938,7 +938,7 @@ func (c *Container) createGoferProcess(spec *specs.Spec, conf *config.Config, bu
// Add root mount and then add any other additional mounts.
mountCount := 1
for _, m := range spec.Mounts {
if specutils.IsGoferMount(m, conf.VFS2) {
if specutils.IsGoferMount(m) {
mountCount++
}
}
+2 -25
View File
@@ -335,9 +335,9 @@ func capsFromNames(names []string, skipSet map[linux.Capability]struct{}) (auth.
// IsGoferMount returns true if the given mount can be mounted as an external
// gofer.
func IsGoferMount(m specs.Mount, vfs2Enabled bool) bool {
func IsGoferMount(m specs.Mount) bool {
MaybeConvertToBindMount(&m)
return m.Type == "bind" && m.Source != "" && IsSupportedDevMount(m, vfs2Enabled)
return m.Type == "bind" && m.Source != ""
}
// MaybeConvertToBindMount converts mount type to "bind" in case any of the
@@ -357,29 +357,6 @@ func MaybeConvertToBindMount(m *specs.Mount) {
}
}
// IsSupportedDevMount returns true if m.Destination does not specify a
// path that is hardcoded by VFS1's implementation of /dev.
func IsSupportedDevMount(m specs.Mount, vfs2Enabled bool) bool {
// VFS2 has no hardcoded files under /dev, so everything is allowed.
if vfs2Enabled {
return true
}
// See pkg/sentry/fs/dev/dev.go.
var existingDevices = []string{
"/dev/fd", "/dev/stdin", "/dev/stdout", "/dev/stderr",
"/dev/null", "/dev/zero", "/dev/full", "/dev/random",
"/dev/urandom", "/dev/shm", "/dev/ptmx",
}
dst := filepath.Clean(m.Destination)
for _, dev := range existingDevices {
if dst == dev || strings.HasPrefix(dst, dev+"/") {
return false
}
}
return true
}
// WaitForReady waits for a process to become ready. The process is ready when
// the 'ready' function returns true. It continues to wait if 'ready' returns
// false. It returns error on timeout, if the process stops or if 'ready' fails.