diff options
Diffstat (limited to 'pkg/sentry')
-rw-r--r-- | pkg/sentry/fs/copy_up.go | 18 | ||||
-rw-r--r-- | pkg/sentry/fs/gofer/path.go | 20 | ||||
-rw-r--r-- | pkg/sentry/fs/inode_operations.go | 4 |
3 files changed, 33 insertions, 9 deletions
diff --git a/pkg/sentry/fs/copy_up.go b/pkg/sentry/fs/copy_up.go index ee2d3d115..41265704c 100644 --- a/pkg/sentry/fs/copy_up.go +++ b/pkg/sentry/fs/copy_up.go @@ -113,13 +113,13 @@ func copyUpLockedForRename(ctx context.Context, d *Dirent) error { // Did we race with another copy up or does there // already exist something in the upper filesystem // for d? - d.Inode.overlay.copyMu.Lock() + d.Inode.overlay.copyMu.RLock() if d.Inode.overlay.upper != nil { - d.Inode.overlay.copyMu.Unlock() + d.Inode.overlay.copyMu.RUnlock() // Done, d is in the upper filesystem. return nil } - d.Inode.overlay.copyMu.Unlock() + d.Inode.overlay.copyMu.RUnlock() // Find the next component to copy up. We will work our way // down to the last component of d and finally copy it. @@ -155,6 +155,14 @@ func findNextCopyUp(ctx context.Context, d *Dirent) *Dirent { } func doCopyUp(ctx context.Context, d *Dirent) error { + // Fail fast on Inode types we won't be able to copy up anyways. These + // Inodes may block in GetFile while holding copyMu for reading. If we + // then try to take copyMu for writing here, we'd deadlock. + t := d.Inode.overlay.lower.StableAttr.Type + if t != RegularFile && t != Directory && t != Symlink { + return syserror.EINVAL + } + // Wait to get exclusive access to the upper Inode. d.Inode.overlay.copyMu.Lock() defer d.Inode.overlay.copyMu.Unlock() @@ -177,6 +185,8 @@ func doCopyUp(ctx context.Context, d *Dirent) error { // - parent.Inode.overlay.upper must be non-nil. // - next.Inode.overlay.copyMu must be locked writable. // - next.Inode.overlay.lower must be non-nil. +// - next.Inode.overlay.lower.StableAttr.Type must be RegularFile, Directory, +// or Symlink. // - upper filesystem must support setting file ownership and timestamps. func copyUpLocked(ctx context.Context, parent *Dirent, next *Dirent) error { // Extract the attributes of the file we wish to copy. @@ -239,7 +249,7 @@ func copyUpLocked(ctx context.Context, parent *Dirent, next *Dirent) error { childUpperInode = childUpper.Inode default: - return syserror.EINVAL + panic(fmt.Sprintf("copy up of invalid type %v on %+v", next.Inode.StableAttr.Type, next)) } // Bring file attributes up to date. This does not include size, which will be diff --git a/pkg/sentry/fs/gofer/path.go b/pkg/sentry/fs/gofer/path.go index 6ed50a77f..092f8b586 100644 --- a/pkg/sentry/fs/gofer/path.go +++ b/pkg/sentry/fs/gofer/path.go @@ -282,10 +282,22 @@ func (i *inodeOperations) Bind(ctx context.Context, dir *fs.Inode, name string, return childDir, nil } -// CreateFifo implements fs.InodeOperations.CreateFifo. Gofer nodes do not support the -// creation of fifos and always returns EPERM. -func (*inodeOperations) CreateFifo(context.Context, *fs.Inode, string, fs.FilePermissions) error { - return syscall.EPERM +// CreateFifo implements fs.InodeOperations.CreateFifo. +func (i *inodeOperations) CreateFifo(ctx context.Context, dir *fs.Inode, name string, perm fs.FilePermissions) error { + if len(name) > maxFilenameLen { + return syserror.ENAMETOOLONG + } + + owner := fs.FileOwnerFromContext(ctx) + mode := p9.FileMode(perm.LinuxMode()) | p9.ModeNamedPipe + + // N.B. FIFOs use major/minor numbers 0. + if _, err := i.fileState.file.mknod(ctx, name, mode, 0, 0, p9.UID(owner.UID), p9.GID(owner.GID)); err != nil { + return err + } + + i.touchModificationAndStatusChangeTime(ctx, dir) + return nil } // Remove implements InodeOperations.Remove. diff --git a/pkg/sentry/fs/inode_operations.go b/pkg/sentry/fs/inode_operations.go index 3211f1817..2ed89d482 100644 --- a/pkg/sentry/fs/inode_operations.go +++ b/pkg/sentry/fs/inode_operations.go @@ -161,7 +161,9 @@ type InodeOperations interface { BoundEndpoint(inode *Inode, path string) transport.BoundEndpoint // GetFile returns a new open File backed by a Dirent and FileFlags. - // It may block as long as it is done with ctx. + // + // Special Inode types may block using ctx.Sleeper. RegularFiles, + // Directories, and Symlinks must not block (see doCopyUp). // // The returned File will uniquely back an application fd. GetFile(ctx context.Context, d *Dirent, flags FileFlags) (*File, error) |