1 // SPDX-License-Identifier: GPL-2.0
2 
3 #define _GNU_SOURCE
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <linux/netlink.h>
7 #include <signal.h>
8 #include <stdbool.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/prctl.h>
13 #include <sys/socket.h>
14 #include <sched.h>
15 #include <sys/eventfd.h>
16 #include <sys/stat.h>
17 #include <sys/syscall.h>
18 #include <sys/types.h>
19 #include <sys/wait.h>
20 #include <unistd.h>
21 
22 #include "../kselftest_harness.h"
23 
24 #define __DEV_FULL "/sys/devices/virtual/mem/full/uevent"
25 #define __UEVENT_BUFFER_SIZE (2048 * 2)
26 #define __UEVENT_HEADER "add@/devices/virtual/mem/full"
27 #define __UEVENT_HEADER_LEN sizeof("add@/devices/virtual/mem/full")
28 #define __UEVENT_LISTEN_ALL -1
29 
read_nointr(int fd,void * buf,size_t count)30 ssize_t read_nointr(int fd, void *buf, size_t count)
31 {
32 	ssize_t ret;
33 
34 again:
35 	ret = read(fd, buf, count);
36 	if (ret < 0 && errno == EINTR)
37 		goto again;
38 
39 	return ret;
40 }
41 
write_nointr(int fd,const void * buf,size_t count)42 ssize_t write_nointr(int fd, const void *buf, size_t count)
43 {
44 	ssize_t ret;
45 
46 again:
47 	ret = write(fd, buf, count);
48 	if (ret < 0 && errno == EINTR)
49 		goto again;
50 
51 	return ret;
52 }
53 
wait_for_pid(pid_t pid)54 int wait_for_pid(pid_t pid)
55 {
56 	int status, ret;
57 
58 again:
59 	ret = waitpid(pid, &status, 0);
60 	if (ret == -1) {
61 		if (errno == EINTR)
62 			goto again;
63 
64 		return -1;
65 	}
66 
67 	if (ret != pid)
68 		goto again;
69 
70 	if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
71 		return -1;
72 
73 	return 0;
74 }
75 
uevent_listener(unsigned long post_flags,bool expect_uevent,int sync_fd)76 static int uevent_listener(unsigned long post_flags, bool expect_uevent,
77 			   int sync_fd)
78 {
79 	int sk_fd, ret;
80 	socklen_t sk_addr_len;
81 	int fret = -1, rcv_buf_sz = __UEVENT_BUFFER_SIZE;
82 	uint64_t sync_add = 1;
83 	struct sockaddr_nl sk_addr = { 0 }, rcv_addr = { 0 };
84 	char buf[__UEVENT_BUFFER_SIZE] = { 0 };
85 	struct iovec iov = { buf, __UEVENT_BUFFER_SIZE };
86 	char control[CMSG_SPACE(sizeof(struct ucred))];
87 	struct msghdr hdr = {
88 		&rcv_addr, sizeof(rcv_addr), &iov, 1,
89 		control,   sizeof(control),  0,
90 	};
91 
92 	sk_fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC,
93 		       NETLINK_KOBJECT_UEVENT);
94 	if (sk_fd < 0) {
95 		fprintf(stderr, "%s - Failed to open uevent socket\n", strerror(errno));
96 		return -1;
97 	}
98 
99 	ret = setsockopt(sk_fd, SOL_SOCKET, SO_RCVBUF, &rcv_buf_sz,
100 			 sizeof(rcv_buf_sz));
101 	if (ret < 0) {
102 		fprintf(stderr, "%s - Failed to set socket options\n", strerror(errno));
103 		goto on_error;
104 	}
105 
106 	sk_addr.nl_family = AF_NETLINK;
107 	sk_addr.nl_groups = __UEVENT_LISTEN_ALL;
108 
109 	sk_addr_len = sizeof(sk_addr);
110 	ret = bind(sk_fd, (struct sockaddr *)&sk_addr, sk_addr_len);
111 	if (ret < 0) {
112 		fprintf(stderr, "%s - Failed to bind socket\n", strerror(errno));
113 		goto on_error;
114 	}
115 
116 	ret = getsockname(sk_fd, (struct sockaddr *)&sk_addr, &sk_addr_len);
117 	if (ret < 0) {
118 		fprintf(stderr, "%s - Failed to retrieve socket name\n", strerror(errno));
119 		goto on_error;
120 	}
121 
122 	if ((size_t)sk_addr_len != sizeof(sk_addr)) {
123 		fprintf(stderr, "Invalid socket address size\n");
124 		goto on_error;
125 	}
126 
127 	if (post_flags & CLONE_NEWUSER) {
128 		ret = unshare(CLONE_NEWUSER);
129 		if (ret < 0) {
130 			fprintf(stderr,
131 				"%s - Failed to unshare user namespace\n",
132 				strerror(errno));
133 			goto on_error;
134 		}
135 	}
136 
137 	if (post_flags & CLONE_NEWNET) {
138 		ret = unshare(CLONE_NEWNET);
139 		if (ret < 0) {
140 			fprintf(stderr,
141 				"%s - Failed to unshare network namespace\n",
142 				strerror(errno));
143 			goto on_error;
144 		}
145 	}
146 
147 	ret = write_nointr(sync_fd, &sync_add, sizeof(sync_add));
148 	close(sync_fd);
149 	if (ret != sizeof(sync_add)) {
150 		fprintf(stderr, "Failed to synchronize with parent process\n");
151 		goto on_error;
152 	}
153 
154 	fret = 0;
155 	for (;;) {
156 		ssize_t r;
157 
158 		r = recvmsg(sk_fd, &hdr, 0);
159 		if (r <= 0) {
160 			fprintf(stderr, "%s - Failed to receive uevent\n", strerror(errno));
161 			ret = -1;
162 			break;
163 		}
164 
165 		/* ignore libudev messages */
166 		if (memcmp(buf, "libudev", 8) == 0)
167 			continue;
168 
169 		/* ignore uevents we didn't trigger */
170 		if (memcmp(buf, __UEVENT_HEADER, __UEVENT_HEADER_LEN) != 0)
171 			continue;
172 
173 		if (!expect_uevent) {
174 			fprintf(stderr, "Received unexpected uevent:\n");
175 			ret = -1;
176 		}
177 
178 		if (TH_LOG_ENABLED) {
179 			/* If logging is enabled dump the received uevent. */
180 			(void)write_nointr(STDERR_FILENO, buf, r);
181 			(void)write_nointr(STDERR_FILENO, "\n", 1);
182 		}
183 
184 		break;
185 	}
186 
187 on_error:
188 	close(sk_fd);
189 
190 	return fret;
191 }
192 
trigger_uevent(unsigned int times)193 int trigger_uevent(unsigned int times)
194 {
195 	int fd, ret;
196 	unsigned int i;
197 
198 	fd = open(__DEV_FULL, O_RDWR | O_CLOEXEC);
199 	if (fd < 0) {
200 		if (errno != ENOENT)
201 			return -EINVAL;
202 
203 		return -1;
204 	}
205 
206 	for (i = 0; i < times; i++) {
207 		ret = write_nointr(fd, "add\n", sizeof("add\n") - 1);
208 		if (ret < 0) {
209 			fprintf(stderr, "Failed to trigger uevent\n");
210 			break;
211 		}
212 	}
213 	close(fd);
214 
215 	return ret;
216 }
217 
set_death_signal(void)218 int set_death_signal(void)
219 {
220 	int ret;
221 	pid_t ppid;
222 
223 	ret = prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
224 
225 	/* Check whether we have been orphaned. */
226 	ppid = getppid();
227 	if (ppid == 1) {
228 		pid_t self;
229 
230 		self = getpid();
231 		ret = kill(self, SIGKILL);
232 	}
233 
234 	if (ret < 0)
235 		return -1;
236 
237 	return 0;
238 }
239 
do_test(unsigned long pre_flags,unsigned long post_flags,bool expect_uevent,int sync_fd)240 static int do_test(unsigned long pre_flags, unsigned long post_flags,
241 		   bool expect_uevent, int sync_fd)
242 {
243 	int ret;
244 	uint64_t wait_val;
245 	pid_t pid;
246 	sigset_t mask;
247 	sigset_t orig_mask;
248 	struct timespec timeout;
249 
250 	sigemptyset(&mask);
251 	sigaddset(&mask, SIGCHLD);
252 
253 	ret = sigprocmask(SIG_BLOCK, &mask, &orig_mask);
254 	if (ret < 0) {
255 		fprintf(stderr, "%s- Failed to block SIGCHLD\n", strerror(errno));
256 		return -1;
257 	}
258 
259 	pid = fork();
260 	if (pid < 0) {
261 		fprintf(stderr, "%s - Failed to fork() new process\n", strerror(errno));
262 		return -1;
263 	}
264 
265 	if (pid == 0) {
266 		/* Make sure that we go away when our parent dies. */
267 		ret = set_death_signal();
268 		if (ret < 0) {
269 			fprintf(stderr, "Failed to set PR_SET_PDEATHSIG to SIGKILL\n");
270 			_exit(EXIT_FAILURE);
271 		}
272 
273 		if (pre_flags & CLONE_NEWUSER) {
274 			ret = unshare(CLONE_NEWUSER);
275 			if (ret < 0) {
276 				fprintf(stderr,
277 					"%s - Failed to unshare user namespace\n",
278 					strerror(errno));
279 				_exit(EXIT_FAILURE);
280 			}
281 		}
282 
283 		if (pre_flags & CLONE_NEWNET) {
284 			ret = unshare(CLONE_NEWNET);
285 			if (ret < 0) {
286 				fprintf(stderr,
287 					"%s - Failed to unshare network namespace\n",
288 					strerror(errno));
289 				_exit(EXIT_FAILURE);
290 			}
291 		}
292 
293 		if (uevent_listener(post_flags, expect_uevent, sync_fd) < 0)
294 			_exit(EXIT_FAILURE);
295 
296 		_exit(EXIT_SUCCESS);
297 	}
298 
299 	ret = read_nointr(sync_fd, &wait_val, sizeof(wait_val));
300 	if (ret != sizeof(wait_val)) {
301 		fprintf(stderr, "Failed to synchronize with child process\n");
302 		_exit(EXIT_FAILURE);
303 	}
304 
305 	/* Trigger 10 uevents to account for the case where the kernel might
306 	 * drop some.
307 	 */
308 	ret = trigger_uevent(10);
309 	if (ret < 0)
310 		fprintf(stderr, "Failed triggering uevents\n");
311 
312 	/* Wait for 2 seconds before considering this failed. This should be
313 	 * plenty of time for the kernel to deliver the uevent even under heavy
314 	 * load.
315 	 */
316 	timeout.tv_sec = 2;
317 	timeout.tv_nsec = 0;
318 
319 again:
320 	ret = sigtimedwait(&mask, NULL, &timeout);
321 	if (ret < 0) {
322 		if (errno == EINTR)
323 			goto again;
324 
325 		if (!expect_uevent)
326 			ret = kill(pid, SIGTERM); /* success */
327 		else
328 			ret = kill(pid, SIGUSR1); /* error */
329 		if (ret < 0)
330 			return -1;
331 	}
332 
333 	ret = wait_for_pid(pid);
334 	if (ret < 0)
335 		return -1;
336 
337 	return ret;
338 }
339 
signal_handler(int sig)340 static void signal_handler(int sig)
341 {
342 	if (sig == SIGTERM)
343 		_exit(EXIT_SUCCESS);
344 
345 	_exit(EXIT_FAILURE);
346 }
347 
TEST(uevent_filtering)348 TEST(uevent_filtering)
349 {
350 	int ret, sync_fd;
351 	struct sigaction act;
352 
353 	if (geteuid()) {
354 		TH_LOG("Uevent filtering tests require root privileges. Skipping test");
355 		_exit(KSFT_SKIP);
356 	}
357 
358 	ret = access(__DEV_FULL, F_OK);
359 	EXPECT_EQ(0, ret) {
360 		if (errno == ENOENT) {
361 			TH_LOG(__DEV_FULL " does not exist. Skipping test");
362 			_exit(KSFT_SKIP);
363 		}
364 
365 		_exit(KSFT_FAIL);
366 	}
367 
368 	act.sa_handler = signal_handler;
369 	act.sa_flags = 0;
370 	sigemptyset(&act.sa_mask);
371 
372 	ret = sigaction(SIGTERM, &act, NULL);
373 	ASSERT_EQ(0, ret);
374 
375 	sync_fd = eventfd(0, EFD_CLOEXEC);
376 	ASSERT_GE(sync_fd, 0);
377 
378 	/*
379 	 * Setup:
380 	 * - Open uevent listening socket in initial network namespace owned by
381 	 *   initial user namespace.
382 	 * - Trigger uevent in initial network namespace owned by initial user
383 	 *   namespace.
384 	 * Expected Result:
385 	 * - uevent listening socket receives uevent
386 	 */
387 	ret = do_test(0, 0, true, sync_fd);
388 	ASSERT_EQ(0, ret) {
389 		goto do_cleanup;
390 	}
391 
392 	/*
393 	 * Setup:
394 	 * - Open uevent listening socket in non-initial network namespace
395 	 *   owned by initial user namespace.
396 	 * - Trigger uevent in initial network namespace owned by initial user
397 	 *   namespace.
398 	 * Expected Result:
399 	 * - uevent listening socket receives uevent
400 	 */
401 	ret = do_test(CLONE_NEWNET, 0, true, sync_fd);
402 	ASSERT_EQ(0, ret) {
403 		goto do_cleanup;
404 	}
405 
406 	/*
407 	 * Setup:
408 	 * - unshare user namespace
409 	 * - Open uevent listening socket in initial network namespace
410 	 *   owned by initial user namespace.
411 	 * - Trigger uevent in initial network namespace owned by initial user
412 	 *   namespace.
413 	 * Expected Result:
414 	 * - uevent listening socket receives uevent
415 	 */
416 	ret = do_test(CLONE_NEWUSER, 0, true, sync_fd);
417 	ASSERT_EQ(0, ret) {
418 		goto do_cleanup;
419 	}
420 
421 	/*
422 	 * Setup:
423 	 * - Open uevent listening socket in non-initial network namespace
424 	 *   owned by non-initial user namespace.
425 	 * - Trigger uevent in initial network namespace owned by initial user
426 	 *   namespace.
427 	 * Expected Result:
428 	 * - uevent listening socket receives no uevent
429 	 */
430 	ret = do_test(CLONE_NEWUSER | CLONE_NEWNET, 0, false, sync_fd);
431 	ASSERT_EQ(0, ret) {
432 		goto do_cleanup;
433 	}
434 
435 	/*
436 	 * Setup:
437 	 * - Open uevent listening socket in initial network namespace
438 	 *   owned by initial user namespace.
439 	 * - unshare network namespace
440 	 * - Trigger uevent in initial network namespace owned by initial user
441 	 *   namespace.
442 	 * Expected Result:
443 	 * - uevent listening socket receives uevent
444 	 */
445 	ret = do_test(0, CLONE_NEWNET, true, sync_fd);
446 	ASSERT_EQ(0, ret) {
447 		goto do_cleanup;
448 	}
449 
450 	/*
451 	 * Setup:
452 	 * - Open uevent listening socket in initial network namespace
453 	 *   owned by initial user namespace.
454 	 * - unshare user namespace
455 	 * - Trigger uevent in initial network namespace owned by initial user
456 	 *   namespace.
457 	 * Expected Result:
458 	 * - uevent listening socket receives uevent
459 	 */
460 	ret = do_test(0, CLONE_NEWUSER, true, sync_fd);
461 	ASSERT_EQ(0, ret) {
462 		goto do_cleanup;
463 	}
464 
465 	/*
466 	 * Setup:
467 	 * - Open uevent listening socket in initial network namespace
468 	 *   owned by initial user namespace.
469 	 * - unshare user namespace
470 	 * - unshare network namespace
471 	 * - Trigger uevent in initial network namespace owned by initial user
472 	 *   namespace.
473 	 * Expected Result:
474 	 * - uevent listening socket receives uevent
475 	 */
476 	ret = do_test(0, CLONE_NEWUSER | CLONE_NEWNET, true, sync_fd);
477 	ASSERT_EQ(0, ret) {
478 		goto do_cleanup;
479 	}
480 
481 do_cleanup:
482 	close(sync_fd);
483 }
484 
485 TEST_HARNESS_MAIN
486