diff options
Diffstat (limited to 'pkg')
67 files changed, 281 insertions, 206 deletions
diff --git a/pkg/sentry/fs/anon/anon.go b/pkg/sentry/fs/anon/anon.go index 28bd0998f..7323c7222 100644 --- a/pkg/sentry/fs/anon/anon.go +++ b/pkg/sentry/fs/anon/anon.go @@ -33,7 +33,7 @@ func NewInode(ctx context.Context) *fs.Inode { User: fs.PermMask{Read: true, Write: true}, }, linux.ANON_INODE_FS_MAGIC), } - return fs.NewInode(iops, fs.NewPseudoMountSource(), fs.StableAttr{ + return fs.NewInode(ctx, iops, fs.NewPseudoMountSource(ctx), fs.StableAttr{ Type: fs.Anonymous, DeviceID: PseudoDevice.DeviceID(), InodeID: PseudoDevice.NextIno(), diff --git a/pkg/sentry/fs/ashmem/area.go b/pkg/sentry/fs/ashmem/area.go index cae3e4dda..e1971f91c 100644 --- a/pkg/sentry/fs/ashmem/area.go +++ b/pkg/sentry/fs/ashmem/area.go @@ -116,8 +116,8 @@ func (a *Area) ConfigureMMap(ctx context.Context, file *fs.File, opts *memmap.MM if a.tmpfsFile == nil { tmpfsInodeOps := tmpfs.NewInMemoryFile(ctx, usage.Tmpfs, fs.UnstableAttr{}) - tmpfsInode := fs.NewInode(tmpfsInodeOps, fs.NewPseudoMountSource(), fs.StableAttr{}) - dirent := fs.NewDirent(tmpfsInode, namePrefix+"/"+a.name) + tmpfsInode := fs.NewInode(ctx, tmpfsInodeOps, fs.NewPseudoMountSource(ctx), fs.StableAttr{}) + dirent := fs.NewDirent(ctx, tmpfsInode, namePrefix+"/"+a.name) tmpfsFile, err := tmpfsInode.GetFile(ctx, dirent, fs.FileFlags{Read: true, Write: true}) // Drop the extra reference on the Dirent. dirent.DecRef() diff --git a/pkg/sentry/fs/dev/dev.go b/pkg/sentry/fs/dev/dev.go index 317be246c..fb6c30ff0 100644 --- a/pkg/sentry/fs/dev/dev.go +++ b/pkg/sentry/fs/dev/dev.go @@ -40,8 +40,8 @@ const ( urandomDevMinor uint32 = 9 ) -func newCharacterDevice(iops fs.InodeOperations, msrc *fs.MountSource) *fs.Inode { - return fs.NewInode(iops, msrc, fs.StableAttr{ +func newCharacterDevice(ctx context.Context, iops fs.InodeOperations, msrc *fs.MountSource) *fs.Inode { + return fs.NewInode(ctx, iops, msrc, fs.StableAttr{ DeviceID: devDevice.DeviceID(), InodeID: devDevice.NextIno(), BlockSize: usermem.PageSize, @@ -49,8 +49,8 @@ func newCharacterDevice(iops fs.InodeOperations, msrc *fs.MountSource) *fs.Inode }) } -func newMemDevice(iops fs.InodeOperations, msrc *fs.MountSource, minor uint32) *fs.Inode { - return fs.NewInode(iops, msrc, fs.StableAttr{ +func newMemDevice(ctx context.Context, iops fs.InodeOperations, msrc *fs.MountSource, minor uint32) *fs.Inode { + return fs.NewInode(ctx, iops, msrc, fs.StableAttr{ DeviceID: devDevice.DeviceID(), InodeID: devDevice.NextIno(), BlockSize: usermem.PageSize, @@ -62,7 +62,7 @@ func newMemDevice(iops fs.InodeOperations, msrc *fs.MountSource, minor uint32) * func newDirectory(ctx context.Context, msrc *fs.MountSource) *fs.Inode { iops := ramfs.NewDir(ctx, nil, fs.RootOwner, fs.FilePermsFromMode(0555)) - return fs.NewInode(iops, msrc, fs.StableAttr{ + return fs.NewInode(ctx, iops, msrc, fs.StableAttr{ DeviceID: devDevice.DeviceID(), InodeID: devDevice.NextIno(), BlockSize: usermem.PageSize, @@ -72,7 +72,7 @@ func newDirectory(ctx context.Context, msrc *fs.MountSource) *fs.Inode { func newSymlink(ctx context.Context, target string, msrc *fs.MountSource) *fs.Inode { iops := ramfs.NewSymlink(ctx, fs.RootOwner, target) - return fs.NewInode(iops, msrc, fs.StableAttr{ + return fs.NewInode(ctx, iops, msrc, fs.StableAttr{ DeviceID: devDevice.DeviceID(), InodeID: devDevice.NextIno(), BlockSize: usermem.PageSize, @@ -88,17 +88,17 @@ func New(ctx context.Context, msrc *fs.MountSource, binderEnabled bool, ashmemEn "stdout": newSymlink(ctx, "/proc/self/fd/1", msrc), "stderr": newSymlink(ctx, "/proc/self/fd/2", msrc), - "null": newMemDevice(newNullDevice(ctx, fs.RootOwner, 0666), msrc, nullDevMinor), - "zero": newMemDevice(newZeroDevice(ctx, fs.RootOwner, 0666), msrc, zeroDevMinor), - "full": newMemDevice(newFullDevice(ctx, fs.RootOwner, 0666), msrc, fullDevMinor), + "null": newMemDevice(ctx, newNullDevice(ctx, fs.RootOwner, 0666), msrc, nullDevMinor), + "zero": newMemDevice(ctx, newZeroDevice(ctx, fs.RootOwner, 0666), msrc, zeroDevMinor), + "full": newMemDevice(ctx, newFullDevice(ctx, fs.RootOwner, 0666), msrc, fullDevMinor), // This is not as good as /dev/random in linux because go // runtime uses sys_random and /dev/urandom internally. // According to 'man 4 random', this will be sufficient unless // application uses this to generate long-lived GPG/SSL/SSH // keys. - "random": newMemDevice(newRandomDevice(ctx, fs.RootOwner, 0444), msrc, randomDevMinor), - "urandom": newMemDevice(newRandomDevice(ctx, fs.RootOwner, 0444), msrc, urandomDevMinor), + "random": newMemDevice(ctx, newRandomDevice(ctx, fs.RootOwner, 0444), msrc, randomDevMinor), + "urandom": newMemDevice(ctx, newRandomDevice(ctx, fs.RootOwner, 0444), msrc, urandomDevMinor), "shm": tmpfs.NewDir(ctx, nil, fs.RootOwner, fs.FilePermsFromMode(0777), msrc), @@ -120,16 +120,16 @@ func New(ctx context.Context, msrc *fs.MountSource, binderEnabled bool, ashmemEn if binderEnabled { binder := binder.NewDevice(ctx, fs.RootOwner, fs.FilePermsFromMode(0666)) - contents["binder"] = newCharacterDevice(binder, msrc) + contents["binder"] = newCharacterDevice(ctx, binder, msrc) } if ashmemEnabled { ashmem := ashmem.NewDevice(ctx, fs.RootOwner, fs.FilePermsFromMode(0666)) - contents["ashmem"] = newCharacterDevice(ashmem, msrc) + contents["ashmem"] = newCharacterDevice(ctx, ashmem, msrc) } iops := ramfs.NewDir(ctx, contents, fs.RootOwner, fs.FilePermsFromMode(0555)) - return fs.NewInode(iops, msrc, fs.StableAttr{ + return fs.NewInode(ctx, iops, msrc, fs.StableAttr{ DeviceID: devDevice.DeviceID(), InodeID: devDevice.NextIno(), BlockSize: usermem.PageSize, diff --git a/pkg/sentry/fs/dev/fs.go b/pkg/sentry/fs/dev/fs.go index 9ea6e91e9..6dbc8c382 100644 --- a/pkg/sentry/fs/dev/fs.go +++ b/pkg/sentry/fs/dev/fs.go @@ -95,5 +95,5 @@ func (f *filesystem) Mount(ctx context.Context, device string, flags fs.MountSou } // Construct the devtmpfs root. - return New(ctx, fs.NewNonCachingMountSource(f, flags), binderEnabled, ashmemEnabled), nil + return New(ctx, fs.NewNonCachingMountSource(ctx, f, flags), binderEnabled, ashmemEnabled), nil } diff --git a/pkg/sentry/fs/dirent.go b/pkg/sentry/fs/dirent.go index 9694d915d..ca417d2bc 100644 --- a/pkg/sentry/fs/dirent.go +++ b/pkg/sentry/fs/dirent.go @@ -206,7 +206,7 @@ type Dirent struct { // NewDirent returns a new root Dirent, taking the caller's reference on inode. The caller // holds the only reference to the Dirent. Parents may call hashChild to parent this Dirent. -func NewDirent(inode *Inode, name string) *Dirent { +func NewDirent(ctx context.Context, inode *Inode, name string) *Dirent { d := newDirent(inode, name) allDirents.add(d) d.userVisible = true @@ -1068,7 +1068,7 @@ func (d *Dirent) mount(ctx context.Context, inode *Inode) (newChild *Dirent, err // // Note that NewDirent returns with one reference taken; the reference // is donated to the caller as the mount reference. - replacement := NewDirent(inode, d.name) + replacement := NewDirent(ctx, inode, d.name) replacement.mounted = true weakRef, ok := d.parent.hashChild(replacement) diff --git a/pkg/sentry/fs/gofer/path.go b/pkg/sentry/fs/gofer/path.go index 24f6cc093..b91386909 100644 --- a/pkg/sentry/fs/gofer/path.go +++ b/pkg/sentry/fs/gofer/path.go @@ -73,7 +73,7 @@ func (i *inodeOperations) Lookup(ctx context.Context, dir *fs.Inode, name string sattr, node := newInodeOperations(ctx, i.fileState.s, newFile, qids[0], mask, p9attr, false) // Construct a positive Dirent. - return fs.NewDirent(fs.NewInode(node, dir.MountSource, sattr), name), nil + return fs.NewDirent(ctx, fs.NewInode(ctx, node, dir.MountSource, sattr), name), nil } // Creates a new Inode at name and returns its File based on the session's cache policy. @@ -141,7 +141,7 @@ func (i *inodeOperations) Create(ctx context.Context, dir *fs.Inode, name string sattr, iops := newInodeOperations(ctx, i.fileState.s, unopened, qid, mask, p9attr, false) // Construct the positive Dirent. - d := fs.NewDirent(fs.NewInode(iops, dir.MountSource, sattr), name) + d := fs.NewDirent(ctx, fs.NewInode(ctx, iops, dir.MountSource, sattr), name) defer d.DecRef() // Construct the new file, caching the handles if allowed. @@ -277,7 +277,7 @@ func (i *inodeOperations) Bind(ctx context.Context, dir *fs.Inode, name string, sattr, iops := newInodeOperations(ctx, i.fileState.s, unopened, qid, mask, attr, true) // Construct the positive Dirent. - childDir := fs.NewDirent(fs.NewInode(iops, dir.MountSource, sattr), name) + childDir := fs.NewDirent(ctx, fs.NewInode(ctx, iops, dir.MountSource, sattr), name) i.session().endpoints.add(key, childDir, ep) return childDir, nil } diff --git a/pkg/sentry/fs/gofer/session.go b/pkg/sentry/fs/gofer/session.go index 1763c8692..7ad0d8bc5 100644 --- a/pkg/sentry/fs/gofer/session.go +++ b/pkg/sentry/fs/gofer/session.go @@ -251,7 +251,7 @@ func Root(ctx context.Context, dev string, filesystem fs.Filesystem, superBlockF } // Construct the MountSource with the session and superBlockFlags. - m := fs.NewMountSource(s, filesystem, superBlockFlags) + m := fs.NewMountSource(ctx, s, filesystem, superBlockFlags) // Given that gofer files can consume host FDs, restrict the number // of files that can be held by the cache. @@ -286,7 +286,7 @@ func Root(ctx context.Context, dev string, filesystem fs.Filesystem, superBlockF } sattr, iops := newInodeOperations(ctx, s, s.attach, qid, valid, attr, false) - return fs.NewInode(iops, m, sattr), nil + return fs.NewInode(ctx, iops, m, sattr), nil } // newEndpointMaps creates a new endpointMaps. diff --git a/pkg/sentry/fs/gofer/socket.go b/pkg/sentry/fs/gofer/socket.go index 6a9994264..a45a8f36c 100644 --- a/pkg/sentry/fs/gofer/socket.go +++ b/pkg/sentry/fs/gofer/socket.go @@ -18,6 +18,7 @@ import ( "gvisor.dev/gvisor/pkg/abi/linux" "gvisor.dev/gvisor/pkg/log" "gvisor.dev/gvisor/pkg/p9" + "gvisor.dev/gvisor/pkg/sentry/context" "gvisor.dev/gvisor/pkg/sentry/fs" "gvisor.dev/gvisor/pkg/sentry/fs/host" "gvisor.dev/gvisor/pkg/sentry/socket/unix/transport" @@ -75,7 +76,7 @@ func sockTypeToP9(t linux.SockType) (p9.ConnectFlags, bool) { } // BidirectionalConnect implements ConnectableEndpoint.BidirectionalConnect. -func (e *endpoint) BidirectionalConnect(ce transport.ConnectingEndpoint, returnConnect func(transport.Receiver, transport.ConnectedEndpoint)) *syserr.Error { +func (e *endpoint) BidirectionalConnect(ctx context.Context, ce transport.ConnectingEndpoint, returnConnect func(transport.Receiver, transport.ConnectedEndpoint)) *syserr.Error { cf, ok := sockTypeToP9(ce.Type()) if !ok { return syserr.ErrConnectionRefused @@ -100,7 +101,7 @@ func (e *endpoint) BidirectionalConnect(ce transport.ConnectingEndpoint, returnC return syserr.ErrConnectionRefused } - c, serr := host.NewConnectedEndpoint(hostFile, ce.WaiterQueue(), e.path) + c, serr := host.NewConnectedEndpoint(ctx, hostFile, ce.WaiterQueue(), e.path) if serr != nil { ce.Unlock() log.Warningf("Gofer returned invalid host socket for BidirectionalConnect; file %+v flags %+v: %v", e.file, cf, serr) @@ -116,13 +117,13 @@ func (e *endpoint) BidirectionalConnect(ce transport.ConnectingEndpoint, returnC // UnidirectionalConnect implements // transport.BoundEndpoint.UnidirectionalConnect. -func (e *endpoint) UnidirectionalConnect() (transport.ConnectedEndpoint, *syserr.Error) { +func (e *endpoint) UnidirectionalConnect(ctx context.Context) (transport.ConnectedEndpoint, *syserr.Error) { hostFile, err := e.file.Connect(p9.DgramSocket) if err != nil { return nil, syserr.ErrConnectionRefused } - c, serr := host.NewConnectedEndpoint(hostFile, &waiter.Queue{}, e.path) + c, serr := host.NewConnectedEndpoint(ctx, hostFile, &waiter.Queue{}, e.path) if serr != nil { log.Warningf("Gofer returned invalid host socket for UnidirectionalConnect; file %+v: %v", e.file, serr) return nil, serr diff --git a/pkg/sentry/fs/host/file.go b/pkg/sentry/fs/host/file.go index 45d5c8695..bd665a6b1 100644 --- a/pkg/sentry/fs/host/file.go +++ b/pkg/sentry/fs/host/file.go @@ -109,7 +109,7 @@ func newFileFromDonatedFD(ctx context.Context, donated int, mounter fs.FileOwner iops := inode.InodeOperations.(*inodeOperations) name := fmt.Sprintf("host:[%d]", inode.StableAttr.InodeID) - dirent := fs.NewDirent(inode, name) + dirent := fs.NewDirent(ctx, inode, name) defer dirent.DecRef() if isTTY { diff --git a/pkg/sentry/fs/host/fs.go b/pkg/sentry/fs/host/fs.go index 914d95d27..68d2697c0 100644 --- a/pkg/sentry/fs/host/fs.go +++ b/pkg/sentry/fs/host/fs.go @@ -262,7 +262,7 @@ func childDentAttrs(ctx context.Context, d *fs.Dirent) map[string]fs.DentAttr { // newMountSource constructs a new host fs.MountSource // relative to a root path. The root should match the mount point. func newMountSource(ctx context.Context, root string, mounter fs.FileOwner, filesystem fs.Filesystem, flags fs.MountSourceFlags, dontTranslateOwnership bool) *fs.MountSource { - return fs.NewMountSource(&superOperations{ + return fs.NewMountSource(ctx, &superOperations{ root: root, inodeMappings: make(map[uint64]string), mounter: mounter, diff --git a/pkg/sentry/fs/host/inode.go b/pkg/sentry/fs/host/inode.go index ca352a8c2..679d8321a 100644 --- a/pkg/sentry/fs/host/inode.go +++ b/pkg/sentry/fs/host/inode.go @@ -205,7 +205,7 @@ func newInode(ctx context.Context, msrc *fs.MountSource, fd int, saveable bool, } // Return the fs.Inode. - return fs.NewInode(iops, msrc, fileState.sattr), nil + return fs.NewInode(ctx, iops, msrc, fileState.sattr), nil } // Mappable implements fs.InodeOperations.Mappable. @@ -245,7 +245,7 @@ func (i *inodeOperations) Lookup(ctx context.Context, dir *fs.Inode, name string } // Return the fs.Dirent. - return fs.NewDirent(inode, name), nil + return fs.NewDirent(ctx, inode, name), nil } // Create implements fs.InodeOperations.Create. @@ -265,7 +265,7 @@ func (i *inodeOperations) Create(ctx context.Context, dir *fs.Inode, name string return nil, err } - d := fs.NewDirent(inode, name) + d := fs.NewDirent(ctx, inode, name) defer d.DecRef() return inode.GetFile(ctx, d, flags) } diff --git a/pkg/sentry/fs/host/socket.go b/pkg/sentry/fs/host/socket.go index a40890b41..7fedc88bc 100644 --- a/pkg/sentry/fs/host/socket.go +++ b/pkg/sentry/fs/host/socket.go @@ -118,7 +118,7 @@ func (c *ConnectedEndpoint) init() *syserr.Error { // The caller is responsible for calling Init(). Additionaly, Release needs to // be called twice because ConnectedEndpoint is both a transport.Receiver and // transport.ConnectedEndpoint. -func NewConnectedEndpoint(file *fd.FD, queue *waiter.Queue, path string) (*ConnectedEndpoint, *syserr.Error) { +func NewConnectedEndpoint(ctx context.Context, file *fd.FD, queue *waiter.Queue, path string) (*ConnectedEndpoint, *syserr.Error) { e := ConnectedEndpoint{ path: path, queue: queue, @@ -151,7 +151,7 @@ func (c *ConnectedEndpoint) Init() { func NewSocketWithDirent(ctx context.Context, d *fs.Dirent, f *fd.FD, flags fs.FileFlags) (*fs.File, error) { f2 := fd.New(f.FD()) var q waiter.Queue - e, err := NewConnectedEndpoint(f2, &q, "" /* path */) + e, err := NewConnectedEndpoint(ctx, f2, &q, "" /* path */) if err != nil { f2.Release() return nil, err.ToError() @@ -162,7 +162,7 @@ func NewSocketWithDirent(ctx context.Context, d *fs.Dirent, f *fd.FD, flags fs.F e.Init() - ep := transport.NewExternal(e.stype, uniqueid.GlobalProviderFromContext(ctx), &q, e, e) + ep := transport.NewExternal(ctx, e.stype, uniqueid.GlobalProviderFromContext(ctx), &q, e, e) return unixsocket.NewWithDirent(ctx, d, ep, e.stype, flags), nil } @@ -181,7 +181,7 @@ func newSocket(ctx context.Context, orgfd int, saveable bool) (*fs.File, error) } f := fd.New(ownedfd) var q waiter.Queue - e, err := NewConnectedEndpoint(f, &q, "" /* path */) + e, err := NewConnectedEndpoint(ctx, f, &q, "" /* path */) if err != nil { if saveable { f.Close() @@ -194,7 +194,7 @@ func newSocket(ctx context.Context, orgfd int, saveable bool) (*fs.File, error) e.srfd = srfd e.Init() - ep := transport.NewExternal(e.stype, uniqueid.GlobalProviderFromContext(ctx), &q, e, e) + ep := transport.NewExternal(ctx, e.stype, uniqueid.GlobalProviderFromContext(ctx), &q, e, e) return unixsocket.New(ctx, ep, e.stype), nil } diff --git a/pkg/sentry/fs/inode.go b/pkg/sentry/fs/inode.go index a19744ab1..a889586aa 100644 --- a/pkg/sentry/fs/inode.go +++ b/pkg/sentry/fs/inode.go @@ -76,7 +76,7 @@ type LockCtx struct { // NewInode constructs an Inode from InodeOperations, a MountSource, and stable attributes. // // NewInode takes a reference on msrc. -func NewInode(iops InodeOperations, msrc *MountSource, sattr StableAttr) *Inode { +func NewInode(ctx context.Context, iops InodeOperations, msrc *MountSource, sattr StableAttr) *Inode { msrc.IncRef() return &Inode{ InodeOperations: iops, diff --git a/pkg/sentry/fs/inode_overlay.go b/pkg/sentry/fs/inode_overlay.go index 805187f60..57b8b14e3 100644 --- a/pkg/sentry/fs/inode_overlay.go +++ b/pkg/sentry/fs/inode_overlay.go @@ -111,7 +111,7 @@ func overlayLookup(ctx context.Context, parent *overlayEntry, inode *Inode, name parent.copyMu.RUnlock() return nil, false, err } - d, err := NewDirent(newOverlayInode(ctx, entry, inode.MountSource), name), nil + d, err := NewDirent(ctx, newOverlayInode(ctx, entry, inode.MountSource), name), nil parent.copyMu.RUnlock() return d, true, err } @@ -201,7 +201,7 @@ func overlayLookup(ctx context.Context, parent *overlayEntry, inode *Inode, name parent.copyMu.RUnlock() return nil, false, err } - d, err := NewDirent(newOverlayInode(ctx, entry, inode.MountSource), name), nil + d, err := NewDirent(ctx, newOverlayInode(ctx, entry, inode.MountSource), name), nil parent.copyMu.RUnlock() return d, upperInode != nil, err } @@ -245,7 +245,7 @@ func overlayCreate(ctx context.Context, o *overlayEntry, parent *Dirent, name st // overlay file. overlayInode := newOverlayInode(ctx, entry, parent.Inode.MountSource) // d will own the inode reference. - overlayDirent := NewDirent(overlayInode, name) + overlayDirent := NewDirent(ctx, overlayInode, name) // The overlay file created below with NewFile will take a reference on // the overlayDirent, and it should be the only thing holding a // reference at the time of creation, so we must drop this reference. @@ -422,7 +422,7 @@ func overlayBind(ctx context.Context, o *overlayEntry, parent *Dirent, name stri inode.DecRef() return nil, err } - return NewDirent(newOverlayInode(ctx, entry, inode.MountSource), name), nil + return NewDirent(ctx, newOverlayInode(ctx, entry, inode.MountSource), name), nil } func overlayBoundEndpoint(o *overlayEntry, path string) transport.BoundEndpoint { @@ -648,13 +648,13 @@ func NewTestOverlayDir(ctx context.Context, upper, lower *Inode, revalidate bool fs := &overlayFilesystem{} var upperMsrc *MountSource if revalidate { - upperMsrc = NewRevalidatingMountSource(fs, MountSourceFlags{}) + upperMsrc = NewRevalidatingMountSource(ctx, fs, MountSourceFlags{}) } else { - upperMsrc = NewNonCachingMountSource(fs, MountSourceFlags{}) + upperMsrc = NewNonCachingMountSource(ctx, fs, MountSourceFlags{}) } - msrc := NewMountSource(&overlayMountSourceOperations{ + msrc := NewMountSource(ctx, &overlayMountSourceOperations{ upper: upperMsrc, - lower: NewNonCachingMountSource(fs, MountSourceFlags{}), + lower: NewNonCachingMountSource(ctx, fs, MountSourceFlags{}), }, fs, MountSourceFlags{}) overlay := &overlayEntry{ upper: upper, diff --git a/pkg/sentry/fs/mock.go b/pkg/sentry/fs/mock.go index c4e12acfe..b3c4ad80b 100644 --- a/pkg/sentry/fs/mock.go +++ b/pkg/sentry/fs/mock.go @@ -34,7 +34,7 @@ type MockInodeOperations struct { // NewMockInode returns a mock *Inode using MockInodeOperations. func NewMockInode(ctx context.Context, msrc *MountSource, sattr StableAttr) *Inode { - return NewInode(NewMockInodeOperations(ctx), msrc, sattr) + return NewInode(ctx, NewMockInodeOperations(ctx), msrc, sattr) } // NewMockInodeOperations returns a *MockInodeOperations. @@ -93,7 +93,7 @@ func (n *MockInodeOperations) IsVirtual() bool { // Lookup implements fs.InodeOperations.Lookup. func (n *MockInodeOperations) Lookup(ctx context.Context, dir *Inode, p string) (*Dirent, error) { n.walkCalled = true - return NewDirent(NewInode(&MockInodeOperations{}, dir.MountSource, StableAttr{}), p), nil + return NewDirent(ctx, NewInode(ctx, &MockInodeOperations{}, dir.MountSource, StableAttr{}), p), nil } // SetPermissions implements fs.InodeOperations.SetPermissions. @@ -114,7 +114,7 @@ func (n *MockInodeOperations) SetTimestamps(context.Context, *Inode, TimeSpec) e // Create implements fs.InodeOperations.Create. func (n *MockInodeOperations) Create(ctx context.Context, dir *Inode, p string, flags FileFlags, perms FilePermissions) (*File, error) { n.createCalled = true - d := NewDirent(NewInode(&MockInodeOperations{}, dir.MountSource, StableAttr{}), p) + d := NewDirent(ctx, NewInode(ctx, &MockInodeOperations{}, dir.MountSource, StableAttr{}), p) return &File{Dirent: d}, nil } diff --git a/pkg/sentry/fs/mount.go b/pkg/sentry/fs/mount.go index ae9a4279a..2eb6a9d82 100644 --- a/pkg/sentry/fs/mount.go +++ b/pkg/sentry/fs/mount.go @@ -127,7 +127,7 @@ const DefaultDirentCacheSize uint64 = 1000 // NewMountSource returns a new MountSource. Filesystem may be nil if there is no // filesystem backing the mount. -func NewMountSource(mops MountSourceOperations, filesystem Filesystem, flags MountSourceFlags) *MountSource { +func NewMountSource(ctx context.Context, mops MountSourceOperations, filesystem Filesystem, flags MountSourceFlags) *MountSource { fsType := "none" if filesystem != nil { fsType = filesystem.Name() @@ -188,16 +188,16 @@ func (msrc *MountSource) SetDirentCacheLimiter(l *DirentCacheLimiter) { // NewCachingMountSource returns a generic mount that will cache dirents // aggressively. -func NewCachingMountSource(filesystem Filesystem, flags MountSourceFlags) *MountSource { - return NewMountSource(&SimpleMountSourceOperations{ +func NewCachingMountSource(ctx context.Context, filesystem Filesystem, flags MountSourceFlags) *MountSource { + return NewMountSource(ctx, &SimpleMountSourceOperations{ keep: true, revalidate: false, }, filesystem, flags) } // NewNonCachingMountSource returns a generic mount that will never cache dirents. -func NewNonCachingMountSource(filesystem Filesystem, flags MountSourceFlags) *MountSource { - return NewMountSource(&SimpleMountSourceOperations{ +func NewNonCachingMountSource(ctx context.Context, filesystem Filesystem, flags MountSourceFlags) *MountSource { + return NewMountSource(ctx, &SimpleMountSourceOperations{ keep: false, revalidate: false, }, filesystem, flags) @@ -205,8 +205,8 @@ func NewNonCachingMountSource(filesystem Filesystem, flags MountSourceFlags) *Mo // NewRevalidatingMountSource returns a generic mount that will cache dirents, // but will revalidate them on each lookup. -func NewRevalidatingMountSource(filesystem Filesystem, flags MountSourceFlags) *MountSource { - return NewMountSource(&SimpleMountSourceOperations{ +func NewRevalidatingMountSource(ctx context.Context, filesystem Filesystem, flags MountSourceFlags) *MountSource { + return NewMountSource(ctx, &SimpleMountSourceOperations{ keep: true, revalidate: true, }, filesystem, flags) @@ -214,8 +214,8 @@ func NewRevalidatingMountSource(filesystem Filesystem, flags MountSourceFlags) * // NewPseudoMountSource returns a "pseudo" mount source that is not backed by // an actual filesystem. It is always non-caching. -func NewPseudoMountSource() *MountSource { - return NewMountSource(&SimpleMountSourceOperations{ +func NewPseudoMountSource(ctx context.Context) *MountSource { + return NewMountSource(ctx, &SimpleMountSourceOperations{ keep: false, revalidate: false, }, nil, MountSourceFlags{}) diff --git a/pkg/sentry/fs/mount_overlay.go b/pkg/sentry/fs/mount_overlay.go index cb413e8dc..bc0ce7adc 100644 --- a/pkg/sentry/fs/mount_overlay.go +++ b/pkg/sentry/fs/mount_overlay.go @@ -28,10 +28,10 @@ type overlayMountSourceOperations struct { lower *MountSource } -func newOverlayMountSource(upper, lower *MountSource, flags MountSourceFlags) *MountSource { +func newOverlayMountSource(ctx context.Context, upper, lower *MountSource, flags MountSourceFlags) *MountSource { upper.IncRef() lower.IncRef() - msrc := NewMountSource(&overlayMountSourceOperations{ + msrc := NewMountSource(ctx, &overlayMountSourceOperations{ upper: upper, lower: lower, }, &overlayFilesystem{}, flags) diff --git a/pkg/sentry/fs/mounts.go b/pkg/sentry/fs/mounts.go index c15d76e90..a5d6f8b9a 100644 --- a/pkg/sentry/fs/mounts.go +++ b/pkg/sentry/fs/mounts.go @@ -166,7 +166,7 @@ func NewMountNamespace(ctx context.Context, root *Inode) (*MountNamespace, error // Set the root dirent and id on the root mount. The reference returned from // NewDirent will be donated to the MountNamespace constructed below. - d := NewDirent(root, "/") + d := NewDirent(ctx, root, "/") mnts := map[*Dirent]*Mount{ d: newRootMount(1, d), diff --git a/pkg/sentry/fs/overlay.go b/pkg/sentry/fs/overlay.go index 0ad11131c..c87f24997 100644 --- a/pkg/sentry/fs/overlay.go +++ b/pkg/sentry/fs/overlay.go @@ -104,7 +104,7 @@ func NewOverlayRoot(ctx context.Context, upper *Inode, lower *Inode, flags Mount return nil, fmt.Errorf("cannot nest overlay in upper file of another overlay") } - msrc := newOverlayMountSource(upper.MountSource, lower.MountSource, flags) + msrc := newOverlayMountSource(ctx, upper.MountSource, lower.MountSource, flags) overlay, err := newOverlayEntry(ctx, upper, lower, true) if err != nil { msrc.DecRef() @@ -127,7 +127,7 @@ func NewOverlayRootFile(ctx context.Context, upperMS *MountSource, lower *Inode, if !IsRegular(lower.StableAttr) { return nil, fmt.Errorf("lower Inode is not a regular file") } - msrc := newOverlayMountSource(upperMS, lower.MountSource, flags) + msrc := newOverlayMountSource(ctx, upperMS, lower.MountSource, flags) overlay, err := newOverlayEntry(ctx, nil, lower, true) if err != nil { msrc.DecRef() @@ -140,9 +140,9 @@ func NewOverlayRootFile(ctx context.Context, upperMS *MountSource, lower *Inode, func newOverlayInode(ctx context.Context, o *overlayEntry, msrc *MountSource) *Inode { var inode *Inode if o.upper != nil { - inode = NewInode(nil, msrc, o.upper.StableAttr) + inode = NewInode(ctx, nil, msrc, o.upper.StableAttr) } else { - inode = NewInode(nil, msrc, o.lower.StableAttr) + inode = NewInode(ctx, nil, msrc, o.lower.StableAttr) } inode.overlay = o return inode diff --git a/pkg/sentry/fs/proc/exec_args.go b/pkg/sentry/fs/proc/exec_args.go index 9de0177e8..1d3a2d426 100644 --- a/pkg/sentry/fs/proc/exec_args.go +++ b/pkg/sentry/fs/proc/exec_args.go @@ -64,7 +64,7 @@ func newExecArgInode(t *kernel.Task, msrc *fs.MountSource, arg execArgType) *fs. arg: arg, t: t, } - return newProcInode(f, msrc, fs.SpecialFile, t) + return newProcInode(t, f, msrc, fs.SpecialFile, t) } // GetFile implements fs.InodeOperations.GetFile. diff --git a/pkg/sentry/fs/proc/fds.go b/pkg/sentry/fs/proc/fds.go index 1e4e72b87..ea7aded9a 100644 --- a/pkg/sentry/fs/proc/fds.go +++ b/pkg/sentry/fs/proc/fds.go @@ -105,7 +105,7 @@ func newFd(t *kernel.Task, f *fs.File, msrc *fs.MountSource) *fs.Inode { Symlink: *ramfs.NewSymlink(t, fs.RootOwner, ""), file: f, } - return newProcInode(fd, msrc, fs.Symlink, t) + return newProcInode(t, fd, msrc, fs.Symlink, t) } // GetFile returns the fs.File backing this fd. The dirent and flags @@ -168,7 +168,7 @@ func newFdDir(t *kernel.Task, msrc *fs.MountSource) *fs.Inode { Dir: *ramfs.NewDir(t, nil, fs.RootOwner, fs.FilePermissions{User: fs.PermMask{Read: true, Execute: true}}), t: t, } - return newProcInode(f, msrc, fs.SpecialDirectory, t) + return newProcInode(t, f, msrc, fs.SpecialDirectory, t) } // Check implements InodeOperations.Check. @@ -198,7 +198,7 @@ func (f *fdDir) Lookup(ctx context.Context, dir *fs.Inode, p string) (*fs.Dirent if err != nil { return nil, err } - return fs.NewDirent(n, p), nil + return fs.NewDirent(ctx, n, p), nil } // GetFile implements fs.FileOperations.GetFile. @@ -252,7 +252,7 @@ func newFdInfoDir(t *kernel.Task, msrc *fs.MountSource) *fs.Inode { Dir: *ramfs.NewDir(t, nil, fs.RootOwner, fs.FilePermsFromMode(0500)), t: t, } - return newProcInode(fdid, msrc, fs.SpecialDirectory, t) + return newProcInode(t, fdid, msrc, fs.SpecialDirectory, t) } // Lookup loads an fd in /proc/TID/fdinfo into a Dirent. @@ -272,7 +272,7 @@ func (fdid *fdInfoDir) Lookup(ctx context.Context, dir *fs.Inode, p string) (*fs if err != nil { return nil, err } - return fs.NewDirent(inode, p), nil + return fs.NewDirent(ctx, inode, p), nil } // GetFile implements fs.FileOperations.GetFile. diff --git a/pkg/sentry/fs/proc/fs.go b/pkg/sentry/fs/proc/fs.go index f4ac4949a..715591ae5 100644 --- a/pkg/sentry/fs/proc/fs.go +++ b/pkg/sentry/fs/proc/fs.go @@ -77,5 +77,5 @@ func (f *filesystem) Mount(ctx context.Context, device string, flags fs.MountSou // Construct the procfs root. Since procfs files are all virtual, we // never want them cached. - return New(ctx, fs.NewNonCachingMountSource(f, flags), cgroups) + return New(ctx, fs.NewNonCachingMountSource(ctx, f, flags), cgroups) } diff --git a/pkg/sentry/fs/proc/inode.go b/pkg/sentry/fs/proc/inode.go index 1d81488cd..0c04f81fa 100644 --- a/pkg/sentry/fs/proc/inode.go +++ b/pkg/sentry/fs/proc/inode.go @@ -115,11 +115,11 @@ func newStaticProcInode(ctx context.Context, msrc *fs.MountSource, contents []by Contents: contents, }, } - return newProcInode(iops, msrc, fs.SpecialFile, nil) + return newProcInode(ctx, iops, msrc, fs.SpecialFile, nil) } // newProcInode creates a new inode from the given inode operations. -func newProcInode(iops fs.InodeOperations, msrc *fs.MountSource, typ fs.InodeType, t *kernel.Task) *fs.Inode { +func newProcInode(ctx context.Context, iops fs.InodeOperations, msrc *fs.MountSource, typ fs.InodeType, t *kernel.Task) *fs.Inode { sattr := fs.StableAttr{ DeviceID: device.ProcDevice.DeviceID(), InodeID: device.ProcDevice.NextIno(), @@ -129,5 +129,5 @@ func newProcInode(iops fs.InodeOperations, msrc *fs.MountSource, typ fs.InodeTyp if t != nil { iops = &taskOwnedInodeOps{iops, t} } - return fs.NewInode(iops, msrc, sattr) + return fs.NewInode(ctx, iops, msrc, sattr) } diff --git a/pkg/sentry/fs/proc/net.go b/pkg/sentry/fs/proc/net.go index cbc8f4dbf..caa1a5c4d 100644 --- a/pkg/sentry/fs/proc/net.go +++ b/pkg/sentry/fs/proc/net.go @@ -70,7 +70,7 @@ func (p *proc) newNetDir(ctx context.Context, k *kernel.Kernel, msrc *fs.MountSo } } d := ramfs.NewDir(ctx, contents, fs.RootOwner, fs.FilePermsFromMode(0555)) - return newProcInode(d, msrc, fs.SpecialDirectory, nil) + return newProcInode(ctx, d, msrc, fs.SpecialDirectory, nil) } // ifinet6 implements seqfile.SeqSource for /proc/net/if_inet6. diff --git a/pkg/sentry/fs/proc/proc.go b/pkg/sentry/fs/proc/proc.go index 170e2af4f..0ef13f2f5 100644 --- a/pkg/sentry/fs/proc/proc.go +++ b/pkg/sentry/fs/proc/proc.go @@ -68,7 +68,7 @@ func New(ctx context.Context, msrc *fs.MountSource, cgroupControllers map[string "filesystems": seqfile.NewSeqFileInode(ctx, &filesystemsData{}, msrc), "loadavg": seqfile.NewSeqFileInode(ctx, &loadavgData{}, msrc), "meminfo": seqfile.NewSeqFileInode(ctx, &meminfoData{k}, msrc), - "mounts": newProcInode(ramfs.NewSymlink(ctx, fs.RootOwner, "self/mounts"), msrc, fs.Symlink, nil), + "mounts": newProcInode(ctx, ramfs.NewSymlink(ctx, fs.RootOwner, "self/mounts"), msrc, fs.Symlink, nil), "self": newSelf(ctx, pidns, msrc), "stat": seqfile.NewSeqFileInode(ctx, &statData{k}, msrc), "thread-self": newThreadSelf(ctx, pidns, msrc), @@ -94,7 +94,7 @@ func New(ctx context.Context, msrc *fs.MountSource, cgroupControllers map[string p.AddChild(ctx, "net", p.newNetDir(ctx, k, msrc)) } - return newProcInode(p, msrc, fs.SpecialDirectory, nil), nil + return newProcInode(ctx, p, msrc, fs.SpecialDirectory, nil), nil } // self is a magical link. @@ -112,7 +112,7 @@ func newSelf(ctx context.Context, pidns *kernel.PIDNamespace, msrc *fs.MountSour Symlink: *ramfs.NewSymlink(ctx, fs.RootOwner, ""), pidns: pidns, } - return newProcInode(s, msrc, fs.Symlink, nil) + return newProcInode(ctx, s, msrc, fs.Symlink, nil) } // newThreadSelf returns a new "threadSelf" node. @@ -121,7 +121,7 @@ func newThreadSelf(ctx context.Context, pidns *kernel.PIDNamespace, msrc *fs.Mou Symlink: *ramfs.NewSymlink(ctx, fs.RootOwner, ""), pidns: pidns, } - return newProcInode(s, msrc, fs.Symlink, nil) + return newProcInode(ctx, s, msrc, fs.Symlink, nil) } // Readlink implements fs.InodeOperations.Readlink. @@ -185,7 +185,7 @@ func (p *proc) Lookup(ctx context.Context, dir *fs.Inode, name string) (*fs.Dire // Wrap it in a taskDir. td := p.newTaskDir(otherTask, dir.MountSource, true) - return fs.NewDirent(td, name), nil + return fs.NewDirent(ctx, td, name), nil } // GetFile implements fs.InodeOperations. diff --git a/pkg/sentry/fs/proc/rpcinet_proc.go b/pkg/sentry/fs/proc/rpcinet_proc.go index d37a83501..c1405a746 100644 --- a/pkg/sentry/fs/proc/rpcinet_proc.go +++ b/pkg/sentry/fs/proc/rpcinet_proc.go @@ -45,7 +45,7 @@ func newRPCInetInode(ctx context.Context, msrc *fs.MountSource, filepath string, filepath: filepath, k: kernel.KernelFromContext(ctx), } - return newProcInode(f, msrc, fs.SpecialFile, nil) + return newProcInode(ctx, f, msrc, fs.SpecialFile, nil) } // GetFile implements fs.InodeOperations.GetFile. @@ -141,7 +141,7 @@ func newRPCInetProcNet(ctx context.Context, msrc *fs.MountSource) *fs.Inode { } d := ramfs.NewDir(ctx, contents, fs.RootOwner, fs.FilePermsFromMode(0555)) - return newProcInode(d, msrc, fs.SpecialDirectory, nil) + return newProcInode(ctx, d, msrc, fs.SpecialDirectory, nil) } // newRPCInetProcSysNet will build an inode for /proc/sys/net. @@ -152,7 +152,7 @@ func newRPCInetProcSysNet(ctx context.Context, msrc *fs.MountSource) *fs.Inode { } d := ramfs.NewDir(ctx, contents, fs.RootOwner, fs.FilePermsFromMode(0555)) - return newProcInode(d, msrc, fs.SpecialDirectory, nil) + return newProcInode(ctx, d, msrc, fs.SpecialDirectory, nil) } // newRPCInetSysNetCore builds the /proc/sys/net/core directory. @@ -170,7 +170,7 @@ func newRPCInetSysNetCore(ctx context.Context, msrc *fs.MountSource) *fs.Inode { } d := ramfs.NewDir(ctx, contents, fs.RootOwner, fs.FilePermsFromMode(0555)) - return newProcInode(d, msrc, fs.SpecialDirectory, nil) + return newProcInode(ctx, d, msrc, fs.SpecialDirectory, nil) } // newRPCInetSysNetIPv4Dir builds the /proc/sys/net/ipv4 directory. @@ -213,5 +213,5 @@ func newRPCInetSysNetIPv4Dir(ctx context.Context, msrc *fs.MountSource) *fs.Inod } d := ramfs.NewDir(ctx, contents, fs.RootOwner, fs.FilePermsFromMode(0555)) - return newProcInode(d, msrc, fs.SpecialDirectory, nil) + return newProcInode(ctx, d, msrc, fs.SpecialDirectory, nil) } diff --git a/pkg/sentry/fs/proc/seqfile/seqfile.go b/pkg/sentry/fs/proc/seqfile/seqfile.go index 8ee7f5fa5..d5590e2d3 100644 --- a/pkg/sentry/fs/proc/seqfile/seqfile.go +++ b/pkg/sentry/fs/proc/seqfile/seqfile.go @@ -133,7 +133,7 @@ func NewSeqFileInode(ctx context.Context, source SeqSource, msrc *fs.MountSource BlockSize: usermem.PageSize, Type: fs.SpecialFile, } - return fs.NewInode(iops, msrc, sattr) + return fs.NewInode(ctx, iops, msrc, sattr) } // UnstableAttr returns unstable attributes of the SeqFile. diff --git a/pkg/sentry/fs/proc/sys.go b/pkg/sentry/fs/proc/sys.go index 4288b9a36..cd37776c8 100644 --- a/pkg/sentry/fs/proc/sys.go +++ b/pkg/sentry/fs/proc/sys.go @@ -82,14 +82,14 @@ func (p *proc) newKernelDir(ctx context.Context, msrc *fs.MountSource) *fs.Inode } children := map[string]*fs.Inode{ - "hostname": newProcInode(&h, msrc, fs.SpecialFile, nil), + "hostname": newProcInode(ctx, &h, msrc, fs.SpecialFile, nil), "shmall": newStaticProcInode(ctx, msrc, []byte(strconv.FormatUint(linux.SHMALL, 10))), "shmmax": newStaticProcInode(ctx, msrc, []byte(strconv.FormatUint(linux.SHMMAX, 10))), "shmmni": newStaticProcInode(ctx, msrc, []byte(strconv.FormatUint(linux.SHMMNI, 10))), } d := ramfs.NewDir(ctx, children, fs.RootOwner, fs.FilePermsFromMode(0555)) - return newProcInode(d, msrc, fs.SpecialDirectory, nil) + return newProcInode(ctx, d, msrc, fs.SpecialDirectory, nil) } func (p *proc) newVMDir(ctx context.Context, msrc *fs.MountSource) *fs.Inode { @@ -98,7 +98,7 @@ func (p *proc) newVMDir(ctx context.Context, msrc *fs.MountSource) *fs.Inode { "overcommit_memory": seqfile.NewSeqFileInode(ctx, &overcommitMemory{}, msrc), } d := ramfs.NewDir(ctx, children, fs.RootOwner, fs.FilePermsFromMode(0555)) - return newProcInode(d, msrc, fs.SpecialDirectory, nil) + return newProcInode(ctx, d, msrc, fs.SpecialDirectory, nil) } func (p *proc) newSysDir(ctx context.Context, msrc *fs.MountSource) *fs.Inode { @@ -115,7 +115,7 @@ func (p *proc) newSysDir(ctx context.Context, msrc *fs.MountSource) *fs.Inode { } d := ramfs.NewDir(ctx, children, fs.RootOwner, fs.FilePermsFromMode(0555)) - return newProcInode(d, msrc, fs.SpecialDirectory, nil) + return newProcInode(ctx, d, msrc, fs.SpecialDirectory, nil) } // hostname is the inode for a file containing the system hostname. diff --git a/pkg/sentry/fs/proc/sys_net.go b/pkg/sentry/fs/proc/sys_net.go index 7e05240f8..f3b63dfc2 100644 --- a/pkg/sentry/fs/proc/sys_net.go +++ b/pkg/sentry/fs/proc/sys_net.go @@ -74,7 +74,7 @@ func newTCPMemInode(ctx context.Context, msrc *fs.MountSource, s inet.Stack, dir BlockSize: usermem.PageSize, Type: fs.SpecialFile, } - return fs.NewInode(tm, msrc, sattr) + return fs.NewInode(ctx, tm, msrc, sattr) } // GetFile implements fs.InodeOperations.GetFile. @@ -184,7 +184,7 @@ func newTCPSackInode(ctx context.Context, msrc *fs.MountSource, s inet.Stack) *f BlockSize: usermem.PageSize, Type: fs.SpecialFile, } - return fs.NewInode(ts, msrc, sattr) + return fs.NewInode(ctx, ts, msrc, sattr) } // GetFile implements fs.InodeOperations.GetFile. @@ -277,7 +277,7 @@ func (p *proc) newSysNetCore(ctx context.Context, msrc *fs.MountSource, s inet.S } d := ramfs.NewDir(ctx, contents, fs.RootOwner, fs.FilePermsFromMode(0555)) - return newProcInode(d, msrc, fs.SpecialDirectory, nil) + return newProcInode(ctx, d, msrc, fs.SpecialDirectory, nil) } func (p *proc) newSysNetIPv4Dir(ctx context.Context, msrc *fs.MountSource, s inet.Stack) *fs.Inode { @@ -339,7 +339,7 @@ func (p *proc) newSysNetIPv4Dir(ctx context.Context, msrc *fs.MountSource, s ine } d := ramfs.NewDir(ctx, contents, fs.RootOwner, fs.FilePermsFromMode(0555)) - return newProcInode(d, msrc, fs.SpecialDirectory, nil) + return newProcInode(ctx, d, msrc, fs.SpecialDirectory, nil) } func (p *proc) newSysNetDir(ctx context.Context, msrc *fs.MountSource) *fs.Inode { @@ -351,5 +351,5 @@ func (p *proc) newSysNetDir(ctx context.Context, msrc *fs.MountSource) *fs.Inode } } d := ramfs.NewDir(ctx, contents, fs.RootOwner, fs.FilePermsFromMode(0555)) - return newProcInode(d, msrc, fs.SpecialDirectory, nil) + return newProcInode(ctx, d, msrc, fs.SpecialDirectory, nil) } diff --git a/pkg/sentry/fs/proc/task.go b/pkg/sentry/fs/proc/task.go index 412c0204a..b2e36aeee 100644 --- a/pkg/sentry/fs/proc/task.go +++ b/pkg/sentry/fs/proc/task.go @@ -101,7 +101,7 @@ func (p *proc) newTaskDir(t *kernel.Task, msrc *fs.MountSource, showSubtasks boo Dir: *ramfs.NewDir(t, contents, fs.RootOwner, fs.FilePermsFromMode(0555)), t: t, } - return newProcInode(d, msrc, fs.SpecialDirectory, t) + return newProcInode(t, d, msrc, fs.SpecialDirectory, t) } // subtasks represents a /proc/TID/task directory. @@ -122,7 +122,7 @@ func (p *proc) newSubtasks(t *kernel.Task, msrc *fs.MountSource) *fs.Inode { t: t, p: p, } - return newProcInode(s, msrc, fs.SpecialDirectory, t) + return newProcInode(t, s, msrc, fs.SpecialDirectory, t) } // UnstableAttr returns unstable attributes of the subtasks. @@ -223,7 +223,7 @@ func (s *subtasks) Lookup(ctx context.Context, dir *fs.Inode, p string) (*fs.Dir } td := s.p.newTaskDir(task, dir.MountSource, false) - return fs.NewDirent(td, p), nil + return fs.NewDirent(ctx, td, p), nil } // exe is an fs.InodeOperations symlink for the /proc/PID/exe file. @@ -240,7 +240,7 @@ func newExe(t *kernel.Task, msrc *fs.MountSource) *fs.Inode { Symlink: *ramfs.NewSymlink(t, fs.RootOwner, ""), t: t, } - return newProcInode(exeSymlink, msrc, fs.Symlink, t) + return newProcInode(t, exeSymlink, msrc, fs.Symlink, t) } func (e *exe) executable() (d *fs.Dirent, err error) { @@ -308,7 +308,7 @@ func newNamespaceSymlink(t *kernel.Task, msrc *fs.MountSource, name string) *fs. Symlink: *ramfs.NewSymlink(t, fs.RootOwner, target), t: t, } - return newProcInode(n, msrc, fs.Symlink, t) + return newProcInode(t, n, msrc, fs.Symlink, t) } // Getlink implements fs.InodeOperations.Getlink. @@ -319,7 +319,7 @@ func (n *namespaceSymlink) Getlink(ctx context.Context, inode *fs.Inode) (*fs.Di // Create a new regular file to fake the namespace file. iops := fsutil.NewNoReadWriteFileInode(ctx, fs.RootOwner, fs.FilePermsFromMode(0777), linux.PROC_SUPER_MAGIC) - return fs.NewDirent(newProcInode(iops, inode.MountSource, fs.RegularFile, nil), n.Symlink.Target), nil + return fs.NewDirent(ctx, newProcInode(ctx, iops, inode.MountSource, fs.RegularFile, nil), n.Symlink.Target), nil } func newNamespaceDir(t *kernel.Task, msrc *fs.MountSource) *fs.Inode { @@ -329,7 +329,7 @@ func newNamespaceDir(t *kernel.Task, msrc *fs.MountSource) *fs.Inode { "user": newNamespaceSymlink(t, msrc, "user"), } d := ramfs.NewDir(t, contents, fs.RootOwner, fs.FilePermsFromMode(0511)) - return newProcInode(d, msrc, fs.SpecialDirectory, t) + return newProcInode(t, d, msrc, fs.SpecialDirectory, t) } // mapsData implements seqfile.SeqSource for /proc/[pid]/maps. @@ -340,7 +340,7 @@ type mapsData struct { } func newMaps(t *kernel.Task, msrc *fs.MountSource) *fs.Inode { - return newProcInode(seqfile.NewSeqFile(t, &mapsData{t}), msrc, fs.SpecialFile, t) + return newProcInode(t, seqfile.NewSeqFile(t, &mapsData{t}), msrc, fs.SpecialFile, t) } func (md *mapsData) mm() *mm.MemoryManager { @@ -380,7 +380,7 @@ type smapsData struct { } func newSmaps(t *kernel.Task, msrc *fs.MountSource) *fs.Inode { - return newProcInode(seqfile.NewSeqFile(t, &smapsData{t}), msrc, fs.SpecialFile, t) + return newProcInode(t, seqfile.NewSeqFile(t, &smapsData{t}), msrc, fs.SpecialFile, t) } func (sd *smapsData) mm() *mm.MemoryManager { @@ -426,7 +426,7 @@ type taskStatData struct { } func newTaskStat(t *kernel.Task, msrc *fs.MountSource, showSubtasks bool, pidns *kernel.PIDNamespace) *fs.Inode { - return newProcInode(seqfile.NewSeqFile(t, &taskStatData{t, showSubtasks /* tgstats */, pidns}), msrc, fs.SpecialFile, t) + return newProcInode(t, seqfile.NewSeqFile(t, &taskStatData{t, showSubtasks /* tgstats */, pidns}), msrc, fs.SpecialFile, t) } // NeedsUpdate returns whether the generation is old or not. @@ -511,7 +511,7 @@ type statmData struct { } func newStatm(t *kernel.Task, msrc *fs.MountSource) *fs.Inode { - return newProcInode(seqfile.NewSeqFile(t, &statmData{t}), msrc, fs.SpecialFile, t) + return newProcInode(t, seqfile.NewSeqFile(t, &statmData{t}), msrc, fs.SpecialFile, t) } // NeedsUpdate implements seqfile.SeqSource.NeedsUpdate. @@ -548,7 +548,7 @@ type statusData struct { } func newStatus(t *kernel.Task, msrc *fs.MountSource, pidns *kernel.PIDNamespace) *fs.Inode { - return newProcInode(seqfile.NewSeqFile(t, &statusData{t, pidns}), msrc, fs.SpecialFile, t) + return newProcInode(t, seqfile.NewSeqFile(t, &statusData{t, pidns}), msrc, fs.SpecialFile, t) } // NeedsUpdate implements seqfile.SeqSource.NeedsUpdate. @@ -615,7 +615,7 @@ type ioData struct { } func newIO(t *kernel.Task, msrc *fs.MountSource) *fs.Inode { - return newProcInode(seqfile.NewSeqFile(t, &ioData{t.ThreadGroup()}), msrc, fs.SpecialFile, t) + return newProcInode(t, seqfile.NewSeqFile(t, &ioData{t.ThreadGroup()}), msrc, fs.SpecialFile, t) } // NeedsUpdate returns whether the generation is old or not. @@ -664,7 +664,7 @@ func newComm(t *kernel.Task, msrc *fs.MountSource) *fs.Inode { SimpleFileInode: *fsutil.NewSimpleFileInode(t, fs.RootOwner, fs.FilePermsFromMode(0444), linux.PROC_SUPER_MAGIC), t: t, } - return newProcInode(c, msrc, fs.SpecialFile, t) + return newProcInode(t, c, msrc, fs.SpecialFile, t) } // Check implements fs.InodeOperations.Check. @@ -736,7 +736,7 @@ func newAuxvec(t *kernel.Task, msrc *fs.MountSource) *fs.Inode { SimpleFileInode: *fsutil.NewSimpleFileInode(t, fs.RootOwner, fs.FilePermsFromMode(0444), linux.PROC_SUPER_MAGIC), t: t, } - return newProcInode(a, msrc, fs.SpecialFile, t) + return newProcInode(t, a, msrc, fs.SpecialFile, t) } // GetFile implements fs.InodeOperations.GetFile. diff --git a/pkg/sentry/fs/proc/uid_gid_map.go b/pkg/sentry/fs/proc/uid_gid_map.go index d734a48f4..eea37d15c 100644 --- a/pkg/sentry/fs/proc/uid_gid_map.go +++ b/pkg/sentry/fs/proc/uid_gid_map.go @@ -66,7 +66,7 @@ func newGIDMap(t *kernel.Task, msrc *fs.MountSource) *fs.Inode { } func newIDMap(t *kernel.Task, msrc *fs.MountSource, gids bool) *fs.Inode { - return newProcInode(&idMapInodeOperations{ + return newProcInode(t, &idMapInodeOperations{ InodeSimpleAttributes: fsutil.NewInodeSimpleAttributes(t, fs.RootOwner, fs.FilePermsFromMode(0644), linux.PROC_SUPER_MAGIC), t: t, gids: gids, diff --git a/pkg/sentry/fs/proc/uptime.go b/pkg/sentry/fs/proc/uptime.go index 37e9ae379..4e903917a 100644 --- a/pkg/sentry/fs/proc/uptime.go +++ b/pkg/sentry/fs/proc/uptime.go @@ -44,7 +44,7 @@ func newUptime(ctx context.Context, msrc *fs.MountSource) *fs.Inode { SimpleFileInode: *fsutil.NewSimpleFileInode(ctx, fs.RootOwner, fs.FilePermsFromMode(0444), linux.PROC_SUPER_MAGIC), startTime: ktime.NowFromContext(ctx), } - return newProcInode(u, msrc, fs.SpecialFile, nil) + return newProcInode(ctx, u, msrc, fs.SpecialFile, nil) } // GetFile implements fs.InodeOperations.GetFile. diff --git a/pkg/sentry/fs/ramfs/dir.go b/pkg/sentry/fs/ramfs/dir.go index b5da36c1c..db97f400b 100644 --- a/pkg/sentry/fs/ramfs/dir.go +++ b/pkg/sentry/fs/ramfs/dir.go @@ -269,7 +269,7 @@ func (d *Dir) Lookup(ctx context.Context, _ *fs.Inode, p string) (*fs.Dirent, er // Take a reference on the inode before returning it. This reference // is owned by the dirent we are about to create. inode.IncRef() - return fs.NewDirent(inode, p), nil + return fs.NewDirent(ctx, inode, p), nil } // walkLocked must be called with d.mu held. @@ -321,7 +321,7 @@ func (d *Dir) Create(ctx context.Context, dir *fs.Inode, name string, flags fs.F inode.IncRef() // Create the Dirent and corresponding file. - created := fs.NewDirent(inode, name) + created := fs.NewDirent(ctx, inode, name) defer created.DecRef() return created.Inode.GetFile(ctx, created, flags) } @@ -382,7 +382,7 @@ func (d *Dir) Bind(ctx context.Context, dir *fs.Inode, name string, ep transport } // Take another ref on inode which will be donated to the new dirent. inode.IncRef() - return fs.NewDirent(inode, name), nil + return fs.NewDirent(ctx, inode, name), nil } // CreateFifo implements fs.InodeOperations.CreateFifo. diff --git a/pkg/sentry/fs/ramfs/tree.go b/pkg/sentry/fs/ramfs/tree.go index 4d9deb174..702cc4a1e 100644 --- a/pkg/sentry/fs/ramfs/tree.go +++ b/pkg/sentry/fs/ramfs/tree.go @@ -68,7 +68,7 @@ func makeSubdir(ctx context.Context, msrc *fs.MountSource, root *Dir, subdir str // emptyDir returns an empty *ramfs.Dir with all permissions granted. func emptyDir(ctx context.Context, msrc *fs.MountSource) *fs.Inode { dir := NewDir(ctx, make(map[string]*fs.Inode), fs.RootOwner, fs.FilePermsFromMode(0777)) - return fs.NewInode(dir, msrc, fs.StableAttr{ + return fs.NewInode(ctx, dir, msrc, fs.StableAttr{ DeviceID: anon.PseudoDevice.DeviceID(), InodeID: anon.PseudoDevice.NextIno(), BlockSize: usermem.PageSize, diff --git a/pkg/sentry/fs/sys/devices.go b/pkg/sentry/fs/sys/devices.go index a6009ba8a..4f78ca8d2 100644 --- a/pkg/sentry/fs/sys/devices.go +++ b/pkg/sentry/fs/sys/devices.go @@ -58,7 +58,7 @@ func newPossible(ctx context.Context, msrc *fs.MountSource) *fs.Inode { Contents: contents, }, } - return newFile(c, msrc) + return newFile(ctx, c, msrc) } func newCPU(ctx context.Context, msrc *fs.MountSource) *fs.Inode { diff --git a/pkg/sentry/fs/sys/fs.go b/pkg/sentry/fs/sys/fs.go index 257048df5..b31c46bf9 100644 --- a/pkg/sentry/fs/sys/fs.go +++ b/pkg/sentry/fs/sys/fs.go @@ -61,5 +61,5 @@ func (f *filesystem) Mount(ctx context.Context, device string, flags fs.MountSou // device is always ignored. // sysfs ignores data, see fs/sysfs/mount.c:sysfs_mount. - return New(ctx, fs.NewNonCachingMountSource(f, flags)), nil + return New(ctx, fs.NewNonCachingMountSource(ctx, f, flags)), nil } diff --git a/pkg/sentry/fs/sys/sys.go b/pkg/sentry/fs/sys/sys.go index 9db41a1b8..b14bf3f55 100644 --- a/pkg/sentry/fs/sys/sys.go +++ b/pkg/sentry/fs/sys/sys.go @@ -22,19 +22,19 @@ import ( "gvisor.dev/gvisor/pkg/sentry/usermem" ) -func newFile(node fs.InodeOperations, msrc *fs.MountSource) *fs.Inode { +func newFile(ctx context.Context, node fs.InodeOperations, msrc *fs.MountSource) *fs.Inode { sattr := fs.StableAttr{ DeviceID: sysfsDevice.DeviceID(), InodeID: sysfsDevice.NextIno(), BlockSize: usermem.PageSize, Type: fs.SpecialFile, } - return fs.NewInode(node, msrc, sattr) + return fs.NewInode(ctx, node, msrc, sattr) } func newDir(ctx context.Context, msrc *fs.MountSource, contents map[string]*fs.Inode) *fs.Inode { d := ramfs.NewDir(ctx, contents, fs.RootOwner, fs.FilePermsFromMode(0555)) - return fs.NewInode(d, msrc, fs.StableAttr{ + return fs.NewInode(ctx, d, msrc, fs.StableAttr{ DeviceID: sysfsDevice.DeviceID(), InodeID: sysfsDevice.NextIno(), BlockSize: usermem.PageSize, diff --git a/pkg/sentry/fs/timerfd/timerfd.go b/pkg/sentry/fs/timerfd/timerfd.go index 704a846a4..59403d9db 100644 --- a/pkg/sentry/fs/timerfd/timerfd.go +++ b/pkg/sentry/fs/timerfd/timerfd.go @@ -53,7 +53,7 @@ type TimerOperations struct { // NewFile returns a timerfd File that receives time from c. func NewFile(ctx context.Context, c ktime.Clock) *fs.File { - dirent := fs.NewDirent(anon.NewInode(ctx), "anon_inode:[timerfd]") + dirent := fs.NewDirent(ctx, anon.NewInode(ctx), "anon_inode:[timerfd]") // Release the initial dirent reference after NewFile takes a reference. defer dirent.DecRef() tops := &TimerOperations{} diff --git a/pkg/sentry/fs/tmpfs/fs.go b/pkg/sentry/fs/tmpfs/fs.go index bfaf3cde3..a5fcdf969 100644 --- a/pkg/sentry/fs/tmpfs/fs.go +++ b/pkg/sentry/fs/tmpfs/fs.go @@ -136,9 +136,9 @@ func (f *Filesystem) Mount(ctx context.Context, device string, flags fs.MountSou var msrc *fs.MountSource switch options[cacheKey] { case "", cacheAll: - msrc = fs.NewCachingMountSource(f, flags) + msrc = fs.NewCachingMountSource(ctx, f, flags) case cacheRevalidate: - msrc = fs.NewRevalidatingMountSource(f, flags) + msrc = fs.NewRevalidatingMountSource(ctx, f, flags) default: return nil, fmt.Errorf("invalid cache policy option %q", options[cacheKey]) } diff --git a/pkg/sentry/fs/tmpfs/inode_file.go b/pkg/sentry/fs/tmpfs/inode_file.go index d20dce173..f86dfaa36 100644 --- a/pkg/sentry/fs/tmpfs/inode_file.go +++ b/pkg/sentry/fs/tmpfs/inode_file.go @@ -128,7 +128,7 @@ func NewMemfdInode(ctx context.Context, allowSeals bool) *fs.Inode { if allowSeals { iops.seals = 0 } - return fs.NewInode(iops, fs.NewNonCachingMountSource(nil, fs.MountSourceFlags{}), fs.StableAttr{ + return fs.NewInode(ctx, iops, fs.NewNonCachingMountSource(ctx, nil, fs.MountSourceFlags{}), fs.StableAttr{ Type: fs.RegularFile, DeviceID: tmpfsDevice.DeviceID(), InodeID: tmpfsDevice.NextIno(), diff --git a/pkg/sentry/fs/tmpfs/tmpfs.go b/pkg/sentry/fs/tmpfs/tmpfs.go index e8178c9dd..0f4497cd6 100644 --- a/pkg/sentry/fs/tmpfs/tmpfs.go +++ b/pkg/sentry/fs/tmpfs/tmpfs.go @@ -90,7 +90,7 @@ func NewDir(ctx context.Context, contents map[string]*fs.Inode, owner fs.FileOwn // Manually set the CreateOps. d.ramfsDir.CreateOps = d.newCreateOps() - return fs.NewInode(d, msrc, fs.StableAttr{ + return fs.NewInode(ctx, d, msrc, fs.StableAttr{ DeviceID: tmpfsDevice.DeviceID(), InodeID: tmpfsDevice.NextIno(), BlockSize: usermem.PageSize, @@ -218,7 +218,7 @@ func (d *Dir) newCreateOps() *ramfs.CreateOps { Links: 0, }) iops := NewInMemoryFile(ctx, usage.Tmpfs, uattr) - return fs.NewInode(iops, dir.MountSource, fs.StableAttr{ + return fs.NewInode(ctx, iops, dir.MountSource, fs.StableAttr{ DeviceID: tmpfsDevice.DeviceID(), InodeID: tmpfsDevice.NextIno(), BlockSize: usermem.PageSize, @@ -262,7 +262,7 @@ type Symlink struct { // NewSymlink returns a new symlink with the provided permissions. func NewSymlink(ctx context.Context, target string, owner fs.FileOwner, msrc *fs.MountSource) *fs.Inode { s := &Symlink{Symlink: *ramfs.NewSymlink(ctx, owner, target)} - return fs.NewInode(s, msrc, fs.StableAttr{ + return fs.NewInode(ctx, s, msrc, fs.StableAttr{ DeviceID: tmpfsDevice.DeviceID(), InodeID: tmpfsDevice.NextIno(), BlockSize: usermem.PageSize, @@ -292,7 +292,7 @@ type Socket struct { // NewSocket returns a new socket with the provided permissions. func NewSocket(ctx context.Context, socket transport.BoundEndpoint, owner fs.FileOwner, perms fs.FilePermissions, msrc *fs.MountSource) *fs.Inode { s := &Socket{Socket: *ramfs.NewSocket(ctx, socket, owner, perms)} - return fs.NewInode(s, msrc, fs.StableAttr{ + return fs.NewInode(ctx, s, msrc, fs.StableAttr{ DeviceID: tmpfsDevice.DeviceID(), InodeID: tmpfsDevice.NextIno(), BlockSize: usermem.PageSize, @@ -329,7 +329,7 @@ func NewFifo(ctx context.Context, owner fs.FileOwner, perms fs.FilePermissions, fifoIops := &Fifo{iops} // Build a new Inode. - return fs.NewInode(fifoIops, msrc, fs.StableAttr{ + return fs.NewInode(ctx, fifoIops, msrc, fs.StableAttr{ DeviceID: tmpfsDevice.DeviceID(), InodeID: tmpfsDevice.NextIno(), BlockSize: usermem.PageSize, diff --git a/pkg/sentry/fs/tty/dir.go b/pkg/sentry/fs/tty/dir.go index 679057d1f..58a26742c 100644 --- a/pkg/sentry/fs/tty/dir.go +++ b/pkg/sentry/fs/tty/dir.go @@ -114,7 +114,7 @@ func newDir(ctx context.Context, m *fs.MountSource) *fs.Inode { InodeID: d.master.StableAttr.InodeID, }) - return fs.NewInode(d, m, fs.StableAttr{ + return fs.NewInode(ctx, d, m, fs.StableAttr{ DeviceID: ptsDevice.DeviceID(), // N.B. Linux always uses inode id 1 for the directory. See // fs/devpts/inode.c:devpts_fill_super. @@ -143,7 +143,7 @@ func (d *dirInodeOperations) Lookup(ctx context.Context, dir *fs.Inode, name str // Master? if name == "ptmx" { d.master.IncRef() - return fs.NewDirent(d.master, name), nil + return fs.NewDirent(ctx, d.master, name), nil } // Slave number? @@ -159,7 +159,7 @@ func (d *dirInodeOperations) Lookup(ctx context.Context, dir *fs.Inode, name str } s.IncRef() - return fs.NewDirent(s, name), nil + return fs.NewDirent(ctx, s, name), nil } // Create implements fs.InodeOperations.Create. diff --git a/pkg/sentry/fs/tty/fs.go b/pkg/sentry/fs/tty/fs.go index 08843c115..1bbfbb90a 100644 --- a/pkg/sentry/fs/tty/fs.go +++ b/pkg/sentry/fs/tty/fs.go @@ -67,7 +67,7 @@ func (f *filesystem) Mount(ctx context.Context, device string, flags fs.MountSou return nil, syserror.EINVAL } - return newDir(ctx, fs.NewMountSource(&superOperations{}, f, flags)), nil + return newDir(ctx, fs.NewMountSource(ctx, &superOperations{}, f, flags)), nil } // superOperations implements fs.MountSourceOperations, preventing caching. diff --git a/pkg/sentry/fs/tty/master.go b/pkg/sentry/fs/tty/master.go index c02142ff3..54dd3d6b7 100644 --- a/pkg/sentry/fs/tty/master.go +++ b/pkg/sentry/fs/tty/master.go @@ -46,7 +46,7 @@ func newMasterInode(ctx context.Context, d *dirInodeOperations, owner fs.FileOwn d: d, } - return fs.NewInode(iops, d.msrc, fs.StableAttr{ + return fs.NewInode(ctx, iops, d.msrc, fs.StableAttr{ DeviceID: ptsDevice.DeviceID(), // N.B. Linux always uses inode id 2 for ptmx. See // fs/devpts/inode.c:mknod_ptmx. diff --git a/pkg/sentry/fs/tty/slave.go b/pkg/sentry/fs/tty/slave.go index a382dcd13..2d68978dd 100644 --- a/pkg/sentry/fs/tty/slave.go +++ b/pkg/sentry/fs/tty/slave.go @@ -51,7 +51,7 @@ func newSlaveInode(ctx context.Context, d *dirInodeOperations, t *Terminal, owne t: t, } - return fs.NewInode(iops, d.msrc, fs.StableAttr{ + return fs.NewInode(ctx, iops, d.msrc, fs.StableAttr{ DeviceID: ptsDevice.DeviceID(), // N.B. Linux always uses inode id = tty index + 3. See // fs/devpts/inode.c:devpts_pty_new. diff --git a/pkg/sentry/kernel/epoll/epoll.go b/pkg/sentry/kernel/epoll/epoll.go index 86ddbec12..33c7dccae 100644 --- a/pkg/sentry/kernel/epoll/epoll.go +++ b/pkg/sentry/kernel/epoll/epoll.go @@ -155,7 +155,7 @@ var cycleMu sync.Mutex // NewEventPoll allocates and initializes a new event poll object. func NewEventPoll(ctx context.Context) *fs.File { // name matches fs/eventpoll.c:epoll_create1. - dirent := fs.NewDirent(anon.NewInode(ctx), fmt.Sprintf("anon_inode:[eventpoll]")) + dirent := fs.NewDirent(ctx, anon.NewInode(ctx), fmt.Sprintf("anon_inode:[eventpoll]")) // Release the initial dirent reference after NewFile takes a reference. defer dirent.DecRef() return fs.NewFile(ctx, dirent, fs.FileFlags{}, &EventPoll{ diff --git a/pkg/sentry/kernel/eventfd/eventfd.go b/pkg/sentry/kernel/eventfd/eventfd.go index 610c73d6f..12f0d429b 100644 --- a/pkg/sentry/kernel/eventfd/eventfd.go +++ b/pkg/sentry/kernel/eventfd/eventfd.go @@ -68,7 +68,7 @@ type EventOperations struct { // New creates a new event object with the supplied initial value and mode. func New(ctx context.Context, initVal uint64, semMode bool) *fs.File { // name matches fs/eventfd.c:eventfd_file_create. - dirent := fs.NewDirent(anon.NewInode(ctx), "anon_inode:[eventfd]") + dirent := fs.NewDirent(ctx, anon.NewInode(ctx), "anon_inode:[eventfd]") // Release the initial dirent reference after NewFile takes a reference. defer dirent.DecRef() return fs.NewFile(ctx, dirent, fs.FileFlags{Read: true, Write: true}, &EventOperations{ diff --git a/pkg/sentry/kernel/fasync/fasync.go b/pkg/sentry/kernel/fasync/fasync.go index bcaca58f7..6b0bb0324 100644 --- a/pkg/sentry/kernel/fasync/fasync.go +++ b/pkg/sentry/kernel/fasync/fasync.go @@ -34,9 +34,23 @@ func New() fs.FileAsync { // // +stateify savable type FileAsync struct { - mu sync.Mutex `state:"nosave"` - e waiter.Entry - requester *auth.Credentials + // e is immutable after first use (which is protected by mu below). + e waiter.Entry + + // regMu protects registeration and unregistration actions on e. + // + // regMu must be held while registration decisions are being made + // through the registration action itself. + // + // Lock ordering: regMu, mu. + regMu sync.Mutex `state:"nosave"` + + // mu protects all following fields. + // + // Lock ordering: e.mu, mu. + mu sync.Mutex `state:"nosave"` + requester *auth.Credentials + registered bool // Only one of the following is allowed to be non-nil. recipientPG *kernel.ProcessGroup @@ -47,7 +61,7 @@ type FileAsync struct { // Callback sends a signal. func (a *FileAsync) Callback(e *waiter.Entry) { a.mu.Lock() - if a.e.Callback == nil { + if !a.registered { a.mu.Unlock() return } @@ -80,14 +94,21 @@ func (a *FileAsync) Callback(e *waiter.Entry) { // // The file must not be currently registered. func (a *FileAsync) Register(w waiter.Waitable) { + a.regMu.Lock() + defer a.regMu.Unlock() a.mu.Lock() - defer a.mu.Unlock() - if a.e.Callback != nil { + if a.registered { + a.mu.Unlock() panic("registering already registered file") } - a.e.Callback = a + if a.e.Callback == nil { + a.e.Callback = a + } + a.registered = true + + a.mu.Unlock() w.EventRegister(&a.e, waiter.EventIn|waiter.EventOut|waiter.EventErr|waiter.EventHUp) } @@ -95,15 +116,19 @@ func (a *FileAsync) Register(w waiter.Waitable) { // // The file must be currently registered. func (a *FileAsync) Unregister(w waiter.Waitable) { + a.regMu.Lock() + defer a.regMu.Unlock() a.mu.Lock() - defer a.mu.Unlock() - if a.e.Callback == nil { + if !a.registered { + a.mu.Unlock() panic("unregistering unregistered file") } + a.registered = false + + a.mu.Unlock() w.EventUnregister(&a.e) - a.e.Callback = nil } // Owner returns who is currently getting signals. All return values will be diff --git a/pkg/sentry/kernel/fasync/fasync_state_autogen.go b/pkg/sentry/kernel/fasync/fasync_state_autogen.go index 0ffb3f7ad..c17daa8a1 100755 --- a/pkg/sentry/kernel/fasync/fasync_state_autogen.go +++ b/pkg/sentry/kernel/fasync/fasync_state_autogen.go @@ -11,6 +11,7 @@ func (x *FileAsync) save(m state.Map) { x.beforeSave() m.Save("e", &x.e) m.Save("requester", &x.requester) + m.Save("registered", &x.registered) m.Save("recipientPG", &x.recipientPG) m.Save("recipientTG", &x.recipientTG) m.Save("recipientT", &x.recipientT) @@ -20,6 +21,7 @@ func (x *FileAsync) afterLoad() {} func (x *FileAsync) load(m state.Map) { m.Load("e", &x.e) m.Load("requester", &x.requester) + m.Load("registered", &x.registered) m.Load("recipientPG", &x.recipientPG) m.Load("recipientTG", &x.recipientTG) m.Load("recipientT", &x.recipientT) diff --git a/pkg/sentry/kernel/pipe/pipe.go b/pkg/sentry/kernel/pipe/pipe.go index 18e60487f..755326d59 100644 --- a/pkg/sentry/kernel/pipe/pipe.go +++ b/pkg/sentry/kernel/pipe/pipe.go @@ -150,8 +150,8 @@ func NewConnectedPipe(ctx context.Context, sizeBytes, atomicIOBytes int64) (*fs. InodeID: ino, BlockSize: int64(atomicIOBytes), } - ms := fs.NewPseudoMountSource() - d := fs.NewDirent(fs.NewInode(iops, ms, sattr), fmt.Sprintf("pipe:[%d]", ino)) + ms := fs.NewPseudoMountSource(ctx) + d := fs.NewDirent(ctx, fs.NewInode(ctx, iops, ms, sattr), fmt.Sprintf("pipe:[%d]", ino)) // The p.Open calls below will each take a reference on the Dirent. We // must drop the one we already have. defer d.DecRef() diff --git a/pkg/sentry/kernel/seqatomic_taskgoroutineschedinfo.go b/pkg/sentry/kernel/seqatomic_taskgoroutineschedinfo.go index 25ad17a4e..c284a1b11 100755 --- a/pkg/sentry/kernel/seqatomic_taskgoroutineschedinfo.go +++ b/pkg/sentry/kernel/seqatomic_taskgoroutineschedinfo.go @@ -1,11 +1,11 @@ package kernel import ( - "fmt" "reflect" "strings" "unsafe" + "fmt" "gvisor.dev/gvisor/third_party/gvsync" ) diff --git a/pkg/sentry/loader/vdso.go b/pkg/sentry/loader/vdso.go index 4ba56c44d..ada28aea3 100644 --- a/pkg/sentry/loader/vdso.go +++ b/pkg/sentry/loader/vdso.go @@ -69,11 +69,12 @@ type byteReader struct { var _ fs.FileOperations = (*byteReader)(nil) // newByteReaderFile creates a fake file to read data from. -func newByteReaderFile(data []byte) *fs.File { +func newByteReaderFile(ctx context.Context, data []byte) *fs.File { // Create a fake inode. inode := fs.NewInode( + ctx, &fsutil.SimpleFileInode{}, - fs.NewPseudoMountSource(), + fs.NewPseudoMountSource(ctx), fs.StableAttr{ Type: fs.Anonymous, DeviceID: anon.PseudoDevice.DeviceID(), @@ -219,8 +220,8 @@ type VDSO struct { // PrepareVDSO validates the system VDSO and returns a VDSO, containing the // param page for updating by the kernel. -func PrepareVDSO(mfp pgalloc.MemoryFileProvider) (*VDSO, error) { - vdsoFile := newByteReaderFile(vdsoBin) +func PrepareVDSO(ctx context.Context, mfp pgalloc.MemoryFileProvider) (*VDSO, error) { + vdsoFile := newByteReaderFile(ctx, vdsoBin) // First make sure the VDSO is valid. vdsoFile does not use ctx, so a // nil context can be passed. diff --git a/pkg/sentry/platform/ring0/defs_impl.go b/pkg/sentry/platform/ring0/defs_impl.go index ea3f514cd..d4bfc5a4a 100755 --- a/pkg/sentry/platform/ring0/defs_impl.go +++ b/pkg/sentry/platform/ring0/defs_impl.go @@ -1,10 +1,10 @@ package ring0 import ( - "gvisor.dev/gvisor/pkg/cpuid" "syscall" "fmt" + "gvisor.dev/gvisor/pkg/cpuid" "gvisor.dev/gvisor/pkg/sentry/platform/ring0/pagetables" "gvisor.dev/gvisor/pkg/sentry/usermem" "io" diff --git a/pkg/sentry/socket/epsocket/epsocket.go b/pkg/sentry/socket/epsocket/epsocket.go index 8b783ae2f..ce3b247d0 100644 --- a/pkg/sentry/socket/epsocket/epsocket.go +++ b/pkg/sentry/socket/epsocket/epsocket.go @@ -668,12 +668,6 @@ func GetSockOpt(t *kernel.Task, s socket.Socket, ep commonEndpoint, family int, func getSockOptSocket(t *kernel.Task, s socket.Socket, ep commonEndpoint, family int, skType linux.SockType, name, outLen int) (interface{}, *syserr.Error) { // TODO(b/124056281): Stop rejecting short optLen values in getsockopt. switch name { - case linux.SO_TYPE: - if outLen < sizeOfInt32 { - return nil, syserr.ErrInvalidArgument - } - return int32(skType), nil - case linux.SO_ERROR: if outLen < sizeOfInt32 { return nil, syserr.ErrInvalidArgument diff --git a/pkg/sentry/socket/epsocket/provider.go b/pkg/sentry/socket/epsocket/provider.go index 37f3160cd..6d2b5d038 100644 --- a/pkg/sentry/socket/epsocket/provider.go +++ b/pkg/sentry/socket/epsocket/provider.go @@ -111,7 +111,7 @@ func (p *provider) Socket(t *kernel.Task, stype linux.SockType, protocol int) (* return nil, syserr.TranslateNetstackError(e) } - return New(t, p.family, stype, protocol, wq, ep) + return New(t, p.family, stype, int(transProto), wq, ep) } // Pair just returns nil sockets (not supported). diff --git a/pkg/sentry/socket/hostinet/socket.go b/pkg/sentry/socket/hostinet/socket.go index 2ca952920..cef007aca 100644 --- a/pkg/sentry/socket/hostinet/socket.go +++ b/pkg/sentry/socket/hostinet/socket.go @@ -288,7 +288,7 @@ func (s *socketOperations) GetSockOpt(t *kernel.Task, level int, name int, outLe } case syscall.SOL_SOCKET: switch name { - case syscall.SO_ERROR, syscall.SO_KEEPALIVE, syscall.SO_SNDBUF, syscall.SO_RCVBUF, syscall.SO_REUSEADDR, syscall.SO_TYPE: + case syscall.SO_ERROR, syscall.SO_KEEPALIVE, syscall.SO_SNDBUF, syscall.SO_RCVBUF, syscall.SO_REUSEADDR: optlen = sizeofInt32 case syscall.SO_LINGER: optlen = syscall.SizeofLinger diff --git a/pkg/sentry/socket/netlink/socket.go b/pkg/sentry/socket/netlink/socket.go index 985a5f24a..87c0c77bc 100644 --- a/pkg/sentry/socket/netlink/socket.go +++ b/pkg/sentry/socket/netlink/socket.go @@ -111,7 +111,7 @@ var _ socket.Socket = (*Socket)(nil) // NewSocket creates a new Socket. func NewSocket(t *kernel.Task, skType linux.SockType, protocol Protocol) (*Socket, *syserr.Error) { // Datagram endpoint used to buffer kernel -> user messages. - ep := transport.NewConnectionless() + ep := transport.NewConnectionless(t) // Bind the endpoint for good measure so we can connect to it. The // bound address will never be exposed. @@ -121,7 +121,7 @@ func NewSocket(t *kernel.Task, skType linux.SockType, protocol Protocol) (*Socke } // Create a connection from which the kernel can write messages. - connection, err := ep.(transport.BoundEndpoint).UnidirectionalConnect() + connection, err := ep.(transport.BoundEndpoint).UnidirectionalConnect(t) if err != nil { ep.Close() return nil, err diff --git a/pkg/sentry/socket/socket.go b/pkg/sentry/socket/socket.go index 65f38f61f..933120f34 100644 --- a/pkg/sentry/socket/socket.go +++ b/pkg/sentry/socket/socket.go @@ -199,7 +199,7 @@ func NewDirent(ctx context.Context, d *device.Device) *fs.Dirent { User: fs.PermMask{Read: true, Write: true}, }, linux.SOCKFS_MAGIC), } - inode := fs.NewInode(iops, fs.NewPseudoMountSource(), fs.StableAttr{ + inode := fs.NewInode(ctx, iops, fs.NewPseudoMountSource(ctx), fs.StableAttr{ Type: fs.Socket, DeviceID: d.DeviceID(), InodeID: ino, @@ -207,7 +207,7 @@ func NewDirent(ctx context.Context, d *device.Device) *fs.Dirent { }) // Dirent name matches net/socket.c:sockfs_dname. - return fs.NewDirent(inode, fmt.Sprintf("socket:[%d]", ino)) + return fs.NewDirent(ctx, inode, fmt.Sprintf("socket:[%d]", ino)) } // SendReceiveTimeout stores timeouts for send and receive calls. diff --git a/pkg/sentry/socket/unix/io.go b/pkg/sentry/socket/unix/io.go index 023c2f135..760c7beab 100644 --- a/pkg/sentry/socket/unix/io.go +++ b/pkg/sentry/socket/unix/io.go @@ -15,6 +15,7 @@ package unix import ( + "gvisor.dev/gvisor/pkg/sentry/context" "gvisor.dev/gvisor/pkg/sentry/safemem" "gvisor.dev/gvisor/pkg/sentry/socket/unix/transport" "gvisor.dev/gvisor/pkg/tcpip" @@ -24,6 +25,8 @@ import ( // // EndpointWriter is not thread-safe. type EndpointWriter struct { + Ctx context.Context + // Endpoint is the transport.Endpoint to write to. Endpoint transport.Endpoint @@ -37,7 +40,7 @@ type EndpointWriter struct { // WriteFromBlocks implements safemem.Writer.WriteFromBlocks. func (w *EndpointWriter) WriteFromBlocks(srcs safemem.BlockSeq) (uint64, error) { return safemem.FromVecWriterFunc{func(bufs [][]byte) (int64, error) { - n, err := w.Endpoint.SendMsg(bufs, w.Control, w.To) + n, err := w.Endpoint.SendMsg(w.Ctx, bufs, w.Control, w.To) if err != nil { return int64(n), err.ToError() } @@ -50,6 +53,8 @@ func (w *EndpointWriter) WriteFromBlocks(srcs safemem.BlockSeq) (uint64, error) // // EndpointReader is not thread-safe. type EndpointReader struct { + Ctx context.Context + // Endpoint is the transport.Endpoint to read from. Endpoint transport.Endpoint @@ -81,7 +86,7 @@ type EndpointReader struct { // ReadToBlocks implements safemem.Reader.ReadToBlocks. func (r *EndpointReader) ReadToBlocks(dsts safemem.BlockSeq) (uint64, error) { return safemem.FromVecReaderFunc{func(bufs [][]byte) (int64, error) { - n, ms, c, ct, err := r.Endpoint.RecvMsg(bufs, r.Creds, r.NumRights, r.Peek, r.From) + n, ms, c, ct, err := r.Endpoint.RecvMsg(r.Ctx, bufs, r.Creds, r.NumRights, r.Peek, r.From) r.Control = c r.ControlTrunc = ct r.MsgSize = ms diff --git a/pkg/sentry/socket/unix/transport/connectioned.go b/pkg/sentry/socket/unix/transport/connectioned.go index 9d07cde22..e4c416233 100644 --- a/pkg/sentry/socket/unix/transport/connectioned.go +++ b/pkg/sentry/socket/unix/transport/connectioned.go @@ -18,6 +18,7 @@ import ( "sync" "gvisor.dev/gvisor/pkg/abi/linux" + "gvisor.dev/gvisor/pkg/sentry/context" "gvisor.dev/gvisor/pkg/syserr" "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/waiter" @@ -111,8 +112,13 @@ type connectionedEndpoint struct { acceptedChan chan *connectionedEndpoint `state:".([]*connectionedEndpoint)"` } +var ( + _ = BoundEndpoint((*connectionedEndpoint)(nil)) + _ = Endpoint((*connectionedEndpoint)(nil)) +) + // NewConnectioned creates a new unbound connectionedEndpoint. -func NewConnectioned(stype linux.SockType, uid UniqueIDProvider) Endpoint { +func NewConnectioned(ctx context.Context, stype linux.SockType, uid UniqueIDProvider) Endpoint { return &connectionedEndpoint{ baseEndpoint: baseEndpoint{Queue: &waiter.Queue{}}, id: uid.UniqueID(), @@ -122,7 +128,7 @@ func NewConnectioned(stype linux.SockType, uid UniqueIDProvider) Endpoint { } // NewPair allocates a new pair of connected unix-domain connectionedEndpoints. -func NewPair(stype linux.SockType, uid UniqueIDProvider) (Endpoint, Endpoint) { +func NewPair(ctx context.Context, stype linux.SockType, uid UniqueIDProvider) (Endpoint, Endpoint) { a := &connectionedEndpoint{ baseEndpoint: baseEndpoint{Queue: &waiter.Queue{}}, id: uid.UniqueID(), @@ -163,7 +169,7 @@ func NewPair(stype linux.SockType, uid UniqueIDProvider) (Endpoint, Endpoint) { // NewExternal creates a new externally backed Endpoint. It behaves like a // socketpair. -func NewExternal(stype linux.SockType, uid UniqueIDProvider, queue *waiter.Queue, receiver Receiver, connected ConnectedEndpoint) Endpoint { +func NewExternal(ctx context.Context, stype linux.SockType, uid UniqueIDProvider, queue *waiter.Queue, receiver Receiver, connected ConnectedEndpoint) Endpoint { return &connectionedEndpoint{ baseEndpoint: baseEndpoint{Queue: queue, receiver: receiver, connected: connected}, id: uid.UniqueID(), @@ -238,7 +244,7 @@ func (e *connectionedEndpoint) Close() { } // BidirectionalConnect implements BoundEndpoint.BidirectionalConnect. -func (e *connectionedEndpoint) BidirectionalConnect(ce ConnectingEndpoint, returnConnect func(Receiver, ConnectedEndpoint)) *syserr.Error { +func (e *connectionedEndpoint) BidirectionalConnect(ctx context.Context, ce ConnectingEndpoint, returnConnect func(Receiver, ConnectedEndpoint)) *syserr.Error { if ce.Type() != e.stype { return syserr.ErrConnectionRefused } @@ -334,19 +340,19 @@ func (e *connectionedEndpoint) BidirectionalConnect(ce ConnectingEndpoint, retur } // UnidirectionalConnect implements BoundEndpoint.UnidirectionalConnect. -func (e *connectionedEndpoint) UnidirectionalConnect() (ConnectedEndpoint, *syserr.Error) { +func (e *connectionedEndpoint) UnidirectionalConnect(ctx context.Context) (ConnectedEndpoint, *syserr.Error) { return nil, syserr.ErrConnectionRefused } // Connect attempts to directly connect to another Endpoint. // Implements Endpoint.Connect. -func (e *connectionedEndpoint) Connect(server BoundEndpoint) *syserr.Error { +func (e *connectionedEndpoint) Connect(ctx context.Context, server BoundEndpoint) *syserr.Error { returnConnect := func(r Receiver, ce ConnectedEndpoint) { e.receiver = r e.connected = ce } - return server.BidirectionalConnect(e, returnConnect) + return server.BidirectionalConnect(ctx, e, returnConnect) } // Listen starts listening on the connection. @@ -426,13 +432,13 @@ func (e *connectionedEndpoint) Bind(addr tcpip.FullAddress, commit func() *syser // SendMsg writes data and a control message to the endpoint's peer. // This method does not block if the data cannot be written. -func (e *connectionedEndpoint) SendMsg(data [][]byte, c ControlMessages, to BoundEndpoint) (uintptr, *syserr.Error) { +func (e *connectionedEndpoint) SendMsg(ctx context.Context, data [][]byte, c ControlMessages, to BoundEndpoint) (uintptr, *syserr.Error) { // Stream sockets do not support specifying the endpoint. Seqpacket // sockets ignore the passed endpoint. if e.stype == linux.SOCK_STREAM && to != nil { return 0, syserr.ErrNotSupported } - return e.baseEndpoint.SendMsg(data, c, to) + return e.baseEndpoint.SendMsg(ctx, data, c, to) } // Readiness returns the current readiness of the connectionedEndpoint. For diff --git a/pkg/sentry/socket/unix/transport/connectionless.go b/pkg/sentry/socket/unix/transport/connectionless.go index 254148286..cb2b60339 100644 --- a/pkg/sentry/socket/unix/transport/connectionless.go +++ b/pkg/sentry/socket/unix/transport/connectionless.go @@ -16,6 +16,7 @@ package transport import ( "gvisor.dev/gvisor/pkg/abi/linux" + "gvisor.dev/gvisor/pkg/sentry/context" "gvisor.dev/gvisor/pkg/syserr" "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/waiter" @@ -32,8 +33,13 @@ type connectionlessEndpoint struct { baseEndpoint } +var ( + _ = BoundEndpoint((*connectionlessEndpoint)(nil)) + _ = Endpoint((*connectionlessEndpoint)(nil)) +) + // NewConnectionless creates a new unbound dgram endpoint. -func NewConnectionless() Endpoint { +func NewConnectionless(ctx context.Context) Endpoint { ep := &connectionlessEndpoint{baseEndpoint{Queue: &waiter.Queue{}}} ep.receiver = &queueReceiver{readQueue: &queue{ReaderQueue: ep.Queue, WriterQueue: &waiter.Queue{}, limit: initialLimit}} return ep @@ -72,12 +78,12 @@ func (e *connectionlessEndpoint) Close() { } // BidirectionalConnect implements BoundEndpoint.BidirectionalConnect. -func (e *connectionlessEndpoint) BidirectionalConnect(ce ConnectingEndpoint, returnConnect func(Receiver, ConnectedEndpoint)) *syserr.Error { +func (e *connectionlessEndpoint) BidirectionalConnect(ctx context.Context, ce ConnectingEndpoint, returnConnect func(Receiver, ConnectedEndpoint)) *syserr.Error { return syserr.ErrConnectionRefused } // UnidirectionalConnect implements BoundEndpoint.UnidirectionalConnect. -func (e *connectionlessEndpoint) UnidirectionalConnect() (ConnectedEndpoint, *syserr.Error) { +func (e *connectionlessEndpoint) UnidirectionalConnect(ctx context.Context) (ConnectedEndpoint, *syserr.Error) { e.Lock() r := e.receiver e.Unlock() @@ -96,12 +102,12 @@ func (e *connectionlessEndpoint) UnidirectionalConnect() (ConnectedEndpoint, *sy // SendMsg writes data and a control message to the specified endpoint. // This method does not block if the data cannot be written. -func (e *connectionlessEndpoint) SendMsg(data [][]byte, c ControlMessages, to BoundEndpoint) (uintptr, *syserr.Error) { +func (e *connectionlessEndpoint) SendMsg(ctx context.Context, data [][]byte, c ControlMessages, to BoundEndpoint) (uintptr, *syserr.Error) { if to == nil { - return e.baseEndpoint.SendMsg(data, c, nil) + return e.baseEndpoint.SendMsg(ctx, data, c, nil) } - connected, err := to.UnidirectionalConnect() + connected, err := to.UnidirectionalConnect(ctx) if err != nil { return 0, syserr.ErrInvalidEndpointState } @@ -124,8 +130,8 @@ func (e *connectionlessEndpoint) Type() linux.SockType { } // Connect attempts to connect directly to server. -func (e *connectionlessEndpoint) Connect(server BoundEndpoint) *syserr.Error { - connected, err := server.UnidirectionalConnect() +func (e *connectionlessEndpoint) Connect(ctx context.Context, server BoundEndpoint) *syserr.Error { + connected, err := server.UnidirectionalConnect(ctx) if err != nil { return err } diff --git a/pkg/sentry/socket/unix/transport/unix.go b/pkg/sentry/socket/unix/transport/unix.go index a4d41e355..b0765ba55 100644 --- a/pkg/sentry/socket/unix/transport/unix.go +++ b/pkg/sentry/socket/unix/transport/unix.go @@ -20,6 +20,7 @@ import ( "sync/atomic" "gvisor.dev/gvisor/pkg/abi/linux" + "gvisor.dev/gvisor/pkg/sentry/context" "gvisor.dev/gvisor/pkg/syserr" "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/tcpip/buffer" @@ -120,13 +121,13 @@ type Endpoint interface { // CMTruncated indicates that the numRights hint was used to receive fewer // than the total available SCM_RIGHTS FDs. Additional truncation may be // required by the caller. - RecvMsg(data [][]byte, creds bool, numRights uintptr, peek bool, addr *tcpip.FullAddress) (recvLen, msgLen uintptr, cm ControlMessages, CMTruncated bool, err *syserr.Error) + RecvMsg(ctx context.Context, data [][]byte, creds bool, numRights uintptr, peek bool, addr *tcpip.FullAddress) (recvLen, msgLen uintptr, cm ControlMessages, CMTruncated bool, err *syserr.Error) // SendMsg writes data and a control message to the endpoint's peer. // This method does not block if the data cannot be written. // // SendMsg does not take ownership of any of its arguments on error. - SendMsg([][]byte, ControlMessages, BoundEndpoint) (uintptr, *syserr.Error) + SendMsg(context.Context, [][]byte, ControlMessages, BoundEndpoint) (uintptr, *syserr.Error) // Connect connects this endpoint directly to another. // @@ -134,7 +135,7 @@ type Endpoint interface { // endpoint passed in as a parameter. // // The error codes are the same as Connect. - Connect(server BoundEndpoint) *syserr.Error + Connect(ctx context.Context, server BoundEndpoint) *syserr.Error // Shutdown closes the read and/or write end of the endpoint connection // to its peer. @@ -215,7 +216,7 @@ type BoundEndpoint interface { // // This method will return syserr.ErrConnectionRefused on endpoints with a // type that isn't SockStream or SockSeqpacket. - BidirectionalConnect(ep ConnectingEndpoint, returnConnect func(Receiver, ConnectedEndpoint)) *syserr.Error + BidirectionalConnect(ctx context.Context, ep ConnectingEndpoint, returnConnect func(Receiver, ConnectedEndpoint)) *syserr.Error // UnidirectionalConnect establishes a write-only connection to a unix // endpoint. @@ -225,7 +226,7 @@ type BoundEndpoint interface { // // This method will return syserr.ErrConnectionRefused on a non-SockDgram // endpoint. - UnidirectionalConnect() (ConnectedEndpoint, *syserr.Error) + UnidirectionalConnect(ctx context.Context) (ConnectedEndpoint, *syserr.Error) // Passcred returns whether or not the SO_PASSCRED socket option is // enabled on this end. @@ -776,7 +777,7 @@ func (e *baseEndpoint) Connected() bool { } // RecvMsg reads data and a control message from the endpoint. -func (e *baseEndpoint) RecvMsg(data [][]byte, creds bool, numRights uintptr, peek bool, addr *tcpip.FullAddress) (uintptr, uintptr, ControlMessages, bool, *syserr.Error) { +func (e *baseEndpoint) RecvMsg(ctx context.Context, data [][]byte, creds bool, numRights uintptr, peek bool, addr *tcpip.FullAddress) (uintptr, uintptr, ControlMessages, bool, *syserr.Error) { e.Lock() if e.receiver == nil { @@ -802,7 +803,7 @@ func (e *baseEndpoint) RecvMsg(data [][]byte, creds bool, numRights uintptr, pee // SendMsg writes data and a control message to the endpoint's peer. // This method does not block if the data cannot be written. -func (e *baseEndpoint) SendMsg(data [][]byte, c ControlMessages, to BoundEndpoint) (uintptr, *syserr.Error) { +func (e *baseEndpoint) SendMsg(ctx context.Context, data [][]byte, c ControlMessages, to BoundEndpoint) (uintptr, *syserr.Error) { e.Lock() if !e.Connected() { e.Unlock() diff --git a/pkg/sentry/socket/unix/unix.go b/pkg/sentry/socket/unix/unix.go index 58483a279..97db87f3e 100644 --- a/pkg/sentry/socket/unix/unix.go +++ b/pkg/sentry/socket/unix/unix.go @@ -363,7 +363,7 @@ func (s *SocketOperations) Connect(t *kernel.Task, sockaddr []byte, blocking boo defer ep.Release() // Connect the server endpoint. - return s.ep.Connect(ep) + return s.ep.Connect(t, ep) } // Writev implements fs.FileOperations.Write. @@ -372,11 +372,12 @@ func (s *SocketOperations) Write(ctx context.Context, _ *fs.File, src usermem.IO ctrl := control.New(t, s.ep, nil) if src.NumBytes() == 0 { - nInt, err := s.ep.SendMsg([][]byte{}, ctrl, nil) + nInt, err := s.ep.SendMsg(ctx, [][]byte{}, ctrl, nil) return int64(nInt), err.ToError() } return src.CopyInTo(ctx, &EndpointWriter{ + Ctx: ctx, Endpoint: s.ep, Control: ctrl, To: nil, @@ -387,6 +388,7 @@ func (s *SocketOperations) Write(ctx context.Context, _ *fs.File, src usermem.IO // a transport.Endpoint. func (s *SocketOperations) SendMsg(t *kernel.Task, src usermem.IOSequence, to []byte, flags int, haveDeadline bool, deadline ktime.Time, controlMessages socket.ControlMessages) (int, *syserr.Error) { w := EndpointWriter{ + Ctx: t, Endpoint: s.ep, Control: controlMessages.Unix, To: nil, @@ -486,6 +488,7 @@ func (s *SocketOperations) Read(ctx context.Context, _ *fs.File, dst usermem.IOS return 0, nil } return dst.CopyOutFrom(ctx, &EndpointReader{ + Ctx: ctx, Endpoint: s.ep, NumRights: 0, Peek: false, @@ -522,6 +525,7 @@ func (s *SocketOperations) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags } r := EndpointReader{ + Ctx: t, Endpoint: s.ep, Creds: wantCreds, NumRights: uintptr(numRights), @@ -635,9 +639,9 @@ func (*provider) Socket(t *kernel.Task, stype linux.SockType, protocol int) (*fs var ep transport.Endpoint switch stype { case linux.SOCK_DGRAM: - ep = transport.NewConnectionless() + ep = transport.NewConnectionless(t) case linux.SOCK_SEQPACKET, linux.SOCK_STREAM: - ep = transport.NewConnectioned(stype, t.Kernel()) + ep = transport.NewConnectioned(t, stype, t.Kernel()) default: return nil, syserr.ErrInvalidArgument } @@ -660,7 +664,7 @@ func (*provider) Pair(t *kernel.Task, stype linux.SockType, protocol int) (*fs.F } // Create the endpoints and sockets. - ep1, ep2 := transport.NewPair(stype, t.Kernel()) + ep1, ep2 := transport.NewPair(t, stype, t.Kernel()) s1 := New(t, ep1, stype) s2 := New(t, ep2, stype) diff --git a/pkg/sentry/syscalls/linux/sys_file.go b/pkg/sentry/syscalls/linux/sys_file.go index b20991192..31c26fd5c 100644 --- a/pkg/sentry/syscalls/linux/sys_file.go +++ b/pkg/sentry/syscalls/linux/sys_file.go @@ -2067,7 +2067,7 @@ func MemfdCreate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.S name = memfdPrefix + name inode := tmpfs.NewMemfdInode(t, allowSeals) - dirent := fs.NewDirent(inode, name) + dirent := fs.NewDirent(t, inode, name) // Per Linux, mm/shmem.c:__shmem_file_setup(), memfd files are set up with // FMODE_READ | FMODE_WRITE. file, err := inode.GetFile(t, dirent, fs.FileFlags{Read: true, Write: true}) diff --git a/pkg/sentry/syscalls/linux/sys_inotify.go b/pkg/sentry/syscalls/linux/sys_inotify.go index 49aff608a..043ecf96c 100644 --- a/pkg/sentry/syscalls/linux/sys_inotify.go +++ b/pkg/sentry/syscalls/linux/sys_inotify.go @@ -35,7 +35,7 @@ func InotifyInit1(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel. return 0, nil, syscall.EINVAL } - dirent := fs.NewDirent(anon.NewInode(t), "inotify") + dirent := fs.NewDirent(t, anon.NewInode(t), "inotify") fileFlags := fs.FileFlags{ Read: true, Write: true, diff --git a/pkg/sentry/syscalls/linux/sys_socket.go b/pkg/sentry/syscalls/linux/sys_socket.go index 4e3c682ed..ccdb079bb 100644 --- a/pkg/sentry/syscalls/linux/sys_socket.go +++ b/pkg/sentry/syscalls/linux/sys_socket.go @@ -29,6 +29,7 @@ import ( "gvisor.dev/gvisor/pkg/sentry/socket/control" "gvisor.dev/gvisor/pkg/sentry/socket/unix/transport" "gvisor.dev/gvisor/pkg/sentry/usermem" + "gvisor.dev/gvisor/pkg/syserr" "gvisor.dev/gvisor/pkg/syserror" ) @@ -61,6 +62,8 @@ const controlLenOffset = 40 // to the Flags field. const flagsOffset = 48 +const sizeOfInt32 = 4 + // messageHeader64Len is the length of a MessageHeader64 struct. var messageHeader64Len = uint64(binary.Size(MessageHeader64{})) @@ -466,7 +469,7 @@ func GetSockOpt(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy } // Call syscall implementation then copy both value and value len out. - v, e := s.GetSockOpt(t, int(level), int(name), int(optLen)) + v, e := getSockOpt(t, s, int(level), int(name), int(optLen)) if e != nil { return 0, nil, e.ToError() } @@ -487,6 +490,33 @@ func GetSockOpt(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy return 0, nil, nil } +// getSockOpt tries to handle common socket options, or dispatches to a specific +// socket implementation. +func getSockOpt(t *kernel.Task, s socket.Socket, level, name, len int) (interface{}, *syserr.Error) { + if level == linux.SOL_SOCKET { + switch name { + case linux.SO_TYPE, linux.SO_DOMAIN, linux.SO_PROTOCOL: + if len < sizeOfInt32 { + return nil, syserr.ErrInvalidArgument + } + } + + switch name { + case linux.SO_TYPE: + _, skType, _ := s.Type() + return int32(skType), nil + case linux.SO_DOMAIN: + family, _, _ := s.Type() + return int32(family), nil + case linux.SO_PROTOCOL: + _, _, protocol := s.Type() + return int32(protocol), nil + } + } + + return s.GetSockOpt(t, level, name, len) +} + // SetSockOpt implements the linux syscall setsockopt(2). // // Note that unlike Linux, enabling SO_PASSCRED does not autobind the socket. diff --git a/pkg/sentry/time/seqatomic_parameters.go b/pkg/sentry/time/seqatomic_parameters.go index 89792c56d..1ec221edd 100755 --- a/pkg/sentry/time/seqatomic_parameters.go +++ b/pkg/sentry/time/seqatomic_parameters.go @@ -1,11 +1,11 @@ package time import ( - "fmt" "reflect" "strings" "unsafe" + "fmt" "gvisor.dev/gvisor/third_party/gvsync" ) |