summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/fs
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/sentry/fs')
-rw-r--r--pkg/sentry/fs/copy_up.go18
-rw-r--r--pkg/sentry/fs/gofer/path.go20
-rw-r--r--pkg/sentry/fs/inode_operations.go4
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)