diff --git a/pkg/sentry/fsimpl/gofer/filesystem.go b/pkg/sentry/fsimpl/gofer/filesystem.go index d1af32204..9ef905d2e 100644 --- a/pkg/sentry/fsimpl/gofer/filesystem.go +++ b/pkg/sentry/fsimpl/gofer/filesystem.go @@ -1486,6 +1486,9 @@ func (fs *filesystem) RenameAt(ctx context.Context, rp *vfs.ResolvingPath, oldPa } return linuxerr.EBUSY } + if len(newName) > MaxFilenameLen { + return linuxerr.ENAMETOOLONG + } mnt := rp.Mount() if mnt != oldParentVD.Mount() { return linuxerr.EXDEV diff --git a/pkg/sentry/fsimpl/kernfs/filesystem.go b/pkg/sentry/fsimpl/kernfs/filesystem.go index f42687218..3c3ea5687 100644 --- a/pkg/sentry/fsimpl/kernfs/filesystem.go +++ b/pkg/sentry/fsimpl/kernfs/filesystem.go @@ -707,6 +707,9 @@ func (fs *Filesystem) RenameAt(ctx context.Context, rp *vfs.ResolvingPath, oldPa } return linuxerr.EBUSY } + if len(newName) > linux.NAME_MAX { + return linuxerr.ENAMETOOLONG + } err = checkCreateLocked(ctx, rp.Credentials(), newName, dstDir) switch { diff --git a/pkg/sentry/fsimpl/overlay/filesystem.go b/pkg/sentry/fsimpl/overlay/filesystem.go index 799e5c7e2..0bb8b439a 100644 --- a/pkg/sentry/fsimpl/overlay/filesystem.go +++ b/pkg/sentry/fsimpl/overlay/filesystem.go @@ -1081,6 +1081,9 @@ func (fs *filesystem) RenameAt(ctx context.Context, rp *vfs.ResolvingPath, oldPa } return linuxerr.EBUSY } + // Do not check for newName length, since different filesystem + // implementations impose different name limits. upperfs.RenameAt() will fail + // appropriately if it has to. mnt := rp.Mount() if mnt != oldParentVD.Mount() { return linuxerr.EXDEV diff --git a/pkg/sentry/fsimpl/tmpfs/filesystem.go b/pkg/sentry/fsimpl/tmpfs/filesystem.go index 6a2eab7a0..c03b97130 100644 --- a/pkg/sentry/fsimpl/tmpfs/filesystem.go +++ b/pkg/sentry/fsimpl/tmpfs/filesystem.go @@ -532,6 +532,9 @@ func (fs *filesystem) RenameAt(ctx context.Context, rp *vfs.ResolvingPath, oldPa } return linuxerr.EBUSY } + if len(newName) > fs.maxFilenameLen { + return linuxerr.ENAMETOOLONG + } mnt := rp.Mount() if mnt != oldParentVD.Mount() { return linuxerr.EXDEV diff --git a/pkg/sentry/vfs/vfs.go b/pkg/sentry/vfs/vfs.go index 0ce44038b..fd7a4da42 100644 --- a/pkg/sentry/vfs/vfs.go +++ b/pkg/sentry/vfs/vfs.go @@ -494,6 +494,10 @@ func (vfs *VirtualFilesystem) RenameAt(ctx context.Context, creds *auth.Credenti oldParentVD.DecRef(ctx) return linuxerr.EBUSY } + if len(oldName) > linux.NAME_MAX { + oldParentVD.DecRef(ctx) + return linuxerr.ENAMETOOLONG + } if !newpop.Path.Begin.Ok() { oldParentVD.DecRef(ctx) diff --git a/test/syscalls/linux/rename.cc b/test/syscalls/linux/rename.cc index dcbc47a88..5ae9dc0d0 100644 --- a/test/syscalls/linux/rename.cc +++ b/test/syscalls/linux/rename.cc @@ -88,6 +88,16 @@ TEST(RenameTest, FileToSameDirectory) { EXPECT_THAT(Exists(newpath), IsPosixErrorOkAndHolds(true)); } +TEST(RenameTest, FileNameTooLong) { + auto old_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); + auto new_base = NextTempBasename(); + int padding = (NAME_MAX + 1) - new_base.size(); + new_base.append(padding, 'x'); + auto new_path = JoinPath(Dirname(old_file.path()), new_base); + ASSERT_THAT(rename(old_file.path().c_str(), new_path.c_str()), + SyscallFailsWithErrno(ENAMETOOLONG)); +} + TEST(RenameTest, RenameAfterWritableFDAndChmod) { // Restore will require re-opening the writable FD which will fail. const DisableSave ds;