• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2014 Red Hat, Inc.
4  * Copyright (C) 2021 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
5  */
6 
7 /*\
8  * [Description]
9  *
10  * Tests a slave mount: slave mount is like a shared mount except that
11  * mount and umount events only propagate towards it.
12  *
13  * [Algorithm]
14  *
15  * - Creates directories DIRA, DIRB and files DIRA/"A", DIRB/"B"
16  * - Unshares mount namespace and makes it private (so mounts/umounts have no
17  *   effect on a real system)
18  * - Bind mounts directory DIRA to itself
19  * - Makes directory DIRA shared
20  * - Clones a new child process with CLONE_NEWNS flag and makes "A" a slave
21  *   mount
22  * - There are two testcases (where X is parent namespace and Y child
23  *   namespace):
24  *  1. First test case
25  *   .. X: bind mounts DIRB to DIRA
26  *   .. Y: must see the file DIRA/"B"
27  *   .. X: umounts DIRA
28  *  2. Second test case
29  *   .. Y: bind mounts DIRB to DIRA
30  *   .. X: must see only the DIRA/"A" and must not see DIRA/"B" (as slave mount does
31  *         not forward propagation)
32  *   .. Y: umounts DIRA
33  */
34 
35 #include <sys/wait.h>
36 #include <sys/mount.h>
37 #include "mountns.h"
38 #include "tst_test.h"
39 
child_func(LTP_ATTRIBUTE_UNUSED void * arg)40 static int child_func(LTP_ATTRIBUTE_UNUSED void *arg)
41 {
42 	/*
43 	 * makes mount DIRA a slave of DIRA (all slave mounts have
44 	 * a master mount which is a shared mount)
45 	 */
46 	SAFE_MOUNT("none", DIRA, "none", MS_SLAVE, NULL);
47 
48 	TST_CHECKPOINT_WAKE_AND_WAIT(0);
49 
50 	if (access(DIRA "/B", F_OK) == 0)
51 		tst_res(TPASS, "propagation to slave mount passed");
52 	else
53 		tst_res(TFAIL, "propagation to slave mount failed");
54 
55 	TST_CHECKPOINT_WAKE_AND_WAIT(0);
56 
57 	SAFE_MOUNT(DIRB, DIRA, "none", MS_BIND, NULL);
58 
59 	TST_CHECKPOINT_WAKE_AND_WAIT(0);
60 
61 	SAFE_UMOUNT(DIRA);
62 
63 	return 0;
64 }
65 
run(void)66 static void run(void)
67 {
68 	int ret;
69 
70 	SAFE_UNSHARE(CLONE_NEWNS);
71 
72 	/* makes sure parent mounts/umounts have no effect on a real system */
73 	SAFE_MOUNT("none", "/", "none", MS_REC | MS_PRIVATE, NULL);
74 
75 	SAFE_MOUNT(DIRA, DIRA, "none", MS_BIND, NULL);
76 
77 	SAFE_MOUNT("none", DIRA, "none", MS_SHARED, NULL);
78 
79 	ret = ltp_clone_quick(CLONE_NEWNS | SIGCHLD, child_func, NULL);
80 	if (ret < 0)
81 		tst_brk(TBROK, "clone failed");
82 
83 	TST_CHECKPOINT_WAIT(0);
84 
85 	SAFE_MOUNT(DIRB, DIRA, "none", MS_BIND, NULL);
86 
87 	TST_CHECKPOINT_WAKE_AND_WAIT(0);
88 
89 	SAFE_UMOUNT(DIRA);
90 
91 	TST_CHECKPOINT_WAKE_AND_WAIT(0);
92 
93 	if ((access(DIRA "/A", F_OK) == 0) && (access(DIRA "/B", F_OK) == -1))
94 		tst_res(TPASS, "propagation from slave mount passed");
95 	else
96 		tst_res(TFAIL, "propagation form slave mount failed");
97 
98 	TST_CHECKPOINT_WAKE(0);
99 
100 	SAFE_WAIT(NULL);
101 
102 	SAFE_UMOUNT(DIRA);
103 }
104 
setup(void)105 static void setup(void)
106 {
107 	check_newns();
108 	create_folders();
109 }
110 
cleanup(void)111 static void cleanup(void)
112 {
113 	umount_folders();
114 }
115 
116 static struct tst_test test = {
117 	.setup = setup,
118 	.cleanup = cleanup,
119 	.test_all = run,
120 	.needs_root = 1,
121 	.needs_checkpoints = 1,
122 };
123