@@ -59,7 +59,7 @@ int open_tree(int dfd, const char *filename, unsigned int flags)
5959#define RENAME_EXCHANGE (1 << 1)
6060#endif
6161
62- #define BINARY_PATH "./true"
62+ static const char bin_true [] = "./true" ;
6363
6464/* Paths (sibling number and depth) */
6565static const char dir_s1d1 [] = TMP_DIR "/s1d1" ;
@@ -1965,8 +1965,8 @@ TEST_F_FORK(layout1, relative_chroot_chdir)
19651965 test_relative_path (_metadata , REL_CHROOT_CHDIR );
19661966}
19671967
1968- static void copy_binary (struct __test_metadata * const _metadata ,
1969- const char * const dst_path )
1968+ static void copy_file (struct __test_metadata * const _metadata ,
1969+ const char * const src_path , const char * const dst_path )
19701970{
19711971 int dst_fd , src_fd ;
19721972 struct stat statbuf ;
@@ -1976,11 +1976,10 @@ static void copy_binary(struct __test_metadata *const _metadata,
19761976 {
19771977 TH_LOG ("Failed to open \"%s\": %s" , dst_path , strerror (errno ));
19781978 }
1979- src_fd = open (BINARY_PATH , O_RDONLY | O_CLOEXEC );
1979+ src_fd = open (src_path , O_RDONLY | O_CLOEXEC );
19801980 ASSERT_LE (0 , src_fd )
19811981 {
1982- TH_LOG ("Failed to open \"" BINARY_PATH "\": %s" ,
1983- strerror (errno ));
1982+ TH_LOG ("Failed to open \"%s\": %s" , src_path , strerror (errno ));
19841983 }
19851984 ASSERT_EQ (0 , fstat (src_fd , & statbuf ));
19861985 ASSERT_EQ (statbuf .st_size ,
@@ -2028,9 +2027,9 @@ TEST_F_FORK(layout1, execute)
20282027 create_ruleset (_metadata , rules [0 ].access , rules );
20292028
20302029 ASSERT_LE (0 , ruleset_fd );
2031- copy_binary (_metadata , file1_s1d1 );
2032- copy_binary (_metadata , file1_s1d2 );
2033- copy_binary (_metadata , file1_s1d3 );
2030+ copy_file (_metadata , bin_true , file1_s1d1 );
2031+ copy_file (_metadata , bin_true , file1_s1d2 );
2032+ copy_file (_metadata , bin_true , file1_s1d3 );
20342033
20352034 enforce_ruleset (_metadata , ruleset_fd );
20362035 ASSERT_EQ (0 , close (ruleset_fd ));
@@ -2048,6 +2047,83 @@ TEST_F_FORK(layout1, execute)
20482047 test_execute (_metadata , 0 , file1_s1d3 );
20492048}
20502049
2050+ TEST_F_FORK (layout1 , umount_sandboxer )
2051+ {
2052+ int pipe_child [2 ], pipe_parent [2 ];
2053+ char buf_parent ;
2054+ pid_t child ;
2055+ int status ;
2056+
2057+ copy_file (_metadata , bin_sandbox_and_launch , file1_s3d3 );
2058+ ASSERT_EQ (0 , pipe2 (pipe_child , 0 ));
2059+ ASSERT_EQ (0 , pipe2 (pipe_parent , 0 ));
2060+
2061+ child = fork ();
2062+ ASSERT_LE (0 , child );
2063+ if (child == 0 ) {
2064+ char pipe_child_str [12 ], pipe_parent_str [12 ];
2065+ char * const argv [] = { (char * )file1_s3d3 ,
2066+ (char * )bin_wait_pipe , pipe_child_str ,
2067+ pipe_parent_str , NULL };
2068+
2069+ /* Passes the pipe FDs to the executed binary and its child. */
2070+ EXPECT_EQ (0 , close (pipe_child [0 ]));
2071+ EXPECT_EQ (0 , close (pipe_parent [1 ]));
2072+ snprintf (pipe_child_str , sizeof (pipe_child_str ), "%d" ,
2073+ pipe_child [1 ]);
2074+ snprintf (pipe_parent_str , sizeof (pipe_parent_str ), "%d" ,
2075+ pipe_parent [0 ]);
2076+
2077+ /*
2078+ * We need bin_sandbox_and_launch (copied inside the mount as
2079+ * file1_s3d3) to execute bin_wait_pipe (outside the mount) to
2080+ * make sure the mount point will not be EBUSY because of
2081+ * file1_s3d3 being in use. This avoids a potential race
2082+ * condition between the following read() and umount() calls.
2083+ */
2084+ ASSERT_EQ (0 , execve (argv [0 ], argv , NULL ))
2085+ {
2086+ TH_LOG ("Failed to execute \"%s\": %s" , argv [0 ],
2087+ strerror (errno ));
2088+ };
2089+ _exit (1 );
2090+ return ;
2091+ }
2092+
2093+ EXPECT_EQ (0 , close (pipe_child [1 ]));
2094+ EXPECT_EQ (0 , close (pipe_parent [0 ]));
2095+
2096+ /* Waits for the child to sandbox itself. */
2097+ EXPECT_EQ (1 , read (pipe_child [0 ], & buf_parent , 1 ));
2098+
2099+ /* Tests that the sandboxer is tied to its mount point. */
2100+ set_cap (_metadata , CAP_SYS_ADMIN );
2101+ EXPECT_EQ (-1 , umount (dir_s3d2 ));
2102+ EXPECT_EQ (EBUSY , errno );
2103+ clear_cap (_metadata , CAP_SYS_ADMIN );
2104+
2105+ /* Signals the child to launch a grandchild. */
2106+ EXPECT_EQ (1 , write (pipe_parent [1 ], "." , 1 ));
2107+
2108+ /* Waits for the grandchild. */
2109+ EXPECT_EQ (1 , read (pipe_child [0 ], & buf_parent , 1 ));
2110+
2111+ /* Tests that the domain's sandboxer is not tied to its mount point. */
2112+ set_cap (_metadata , CAP_SYS_ADMIN );
2113+ EXPECT_EQ (0 , umount (dir_s3d2 ))
2114+ {
2115+ TH_LOG ("Failed to umount \"%s\": %s" , dir_s3d2 ,
2116+ strerror (errno ));
2117+ };
2118+ clear_cap (_metadata , CAP_SYS_ADMIN );
2119+
2120+ /* Signals the grandchild to terminate. */
2121+ EXPECT_EQ (1 , write (pipe_parent [1 ], "." , 1 ));
2122+ ASSERT_EQ (child , waitpid (child , & status , 0 ));
2123+ ASSERT_EQ (1 , WIFEXITED (status ));
2124+ ASSERT_EQ (0 , WEXITSTATUS (status ));
2125+ }
2126+
20512127TEST_F_FORK (layout1 , link )
20522128{
20532129 const struct rule layer1 [] = {
0 commit comments