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