diff --git a/pkg/sentry/fs/tmpfs/tmpfs.go b/pkg/sentry/fs/tmpfs/tmpfs.go index 9a835b556..e06f39730 100644 --- a/pkg/sentry/fs/tmpfs/tmpfs.go +++ b/pkg/sentry/fs/tmpfs/tmpfs.go @@ -40,7 +40,7 @@ var fsInfo = fs.Info{ // of 0. To work around this, claim to have a very large but non-zero size, // chosen to ensure that BlockSize * Blocks does not overflow int64 (which // applications may also handle incorrectly). - // TODO(b/29637826): allow configuring a tmpfs size and enforce it. + // NOTE(b/29637826): Support for configurable tmpfs size was added to VFS2. TotalBlocks: math.MaxInt64 / hostarch.PageSize, FreeBlocks: math.MaxInt64 / hostarch.PageSize, } diff --git a/pkg/sentry/fsimpl/tmpfs/regular_file.go b/pkg/sentry/fsimpl/tmpfs/regular_file.go index b59a4c806..0472f28c0 100644 --- a/pkg/sentry/fsimpl/tmpfs/regular_file.go +++ b/pkg/sentry/fsimpl/tmpfs/regular_file.go @@ -453,6 +453,10 @@ func (fd *regularFileFD) pwrite(ctx context.Context, src usermem.IOSequence, off if err != nil { return 0, offset, err } + + // Reserve enough space assuming the entire write was successful. The + // corresponding update to f.size is done in WriteFromBlocks() which is + // called via src.CopyInTo() below. maybeSizeInc := false src = src.TakeFirst64(srclen) if uint64(end) > f.size.Load() { @@ -461,9 +465,13 @@ func (fd *regularFileFD) pwrite(ctx context.Context, src usermem.IOSequence, off return 0, 0, err } } + + // Perform the write. rw := getRegularFileReadWriter(f, offset) n, err := src.CopyInTo(ctx, rw) - if unwritten := srclen - n; maybeSizeInc && unwritten != 0 { + + // Correct page accounting if this was a partial write. + if maybeSizeInc && srclen-n != 0 { if err := f.inode.fs.updatePagesUsed(uint64(end), f.size.Load()); err != nil { return 0, 0, err }