Skip to content

Commit d346ae7

Browse files
committed
selftests: fifth test for mounting detached mounts onto detached mounts
Add a test to verify that detached mounts behave correctly. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Christian Brauner <[email protected]>
1 parent 1768f9b commit d346ae7

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

tools/testing/selftests/mount_setattr/mount_setattr_test.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1939,4 +1939,82 @@ TEST_F(mount_setattr, attach_detached_mount_then_umount_then_close)
19391939
EXPECT_EQ(close(fd_tree), 0);
19401940
}
19411941

1942+
TEST_F(mount_setattr, mount_detached1_onto_detached2_then_close_detached1_then_mount_detached2_onto_attached)
1943+
{
1944+
int fd_tree1 = -EBADF, fd_tree2 = -EBADF;
1945+
1946+
/*
1947+
* |-/mnt/A testing tmpfs
1948+
* `-/mnt/A/AA testing tmpfs
1949+
* `-/mnt/A/AA/B testing tmpfs
1950+
* `-/mnt/A/AA/B/BB testing tmpfs
1951+
*/
1952+
fd_tree1 = sys_open_tree(-EBADF, "/mnt/A",
1953+
AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW |
1954+
AT_RECURSIVE | OPEN_TREE_CLOEXEC |
1955+
OPEN_TREE_CLONE);
1956+
ASSERT_GE(fd_tree1, 0);
1957+
1958+
/*
1959+
* `-/mnt/B testing ramfs
1960+
*/
1961+
fd_tree2 = sys_open_tree(-EBADF, "/mnt/B",
1962+
AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW |
1963+
AT_EMPTY_PATH | OPEN_TREE_CLOEXEC |
1964+
OPEN_TREE_CLONE);
1965+
ASSERT_GE(fd_tree2, 0);
1966+
1967+
/*
1968+
* Move the source detached mount tree to the target detached
1969+
* mount tree. This will move all the mounts in the source mount
1970+
* tree from the source anonymous mount namespace to the target
1971+
* anonymous mount namespace.
1972+
*
1973+
* The source detached mount tree and the target detached mount
1974+
* tree now both refer to the same anonymous mount namespace.
1975+
*
1976+
* |-"" testing ramfs
1977+
* `-"" testing tmpfs
1978+
* `-""/AA testing tmpfs
1979+
* `-""/AA/B testing tmpfs
1980+
* `-""/AA/B/BB testing tmpfs
1981+
*/
1982+
ASSERT_EQ(move_mount(fd_tree1, "", fd_tree2, "", MOVE_MOUNT_F_EMPTY_PATH | MOVE_MOUNT_T_EMPTY_PATH), 0);
1983+
1984+
/*
1985+
* The source detached mount tree @fd_tree1 is now an attached
1986+
* mount, i.e., it has a parent. Specifically, it now has the
1987+
* root mount of the mount tree of @fd_tree2 as its parent.
1988+
*
1989+
* That means we are no longer allowed to attach it as we only
1990+
* allow attaching the root of an anonymous mount tree, not
1991+
* random bits and pieces. Verify that the kernel enforces this.
1992+
*/
1993+
ASSERT_NE(move_mount(fd_tree1, "", -EBADF, "/tmp/target1", MOVE_MOUNT_F_EMPTY_PATH), 0);
1994+
1995+
/*
1996+
* Closing the source detached mount tree must not unmount and
1997+
* free the shared anonymous mount namespace. The kernel will
1998+
* quickly yell at us because the anonymous mount namespace
1999+
* won't be empty when it's freed.
2000+
*/
2001+
EXPECT_EQ(close(fd_tree1), 0);
2002+
2003+
/*
2004+
* Attach the mount tree to a non-anonymous mount namespace.
2005+
* This can only succeed if closing fd_tree1 had proper
2006+
* semantics and didn't cause the anonymous mount namespace to
2007+
* be freed. If it did this will trigger a UAF which will be
2008+
* visible on any KASAN enabled kernel.
2009+
*
2010+
* |-/tmp/target1 testing ramfs
2011+
* `-/tmp/target1 testing tmpfs
2012+
* `-/tmp/target1/AA testing tmpfs
2013+
* `-/tmp/target1/AA/B testing tmpfs
2014+
* `-/tmp/target1/AA/B/BB testing tmpfs
2015+
*/
2016+
ASSERT_EQ(move_mount(fd_tree2, "", -EBADF, "/tmp/target1", MOVE_MOUNT_F_EMPTY_PATH), 0);
2017+
EXPECT_EQ(close(fd_tree2), 0);
2018+
}
2019+
19422020
TEST_HARNESS_MAIN

0 commit comments

Comments
 (0)