xref: /linux/tools/testing/selftests/filesystems/mntns_cleanup/mntns_cleanup_test.c (revision 1c3e8cef79ea5f1415cff0d3c507e2e07b71ade8)
1*3452eecbSNoah Orlando // SPDX-License-Identifier: GPL-2.0
2*3452eecbSNoah Orlando 
3*3452eecbSNoah Orlando #define _GNU_SOURCE
4*3452eecbSNoah Orlando #include <errno.h>
5*3452eecbSNoah Orlando #include <fcntl.h>
6*3452eecbSNoah Orlando #include <sched.h>
7*3452eecbSNoah Orlando #include <sys/mount.h>
8*3452eecbSNoah Orlando #include <sys/stat.h>
9*3452eecbSNoah Orlando #include <unistd.h>
10*3452eecbSNoah Orlando 
11*3452eecbSNoah Orlando #include "../../kselftest_harness.h"
12*3452eecbSNoah Orlando 
13*3452eecbSNoah Orlando FIXTURE(mntns_cleanup) {
14*3452eecbSNoah Orlando };
15*3452eecbSNoah Orlando 
16*3452eecbSNoah Orlando FIXTURE_SETUP(mntns_cleanup)
17*3452eecbSNoah Orlando {
18*3452eecbSNoah Orlando 	if (geteuid() != 0)
19*3452eecbSNoah Orlando 		SKIP(return, "test requires CAP_SYS_ADMIN");
20*3452eecbSNoah Orlando 
21*3452eecbSNoah Orlando 	ASSERT_EQ(unshare(CLONE_NEWNS), 0);
22*3452eecbSNoah Orlando 	ASSERT_EQ(mount("", "/", NULL, MS_REC | MS_PRIVATE, NULL), 0);
23*3452eecbSNoah Orlando 
24*3452eecbSNoah Orlando 	rmdir("/mnt_dir");
25*3452eecbSNoah Orlando 	ASSERT_EQ(mkdir("/mnt_dir", 0755), 0);
26*3452eecbSNoah Orlando 	ASSERT_EQ(mount("tmpfs", "/mnt_dir", "tmpfs", 0, NULL), 0);
27*3452eecbSNoah Orlando 	ASSERT_EQ(mkdir("/mnt_dir/hidden", 0755), 0);
28*3452eecbSNoah Orlando 	ASSERT_EQ(mkdir("/mnt_dir/hidden/secret", 0755), 0);
29*3452eecbSNoah Orlando 	ASSERT_EQ(mount("tmpfs", "/mnt_dir/hidden", "tmpfs", 0, NULL), 0);
30*3452eecbSNoah Orlando }
31*3452eecbSNoah Orlando 
32*3452eecbSNoah Orlando FIXTURE_TEARDOWN(mntns_cleanup)
33*3452eecbSNoah Orlando {
34*3452eecbSNoah Orlando }
35*3452eecbSNoah Orlando 
36*3452eecbSNoah Orlando /* Mounts must stay connected when a mount namespace is cleaned up. */
37*3452eecbSNoah Orlando TEST_F(mntns_cleanup, keeps_mounts_connected)
38*3452eecbSNoah Orlando {
39*3452eecbSNoah Orlando 	int fd, sfd, err;
40*3452eecbSNoah Orlando 
41*3452eecbSNoah Orlando 	fd = open("/mnt_dir", O_PATH | O_DIRECTORY | O_CLOEXEC);
42*3452eecbSNoah Orlando 	ASSERT_GE(fd, 0);
43*3452eecbSNoah Orlando 
44*3452eecbSNoah Orlando 	/* Destroy the namespace; the fd keeps /mnt_dir alive. */
45*3452eecbSNoah Orlando 	ASSERT_EQ(unshare(CLONE_NEWNS), 0);
46*3452eecbSNoah Orlando 
47*3452eecbSNoah Orlando 	sfd = openat(fd, "hidden/secret", O_RDONLY);
48*3452eecbSNoah Orlando 	err = errno;
49*3452eecbSNoah Orlando 	if (sfd >= 0)
50*3452eecbSNoah Orlando 		close(sfd);
51*3452eecbSNoah Orlando 	close(fd);
52*3452eecbSNoah Orlando 
53*3452eecbSNoah Orlando 	ASSERT_LT(sfd, 0)
54*3452eecbSNoah Orlando 		TH_LOG("mount namespace teardown revealed what the overmount covered");
55*3452eecbSNoah Orlando 	ASSERT_EQ(err, ENOENT);
56*3452eecbSNoah Orlando }
57*3452eecbSNoah Orlando 
58*3452eecbSNoah Orlando TEST_HARNESS_MAIN
59