diff --git a/pkg/sentry/fsimpl/gofer/BUILD b/pkg/sentry/fsimpl/gofer/BUILD index feccaf2b2..36111538c 100644 --- a/pkg/sentry/fsimpl/gofer/BUILD +++ b/pkg/sentry/fsimpl/gofer/BUILD @@ -97,6 +97,7 @@ go_test( deps = [ "//pkg/p9", "//pkg/sentry/contexttest", + "//pkg/sentry/kernel/time", "//pkg/sentry/pgalloc", ], ) diff --git a/pkg/sentry/fsimpl/gofer/gofer.go b/pkg/sentry/fsimpl/gofer/gofer.go index ec8d76551..efdeeabbb 100644 --- a/pkg/sentry/fsimpl/gofer/gofer.go +++ b/pkg/sentry/fsimpl/gofer/gofer.go @@ -1051,18 +1051,31 @@ func (fs *filesystem) newDentry(ctx context.Context, file p9file, qid p9.QID, ma } if mask.ATime { d.atime = atomicbitops.FromInt64(dentryTimestampFromP9(attr.ATimeSeconds, attr.ATimeNanoSeconds)) + } else { + d.atime = atomicbitops.FromInt64(fs.clock.Now().Nanoseconds()) } if mask.MTime { d.mtime = atomicbitops.FromInt64(dentryTimestampFromP9(attr.MTimeSeconds, attr.MTimeNanoSeconds)) + } else { + d.mtime = atomicbitops.FromInt64(fs.clock.Now().Nanoseconds()) } if mask.CTime { d.ctime = atomicbitops.FromInt64(dentryTimestampFromP9(attr.CTimeSeconds, attr.CTimeNanoSeconds)) + } else { + // Approximate ctime with mtime if ctime isn't available. + d.ctime = atomicbitops.FromInt64(d.mtime.Load()) } if mask.BTime { d.btime = atomicbitops.FromInt64(dentryTimestampFromP9(attr.BTimeSeconds, attr.BTimeNanoSeconds)) } if mask.NLink { d.nlink = atomicbitops.FromUint32(uint32(attr.NLink)) + } else { + if attr.Mode.FileType() == p9.ModeDirectory { + d.nlink = atomicbitops.FromUint32(2) + } else { + d.nlink = atomicbitops.FromUint32(1) + } } d.vfsd.Init(d) refsvfs2.Register(d) @@ -1112,18 +1125,31 @@ func (fs *filesystem) newDentryLisa(ctx context.Context, ino *lisafs.Inode) (*de } if ino.Stat.Mask&linux.STATX_ATIME != 0 { d.atime = atomicbitops.FromInt64(dentryTimestampFromLisa(ino.Stat.Atime)) + } else { + d.atime = atomicbitops.FromInt64(fs.clock.Now().Nanoseconds()) } if ino.Stat.Mask&linux.STATX_MTIME != 0 { d.mtime = atomicbitops.FromInt64(dentryTimestampFromLisa(ino.Stat.Mtime)) + } else { + d.mtime = atomicbitops.FromInt64(fs.clock.Now().Nanoseconds()) } if ino.Stat.Mask&linux.STATX_CTIME != 0 { d.ctime = atomicbitops.FromInt64(dentryTimestampFromLisa(ino.Stat.Ctime)) + } else { + // Approximate ctime with mtime if ctime isn't available. + d.ctime = atomicbitops.FromInt64(d.mtime.Load()) } if ino.Stat.Mask&linux.STATX_BTIME != 0 { d.btime = atomicbitops.FromInt64(dentryTimestampFromLisa(ino.Stat.Btime)) } if ino.Stat.Mask&linux.STATX_NLINK != 0 { d.nlink = atomicbitops.FromUint32(ino.Stat.Nlink) + } else { + if ino.Stat.Mode&linux.FileTypeMask == linux.ModeDirectory { + d.nlink = atomicbitops.FromUint32(2) + } else { + d.nlink = atomicbitops.FromUint32(1) + } } d.vfsd.Init(d) refsvfs2.Register(d) diff --git a/pkg/sentry/fsimpl/gofer/gofer_test.go b/pkg/sentry/fsimpl/gofer/gofer_test.go index 4a518b504..addd0c451 100644 --- a/pkg/sentry/fsimpl/gofer/gofer_test.go +++ b/pkg/sentry/fsimpl/gofer/gofer_test.go @@ -19,6 +19,7 @@ import ( "gvisor.dev/gvisor/pkg/p9" "gvisor.dev/gvisor/pkg/sentry/contexttest" + "gvisor.dev/gvisor/pkg/sentry/kernel/time" "gvisor.dev/gvisor/pkg/sentry/pgalloc" ) @@ -29,6 +30,7 @@ func TestDestroyIdempotent(t *testing.T) { syncableDentries: make(map[*dentry]struct{}), inoByQIDPath: make(map[uint64]uint64), inoByKey: make(map[inoKey]uint64), + clock: time.RealtimeClockFromContext(ctx), // Test relies on no dentry being held in the cache. dentryCache: &dentryCache{maxCachedDentries: 0}, }