mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Handle UMOUNT_NOFOLLOW in VFS2 umount(2).
Reported-by: syzbot+f9ecb181a4b3abdde9b9@syzkaller.appspotmail.com Reported-by: syzbot+8c5cb9d7a044a91a513b@syzkaller.appspotmail.com PiperOrigin-RevId: 406951359
This commit is contained in:
@@ -136,14 +136,14 @@ func Umount2(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
tpop, err := getTaskPathOperation(t, linux.AT_FDCWD, path, disallowEmptyPath, nofollowFinalSymlink)
|
||||
tpop, err := getTaskPathOperation(t, linux.AT_FDCWD, path, disallowEmptyPath, shouldFollowFinalSymlink(flags&linux.UMOUNT_NOFOLLOW == 0))
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
defer tpop.Release(t)
|
||||
|
||||
opts := vfs.UmountOptions{
|
||||
Flags: uint32(flags),
|
||||
Flags: uint32(flags &^ linux.UMOUNT_NOFOLLOW),
|
||||
}
|
||||
|
||||
return 0, nil, t.Kernel().VFS().UmountAt(t, creds, &tpop.pop, &opts)
|
||||
|
||||
@@ -115,6 +115,40 @@ TEST(MountTest, OpenFileBusy) {
|
||||
EXPECT_THAT(umount(dir.path().c_str()), SyscallFailsWithErrno(EBUSY));
|
||||
}
|
||||
|
||||
TEST(MountTest, UmountNoFollow) {
|
||||
SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
|
||||
|
||||
auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
|
||||
|
||||
auto const mountPoint = NewTempAbsPathInDir(dir.path());
|
||||
ASSERT_THAT(mkdir(mountPoint.c_str(), 0777), SyscallSucceeds());
|
||||
|
||||
// Create a symlink in dir which will point to the actual mountpoint.
|
||||
const std::string symlinkInDir = NewTempAbsPathInDir(dir.path());
|
||||
EXPECT_THAT(symlink(mountPoint.c_str(), symlinkInDir.c_str()),
|
||||
SyscallSucceeds());
|
||||
|
||||
// Create a symlink to the dir.
|
||||
const std::string symlinkToDir = NewTempAbsPath();
|
||||
EXPECT_THAT(symlink(dir.path().c_str(), symlinkToDir.c_str()),
|
||||
SyscallSucceeds());
|
||||
|
||||
// Should fail with ELOOP when UMOUNT_NOFOLLOW is specified and the last
|
||||
// component is a symlink.
|
||||
auto mount = ASSERT_NO_ERRNO_AND_VALUE(
|
||||
Mount("", mountPoint, "tmpfs", 0, "mode=0700", 0));
|
||||
EXPECT_THAT(umount2(symlinkInDir.c_str(), UMOUNT_NOFOLLOW),
|
||||
SyscallFailsWithErrno(EINVAL));
|
||||
EXPECT_THAT(unlink(symlinkInDir.c_str()), SyscallSucceeds());
|
||||
|
||||
// UMOUNT_NOFOLLOW should only apply to the last path component. A symlink in
|
||||
// non-last path component should be just fine.
|
||||
EXPECT_THAT(umount2(JoinPath(symlinkToDir, Basename(mountPoint)).c_str(),
|
||||
UMOUNT_NOFOLLOW),
|
||||
SyscallSucceeds());
|
||||
mount.Release();
|
||||
}
|
||||
|
||||
TEST(MountTest, UmountDetach) {
|
||||
SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user