mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Add ENAMETOOLONG checks in overlayfs.
Linux overlayfs uses the max of all layers' filename length limit. Do the same in gVisor. This is needed to get PHP runtime test ext/standard/tests/strings/007.phpt to pass with overlayfs. PiperOrigin-RevId: 493942515
This commit is contained in:
@@ -161,6 +161,9 @@ afterSymlink:
|
||||
rp.Advance()
|
||||
return d.parent, d.parent.topLookupLayer(), nil
|
||||
}
|
||||
if uint64(len(name)) > fs.maxFilenameLen {
|
||||
return nil, lookupLayerNone, linuxerr.ENAMETOOLONG
|
||||
}
|
||||
child, topLookupLayer, err := fs.getChildLocked(ctx, d, name, ds)
|
||||
if err != nil {
|
||||
return nil, topLookupLayer, err
|
||||
@@ -504,6 +507,9 @@ func (fs *filesystem) doCreateAt(ctx context.Context, rp *vfs.ResolvingPath, ct
|
||||
if name == "." || name == ".." {
|
||||
return linuxerr.EEXIST
|
||||
}
|
||||
if uint64(len(name)) > fs.maxFilenameLen {
|
||||
return linuxerr.ENAMETOOLONG
|
||||
}
|
||||
if parent.vfsd.IsDead() {
|
||||
return linuxerr.ENOENT
|
||||
}
|
||||
@@ -1090,6 +1096,9 @@ func (fs *filesystem) RenameAt(ctx context.Context, rp *vfs.ResolvingPath, oldPa
|
||||
}
|
||||
return linuxerr.EBUSY
|
||||
}
|
||||
if uint64(len(newName)) > fs.maxFilenameLen {
|
||||
return linuxerr.ENAMETOOLONG
|
||||
}
|
||||
// Do not check for newName length, since different filesystem
|
||||
// implementations impose different name limits. upperfs.RenameAt() will fail
|
||||
// appropriately if it has to.
|
||||
|
||||
@@ -125,6 +125,9 @@ type filesystem struct {
|
||||
// lastDirIno is the last inode number assigned to a directory. lastDirIno
|
||||
// is protected by dirInoCacheMu.
|
||||
lastDirIno uint64
|
||||
|
||||
// MaxFilenameLen is the maximum filename length allowed by the overlayfs.
|
||||
maxFilenameLen uint64
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
@@ -264,9 +267,23 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
|
||||
dirDevMinor: dirDevMinor,
|
||||
lowerDevMinors: make(map[layerDevNumber]uint32),
|
||||
dirInoCache: make(map[layerDevNoAndIno]uint64),
|
||||
maxFilenameLen: linux.NAME_MAX,
|
||||
}
|
||||
fs.vfsfs.Init(vfsObj, &fstype, fs)
|
||||
|
||||
// Configure max filename length. Similar to what Linux does in
|
||||
// fs/overlayfs/super.c:ovl_fill_super() -> ... -> ovl_check_namelen().
|
||||
if fsopts.UpperRoot.Ok() {
|
||||
if err := fs.updateMaxNameLen(ctx, creds, vfsObj, fs.opts.UpperRoot); err != nil {
|
||||
ctx.Debugf("overlay.FilesystemType.GetFilesystem: failed to StatFSAt on upper layer root: %v", err)
|
||||
}
|
||||
}
|
||||
for _, lowerRoot := range fsopts.LowerRoots {
|
||||
if err := fs.updateMaxNameLen(ctx, creds, vfsObj, lowerRoot); err != nil {
|
||||
ctx.Debugf("overlay.FilesystemType.GetFilesystem: failed to StatFSAt on lower layer root: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Construct the root dentry.
|
||||
root := fs.newDentry()
|
||||
root.refs = atomicbitops.FromInt64(1)
|
||||
@@ -368,6 +385,21 @@ func (fs *filesystem) Release(ctx context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// updateMaxNameLen is analogous to fs/overlayfs/super.c:ovl_check_namelen().
|
||||
func (fs *filesystem) updateMaxNameLen(ctx context.Context, creds *auth.Credentials, vfsObj *vfs.VirtualFilesystem, vd vfs.VirtualDentry) error {
|
||||
statfs, err := vfsObj.StatFSAt(ctx, creds, &vfs.PathOperation{
|
||||
Root: vd,
|
||||
Start: vd,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if statfs.NameLength > fs.maxFilenameLen {
|
||||
fs.maxFilenameLen = statfs.NameLength
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fs *filesystem) statFS(ctx context.Context) (linux.Statfs, error) {
|
||||
// Always statfs the root of the topmost layer. Compare Linux's
|
||||
// fs/overlayfs/super.c:ovl_statfs().
|
||||
|
||||
Reference in New Issue
Block a user