• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd., 2015
3  * This program is free software; you can redistribute it and/or modify it
4  * under the terms of the GNU General Public License as published by the Free
5  * Software Foundation; either version 2 of the License, or (at your option)
6  * any later version. This program is distributed in the hope that it will be
7  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
9  * Public License for more details. You should have received a copy of the GNU
10  * General Public License along with this program.
11  */
12 
13 /*
14  * Verify that:
15  * When a process with non-zero user IDs performs an execve(), the process's
16  * capability sets are cleared.
17  * When a process with zero user IDs performs an execve(), the process's
18  * capability sets are set.
19  *
20  */
21 
22 #define _GNU_SOURCE
23 #include <sys/wait.h>
24 #include <assert.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <stdbool.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <errno.h>
31 #include "libclone.h"
32 #include "test.h"
33 #include "config.h"
34 #include "userns_helper.h"
35 
36 #define CHILD1UID 0
37 #define CHILD1GID 0
38 #define CHILD2UID 200
39 #define CHILD2GID 200
40 
41 char *TCID = "user_namespace6";
42 int TST_TOTAL = 1;
43 
44 static int cpid1, parentuid, parentgid;
45 
46 /*
47  * child_fn1() - Inside a new user namespace
48  */
child_fn1(void)49 static int child_fn1(void)
50 {
51 	int exit_val = 0;
52 	char *const args[] = { "userns06_capcheck", "privileged", NULL };
53 
54 	TST_SAFE_CHECKPOINT_WAIT(NULL, 0);
55 
56 	if (execve(args[0], args, NULL) == -1) {
57 		printf("execvp unexpected error: (%d) %s\n",
58 			errno, strerror(errno));
59 		exit_val = 1;
60 	}
61 
62 	return exit_val;
63 }
64 
65 /*
66  * child_fn2() - Inside a new user namespace
67  */
child_fn2(void)68 static int child_fn2(void)
69 {
70 	int exit_val = 0;
71 	int uid, gid;
72 	char *const args[] = { "userns06_capcheck", "unprivileged", NULL };
73 
74 	TST_SAFE_CHECKPOINT_WAIT(NULL, 1);
75 
76 	uid = geteuid();
77 	gid = getegid();
78 
79 	if (uid != CHILD2UID || gid != CHILD2GID) {
80 		printf("unexpected uid=%d gid=%d\n", uid, gid);
81 		exit_val = 1;
82 	}
83 
84 	if (execve(args[0], args, NULL) == -1) {
85 		printf("execvp unexpected error: (%d) %s\n",
86 			errno, strerror(errno));
87 		exit_val = 1;
88 	}
89 
90 	return exit_val;
91 }
92 
cleanup(void)93 static void cleanup(void)
94 {
95 	tst_rmdir();
96 }
97 
setup(void)98 static void setup(void)
99 {
100 	check_newuser();
101 	tst_tmpdir();
102 	TST_CHECKPOINT_INIT(NULL);
103 	TST_RESOURCE_COPY(cleanup, "userns06_capcheck", NULL);
104 }
105 
main(int argc,char * argv[])106 int main(int argc, char *argv[])
107 {
108 	pid_t cpid2;
109 	char path[BUFSIZ];
110 	int lc;
111 	int fd;
112 
113 	tst_parse_opts(argc, argv, NULL, NULL);
114 #ifndef HAVE_LIBCAP
115 	tst_brkm(TCONF, NULL, "System is missing libcap.");
116 #endif
117 	setup();
118 
119 	for (lc = 0; TEST_LOOPING(lc); lc++) {
120 		tst_count = 0;
121 
122 		parentuid = geteuid();
123 		parentgid = getegid();
124 
125 		cpid1 = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD,
126 			(void *)child_fn1, NULL);
127 		if (cpid1 < 0)
128 			tst_brkm(TBROK | TERRNO, cleanup,
129 				"cpid1 clone failed");
130 
131 		cpid2 = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD,
132 			(void *)child_fn2, NULL);
133 		if (cpid2 < 0)
134 			tst_brkm(TBROK | TERRNO, cleanup,
135 				"cpid2 clone failed");
136 
137 		if (access("/proc/self/setgroups", F_OK) == 0) {
138 			sprintf(path, "/proc/%d/setgroups", cpid1);
139 			fd = SAFE_OPEN(cleanup, path, O_WRONLY, 0644);
140 			SAFE_WRITE(cleanup, 1, fd, "deny", 4);
141 			SAFE_CLOSE(cleanup, fd);
142 
143 			sprintf(path, "/proc/%d/setgroups", cpid2);
144 			fd = SAFE_OPEN(cleanup, path, O_WRONLY, 0644);
145 			SAFE_WRITE(cleanup, 1, fd, "deny", 4);
146 			SAFE_CLOSE(cleanup, fd);
147 		}
148 
149 		updatemap(cpid1, UID_MAP, CHILD1UID, parentuid, cleanup);
150 		updatemap(cpid2, UID_MAP, CHILD2UID, parentuid, cleanup);
151 
152 		updatemap(cpid1, GID_MAP, CHILD1GID, parentgid, cleanup);
153 		updatemap(cpid2, GID_MAP, CHILD2GID, parentgid, cleanup);
154 
155 		TST_SAFE_CHECKPOINT_WAKE(cleanup, 0);
156 		TST_SAFE_CHECKPOINT_WAKE(cleanup, 1);
157 
158 		tst_record_childstatus(cleanup, cpid1);
159 		tst_record_childstatus(cleanup, cpid2);
160 	}
161 	cleanup();
162 	tst_exit();
163 }
164