1 // SPDX-License-Identifier: GPL-2.0
6 #include <linux/netlink.h>
12 #include <sys/prctl.h>
13 #include <sys/socket.h>
15 #include <sys/eventfd.h>
17 #include <sys/syscall.h>
18 #include <sys/types.h>
22 #include "../kselftest.h"
23 #include "../kselftest_harness.h"
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
31 ssize_t read_nointr(int fd, void *buf, size_t count)
36 ret = read(fd, buf, count);
37 if (ret < 0 && errno == EINTR)
43 ssize_t write_nointr(int fd, const void *buf, size_t count)
48 ret = write(fd, buf, count);
49 if (ret < 0 && errno == EINTR)
55 int wait_for_pid(pid_t pid)
60 ret = waitpid(pid, &status, 0);
71 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
77 static int uevent_listener(unsigned long post_flags, bool expect_uevent,
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))];
89 &rcv_addr, sizeof(rcv_addr), &iov, 1,
90 control, sizeof(control), 0,
93 sk_fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC,
94 NETLINK_KOBJECT_UEVENT);
96 fprintf(stderr, "%s - Failed to open uevent socket\n", strerror(errno));
100 ret = setsockopt(sk_fd, SOL_SOCKET, SO_RCVBUF, &rcv_buf_sz,
103 fprintf(stderr, "%s - Failed to set socket options\n", strerror(errno));
107 sk_addr.nl_family = AF_NETLINK;
108 sk_addr.nl_groups = __UEVENT_LISTEN_ALL;
110 sk_addr_len = sizeof(sk_addr);
111 ret = bind(sk_fd, (struct sockaddr *)&sk_addr, sk_addr_len);
113 fprintf(stderr, "%s - Failed to bind socket\n", strerror(errno));
117 ret = getsockname(sk_fd, (struct sockaddr *)&sk_addr, &sk_addr_len);
119 fprintf(stderr, "%s - Failed to retrieve socket name\n", strerror(errno));
123 if ((size_t)sk_addr_len != sizeof(sk_addr)) {
124 fprintf(stderr, "Invalid socket address size\n");
128 if (post_flags & CLONE_NEWUSER) {
129 ret = unshare(CLONE_NEWUSER);
132 "%s - Failed to unshare user namespace\n",
138 if (post_flags & CLONE_NEWNET) {
139 ret = unshare(CLONE_NEWNET);
142 "%s - Failed to unshare network namespace\n",
148 ret = write_nointr(sync_fd, &sync_add, sizeof(sync_add));
150 if (ret != sizeof(sync_add)) {
151 fprintf(stderr, "Failed to synchronize with parent process\n");
159 r = recvmsg(sk_fd, &hdr, 0);
161 fprintf(stderr, "%s - Failed to receive uevent\n", strerror(errno));
166 /* ignore libudev messages */
167 if (memcmp(buf, "libudev", 8) == 0)
170 /* ignore uevents we didn't trigger */
171 if (memcmp(buf, __UEVENT_HEADER, __UEVENT_HEADER_LEN) != 0)
174 if (!expect_uevent) {
175 fprintf(stderr, "Received unexpected uevent:\n");
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);
194 int trigger_uevent(unsigned int times)
199 fd = open(__DEV_FULL, O_RDWR | O_CLOEXEC);
207 for (i = 0; i < times; i++) {
208 ret = write_nointr(fd, "add\n", sizeof("add\n") - 1);
210 fprintf(stderr, "Failed to trigger uevent\n");
219 int set_death_signal(void)
224 ret = prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
226 /* Check whether we have been orphaned. */
232 ret = kill(self, SIGKILL);
241 static int do_test(unsigned long pre_flags, unsigned long post_flags,
242 bool expect_uevent, int sync_fd)
249 struct timespec timeout;
252 sigaddset(&mask, SIGCHLD);
254 ret = sigprocmask(SIG_BLOCK, &mask, &orig_mask);
256 fprintf(stderr, "%s- Failed to block SIGCHLD\n", strerror(errno));
262 fprintf(stderr, "%s - Failed to fork() new process\n", strerror(errno));
267 /* Make sure that we go away when our parent dies. */
268 ret = set_death_signal();
270 fprintf(stderr, "Failed to set PR_SET_PDEATHSIG to SIGKILL\n");
274 if (pre_flags & CLONE_NEWUSER) {
275 ret = unshare(CLONE_NEWUSER);
278 "%s - Failed to unshare user namespace\n",
284 if (pre_flags & CLONE_NEWNET) {
285 ret = unshare(CLONE_NEWNET);
288 "%s - Failed to unshare network namespace\n",
294 if (uevent_listener(post_flags, expect_uevent, sync_fd) < 0)
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");
306 /* Trigger 10 uevents to account for the case where the kernel might
309 ret = trigger_uevent(10);
311 fprintf(stderr, "Failed triggering uevents\n");
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
321 ret = sigtimedwait(&mask, NULL, &timeout);
327 ret = kill(pid, SIGTERM); /* success */
329 ret = kill(pid, SIGUSR1); /* error */
334 ret = wait_for_pid(pid);
341 static void signal_handler(int sig)
349 TEST(uevent_filtering)
352 struct sigaction act;
355 TH_LOG("Uevent filtering tests require root privileges. Skipping test");
359 ret = access(__DEV_FULL, F_OK);
361 if (errno == ENOENT) {
362 TH_LOG(__DEV_FULL " does not exist. Skipping test");
369 act.sa_handler = signal_handler;
371 sigemptyset(&act.sa_mask);
373 ret = sigaction(SIGTERM, &act, NULL);
376 sync_fd = eventfd(0, EFD_CLOEXEC);
377 ASSERT_GE(sync_fd, 0);
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
386 * - uevent listening socket receives uevent
388 ret = do_test(0, 0, true, sync_fd);
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
400 * - uevent listening socket receives uevent
402 ret = do_test(CLONE_NEWNET, 0, true, sync_fd);
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
415 * - uevent listening socket receives uevent
417 ret = do_test(CLONE_NEWUSER, 0, true, sync_fd);
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
429 * - uevent listening socket receives no uevent
431 ret = do_test(CLONE_NEWUSER | CLONE_NEWNET, 0, false, sync_fd);
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
444 * - uevent listening socket receives uevent
446 ret = do_test(0, CLONE_NEWNET, true, sync_fd);
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
459 * - uevent listening socket receives uevent
461 ret = do_test(0, CLONE_NEWUSER, true, sync_fd);
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
475 * - uevent listening socket receives uevent
477 ret = do_test(0, CLONE_NEWUSER | CLONE_NEWNET, true, sync_fd);