Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tests: test MOUNT_ATTR_NOSYMFOLLOW with mount_setattr()

Add tests to verify that MOUNT_ATTR_NOSYMFOLLOW is honored.

Cc: Christoph Hellwig <hch@lst.de>
Cc: Mattias Nissler <mnissler@chromium.org>
Cc: Aleksa Sarai <cyphar@cyphar.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Ross Zwisler <zwisler@google.com>
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>

+85 -3
+85 -3
tools/testing/selftests/mount_setattr/mount_setattr_test.c
··· 136 136 #define MOUNT_ATTR_IDMAP 0x00100000 137 137 #endif 138 138 139 + #ifndef MOUNT_ATTR_NOSYMFOLLOW 140 + #define MOUNT_ATTR_NOSYMFOLLOW 0x00200000 141 + #endif 142 + 139 143 static inline int sys_mount_setattr(int dfd, const char *path, unsigned int flags, 140 144 struct mount_attr *attr, size_t size) 141 145 { ··· 239 235 return 0; 240 236 } 241 237 238 + #ifndef ST_NOSYMFOLLOW 239 + #define ST_NOSYMFOLLOW 0x2000 /* do not follow symlinks */ 240 + #endif 241 + 242 242 static int read_mnt_flags(const char *path) 243 243 { 244 244 int ret; ··· 253 245 if (ret != 0) 254 246 return -EINVAL; 255 247 256 - if (stat.f_flag & 257 - ~(ST_RDONLY | ST_NOSUID | ST_NODEV | ST_NOEXEC | ST_NOATIME | 258 - ST_NODIRATIME | ST_RELATIME | ST_SYNCHRONOUS | ST_MANDLOCK)) 248 + if (stat.f_flag & ~(ST_RDONLY | ST_NOSUID | ST_NODEV | ST_NOEXEC | 249 + ST_NOATIME | ST_NODIRATIME | ST_RELATIME | 250 + ST_SYNCHRONOUS | ST_MANDLOCK | ST_NOSYMFOLLOW)) 259 251 return -EINVAL; 260 252 261 253 mnt_flags = 0; ··· 277 269 mnt_flags |= MS_SYNCHRONOUS; 278 270 if (stat.f_flag & ST_MANDLOCK) 279 271 mnt_flags |= ST_MANDLOCK; 272 + if (stat.f_flag & ST_NOSYMFOLLOW) 273 + mnt_flags |= ST_NOSYMFOLLOW; 280 274 281 275 return mnt_flags; 282 276 } ··· 378 368 FIXTURE(mount_setattr) { 379 369 }; 380 370 371 + #define NOSYMFOLLOW_TARGET "/mnt/A/AA/data" 372 + #define NOSYMFOLLOW_SYMLINK "/mnt/A/AA/symlink" 373 + 381 374 FIXTURE_SETUP(mount_setattr) 382 375 { 376 + int fd = -EBADF; 377 + 383 378 if (!mount_setattr_supported()) 384 379 SKIP(return, "mount_setattr syscall not supported"); 385 380 ··· 427 412 428 413 ASSERT_EQ(mount("testing", "/tmp/B/BB", "devpts", 429 414 MS_RELATIME | MS_NOEXEC | MS_RDONLY, 0), 0); 415 + 416 + fd = creat(NOSYMFOLLOW_TARGET, O_RDWR | O_CLOEXEC); 417 + ASSERT_GT(fd, 0); 418 + ASSERT_EQ(symlink(NOSYMFOLLOW_TARGET, NOSYMFOLLOW_SYMLINK), 0); 419 + ASSERT_EQ(close(fd), 0); 430 420 } 431 421 432 422 FIXTURE_TEARDOWN(mount_setattr) ··· 1439 1419 ASSERT_EQ(expected_uid_gid(-EBADF, "/tmp/B/BB/b", 0, 0, 0), 0); 1440 1420 ASSERT_EQ(expected_uid_gid(open_tree_fd, "B/b", 0, 0, 0), 0); 1441 1421 ASSERT_EQ(expected_uid_gid(open_tree_fd, "B/BB/b", 0, 0, 0), 0); 1422 + } 1423 + 1424 + TEST_F(mount_setattr, mount_attr_nosymfollow) 1425 + { 1426 + int fd; 1427 + unsigned int old_flags = 0, new_flags = 0, expected_flags = 0; 1428 + struct mount_attr attr = { 1429 + .attr_set = MOUNT_ATTR_NOSYMFOLLOW, 1430 + }; 1431 + 1432 + if (!mount_setattr_supported()) 1433 + SKIP(return, "mount_setattr syscall not supported"); 1434 + 1435 + fd = open(NOSYMFOLLOW_SYMLINK, O_RDWR | O_CLOEXEC); 1436 + ASSERT_GT(fd, 0); 1437 + ASSERT_EQ(close(fd), 0); 1438 + 1439 + old_flags = read_mnt_flags("/mnt/A"); 1440 + ASSERT_GT(old_flags, 0); 1441 + 1442 + ASSERT_EQ(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0); 1443 + 1444 + expected_flags = old_flags; 1445 + expected_flags |= ST_NOSYMFOLLOW; 1446 + 1447 + new_flags = read_mnt_flags("/mnt/A"); 1448 + ASSERT_EQ(new_flags, expected_flags); 1449 + 1450 + new_flags = read_mnt_flags("/mnt/A/AA"); 1451 + ASSERT_EQ(new_flags, expected_flags); 1452 + 1453 + new_flags = read_mnt_flags("/mnt/A/AA/B"); 1454 + ASSERT_EQ(new_flags, expected_flags); 1455 + 1456 + new_flags = read_mnt_flags("/mnt/A/AA/B/BB"); 1457 + ASSERT_EQ(new_flags, expected_flags); 1458 + 1459 + fd = open(NOSYMFOLLOW_SYMLINK, O_RDWR | O_CLOEXEC); 1460 + ASSERT_LT(fd, 0); 1461 + ASSERT_EQ(errno, ELOOP); 1462 + 1463 + attr.attr_set &= ~MOUNT_ATTR_NOSYMFOLLOW; 1464 + attr.attr_clr |= MOUNT_ATTR_NOSYMFOLLOW; 1465 + 1466 + ASSERT_EQ(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0); 1467 + 1468 + expected_flags &= ~ST_NOSYMFOLLOW; 1469 + new_flags = read_mnt_flags("/mnt/A"); 1470 + ASSERT_EQ(new_flags, expected_flags); 1471 + 1472 + new_flags = read_mnt_flags("/mnt/A/AA"); 1473 + ASSERT_EQ(new_flags, expected_flags); 1474 + 1475 + new_flags = read_mnt_flags("/mnt/A/AA/B"); 1476 + ASSERT_EQ(new_flags, expected_flags); 1477 + 1478 + new_flags = read_mnt_flags("/mnt/A/AA/B/BB"); 1479 + ASSERT_EQ(new_flags, expected_flags); 1480 + 1481 + fd = open(NOSYMFOLLOW_SYMLINK, O_RDWR | O_CLOEXEC); 1482 + ASSERT_GT(fd, 0); 1483 + ASSERT_EQ(close(fd), 0); 1442 1484 } 1443 1485 1444 1486 TEST_HARNESS_MAIN