@@ -1939,4 +1939,82 @@ TEST_F(mount_setattr, attach_detached_mount_then_umount_then_close)
1939
1939
EXPECT_EQ (close (fd_tree ), 0 );
1940
1940
}
1941
1941
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
+
1942
2020
TEST_HARNESS_MAIN
0 commit comments