fs.mount_setattr.nosymfollow.v5.14
-----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQRAhzRXHqcMeLMyaSiRxhvAZXjcogUCYNnKNAAKCRCRxhvAZXjc ok/HAQDz3FK3/yeqxH6OLyCedUcD+YBFPPzrfqX+3y6q3z5tGgD9GAGxFXWcMFA2 /cbfmizwh1eJ3WMnbHUp7x6ogpQhWwQ= =PpNs -----END PGP SIGNATURE----- Merge tag 'fs.mount_setattr.nosymfollow.v5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux Pull mount_setattr updates from Christian Brauner: "A few releases ago the old mount API gained support for a mount options which prevents following symlinks on a given mount. This adds support for it in the new mount api through the MOUNT_ATTR_NOSYMFOLLOW flag via mount_setattr() and fsmount(). With mount_setattr() that flag can even be applied recursively. There's an additional ack from Ross Zwisler who originally authored the nosymfollow patch. As I've already had the patches in my for-next I didn't add his ack explicitly" * tag 'fs.mount_setattr.nosymfollow.v5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux: tests: test MOUNT_ATTR_NOSYMFOLLOW with mount_setattr() mount: Support "nosymfollow" in new mount api
This commit is contained in:
commit
30d1a556a9
|
@ -3464,9 +3464,10 @@ out_type:
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define FSMOUNT_VALID_FLAGS \
|
||||
(MOUNT_ATTR_RDONLY | MOUNT_ATTR_NOSUID | MOUNT_ATTR_NODEV | \
|
||||
MOUNT_ATTR_NOEXEC | MOUNT_ATTR__ATIME | MOUNT_ATTR_NODIRATIME)
|
||||
#define FSMOUNT_VALID_FLAGS \
|
||||
(MOUNT_ATTR_RDONLY | MOUNT_ATTR_NOSUID | MOUNT_ATTR_NODEV | \
|
||||
MOUNT_ATTR_NOEXEC | MOUNT_ATTR__ATIME | MOUNT_ATTR_NODIRATIME | \
|
||||
MOUNT_ATTR_NOSYMFOLLOW)
|
||||
|
||||
#define MOUNT_SETATTR_VALID_FLAGS (FSMOUNT_VALID_FLAGS | MOUNT_ATTR_IDMAP)
|
||||
|
||||
|
@ -3487,6 +3488,8 @@ static unsigned int attr_flags_to_mnt_flags(u64 attr_flags)
|
|||
mnt_flags |= MNT_NOEXEC;
|
||||
if (attr_flags & MOUNT_ATTR_NODIRATIME)
|
||||
mnt_flags |= MNT_NODIRATIME;
|
||||
if (attr_flags & MOUNT_ATTR_NOSYMFOLLOW)
|
||||
mnt_flags |= MNT_NOSYMFOLLOW;
|
||||
|
||||
return mnt_flags;
|
||||
}
|
||||
|
|
|
@ -120,6 +120,7 @@ enum fsconfig_command {
|
|||
#define MOUNT_ATTR_STRICTATIME 0x00000020 /* - Always perform atime updates */
|
||||
#define MOUNT_ATTR_NODIRATIME 0x00000080 /* Do not update directory access times */
|
||||
#define MOUNT_ATTR_IDMAP 0x00100000 /* Idmap mount to @userns_fd in struct mount_attr. */
|
||||
#define MOUNT_ATTR_NOSYMFOLLOW 0x00200000 /* Do not follow symlinks */
|
||||
|
||||
/*
|
||||
* mount_setattr()
|
||||
|
|
|
@ -136,6 +136,10 @@ struct mount_attr {
|
|||
#define MOUNT_ATTR_IDMAP 0x00100000
|
||||
#endif
|
||||
|
||||
#ifndef MOUNT_ATTR_NOSYMFOLLOW
|
||||
#define MOUNT_ATTR_NOSYMFOLLOW 0x00200000
|
||||
#endif
|
||||
|
||||
static inline int sys_mount_setattr(int dfd, const char *path, unsigned int flags,
|
||||
struct mount_attr *attr, size_t size)
|
||||
{
|
||||
|
@ -235,6 +239,10 @@ static int prepare_unpriv_mountns(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef ST_NOSYMFOLLOW
|
||||
#define ST_NOSYMFOLLOW 0x2000 /* do not follow symlinks */
|
||||
#endif
|
||||
|
||||
static int read_mnt_flags(const char *path)
|
||||
{
|
||||
int ret;
|
||||
|
@ -245,9 +253,9 @@ static int read_mnt_flags(const char *path)
|
|||
if (ret != 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (stat.f_flag &
|
||||
~(ST_RDONLY | ST_NOSUID | ST_NODEV | ST_NOEXEC | ST_NOATIME |
|
||||
ST_NODIRATIME | ST_RELATIME | ST_SYNCHRONOUS | ST_MANDLOCK))
|
||||
if (stat.f_flag & ~(ST_RDONLY | ST_NOSUID | ST_NODEV | ST_NOEXEC |
|
||||
ST_NOATIME | ST_NODIRATIME | ST_RELATIME |
|
||||
ST_SYNCHRONOUS | ST_MANDLOCK | ST_NOSYMFOLLOW))
|
||||
return -EINVAL;
|
||||
|
||||
mnt_flags = 0;
|
||||
|
@ -269,6 +277,8 @@ static int read_mnt_flags(const char *path)
|
|||
mnt_flags |= MS_SYNCHRONOUS;
|
||||
if (stat.f_flag & ST_MANDLOCK)
|
||||
mnt_flags |= ST_MANDLOCK;
|
||||
if (stat.f_flag & ST_NOSYMFOLLOW)
|
||||
mnt_flags |= ST_NOSYMFOLLOW;
|
||||
|
||||
return mnt_flags;
|
||||
}
|
||||
|
@ -368,8 +378,13 @@ static bool mount_setattr_supported(void)
|
|||
FIXTURE(mount_setattr) {
|
||||
};
|
||||
|
||||
#define NOSYMFOLLOW_TARGET "/mnt/A/AA/data"
|
||||
#define NOSYMFOLLOW_SYMLINK "/mnt/A/AA/symlink"
|
||||
|
||||
FIXTURE_SETUP(mount_setattr)
|
||||
{
|
||||
int fd = -EBADF;
|
||||
|
||||
if (!mount_setattr_supported())
|
||||
SKIP(return, "mount_setattr syscall not supported");
|
||||
|
||||
|
@ -412,6 +427,11 @@ FIXTURE_SETUP(mount_setattr)
|
|||
|
||||
ASSERT_EQ(mount("testing", "/tmp/B/BB", "devpts",
|
||||
MS_RELATIME | MS_NOEXEC | MS_RDONLY, 0), 0);
|
||||
|
||||
fd = creat(NOSYMFOLLOW_TARGET, O_RDWR | O_CLOEXEC);
|
||||
ASSERT_GT(fd, 0);
|
||||
ASSERT_EQ(symlink(NOSYMFOLLOW_TARGET, NOSYMFOLLOW_SYMLINK), 0);
|
||||
ASSERT_EQ(close(fd), 0);
|
||||
}
|
||||
|
||||
FIXTURE_TEARDOWN(mount_setattr)
|
||||
|
@ -1421,4 +1441,66 @@ TEST_F(mount_setattr_idmapped, idmap_mount_tree_invalid)
|
|||
ASSERT_EQ(expected_uid_gid(open_tree_fd, "B/BB/b", 0, 0, 0), 0);
|
||||
}
|
||||
|
||||
TEST_F(mount_setattr, mount_attr_nosymfollow)
|
||||
{
|
||||
int fd;
|
||||
unsigned int old_flags = 0, new_flags = 0, expected_flags = 0;
|
||||
struct mount_attr attr = {
|
||||
.attr_set = MOUNT_ATTR_NOSYMFOLLOW,
|
||||
};
|
||||
|
||||
if (!mount_setattr_supported())
|
||||
SKIP(return, "mount_setattr syscall not supported");
|
||||
|
||||
fd = open(NOSYMFOLLOW_SYMLINK, O_RDWR | O_CLOEXEC);
|
||||
ASSERT_GT(fd, 0);
|
||||
ASSERT_EQ(close(fd), 0);
|
||||
|
||||
old_flags = read_mnt_flags("/mnt/A");
|
||||
ASSERT_GT(old_flags, 0);
|
||||
|
||||
ASSERT_EQ(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
|
||||
|
||||
expected_flags = old_flags;
|
||||
expected_flags |= ST_NOSYMFOLLOW;
|
||||
|
||||
new_flags = read_mnt_flags("/mnt/A");
|
||||
ASSERT_EQ(new_flags, expected_flags);
|
||||
|
||||
new_flags = read_mnt_flags("/mnt/A/AA");
|
||||
ASSERT_EQ(new_flags, expected_flags);
|
||||
|
||||
new_flags = read_mnt_flags("/mnt/A/AA/B");
|
||||
ASSERT_EQ(new_flags, expected_flags);
|
||||
|
||||
new_flags = read_mnt_flags("/mnt/A/AA/B/BB");
|
||||
ASSERT_EQ(new_flags, expected_flags);
|
||||
|
||||
fd = open(NOSYMFOLLOW_SYMLINK, O_RDWR | O_CLOEXEC);
|
||||
ASSERT_LT(fd, 0);
|
||||
ASSERT_EQ(errno, ELOOP);
|
||||
|
||||
attr.attr_set &= ~MOUNT_ATTR_NOSYMFOLLOW;
|
||||
attr.attr_clr |= MOUNT_ATTR_NOSYMFOLLOW;
|
||||
|
||||
ASSERT_EQ(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0);
|
||||
|
||||
expected_flags &= ~ST_NOSYMFOLLOW;
|
||||
new_flags = read_mnt_flags("/mnt/A");
|
||||
ASSERT_EQ(new_flags, expected_flags);
|
||||
|
||||
new_flags = read_mnt_flags("/mnt/A/AA");
|
||||
ASSERT_EQ(new_flags, expected_flags);
|
||||
|
||||
new_flags = read_mnt_flags("/mnt/A/AA/B");
|
||||
ASSERT_EQ(new_flags, expected_flags);
|
||||
|
||||
new_flags = read_mnt_flags("/mnt/A/AA/B/BB");
|
||||
ASSERT_EQ(new_flags, expected_flags);
|
||||
|
||||
fd = open(NOSYMFOLLOW_SYMLINK, O_RDWR | O_CLOEXEC);
|
||||
ASSERT_GT(fd, 0);
|
||||
ASSERT_EQ(close(fd), 0);
|
||||
}
|
||||
|
||||
TEST_HARNESS_MAIN
|
||||
|
|
Loading…
Reference in New Issue