xref: /aosp_15_r20/external/ltp/testcases/kernel/containers/userns/userns06.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
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 <[email protected]>
5  */
6 
7 /*\
8  * [Description]
9  *
10  * Verify that when a process with non-zero user IDs performs an execve(),
11  * the process's capability sets are cleared.
12  * When a process with zero user IDs performs an execve(), the process's
13  * capability sets are set.
14  */
15 
16 #include "tst_test.h"
17 #include "config.h"
18 
19 #ifdef HAVE_LIBCAP
20 #define _GNU_SOURCE
21 
22 #include <stdio.h>
23 #include "lapi/sched.h"
24 #include "common.h"
25 
26 #define TEST_APP "userns06_capcheck"
27 
28 #define CHILD1UID 0
29 #define CHILD1GID 0
30 #define CHILD2UID 200
31 #define CHILD2GID 200
32 
child_fn1(void)33 static void child_fn1(void)
34 {
35 	char *const args[] = { TEST_APP, "privileged", NULL };
36 	int ret;
37 
38 	TST_CHECKPOINT_WAIT(0);
39 
40 	ret = execv(args[0], args);
41 	if (ret == -1)
42 		tst_brk(TBROK | TERRNO, "execv: unexpected error");
43 }
44 
child_fn2(void)45 static void child_fn2(void)
46 {
47 	int uid, gid, ret;
48 	char *const args[] = { TEST_APP, "unprivileged", NULL };
49 
50 	TST_CHECKPOINT_WAIT(1);
51 
52 	uid = geteuid();
53 	gid = getegid();
54 
55 	TST_EXP_EQ_LI(uid, CHILD2UID);
56 	TST_EXP_EQ_LI(gid, CHILD2GID);
57 
58 	ret = execv(args[0], args);
59 	if (ret == -1)
60 		tst_brk(TBROK | TERRNO, "execv: unexpected error");
61 }
62 
run(void)63 static void run(void)
64 {
65 	const struct tst_clone_args args = {
66 		.flags = CLONE_NEWUSER,
67 		.exit_signal = SIGCHLD,
68 	};
69 	pid_t cpid1;
70 	pid_t cpid2;
71 	int parentuid;
72 	int parentgid;
73 	char path[BUFSIZ];
74 	int fd;
75 
76 	parentuid = geteuid();
77 	parentgid = getegid();
78 
79 	cpid1 = SAFE_CLONE(&args);
80 	if (!cpid1) {
81 		child_fn1();
82 		return;
83 	}
84 
85 	cpid2 = SAFE_CLONE(&args);
86 	if (!cpid2) {
87 		child_fn2();
88 		return;
89 	}
90 
91 	if (access("/proc/self/setgroups", F_OK) == 0) {
92 		sprintf(path, "/proc/%d/setgroups", cpid1);
93 
94 		fd = SAFE_OPEN(path, O_WRONLY, 0644);
95 		SAFE_WRITE(SAFE_WRITE_ALL, fd, "deny", 4);
96 		SAFE_CLOSE(fd);
97 
98 		sprintf(path, "/proc/%d/setgroups", cpid2);
99 
100 		fd = SAFE_OPEN(path, O_WRONLY, 0644);
101 		SAFE_WRITE(SAFE_WRITE_ALL, fd, "deny", 4);
102 		SAFE_CLOSE(fd);
103 	}
104 
105 	updatemap(cpid1, UID_MAP, CHILD1UID, parentuid);
106 	updatemap(cpid2, UID_MAP, CHILD2UID, parentuid);
107 
108 	updatemap(cpid1, GID_MAP, CHILD1GID, parentgid);
109 	updatemap(cpid2, GID_MAP, CHILD2GID, parentgid);
110 
111 	TST_CHECKPOINT_WAKE(0);
112 	TST_CHECKPOINT_WAKE(1);
113 }
114 
115 static struct tst_test test = {
116 	.test_all = run,
117 	.needs_root = 1,
118 	.forks_child = 1,
119 	.needs_checkpoints = 1,
120 	.resource_files = (const char *[]) {
121 		TEST_APP,
122 		NULL,
123 	},
124 	.needs_kconfigs = (const char *[]) {
125 		"CONFIG_USER_NS",
126 		NULL,
127 	},
128 };
129 
130 #else
131 TST_TEST_TCONF("System is missing libcap");
132 #endif
133