Add name length checks to renameat(2).

In Linux, the callers of fs/namei.c:do_renameat2() do this check
by calling fs/namei.c:getname().

This is important of consistency with Linux. Also, without this
we can see panics in overlayfs rename if new file's name is too
long. Because upperlayer RenameAt operation would succeed but
SetXattr operation will fail leading to an inconsistent state.

PiperOrigin-RevId: 464173793
This commit is contained in:
Ayush Ranjan
2022-07-29 15:48:41 -07:00
committed by gVisor bot
parent 8a7a35e9d6
commit f857f268ec
6 changed files with 26 additions and 0 deletions
+3
View File
@@ -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
+3
View File
@@ -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 {
+3
View File
@@ -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
+3
View File
@@ -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
+4
View File
@@ -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)
+10
View File
@@ -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;