diff options
-rw-r--r-- | pkg/sentry/fsimpl/overlay/directory.go | 10 | ||||
-rw-r--r-- | runsc/boot/vfs.go | 27 |
2 files changed, 25 insertions, 12 deletions
diff --git a/pkg/sentry/fsimpl/overlay/directory.go b/pkg/sentry/fsimpl/overlay/directory.go index fccb94105..6a79f7ffe 100644 --- a/pkg/sentry/fsimpl/overlay/directory.go +++ b/pkg/sentry/fsimpl/overlay/directory.go @@ -51,7 +51,7 @@ func (d *dentry) collectWhiteoutsForRmdirLocked(ctx context.Context) (map[string // Reuse slice allocated for maybeWhiteouts from a previous layer to // reduce allocations. maybeWhiteouts = maybeWhiteouts[:0] - if err := layerFD.IterDirents(ctx, vfs.IterDirentsCallbackFunc(func(dirent vfs.Dirent) error { + err = layerFD.IterDirents(ctx, vfs.IterDirentsCallbackFunc(func(dirent vfs.Dirent) error { if dirent.Name == "." || dirent.Name == ".." { return nil } @@ -68,7 +68,8 @@ func (d *dentry) collectWhiteoutsForRmdirLocked(ctx context.Context) (map[string } // Non-whiteout file in the directory prevents rmdir. return syserror.ENOTEMPTY - })); err != nil { + })) + if err != nil { readdirErr = err return false } @@ -182,7 +183,7 @@ func (d *dentry) getDirents(ctx context.Context) ([]vfs.Dirent, error) { // Reuse slice allocated for maybeWhiteouts from a previous layer to // reduce allocations. maybeWhiteouts = maybeWhiteouts[:0] - if err := layerFD.IterDirents(ctx, vfs.IterDirentsCallbackFunc(func(dirent vfs.Dirent) error { + err = layerFD.IterDirents(ctx, vfs.IterDirentsCallbackFunc(func(dirent vfs.Dirent) error { if dirent.Name == "." || dirent.Name == ".." { return nil } @@ -201,7 +202,8 @@ func (d *dentry) getDirents(ctx context.Context) ([]vfs.Dirent, error) { dirent.NextOff = int64(len(dirents) + 1) dirents = append(dirents, dirent) return nil - })); err != nil { + })) + if err != nil { readdirErr = err return false } diff --git a/runsc/boot/vfs.go b/runsc/boot/vfs.go index e7d6035bb..08dce8b6c 100644 --- a/runsc/boot/vfs.go +++ b/runsc/boot/vfs.go @@ -400,21 +400,28 @@ func (c *containerMounter) mountTmpVFS2(ctx context.Context, conf *Config, creds Path: fspath.Parse("/tmp"), } // TODO(gvisor.dev/issue/2782): Use O_PATH when available. - statx, err := c.k.VFS().StatAt(ctx, creds, &pop, &vfs.StatOptions{}) + fd, err := c.k.VFS().OpenAt(ctx, creds, &pop, &vfs.OpenOptions{Flags: linux.O_RDONLY | linux.O_DIRECTORY}) switch err { case nil: - // Found '/tmp' in filesystem, check if it's empty. - if linux.FileMode(statx.Mode).FileType() != linux.ModeDirectory { - // Not a dir?! Leave it be. + defer fd.DecRef(ctx) + + err := fd.IterDirents(ctx, vfs.IterDirentsCallbackFunc(func(dirent vfs.Dirent) error { + if dirent.Name != "." && dirent.Name != ".." { + return syserror.ENOTEMPTY + } return nil - } - if statx.Nlink > 2 { + })) + switch err { + case nil: + log.Infof(`Mounting internal tmpfs on top of empty "/tmp"`) + case syserror.ENOTEMPTY: // If more than "." and ".." is found, skip internal tmpfs to prevent // hiding existing files. log.Infof(`Skipping internal tmpfs mount for "/tmp" because it's not empty`) return nil + default: + return err } - log.Infof(`Mounting internal tmpfs on top of empty "/tmp"`) fallthrough case syserror.ENOENT: @@ -429,8 +436,12 @@ func (c *containerMounter) mountTmpVFS2(ctx context.Context, conf *Config, creds } return c.mountSubmountVFS2(ctx, conf, mns, creds, &mountAndFD{Mount: tmpMount}) + case syserror.ENOTDIR: + // Not a dir?! Let it be. + return nil + default: - return fmt.Errorf(`stating "/tmp" inside container: %w`, err) + return fmt.Errorf(`opening "/tmp" inside container: %w`, err) } } |