iterate_mntns.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. // Copyright (c) 2024 Christian Brauner <brauner@kernel.org>
  3. #define _GNU_SOURCE
  4. #include <fcntl.h>
  5. #include <linux/auto_dev-ioctl.h>
  6. #include <linux/errno.h>
  7. #include <sched.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <sys/stat.h>
  11. #include <sys/mount.h>
  12. #include <unistd.h>
  13. #include "kselftest_harness.h"
  14. #define MNT_NS_COUNT 11
  15. #define MNT_NS_LAST_INDEX 10
  16. struct mnt_ns_info {
  17. __u32 size;
  18. __u32 nr_mounts;
  19. __u64 mnt_ns_id;
  20. };
  21. #define MNT_NS_INFO_SIZE_VER0 16 /* size of first published struct */
  22. /* Get information about namespace. */
  23. #define NS_MNT_GET_INFO _IOR(0xb7, 10, struct mnt_ns_info)
  24. /* Get next namespace. */
  25. #define NS_MNT_GET_NEXT _IOR(0xb7, 11, struct mnt_ns_info)
  26. /* Get previous namespace. */
  27. #define NS_MNT_GET_PREV _IOR(0xb7, 12, struct mnt_ns_info)
  28. FIXTURE(iterate_mount_namespaces) {
  29. int fd_mnt_ns[MNT_NS_COUNT];
  30. __u64 mnt_ns_id[MNT_NS_COUNT];
  31. };
  32. static inline bool mntns_in_list(__u64 *mnt_ns_id, struct mnt_ns_info *info)
  33. {
  34. for (int i = 0; i < MNT_NS_COUNT; i++) {
  35. if (mnt_ns_id[i] == info->mnt_ns_id)
  36. return true;
  37. }
  38. return false;
  39. }
  40. FIXTURE_SETUP(iterate_mount_namespaces)
  41. {
  42. for (int i = 0; i < MNT_NS_COUNT; i++)
  43. self->fd_mnt_ns[i] = -EBADF;
  44. for (int i = 0; i < MNT_NS_COUNT; i++) {
  45. struct mnt_ns_info info = {};
  46. ASSERT_EQ(unshare(CLONE_NEWNS), 0);
  47. self->fd_mnt_ns[i] = open("/proc/self/ns/mnt", O_RDONLY | O_CLOEXEC);
  48. ASSERT_GE(self->fd_mnt_ns[i], 0);
  49. ASSERT_EQ(ioctl(self->fd_mnt_ns[i], NS_MNT_GET_INFO, &info), 0);
  50. self->mnt_ns_id[i] = info.mnt_ns_id;
  51. }
  52. }
  53. FIXTURE_TEARDOWN(iterate_mount_namespaces)
  54. {
  55. for (int i = 0; i < MNT_NS_COUNT; i++) {
  56. if (self->fd_mnt_ns[i] < 0)
  57. continue;
  58. ASSERT_EQ(close(self->fd_mnt_ns[i]), 0);
  59. }
  60. }
  61. TEST_F(iterate_mount_namespaces, iterate_all_forward)
  62. {
  63. int fd_mnt_ns_cur, count = 0;
  64. fd_mnt_ns_cur = fcntl(self->fd_mnt_ns[0], F_DUPFD_CLOEXEC);
  65. ASSERT_GE(fd_mnt_ns_cur, 0);
  66. for (;;) {
  67. struct mnt_ns_info info = {};
  68. int fd_mnt_ns_next;
  69. fd_mnt_ns_next = ioctl(fd_mnt_ns_cur, NS_MNT_GET_NEXT, &info);
  70. if (fd_mnt_ns_next < 0 && errno == ENOENT)
  71. break;
  72. if (mntns_in_list(self->mnt_ns_id, &info))
  73. count++;
  74. ASSERT_GE(fd_mnt_ns_next, 0);
  75. ASSERT_EQ(close(fd_mnt_ns_cur), 0);
  76. fd_mnt_ns_cur = fd_mnt_ns_next;
  77. }
  78. ASSERT_EQ(count, MNT_NS_LAST_INDEX);
  79. }
  80. TEST_F(iterate_mount_namespaces, iterate_all_backwards)
  81. {
  82. int fd_mnt_ns_cur, count = 0;
  83. fd_mnt_ns_cur = fcntl(self->fd_mnt_ns[MNT_NS_LAST_INDEX], F_DUPFD_CLOEXEC);
  84. ASSERT_GE(fd_mnt_ns_cur, 0);
  85. for (;;) {
  86. struct mnt_ns_info info = {};
  87. int fd_mnt_ns_prev;
  88. fd_mnt_ns_prev = ioctl(fd_mnt_ns_cur, NS_MNT_GET_PREV, &info);
  89. if (fd_mnt_ns_prev < 0 && errno == ENOENT)
  90. break;
  91. if (mntns_in_list(self->mnt_ns_id, &info))
  92. count++;
  93. ASSERT_GE(fd_mnt_ns_prev, 0);
  94. ASSERT_EQ(close(fd_mnt_ns_cur), 0);
  95. fd_mnt_ns_cur = fd_mnt_ns_prev;
  96. }
  97. ASSERT_EQ(count, MNT_NS_LAST_INDEX);
  98. }
  99. TEST_F(iterate_mount_namespaces, iterate_forward)
  100. {
  101. int fd_mnt_ns_cur;
  102. ASSERT_EQ(setns(self->fd_mnt_ns[0], CLONE_NEWNS), 0);
  103. fd_mnt_ns_cur = self->fd_mnt_ns[0];
  104. for (int i = 1; i < MNT_NS_COUNT; i++) {
  105. struct mnt_ns_info info = {};
  106. int fd_mnt_ns_next;
  107. fd_mnt_ns_next = ioctl(fd_mnt_ns_cur, NS_MNT_GET_NEXT, &info);
  108. ASSERT_GE(fd_mnt_ns_next, 0);
  109. ASSERT_EQ(close(fd_mnt_ns_cur), 0);
  110. fd_mnt_ns_cur = fd_mnt_ns_next;
  111. }
  112. }
  113. TEST_F(iterate_mount_namespaces, iterate_backward)
  114. {
  115. int fd_mnt_ns_cur;
  116. ASSERT_EQ(setns(self->fd_mnt_ns[MNT_NS_LAST_INDEX], CLONE_NEWNS), 0);
  117. fd_mnt_ns_cur = self->fd_mnt_ns[MNT_NS_LAST_INDEX];
  118. for (int i = MNT_NS_LAST_INDEX - 1; i >= 0; i--) {
  119. struct mnt_ns_info info = {};
  120. int fd_mnt_ns_prev;
  121. fd_mnt_ns_prev = ioctl(fd_mnt_ns_cur, NS_MNT_GET_PREV, &info);
  122. ASSERT_GE(fd_mnt_ns_prev, 0);
  123. ASSERT_EQ(close(fd_mnt_ns_cur), 0);
  124. fd_mnt_ns_cur = fd_mnt_ns_prev;
  125. }
  126. }
  127. TEST_F(iterate_mount_namespaces, nfs_valid_ioctl)
  128. {
  129. ASSERT_NE(ioctl(self->fd_mnt_ns[0], AUTOFS_DEV_IOCTL_OPENMOUNT, NULL), 0);
  130. ASSERT_EQ(errno, ENOTTY);
  131. ASSERT_NE(ioctl(self->fd_mnt_ns[0], AUTOFS_DEV_IOCTL_CLOSEMOUNT, NULL), 0);
  132. ASSERT_EQ(errno, ENOTTY);
  133. ASSERT_NE(ioctl(self->fd_mnt_ns[0], AUTOFS_DEV_IOCTL_READY, NULL), 0);
  134. ASSERT_EQ(errno, ENOTTY);
  135. }
  136. TEST_HARNESS_MAIN