• 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 the kernel allows at least 32 nested levels of user namespaces.
11  */
12 
13 #define _GNU_SOURCE
14 
15 #include <stdio.h>
16 #include <sys/wait.h>
17 #include "common.h"
18 #include "tst_test.h"
19 #include "lapi/sched.h"
20 
21 #define MAXNEST 32
22 
child_fn1(const int level)23 static void child_fn1(const int level)
24 {
25 	const struct tst_clone_args args = {
26 		.flags = CLONE_NEWUSER,
27 		.exit_signal = SIGCHLD,
28 	};
29 	pid_t cpid;
30 	int parentuid;
31 	int parentgid;
32 
33 	TST_CHECKPOINT_WAIT(0);
34 
35 	if (level == MAXNEST) {
36 		tst_res(TPASS, "nested all children");
37 		return;
38 	}
39 
40 	cpid = SAFE_CLONE(&args);
41 	if (!cpid) {
42 		child_fn1(level + 1);
43 		return;
44 	}
45 
46 	parentuid = geteuid();
47 	parentgid = getegid();
48 
49 	updatemap(cpid, UID_MAP, 0, parentuid);
50 	updatemap(cpid, GID_MAP, 0, parentgid);
51 
52 	TST_CHECKPOINT_WAKE(0);
53 
54 	tst_reap_children();
55 }
56 
run(void)57 static void run(void)
58 {
59 	const struct tst_clone_args args = {
60 		.flags = CLONE_NEWUSER,
61 		.exit_signal = SIGCHLD,
62 	};
63 	pid_t cpid;
64 	int parentuid;
65 	int parentgid;
66 	char path[BUFSIZ];
67 
68 	cpid = SAFE_CLONE(&args);
69 	if (!cpid) {
70 		child_fn1(0);
71 		return;
72 	}
73 
74 	parentuid = geteuid();
75 	parentgid = getegid();
76 
77 	if (access("/proc/self/setgroups", F_OK) == 0) {
78 		sprintf(path, "/proc/%d/setgroups", cpid);
79 		SAFE_FILE_PRINTF(path, "deny");
80 	}
81 
82 	updatemap(cpid, UID_MAP, 0, parentuid);
83 	updatemap(cpid, GID_MAP, 0, parentgid);
84 
85 	TST_CHECKPOINT_WAKE(0);
86 }
87 
88 static struct tst_test test = {
89 	.test_all = run,
90 	.needs_root = 1,
91 	.forks_child = 1,
92 	.needs_checkpoints = 1,
93 	.needs_kconfigs = (const char *[]) {
94 		"CONFIG_USER_NS",
95 		NULL,
96 	},
97 	.save_restore = (const struct tst_path_val[]) {
98 		{"/proc/sys/kernel/unprivileged_userns_clone", "1", TST_SR_SKIP},
99 		{}
100 	},
101 };
102