xref: /linux/tools/testing/selftests/namespaces/uid_map_range_test.c (revision fbc59bc7f05c62b0c1607b92eaf8175e75ef755d)
1 // SPDX-License-Identifier: GPL-2.0
2 #define _GNU_SOURCE
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <sched.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <sys/wait.h>
9 #include <unistd.h>
10 #include "../kselftest_harness.h"
11 
12 /*
13  * The fields of a uid_map/gid_map line are stored in u32. Values that
14  * do not fit, and negative values, must be rejected with EINVAL instead
15  * of being silently truncated, and in-range values must still be
16  * accepted.
17  */
18 
19 static int write_file(const char *path, const char *buf)
20 {
21 	ssize_t len = strlen(buf);
22 	ssize_t ret;
23 	int fd;
24 
25 	fd = open(path, O_WRONLY | O_CLOEXEC);
26 	if (fd < 0)
27 		return -errno;
28 	ret = write(fd, buf, len);
29 	if (ret < 0)
30 		ret = -errno;
31 	close(fd);
32 	if (ret < 0)
33 		return ret;
34 	return ret == len ? 0 : -EIO;
35 }
36 
37 static ssize_t read_file(const char *path, char *buf, size_t size)
38 {
39 	ssize_t ret;
40 	int fd;
41 
42 	fd = open(path, O_RDONLY | O_CLOEXEC);
43 	if (fd < 0)
44 		return -errno;
45 	ret = read(fd, buf, size - 1);
46 	if (ret < 0)
47 		ret = -errno;
48 	else
49 		buf[ret] = '\0';
50 	close(fd);
51 	return ret;
52 }
53 
54 /* Enter a fresh user namespace, remembering the outer ids. */
55 static int enter_userns(uid_t *uid, gid_t *gid)
56 {
57 	*uid = geteuid();
58 	*gid = getegid();
59 	if (unshare(CLONE_NEWUSER) < 0)
60 		return -errno;
61 	/* Required before an unprivileged gid_map write. */
62 	return write_file("/proc/self/setgroups", "deny");
63 }
64 
65 static void expect_rejected(struct __test_metadata *_metadata,
66 			    const char *path, const char *line)
67 {
68 	char buf[256];
69 
70 	TH_LOG("writing \"%s\" to %s", line, path);
71 	EXPECT_EQ(write_file(path, line), -EINVAL);
72 	/* Nothing may have been installed. */
73 	EXPECT_EQ(read_file(path, buf, sizeof(buf)), 0) {
74 		TH_LOG("installed: %s", buf);
75 	}
76 }
77 
78 static void expect_accepted(struct __test_metadata *_metadata,
79 			    const char *path, const char *line,
80 			    unsigned int first, unsigned int lower_first,
81 			    unsigned int count)
82 {
83 	unsigned int f, l, c;
84 	char buf[256];
85 
86 	TH_LOG("writing \"%s\" to %s", line, path);
87 	ASSERT_EQ(write_file(path, line), 0);
88 
89 	ASSERT_GT(read_file(path, buf, sizeof(buf)), 0);
90 	ASSERT_EQ(sscanf(buf, "%u %u %u", &f, &l, &c), 3);
91 	EXPECT_EQ(f, first);
92 	EXPECT_EQ(l, lower_first);
93 	EXPECT_EQ(c, count);
94 	/* Exactly one extent. */
95 	EXPECT_EQ(strchr(buf, '\n'), buf + strlen(buf) - 1);
96 }
97 
98 TEST(uid_map_first_above_u32)
99 {
100 	char line[64];
101 	uid_t uid;
102 	gid_t gid;
103 	int ret;
104 
105 	ret = enter_userns(&uid, &gid);
106 	if (ret)
107 		SKIP(return, "cannot set up user namespace: %s", strerror(-ret));
108 	snprintf(line, sizeof(line), "4294967301 %u 1", uid);
109 	expect_rejected(_metadata, "/proc/self/uid_map", line);
110 }
111 
112 TEST(uid_map_lower_first_above_u32)
113 {
114 	char line[64];
115 	uid_t uid;
116 	gid_t gid;
117 	int ret;
118 
119 	ret = enter_userns(&uid, &gid);
120 	if (ret)
121 		SKIP(return, "cannot set up user namespace: %s", strerror(-ret));
122 	snprintf(line, sizeof(line), "0 %llu 1", (1ULL << 32) + uid);
123 	expect_rejected(_metadata, "/proc/self/uid_map", line);
124 }
125 
126 TEST(uid_map_count_above_u32)
127 {
128 	char line[64];
129 	uid_t uid;
130 	gid_t gid;
131 	int ret;
132 
133 	ret = enter_userns(&uid, &gid);
134 	if (ret)
135 		SKIP(return, "cannot set up user namespace: %s", strerror(-ret));
136 	snprintf(line, sizeof(line), "0 %u 4294967297", uid);
137 	expect_rejected(_metadata, "/proc/self/uid_map", line);
138 }
139 
140 TEST(gid_map_first_above_u32)
141 {
142 	char line[64];
143 	uid_t uid;
144 	gid_t gid;
145 	int ret;
146 
147 	ret = enter_userns(&uid, &gid);
148 	if (ret)
149 		SKIP(return, "cannot set up user namespace: %s", strerror(-ret));
150 	snprintf(line, sizeof(line), "4294967301 %u 1", gid);
151 	expect_rejected(_metadata, "/proc/self/gid_map", line);
152 }
153 
154 TEST(uid_map_first_negative)
155 {
156 	char line[64];
157 	uid_t uid;
158 	gid_t gid;
159 	int ret;
160 
161 	ret = enter_userns(&uid, &gid);
162 	if (ret)
163 		SKIP(return, "cannot set up user namespace: %s", strerror(-ret));
164 	snprintf(line, sizeof(line), "-1 %u 1", uid);
165 	expect_rejected(_metadata, "/proc/self/uid_map", line);
166 }
167 
168 TEST(uid_map_lower_first_negative)
169 {
170 	uid_t uid;
171 	gid_t gid;
172 	int ret;
173 
174 	ret = enter_userns(&uid, &gid);
175 	if (ret)
176 		SKIP(return, "cannot set up user namespace: %s", strerror(-ret));
177 	expect_rejected(_metadata, "/proc/self/uid_map", "0 -1 1");
178 }
179 
180 TEST(uid_map_count_negative)
181 {
182 	char line[64];
183 	uid_t uid;
184 	gid_t gid;
185 	int ret;
186 
187 	ret = enter_userns(&uid, &gid);
188 	if (ret)
189 		SKIP(return, "cannot set up user namespace: %s", strerror(-ret));
190 	snprintf(line, sizeof(line), "0 %u -1", uid);
191 	expect_rejected(_metadata, "/proc/self/uid_map", line);
192 }
193 
194 TEST(uid_map_in_range)
195 {
196 	char line[64];
197 	uid_t uid;
198 	gid_t gid;
199 	int ret;
200 
201 	ret = enter_userns(&uid, &gid);
202 	if (ret)
203 		SKIP(return, "cannot set up user namespace: %s", strerror(-ret));
204 	snprintf(line, sizeof(line), "5 %u 1", uid);
205 	expect_accepted(_metadata, "/proc/self/uid_map", line, 5, uid, 1);
206 }
207 
208 TEST(uid_map_zero)
209 {
210 	char line[64];
211 	uid_t uid;
212 	gid_t gid;
213 	int ret;
214 
215 	ret = enter_userns(&uid, &gid);
216 	if (ret)
217 		SKIP(return, "cannot set up user namespace: %s", strerror(-ret));
218 	snprintf(line, sizeof(line), "0 %u 1", uid);
219 	expect_accepted(_metadata, "/proc/self/uid_map", line, 0, uid, 1);
220 }
221 
222 /* 4294967295 is (u32)-1, which map_write() refuses as a starting id. */
223 TEST(uid_map_largest_first)
224 {
225 	char line[64];
226 	uid_t uid;
227 	gid_t gid;
228 	int ret;
229 
230 	ret = enter_userns(&uid, &gid);
231 	if (ret)
232 		SKIP(return, "cannot set up user namespace: %s", strerror(-ret));
233 	snprintf(line, sizeof(line), "4294967294 %u 1", uid);
234 	expect_accepted(_metadata, "/proc/self/uid_map", line,
235 			4294967294U, uid, 1);
236 }
237 
238 TEST(uid_map_extra_spaces)
239 {
240 	char line[64];
241 	uid_t uid;
242 	gid_t gid;
243 	int ret;
244 
245 	ret = enter_userns(&uid, &gid);
246 	if (ret)
247 		SKIP(return, "cannot set up user namespace: %s", strerror(-ret));
248 	snprintf(line, sizeof(line), "0   %u  1", uid);
249 	expect_accepted(_metadata, "/proc/self/uid_map", line, 0, uid, 1);
250 }
251 
252 /*
253  * An unprivileged writer may only map a single id, so the largest count
254  * needs a privileged parent writing the map of a child namespace. With
255  * first and lower_first 0, the no-wrap rule allows up to 4294967295.
256  */
257 TEST(uid_map_largest_count)
258 {
259 	unsigned int first, lower_first, count;
260 	int to_child[2], from_child[2];
261 	char path[64], buf[256];
262 	pid_t pid;
263 	char c;
264 
265 	if (geteuid() != 0)
266 		SKIP(return, "needs root in the initial user namespace");
267 	ASSERT_GT(read_file("/proc/self/uid_map", buf, sizeof(buf)), 0);
268 	ASSERT_EQ(sscanf(buf, "%u %u %u", &first, &lower_first, &count), 3);
269 	if (first != 0 || lower_first != 0 || count != 4294967295U)
270 		SKIP(return, "not in the initial user namespace");
271 
272 	ASSERT_EQ(pipe(to_child), 0);
273 	ASSERT_EQ(pipe(from_child), 0);
274 	pid = fork();
275 	ASSERT_GE(pid, 0);
276 	if (pid == 0) {
277 		close(to_child[1]);
278 		close(from_child[0]);
279 		c = unshare(CLONE_NEWUSER) ? 'F' : 'K';
280 		if (write(from_child[1], &c, 1) != 1)
281 			_exit(1);
282 		/* Stay alive until the parent is done with our uid_map. */
283 		if (read(to_child[0], &c, 1) < 0)
284 			_exit(1);
285 		_exit(0);
286 	}
287 	close(to_child[0]);
288 	close(from_child[1]);
289 
290 	ASSERT_EQ(read(from_child[0], &c, 1), 1);
291 	ASSERT_EQ(c, 'K');
292 	snprintf(path, sizeof(path), "/proc/%d/uid_map", pid);
293 	expect_accepted(_metadata, path, "0 0 4294967295", 0, 0, 4294967295U);
294 
295 	close(to_child[1]);
296 	EXPECT_EQ(waitpid(pid, NULL, 0), pid);
297 }
298 
299 TEST_HARNESS_MAIN
300