Own the patched runsc artifact and bind recovery identity

This commit is contained in:
ms2k 2026-07-26 18:01:03 +09:00
commit 2c420012bd
2 changed files with 1967 additions and 130 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,194 @@
diff --git a/pkg/sentry/fsimpl/gofer/directfs_inode.go b/pkg/sentry/fsimpl/gofer/directfs_inode.go
index dae450399..aede60019 100644
--- a/pkg/sentry/fsimpl/gofer/directfs_inode.go
+++ b/pkg/sentry/fsimpl/gofer/directfs_inode.go
@@ -797,6 +797,10 @@ func (i *directfsInode) openCreate(name string, accessFlags uint32, mode linux.F
func (i *directfsInode) getDirentsLocked(recordDirent func(name string, key inoKey, dType uint8), d *dentry) error {
readFD := int(i.readFD.RacyLoad())
+ return i.getDirentsFromFDLocked(readFD, recordDirent, d)
+}
+
+func (i *directfsInode) getDirentsFromFDLocked(readFD int, recordDirent func(name string, key inoKey, dType uint8), d *dentry) error {
if _, err := unix.Seek(readFD, 0, 0); err != nil {
return err
}
diff --git a/pkg/sentry/fsimpl/gofer/directory.go b/pkg/sentry/fsimpl/gofer/directory.go
index 684b55902..8dca826ff 100644
--- a/pkg/sentry/fsimpl/gofer/directory.go
+++ b/pkg/sentry/fsimpl/gofer/directory.go
@@ -175,13 +175,16 @@ type directoryFD struct {
fileDescription
vfs.DirectoryFileDescriptionDefaultImpl
+ handle handle `state:"nosave"`
+
mu sync.Mutex `state:"nosave"`
off int64
dirents []vfs.Dirent
}
// Release implements vfs.FileDescriptionImpl.Release.
-func (fd *directoryFD) Release(context.Context) {
+func (fd *directoryFD) Release(ctx context.Context) {
+ fd.handle.close(ctx)
}
// IterDirents implements vfs.FileDescriptionImpl.IterDirents.
@@ -191,7 +194,16 @@ func (fd *directoryFD) IterDirents(ctx context.Context, cb vfs.IterDirentsCallba
d := fd.dentry()
if fd.dirents == nil {
- ds, err := d.getDirents(ctx)
+ if d.inode.fs.opts.directoriesUseSpecialFileFD && !d.inode.isSynthetic() && !fd.handle.fdLisa.Ok() && fd.handle.fd < 0 {
+ d.inode.fs.renameMu.RLock()
+ h, err := d.openHandle(ctx, true /* read */, false /* write */, false /* trunc */)
+ d.inode.fs.renameMu.RUnlock()
+ if err != nil {
+ return err
+ }
+ fd.handle = h
+ }
+ ds, err := d.getDirents(ctx, &fd.handle)
if err != nil {
return err
}
@@ -214,7 +226,7 @@ func (fd *directoryFD) IterDirents(ctx context.Context, cb vfs.IterDirentsCallba
// Preconditions:
// - d.isDir().
// - There exists at least one directoryFD representing d.
-func (d *dentry) getDirents(ctx context.Context) ([]vfs.Dirent, error) {
+func (d *dentry) getDirents(ctx context.Context, directoryHandle *handle) ([]vfs.Dirent, error) {
// NOTE(b/135560623): 9P2000.L's readdir does not specify behavior in the
// presence of concurrent mutation of an iterated directory, so
// implementations may duplicate or omit entries in this case, which
@@ -271,13 +283,7 @@ func (d *dentry) getDirents(ctx context.Context) ([]vfs.Dirent, error) {
// duplicate entries for synthetic children.
realChildren = make(map[string]struct{})
}
- d.inode.handleMu.RLock()
- if !d.inode.isReadHandleOk() {
- // This should not be possible because a readable handle should
- // have been opened when the calling directoryFD was opened.
- panic("gofer.dentry.getDirents called without a readable handle")
- }
- err := d.getDirentsLocked(ctx, func(name string, key inoKey, dType uint8) {
+ recordDirent := func(name string, key inoKey, dType uint8) {
dirent := vfs.Dirent{
Name: name,
Ino: d.inode.fs.inoFromKey(key),
@@ -288,8 +294,22 @@ func (d *dentry) getDirents(ctx context.Context) ([]vfs.Dirent, error) {
if realChildren != nil {
realChildren[name] = struct{}{}
}
- })
- d.inode.handleMu.RUnlock()
+ }
+ var err error
+ if directoryHandle.fdLisa.Ok() {
+ inode := d.inode.impl.(*lisafsInode)
+ err = inode.getDirentsFromFDLocked(ctx, directoryHandle.fdLisa, recordDirent)
+ } else if directoryHandle.fd >= 0 {
+ inode := d.inode.impl.(*directfsInode)
+ err = inode.getDirentsFromFDLocked(int(directoryHandle.fd), recordDirent, d)
+ } else {
+ d.inode.handleMu.RLock()
+ if !d.inode.isReadHandleOk() {
+ panic("gofer.dentry.getDirents called without a readable handle")
+ }
+ err = d.getDirentsLocked(ctx, recordDirent)
+ d.inode.handleMu.RUnlock()
+ }
if err != nil {
return nil, err
}
diff --git a/pkg/sentry/fsimpl/gofer/filesystem.go b/pkg/sentry/fsimpl/gofer/filesystem.go
index f11c1fb58..fc65b5eb7 100644
--- a/pkg/sentry/fsimpl/gofer/filesystem.go
+++ b/pkg/sentry/fsimpl/gofer/filesystem.go
@@ -1137,14 +1137,22 @@ func (d *dentry) open(ctx context.Context, rp *vfs.ResolvingPath, opts *vfs.Open
if opts.Flags&linux.O_DIRECT != 0 {
return nil, linuxerr.EINVAL
}
- if !d.inode.isSynthetic() {
+ directoryHandle := noHandle
+ if !d.inode.isSynthetic() && d.inode.fs.opts.directoriesUseSpecialFileFD {
+ h, err := d.openHandle(ctx, ats&vfs.MayRead != 0, false /* write */, false /* trunc */)
+ if err != nil {
+ return nil, err
+ }
+ directoryHandle = h
+ } else if !d.inode.isSynthetic() {
if err := d.ensureSharedHandle(ctx, ats&vfs.MayRead != 0, false /* write */, false /* trunc */); err != nil {
return nil, err
}
}
- fd := &directoryFD{}
+ fd := &directoryFD{handle: directoryHandle}
fd.LockFD.Init(&d.inode.locks)
if err := fd.vfsfd.Init(fd, opts.Flags, rp.Credentials(), mnt, &d.vfsd, &vfs.FileDescriptionOptions{}); err != nil {
+ fd.handle.close(ctx)
return nil, err
}
if d.inode.readFD.Load() >= 0 {
diff --git a/pkg/sentry/fsimpl/gofer/gofer.go b/pkg/sentry/fsimpl/gofer/gofer.go
index 8777d8aa5..f58c58563 100644
--- a/pkg/sentry/fsimpl/gofer/gofer.go
+++ b/pkg/sentry/fsimpl/gofer/gofer.go
@@ -331,6 +331,8 @@ type filesystemOptions struct {
// supported with overlayfsStaleRead for now.
regularFilesUseSpecialFileFD bool
+ directoriesUseSpecialFileFD bool
+
// If disableFifoOpen is true, application attempts to open(2) a host FIFO
// are disallowed.
disableFifoOpen bool
@@ -535,6 +537,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
if _, ok := mopts[moptDisableFileHandleSharing]; ok {
delete(mopts, moptDisableFileHandleSharing)
fsopts.regularFilesUseSpecialFileFD = true
+ fsopts.directoriesUseSpecialFileFD = true
}
if _, ok := mopts[moptDisableFifoOpen]; ok {
delete(mopts, moptDisableFifoOpen)
diff --git a/pkg/sentry/fsimpl/gofer/lisafs_inode.go b/pkg/sentry/fsimpl/gofer/lisafs_inode.go
index 2c4c3d4ca..75852999b 100644
--- a/pkg/sentry/fsimpl/gofer/lisafs_inode.go
+++ b/pkg/sentry/fsimpl/gofer/lisafs_inode.go
@@ -552,6 +552,10 @@ const lisafsGetdentsCount = int32(64 * 1024)
// Preconditions:
// - getDirents may not be called concurrently with another getDirents call.
func (i *lisafsInode) getDirentsLocked(ctx context.Context, recordDirent func(name string, key inoKey, dType uint8)) error {
+ return i.getDirentsFromFDLocked(ctx, i.readFDLisa, recordDirent)
+}
+
+func (i *lisafsInode) getDirentsFromFDLocked(ctx context.Context, readFD lisafs.ClientFD, recordDirent func(name string, key inoKey, dType uint8)) error {
// shouldSeek0 indicates whether the server should SEEK to 0 before reading
// directory entries.
shouldSeek0 := true
@@ -562,7 +566,7 @@ func (i *lisafsInode) getDirentsLocked(ctx context.Context, recordDirent func(na
count = -count
shouldSeek0 = false
}
- dirents, err := i.readFDLisa.Getdents64(ctx, count)
+ dirents, err := readFD.Getdents64(ctx, count)
if err != nil {
return err
}
diff --git a/pkg/sentry/fsimpl/gofer/save_restore.go b/pkg/sentry/fsimpl/gofer/save_restore.go
index 37dbebbf1..b3fc647df 100644
--- a/pkg/sentry/fsimpl/gofer/save_restore.go
+++ b/pkg/sentry/fsimpl/gofer/save_restore.go
@@ -255,6 +255,11 @@ func (fd *specialFileFD) afterLoad(goContext.Context) {
fd.handle.fd = -1
}
+// afterLoad is invoked by stateify.
+func (fd *directoryFD) afterLoad(goContext.Context) {
+ fd.handle.fd = -1
+}
+
// saveParent is called by stateify.
func (d *dentry) saveParent() *dentry {
return d.parent.Load()