@@ -59,7 +59,7 @@ int open_tree(int dfd, const char *filename, unsigned int flags)
59
59
#define RENAME_EXCHANGE (1 << 1)
60
60
#endif
61
61
62
- #define BINARY_PATH "./true"
62
+ static const char bin_true [] = "./true" ;
63
63
64
64
/* Paths (sibling number and depth) */
65
65
static const char dir_s1d1 [] = TMP_DIR "/s1d1" ;
@@ -1965,8 +1965,8 @@ TEST_F_FORK(layout1, relative_chroot_chdir)
1965
1965
test_relative_path (_metadata , REL_CHROOT_CHDIR );
1966
1966
}
1967
1967
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 )
1970
1970
{
1971
1971
int dst_fd , src_fd ;
1972
1972
struct stat statbuf ;
@@ -1976,11 +1976,10 @@ static void copy_binary(struct __test_metadata *const _metadata,
1976
1976
{
1977
1977
TH_LOG ("Failed to open \"%s\": %s" , dst_path , strerror (errno ));
1978
1978
}
1979
- src_fd = open (BINARY_PATH , O_RDONLY | O_CLOEXEC );
1979
+ src_fd = open (src_path , O_RDONLY | O_CLOEXEC );
1980
1980
ASSERT_LE (0 , src_fd )
1981
1981
{
1982
- TH_LOG ("Failed to open \"" BINARY_PATH "\": %s" ,
1983
- strerror (errno ));
1982
+ TH_LOG ("Failed to open \"%s\": %s" , src_path , strerror (errno ));
1984
1983
}
1985
1984
ASSERT_EQ (0 , fstat (src_fd , & statbuf ));
1986
1985
ASSERT_EQ (statbuf .st_size ,
@@ -2028,9 +2027,9 @@ TEST_F_FORK(layout1, execute)
2028
2027
create_ruleset (_metadata , rules [0 ].access , rules );
2029
2028
2030
2029
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 );
2034
2033
2035
2034
enforce_ruleset (_metadata , ruleset_fd );
2036
2035
ASSERT_EQ (0 , close (ruleset_fd ));
@@ -2048,6 +2047,83 @@ TEST_F_FORK(layout1, execute)
2048
2047
test_execute (_metadata , 0 , file1_s1d3 );
2049
2048
}
2050
2049
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
+
2051
2127
TEST_F_FORK (layout1 , link )
2052
2128
{
2053
2129
const struct rule layer1 [] = {
0 commit comments