From 303c913c5e0e6f0bac766970d9ed19c08aabb980 Mon Sep 17 00:00:00 2001 From: Jamie Liu Date: Wed, 24 Feb 2021 12:59:08 -0800 Subject: Use mapped device number + topmost inode number for all files in VFS2 overlay. Before this CL, VFS2's overlayfs uses a single private device number and an autoincrementing generated inode number for directories; this is consistent with Linux's overlayfs in the non-samefs non-xino case. However, this breaks some applications more consistently than on Linux due to more aggressive caching of Linux overlayfs dentries. Switch from using mapped device numbers + the topmost layer's inode number for just non-copied-up non-directory files, to doing so for all files. This still allows directory dev/ino numbers to change across copy-up, but otherwise keeps them consistent. Fixes #5545: ``` $ docker run --runtime=runsc-vfs2-overlay --rm ubuntu:focal bash -c "mkdir -p 1/2/3/4/5/6/7/8 && rm -rf 1 && echo done" done ``` PiperOrigin-RevId: 359350716 --- pkg/sentry/fsimpl/overlay/filesystem.go | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'pkg/sentry/fsimpl/overlay/filesystem.go') diff --git a/pkg/sentry/fsimpl/overlay/filesystem.go b/pkg/sentry/fsimpl/overlay/filesystem.go index 890b01cdb..f7f795b10 100644 --- a/pkg/sentry/fsimpl/overlay/filesystem.go +++ b/pkg/sentry/fsimpl/overlay/filesystem.go @@ -313,22 +313,16 @@ func (fs *filesystem) lookupLocked(ctx context.Context, parent *dentry, name str return nil, topLookupLayer, syserror.ENOENT } - // Device and inode numbers were copied from the topmost layer above; - // override them if necessary. - if child.isDir() { - child.devMajor = linux.UNNAMED_MAJOR - child.devMinor = fs.dirDevMinor - child.ino = fs.newDirIno() - } else if !child.upperVD.Ok() { - childDevMinor, err := fs.getLowerDevMinor(child.devMajor, child.devMinor) - if err != nil { - ctx.Infof("overlay.filesystem.lookupLocked: failed to map lower layer device number (%d, %d) to an overlay-specific device number: %v", child.devMajor, child.devMinor, err) - child.destroyLocked(ctx) - return nil, topLookupLayer, err - } - child.devMajor = linux.UNNAMED_MAJOR - child.devMinor = childDevMinor + // Device and inode numbers were copied from the topmost layer above. Remap + // the device number to an appropriate overlay-private one. + childDevMinor, err := fs.getPrivateDevMinor(child.devMajor, child.devMinor) + if err != nil { + ctx.Infof("overlay.filesystem.lookupLocked: failed to map layer device number (%d, %d) to an overlay-specific device number: %v", child.devMajor, child.devMinor, err) + child.destroyLocked(ctx) + return nil, topLookupLayer, err } + child.devMajor = linux.UNNAMED_MAJOR + child.devMinor = childDevMinor parent.IncRef() child.parent = parent -- cgit v1.2.3