@@ -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+
19422020TEST_HARNESS_MAIN
0 commit comments