From 91d4826f5be789d67a02857f177160e94d1ba0e9 Mon Sep 17 00:00:00 2001 From: Ayush Ranjan Date: Mon, 29 Nov 2021 19:24:41 -0800 Subject: [PATCH] Add support for flexible filename limits for tmpfs. PiperOrigin-RevId: 413038601 --- pkg/sentry/fsimpl/gofer/filesystem.go | 18 +++++++++--------- pkg/sentry/fsimpl/tmpfs/filesystem.go | 6 +++--- pkg/sentry/fsimpl/tmpfs/tmpfs.go | 23 ++++++++++++++++------- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/pkg/sentry/fsimpl/gofer/filesystem.go b/pkg/sentry/fsimpl/gofer/filesystem.go index bf58a9def..c61b66248 100644 --- a/pkg/sentry/fsimpl/gofer/filesystem.go +++ b/pkg/sentry/fsimpl/gofer/filesystem.go @@ -117,9 +117,9 @@ func (fs *filesystem) Sync(ctx context.Context) error { return retErr } -// maxFilenameLen is the maximum length of a filename. This is dictated by 9P's +// MaxFilenameLen is the maximum length of a filename. This is dictated by 9P's // encoding of strings, which uses 2 bytes for the length prefix. -const maxFilenameLen = (1 << 16) - 1 +const MaxFilenameLen = (1 << 16) - 1 // dentrySlicePool is a pool of *[]*dentry used to store dentries for which // dentry.checkCachingLocked() must be called. The pool holds pointers to @@ -275,7 +275,7 @@ func (fs *filesystem) getChildAndWalkPathLocked(ctx context.Context, parent *den // Note that pit is a copy of the iterator that does not affect rp. pit := rp.Pit() first := pit.String() - if len(first) > maxFilenameLen { + if len(first) > MaxFilenameLen { return nil, linuxerr.ENAMETOOLONG } if child, ok := parent.children[first]; ok || parent.isSynthetic() { @@ -368,7 +368,7 @@ func (fs *filesystem) getChildAndWalkPathLocked(ctx context.Context, parent *den // * name is not "." or "..". // * parent and the dentry at name have been revalidated. func (fs *filesystem) getChildLocked(ctx context.Context, parent *dentry, name string, ds **[]*dentry) (*dentry, error) { - if len(name) > maxFilenameLen { + if len(name) > MaxFilenameLen { return nil, linuxerr.ENAMETOOLONG } if child, ok := parent.children[name]; ok || parent.isSynthetic() { @@ -511,7 +511,7 @@ func (fs *filesystem) doCreateAt(ctx context.Context, rp *vfs.ResolvingPath, dir parent.dirMu.Lock() defer parent.dirMu.Unlock() - if len(name) > maxFilenameLen { + if len(name) > MaxFilenameLen { return linuxerr.ENAMETOOLONG } // Check for existence only if caching information is available. Otherwise, @@ -1696,8 +1696,8 @@ func (fs *filesystem) StatFSAt(ctx context.Context, rp *vfs.ResolvingPath) (linu if err := d.controlFDLisa.StatFSTo(ctx, &statFS); err != nil { return linux.Statfs{}, err } - if statFS.NameLength == 0 || statFS.NameLength > maxFilenameLen { - statFS.NameLength = maxFilenameLen + if statFS.NameLength == 0 || statFS.NameLength > MaxFilenameLen { + statFS.NameLength = MaxFilenameLen } return linux.Statfs{ // This is primarily for distinguishing a gofer file system in @@ -1719,8 +1719,8 @@ func (fs *filesystem) StatFSAt(ctx context.Context, rp *vfs.ResolvingPath) (linu return linux.Statfs{}, err } nameLen := uint64(fsstat.NameLength) - if nameLen == 0 || nameLen > maxFilenameLen { - nameLen = maxFilenameLen + if nameLen == 0 || nameLen > MaxFilenameLen { + nameLen = MaxFilenameLen } return linux.Statfs{ // This is primarily for distinguishing a gofer file system in diff --git a/pkg/sentry/fsimpl/tmpfs/filesystem.go b/pkg/sentry/fsimpl/tmpfs/filesystem.go index e067f136e..5d2c48148 100644 --- a/pkg/sentry/fsimpl/tmpfs/filesystem.go +++ b/pkg/sentry/fsimpl/tmpfs/filesystem.go @@ -69,7 +69,7 @@ afterSymlink: rp.Advance() return d.parent, nil } - if len(name) > linux.NAME_MAX { + if len(name) > d.inode.fs.maxFilenameLen { return nil, linuxerr.ENAMETOOLONG } child, ok := dir.childMap[name] @@ -163,7 +163,7 @@ func (fs *filesystem) doCreateAt(ctx context.Context, rp *vfs.ResolvingPath, dir if name == "." || name == ".." { return linuxerr.EEXIST } - if len(name) > linux.NAME_MAX { + if len(name) > fs.maxFilenameLen { return linuxerr.ENAMETOOLONG } if _, ok := parentDir.childMap[name]; ok { @@ -371,7 +371,7 @@ afterTrailingSymlink: if name == "." || name == ".." { return nil, linuxerr.EISDIR } - if len(name) > linux.NAME_MAX { + if len(name) > fs.maxFilenameLen { return nil, linuxerr.ENAMETOOLONG } // Determine whether or not we need to create a file. diff --git a/pkg/sentry/fsimpl/tmpfs/tmpfs.go b/pkg/sentry/fsimpl/tmpfs/tmpfs.go index f84165aba..80813f8bd 100644 --- a/pkg/sentry/fsimpl/tmpfs/tmpfs.go +++ b/pkg/sentry/fsimpl/tmpfs/tmpfs.go @@ -85,6 +85,8 @@ type filesystem struct { nextInoMinusOne uint64 // accessed using atomic memory operations root *dentry + + maxFilenameLen int } // Name implements vfs.FilesystemType.Name. @@ -115,6 +117,9 @@ type FilesystemOpts struct { // Usage is the memory accounting category under which pages backing files in // the filesystem are accounted. Usage *usage.MemoryKind + + // MaxFilenameLen is the maximum filename length allowed by the tmpfs. + MaxFilenameLen int } // GetFilesystem implements vfs.FilesystemType.GetFilesystem. @@ -126,8 +131,8 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt rootFileType := uint16(linux.S_IFDIR) newFSType := vfs.FilesystemType(&fstype) - tmpfsOpts, ok := opts.InternalData.(FilesystemOpts) - if ok { + tmpfsOpts, tmpfsOptsOk := opts.InternalData.(FilesystemOpts) + if tmpfsOptsOk { if tmpfsOpts.RootFileType != 0 { rootFileType = tmpfsOpts.RootFileType } @@ -198,13 +203,17 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt memUsage = *tmpfsOpts.Usage } fs := filesystem{ - mfp: mfp, - clock: clock, - devMinor: devMinor, - mopts: opts.Data, - usage: memUsage, + mfp: mfp, + clock: clock, + devMinor: devMinor, + mopts: opts.Data, + usage: memUsage, + maxFilenameLen: linux.NAME_MAX, } fs.vfsfs.Init(vfsObj, newFSType, &fs) + if tmpfsOptsOk && tmpfsOpts.MaxFilenameLen > 0 { + fs.maxFilenameLen = tmpfsOpts.MaxFilenameLen + } var root *dentry switch rootFileType {