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 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 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 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 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 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 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 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 341 static void signal_handler(int sig) 342 { 343 if (sig == SIGTERM) 344 _exit(EXIT_SUCCESS); 345 346 _exit(EXIT_FAILURE); 347 } 348 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