• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) Huawei Technologies Co., Ltd., 2015
4  * Copyright (C) 2022 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
5  */
6 
7 /*\
8  * [Description]
9  *
10  * Verify that if a process created via fork(2) or clone(2) without the
11  * CLONE_NEWUSER flag is a member of the same user namespace as its parent.
12  *
13  * When unshare an user namespace, the calling process is moved into a new user
14  * namespace which is not shared with any previously existing process.
15  */
16 
17 #define _GNU_SOURCE
18 
19 #include <stdio.h>
20 #include "tst_test.h"
21 #include "lapi/sched.h"
22 #include "common.h"
23 
child_fn1(void)24 static void child_fn1(void)
25 {
26 	TST_CHECKPOINT_WAIT(0);
27 }
28 
getusernsidbypid(int pid)29 static unsigned int getusernsidbypid(int pid)
30 {
31 	char path[BUFSIZ];
32 	char userid[BUFSIZ];
33 	unsigned int id = 0;
34 
35 	sprintf(path, "/proc/%d/ns/user", pid);
36 
37 	SAFE_READLINK(path, userid, BUFSIZ);
38 
39 	if (sscanf(userid, "user:[%u]", &id) < 0)
40 		tst_brk(TBROK | TERRNO, "sscanf failure");
41 
42 	return id;
43 }
44 
run(void)45 static void run(void)
46 {
47 	const struct tst_clone_args args1 = { .exit_signal = SIGCHLD };
48 	const struct tst_clone_args args2 = {
49 		.flags = CLONE_NEWUSER,
50 		.exit_signal = SIGCHLD,
51 	};
52 	int cpid1, cpid2, cpid3;
53 	unsigned int parentuserns, cpid1userns, cpid2userns, newparentuserns;
54 
55 	parentuserns = getusernsidbypid(getpid());
56 
57 	cpid1 = SAFE_CLONE(&args1);
58 	if (!cpid1) {
59 		child_fn1();
60 		return;
61 	}
62 
63 	cpid1userns = getusernsidbypid(cpid1);
64 
65 	TST_CHECKPOINT_WAKE(0);
66 
67 	/* A process created via fork(2) or clone(2) without the
68 	 * CLONE_NEWUSER flag is a member of the same user namespace as its
69 	 * parent
70 	 */
71 	TST_EXP_EQ_LI(parentuserns, cpid1userns);
72 
73 	cpid2 = SAFE_CLONE(&args2);
74 	if (!cpid2) {
75 		child_fn1();
76 		return;
77 	}
78 
79 	cpid2userns = getusernsidbypid(cpid2);
80 
81 	TST_CHECKPOINT_WAKE(0);
82 
83 	TST_EXP_EXPR(parentuserns != cpid2userns,
84 		"parent namespace != child namespace");
85 
86 	cpid3 = SAFE_FORK();
87 	if (!cpid3) {
88 		SAFE_UNSHARE(CLONE_NEWUSER);
89 		newparentuserns = getusernsidbypid(getpid());
90 
91 		/* When unshare an user namespace, the calling process
92 		 * is moved into a new user namespace which is not shared
93 		 * with any previously existing process
94 		 */
95 		TST_EXP_EXPR(parentuserns != newparentuserns,
96 			"parent namespace != unshared child namespace");
97 	}
98 }
99 
100 static struct tst_test test = {
101 	.test_all = run,
102 	.needs_root = 1,
103 	.forks_child = 1,
104 	.needs_checkpoints = 1,
105 	.needs_kconfigs = (const char *[]) {
106 		"CONFIG_USER_NS",
107 		NULL,
108 	},
109 };
110