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