Certain mount attributes are meant to be locked when sharing mounts with another mount namespace. This validates that behaviour holds as expected. - Locked attributes are not changeable - Non-locked attributes can be changed, and changed back Test output: sudo ./mount_setattr_test -t mount_attr_lock make: Nothing to be done for 'all'. TAP version 13 1..1 # Starting 1 tests from 1 test cases. # RUN mount_setattr.mount_attr_lock ... # OK mount_setattr.mount_attr_lock ok 1 mount_setattr.mount_attr_lock # PASSED: 1 / 1 tests passed. # Totals: pass:1 fail:0 xfail:0 xpass:0 skip:0 error:0 Signed-off-by: Sargun Dhillon <sargun@xxxxxxxxx> --- .../mount_setattr/mount_setattr_test.c | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/tools/testing/selftests/mount_setattr/mount_setattr_test.c b/tools/testing/selftests/mount_setattr/mount_setattr_test.c index c6a8c732b802..2aaa4aae41f5 100644 --- a/tools/testing/selftests/mount_setattr/mount_setattr_test.c +++ b/tools/testing/selftests/mount_setattr/mount_setattr_test.c @@ -400,6 +400,11 @@ FIXTURE_SETUP(mount_setattr) ASSERT_EQ(mount("testing", "/tmp/B/BB", "tmpfs", MS_NOATIME | MS_NODEV, "size=100000,mode=700"), 0); + ASSERT_EQ(mkdir("/tmp/C", 0777), 0); + + ASSERT_EQ(mount("testing", "/tmp/C", "tmpfs", MS_NOATIME, + "size=100000,mode=700"), 0); + ASSERT_EQ(mount("testing", "/mnt", "tmpfs", MS_NOATIME | MS_NODEV, "size=100000,mode=700"), 0); @@ -1497,4 +1502,53 @@ TEST_F(mount_setattr, mount_attr_nosymfollow) ASSERT_EQ(close(fd), 0); } +TEST_F(mount_setattr, mount_attr_lock) +{ + struct mount_attr attr = { + .attr_set = MOUNT_ATTR_RDONLY|MOUNT_ATTR_NOSUID|MOUNT_ATTR_NODEV, + }; + + ASSERT_EQ(sys_mount_setattr(-1, "/tmp/C", 0, &attr, sizeof(attr)), 0); + ASSERT_EQ(prepare_unpriv_mountns(), 0); + + attr.attr_set = 0; + attr.attr_clr = MOUNT_ATTR_RDONLY; + ASSERT_EQ(sys_mount_setattr(-1, "/tmp/C", 0, &attr, sizeof(attr)), -1); + ASSERT_EQ(errno, EPERM); + + attr.attr_clr = MOUNT_ATTR_NOSUID; + ASSERT_EQ(sys_mount_setattr(-1, "/tmp/C", 0, &attr, sizeof(attr)), -1); + ASSERT_EQ(errno, EPERM); + + attr.attr_clr = MOUNT_ATTR_NODEV; + ASSERT_EQ(sys_mount_setattr(-1, "/tmp/C", 0, &attr, sizeof(attr)), -1); + ASSERT_EQ(errno, EPERM); + + /* Do not allow changing any atime flags after locking */ + attr.attr_set = MOUNT_ATTR_RELATIME; + attr.attr_clr = MOUNT_ATTR__ATIME; + ASSERT_EQ(sys_mount_setattr(-1, "/tmp/C", 0, &attr, sizeof(attr)), -1); + ASSERT_EQ(errno, EPERM); + + attr.attr_set = MOUNT_ATTR_STRICTATIME; + ASSERT_EQ(sys_mount_setattr(-1, "/tmp/C", 0, &attr, sizeof(attr)), -1); + ASSERT_EQ(errno, EPERM); + + attr.attr_set = MOUNT_ATTR_NODIRATIME; + ASSERT_EQ(sys_mount_setattr(-1, "/tmp/C", 0, &attr, sizeof(attr)), -1); + ASSERT_EQ(errno, EPERM); + + /* + * "re-setting" the atime setting to the same value should work. + * Also, to make sure this isn't a no-op, try making things less permissive + */ + attr.attr_set = MOUNT_ATTR_NOATIME | MOUNT_ATTR_NOEXEC; + ASSERT_EQ(sys_mount_setattr(-1, "/tmp/C", 0, &attr, sizeof(attr)), 0); + + /* We should still be allowed to clear the attribute we set */ + attr.attr_set = 0; + attr.attr_clr = MOUNT_ATTR_NOEXEC; + ASSERT_EQ(sys_mount_setattr(-1, "/tmp/C", 0, &attr, sizeof(attr)), 0); +} + TEST_HARNESS_MAIN -- 2.39.3