|
20 | 20 | #include <stdarg.h>
|
21 | 21 | #include <linux/mount.h>
|
22 | 22 |
|
| 23 | +#include "../filesystems/overlayfs/wrappers.h" |
23 | 24 | #include "../kselftest_harness.h"
|
24 | 25 |
|
25 | 26 | #ifndef CLONE_NEWNS
|
@@ -177,51 +178,6 @@ static inline int sys_open_tree(int dfd, const char *filename, unsigned int flag
|
177 | 178 | return syscall(__NR_open_tree, dfd, filename, flags);
|
178 | 179 | }
|
179 | 180 |
|
180 |
| -/* move_mount() flags */ |
181 |
| -#ifndef MOVE_MOUNT_F_SYMLINKS |
182 |
| -#define MOVE_MOUNT_F_SYMLINKS 0x00000001 /* Follow symlinks on from path */ |
183 |
| -#endif |
184 |
| - |
185 |
| -#ifndef MOVE_MOUNT_F_AUTOMOUNTS |
186 |
| -#define MOVE_MOUNT_F_AUTOMOUNTS 0x00000002 /* Follow automounts on from path */ |
187 |
| -#endif |
188 |
| - |
189 |
| -#ifndef MOVE_MOUNT_F_EMPTY_PATH |
190 |
| -#define MOVE_MOUNT_F_EMPTY_PATH 0x00000004 /* Empty from path permitted */ |
191 |
| -#endif |
192 |
| - |
193 |
| -#ifndef MOVE_MOUNT_T_SYMLINKS |
194 |
| -#define MOVE_MOUNT_T_SYMLINKS 0x00000010 /* Follow symlinks on to path */ |
195 |
| -#endif |
196 |
| - |
197 |
| -#ifndef MOVE_MOUNT_T_AUTOMOUNTS |
198 |
| -#define MOVE_MOUNT_T_AUTOMOUNTS 0x00000020 /* Follow automounts on to path */ |
199 |
| -#endif |
200 |
| - |
201 |
| -#ifndef MOVE_MOUNT_T_EMPTY_PATH |
202 |
| -#define MOVE_MOUNT_T_EMPTY_PATH 0x00000040 /* Empty to path permitted */ |
203 |
| -#endif |
204 |
| - |
205 |
| -#ifndef MOVE_MOUNT_SET_GROUP |
206 |
| -#define MOVE_MOUNT_SET_GROUP 0x00000100 /* Set sharing group instead */ |
207 |
| -#endif |
208 |
| - |
209 |
| -#ifndef MOVE_MOUNT_BENEATH |
210 |
| -#define MOVE_MOUNT_BENEATH 0x00000200 /* Mount beneath top mount */ |
211 |
| -#endif |
212 |
| - |
213 |
| -#ifndef MOVE_MOUNT__MASK |
214 |
| -#define MOVE_MOUNT__MASK 0x00000377 |
215 |
| -#endif |
216 |
| - |
217 |
| -static inline int sys_move_mount(int from_dfd, const char *from_pathname, |
218 |
| - int to_dfd, const char *to_pathname, |
219 |
| - unsigned int flags) |
220 |
| -{ |
221 |
| - return syscall(__NR_move_mount, from_dfd, from_pathname, to_dfd, |
222 |
| - to_pathname, flags); |
223 |
| -} |
224 |
| - |
225 | 181 | static ssize_t write_nointr(int fd, const void *buf, size_t count)
|
226 | 182 | {
|
227 | 183 | ssize_t ret;
|
@@ -1789,6 +1745,41 @@ TEST_F(mount_setattr, open_tree_detached_fail3)
|
1789 | 1745 | ASSERT_EQ(errno, EINVAL);
|
1790 | 1746 | }
|
1791 | 1747 |
|
| 1748 | +TEST_F(mount_setattr, open_tree_subfolder) |
| 1749 | +{ |
| 1750 | + int fd_context, fd_tmpfs, fd_tree; |
| 1751 | + |
| 1752 | + fd_context = sys_fsopen("tmpfs", 0); |
| 1753 | + ASSERT_GE(fd_context, 0); |
| 1754 | + |
| 1755 | + ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0); |
| 1756 | + |
| 1757 | + fd_tmpfs = sys_fsmount(fd_context, 0, 0); |
| 1758 | + ASSERT_GE(fd_tmpfs, 0); |
| 1759 | + |
| 1760 | + EXPECT_EQ(close(fd_context), 0); |
| 1761 | + |
| 1762 | + ASSERT_EQ(mkdirat(fd_tmpfs, "subdir", 0755), 0); |
| 1763 | + |
| 1764 | + fd_tree = sys_open_tree(fd_tmpfs, "subdir", |
| 1765 | + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | |
| 1766 | + AT_RECURSIVE | OPEN_TREE_CLOEXEC | |
| 1767 | + OPEN_TREE_CLONE); |
| 1768 | + ASSERT_GE(fd_tree, 0); |
| 1769 | + |
| 1770 | + EXPECT_EQ(close(fd_tmpfs), 0); |
| 1771 | + |
| 1772 | + ASSERT_EQ(mkdirat(-EBADF, "/mnt/open_tree_subfolder", 0755), 0); |
| 1773 | + |
| 1774 | + ASSERT_EQ(sys_move_mount(fd_tree, "", -EBADF, "/mnt/open_tree_subfolder", MOVE_MOUNT_F_EMPTY_PATH), 0); |
| 1775 | + |
| 1776 | + EXPECT_EQ(close(fd_tree), 0); |
| 1777 | + |
| 1778 | + ASSERT_EQ(umount2("/mnt/open_tree_subfolder", 0), 0); |
| 1779 | + |
| 1780 | + EXPECT_EQ(rmdir("/mnt/open_tree_subfolder"), 0); |
| 1781 | +} |
| 1782 | + |
1792 | 1783 | TEST_F(mount_setattr, mount_detached_mount_on_detached_mount_then_close)
|
1793 | 1784 | {
|
1794 | 1785 | int fd_tree_base = -EBADF, fd_tree_subdir = -EBADF;
|
@@ -2097,4 +2088,74 @@ TEST_F(mount_setattr, two_detached_subtrees_of_same_anonymous_mount_namespace)
|
2097 | 2088 | ASSERT_EQ(move_mount(fd_tree1, "", -EBADF, "/tmp/target1", MOVE_MOUNT_F_EMPTY_PATH), 0);
|
2098 | 2089 | }
|
2099 | 2090 |
|
| 2091 | +TEST_F(mount_setattr, detached_tree_propagation) |
| 2092 | +{ |
| 2093 | + int fd_tree = -EBADF; |
| 2094 | + struct statx stx1, stx2, stx3, stx4; |
| 2095 | + |
| 2096 | + ASSERT_EQ(unshare(CLONE_NEWNS), 0); |
| 2097 | + ASSERT_EQ(mount(NULL, "/mnt", NULL, MS_REC | MS_SHARED, NULL), 0); |
| 2098 | + |
| 2099 | + /* |
| 2100 | + * Copy the following mount tree: |
| 2101 | + * |
| 2102 | + * /mnt testing tmpfs |
| 2103 | + * |-/mnt/A testing tmpfs |
| 2104 | + * | `-/mnt/A/AA testing tmpfs |
| 2105 | + * | `-/mnt/A/AA/B testing tmpfs |
| 2106 | + * | `-/mnt/A/AA/B/BB testing tmpfs |
| 2107 | + * `-/mnt/B testing ramfs |
| 2108 | + */ |
| 2109 | + fd_tree = sys_open_tree(-EBADF, "/mnt", |
| 2110 | + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | |
| 2111 | + AT_RECURSIVE | OPEN_TREE_CLOEXEC | |
| 2112 | + OPEN_TREE_CLONE); |
| 2113 | + ASSERT_GE(fd_tree, 0); |
| 2114 | + |
| 2115 | + ASSERT_EQ(statx(-EBADF, "/mnt/A", 0, 0, &stx1), 0); |
| 2116 | + ASSERT_EQ(statx(fd_tree, "A", 0, 0, &stx2), 0); |
| 2117 | + |
| 2118 | + /* |
| 2119 | + * Copying the mount namespace like done above doesn't alter the |
| 2120 | + * mounts in any way so the filesystem mounted on /mnt must be |
| 2121 | + * identical even though the mounts will differ. Use the device |
| 2122 | + * information to verify that. Note that tmpfs will have a 0 |
| 2123 | + * major number so comparing the major number is misleading. |
| 2124 | + */ |
| 2125 | + ASSERT_EQ(stx1.stx_dev_minor, stx2.stx_dev_minor); |
| 2126 | + |
| 2127 | + /* Mount a tmpfs filesystem over /mnt/A. */ |
| 2128 | + ASSERT_EQ(mount(NULL, "/mnt/A", "tmpfs", 0, NULL), 0); |
| 2129 | + |
| 2130 | + |
| 2131 | + ASSERT_EQ(statx(-EBADF, "/mnt/A", 0, 0, &stx3), 0); |
| 2132 | + ASSERT_EQ(statx(fd_tree, "A", 0, 0, &stx4), 0); |
| 2133 | + |
| 2134 | + /* |
| 2135 | + * A new filesystem has been mounted on top of /mnt/A which |
| 2136 | + * means that the device information will be different for any |
| 2137 | + * statx() that was taken from /mnt/A before the mount compared |
| 2138 | + * to one after the mount. |
| 2139 | + * |
| 2140 | + * Since we already now that the device information between the |
| 2141 | + * stx1 and stx2 samples are identical we also now that stx2 and |
| 2142 | + * stx3 device information will necessarily differ. |
| 2143 | + */ |
| 2144 | + ASSERT_NE(stx1.stx_dev_minor, stx3.stx_dev_minor); |
| 2145 | + |
| 2146 | + /* |
| 2147 | + * If mount propagation worked correctly then the tmpfs mount |
| 2148 | + * that was created after the mount namespace was unshared will |
| 2149 | + * have propagated onto /mnt/A in the detached mount tree. |
| 2150 | + * |
| 2151 | + * Verify that the device information for stx3 and stx4 are |
| 2152 | + * identical. It is already established that stx3 is different |
| 2153 | + * from both stx1 and stx2 sampled before the tmpfs mount was |
| 2154 | + * done so if stx3 and stx4 are identical the proof is done. |
| 2155 | + */ |
| 2156 | + ASSERT_EQ(stx3.stx_dev_minor, stx4.stx_dev_minor); |
| 2157 | + |
| 2158 | + EXPECT_EQ(close(fd_tree), 0); |
| 2159 | +} |
| 2160 | + |
2100 | 2161 | TEST_HARNESS_MAIN
|
0 commit comments