1 // SPDX-License-Identifier: GPL-2.0 OR MIT 2 #define _GNU_SOURCE 3 #include <error.h> 4 #include <limits.h> 5 #include <stddef.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <sys/socket.h> 9 #include <linux/socket.h> 10 #include <unistd.h> 11 #include <string.h> 12 #include <errno.h> 13 #include <pthread.h> 14 #include <sys/un.h> 15 #include <sys/signal.h> 16 #include <sys/types.h> 17 #include <sys/wait.h> 18 19 #include "../../pidfd/pidfd.h" 20 #include "kselftest_harness.h" 21 22 #define clean_errno() (errno == 0 ? "None" : strerror(errno)) 23 #define log_err(MSG, ...) \ 24 fprintf(stderr, "(%s:%d: errno: %s) " MSG "\n", __FILE__, __LINE__, \ 25 clean_errno(), ##__VA_ARGS__) 26 27 #ifndef SCM_PIDFD 28 #define SCM_PIDFD 0x04 29 #endif 30 31 #ifndef SCM_PIDFD_THREAD 32 #define SCM_PIDFD_THREAD 0x05 33 #endif 34 35 #ifndef SO_PASSPIDFD_THREAD 36 #define SO_PASSPIDFD_THREAD 86 37 #endif 38 39 #ifndef SO_PEERPIDFD_THREAD 40 #define SO_PEERPIDFD_THREAD 87 41 #endif 42 43 #define CHILD_EXIT_CODE_OK 123 44 45 static void child_die() 46 { 47 exit(1); 48 } 49 50 static int safe_int(const char *numstr, int *converted) 51 { 52 char *err = NULL; 53 long sli; 54 55 errno = 0; 56 sli = strtol(numstr, &err, 0); 57 if (errno == ERANGE && (sli == LONG_MAX || sli == LONG_MIN)) 58 return -ERANGE; 59 60 if (errno != 0 && sli == 0) 61 return -EINVAL; 62 63 if (err == numstr || *err != '\0') 64 return -EINVAL; 65 66 if (sli > INT_MAX || sli < INT_MIN) 67 return -ERANGE; 68 69 *converted = (int)sli; 70 return 0; 71 } 72 73 static int char_left_gc(const char *buffer, size_t len) 74 { 75 size_t i; 76 77 for (i = 0; i < len; i++) { 78 if (buffer[i] == ' ' || buffer[i] == '\t') 79 continue; 80 81 return i; 82 } 83 84 return 0; 85 } 86 87 static int char_right_gc(const char *buffer, size_t len) 88 { 89 int i; 90 91 for (i = len - 1; i >= 0; i--) { 92 if (buffer[i] == ' ' || buffer[i] == '\t' || 93 buffer[i] == '\n' || buffer[i] == '\0') 94 continue; 95 96 return i + 1; 97 } 98 99 return 0; 100 } 101 102 static char *trim_whitespace_in_place(char *buffer) 103 { 104 buffer += char_left_gc(buffer, strlen(buffer)); 105 buffer[char_right_gc(buffer, strlen(buffer))] = '\0'; 106 return buffer; 107 } 108 109 /* borrowed (with all helpers) from pidfd/pidfd_open_test.c */ 110 static pid_t get_pid_from_fdinfo_file(int pidfd, const char *key, size_t keylen) 111 { 112 int ret; 113 char path[512]; 114 FILE *f; 115 size_t n = 0; 116 pid_t result = -1; 117 char *line = NULL; 118 119 snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", pidfd); 120 121 f = fopen(path, "re"); 122 if (!f) 123 return -1; 124 125 while (getline(&line, &n, f) != -1) { 126 char *numstr; 127 128 if (strncmp(line, key, keylen)) 129 continue; 130 131 numstr = trim_whitespace_in_place(line + 4); 132 ret = safe_int(numstr, &result); 133 if (ret < 0) 134 goto out; 135 136 break; 137 } 138 139 out: 140 free(line); 141 fclose(f); 142 return result; 143 } 144 145 struct cmsg_data { 146 struct ucred *ucred; 147 int *pidfd; 148 }; 149 150 static int parse_cmsg(struct msghdr *msg, struct cmsg_data *res) 151 { 152 struct cmsghdr *cmsg; 153 154 if (msg->msg_flags & (MSG_TRUNC | MSG_CTRUNC)) { 155 log_err("recvmsg: truncated"); 156 return 1; 157 } 158 159 for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; 160 cmsg = CMSG_NXTHDR(msg, cmsg)) { 161 if (cmsg->cmsg_level == SOL_SOCKET && 162 cmsg->cmsg_type == SCM_PIDFD) { 163 if (cmsg->cmsg_len < sizeof(*res->pidfd)) { 164 log_err("CMSG parse: SCM_PIDFD wrong len"); 165 return 1; 166 } 167 168 res->pidfd = (void *)CMSG_DATA(cmsg); 169 } 170 171 if (cmsg->cmsg_level == SOL_SOCKET && 172 cmsg->cmsg_type == SCM_CREDENTIALS) { 173 if (cmsg->cmsg_len < sizeof(*res->ucred)) { 174 log_err("CMSG parse: SCM_CREDENTIALS wrong len"); 175 return 1; 176 } 177 178 res->ucred = (void *)CMSG_DATA(cmsg); 179 } 180 } 181 182 if (!res->pidfd) { 183 log_err("CMSG parse: SCM_PIDFD not found"); 184 return 1; 185 } 186 187 if (!res->ucred) { 188 log_err("CMSG parse: SCM_CREDENTIALS not found"); 189 return 1; 190 } 191 192 return 0; 193 } 194 195 static int cmsg_check(int fd) 196 { 197 struct msghdr msg = { 0 }; 198 struct cmsg_data res; 199 struct iovec iov; 200 int data = 0; 201 char control[CMSG_SPACE(sizeof(struct ucred)) + 202 CMSG_SPACE(sizeof(int))] = { 0 }; 203 pid_t parent_pid; 204 int err; 205 206 iov.iov_base = &data; 207 iov.iov_len = sizeof(data); 208 209 msg.msg_iov = &iov; 210 msg.msg_iovlen = 1; 211 msg.msg_control = control; 212 msg.msg_controllen = sizeof(control); 213 214 err = recvmsg(fd, &msg, 0); 215 if (err < 0) { 216 log_err("recvmsg"); 217 return 1; 218 } 219 220 if (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC)) { 221 log_err("recvmsg: truncated"); 222 return 1; 223 } 224 225 /* send(pfd, "x", sizeof(char), 0) */ 226 if (data != 'x') { 227 log_err("recvmsg: data corruption"); 228 return 1; 229 } 230 231 if (parse_cmsg(&msg, &res)) { 232 log_err("CMSG parse: parse_cmsg() failed"); 233 return 1; 234 } 235 236 /* pidfd from SCM_PIDFD should point to the parent process PID */ 237 parent_pid = 238 get_pid_from_fdinfo_file(*res.pidfd, "Pid:", sizeof("Pid:") - 1); 239 if (parent_pid != getppid()) { 240 log_err("wrong SCM_PIDFD %d != %d", parent_pid, getppid()); 241 close(*res.pidfd); 242 return 1; 243 } 244 245 close(*res.pidfd); 246 return 0; 247 } 248 249 static int cmsg_check_dead(int fd, int expected_pid) 250 { 251 int err; 252 struct msghdr msg = { 0 }; 253 struct cmsg_data res; 254 struct iovec iov; 255 int data = 0; 256 char control[CMSG_SPACE(sizeof(struct ucred)) + 257 CMSG_SPACE(sizeof(int))] = { 0 }; 258 struct pidfd_info info = { 259 .mask = PIDFD_INFO_EXIT, 260 }; 261 262 iov.iov_base = &data; 263 iov.iov_len = sizeof(data); 264 265 msg.msg_iov = &iov; 266 msg.msg_iovlen = 1; 267 msg.msg_control = control; 268 msg.msg_controllen = sizeof(control); 269 270 err = recvmsg(fd, &msg, 0); 271 if (err < 0) { 272 log_err("recvmsg"); 273 return 1; 274 } 275 276 if (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC)) { 277 log_err("recvmsg: truncated"); 278 return 1; 279 } 280 281 /* send(cfd, "y", sizeof(char), 0) */ 282 if (data != 'y') { 283 log_err("recvmsg: data corruption"); 284 return 1; 285 } 286 287 if (parse_cmsg(&msg, &res)) { 288 log_err("CMSG parse: parse_cmsg() failed"); 289 return 1; 290 } 291 292 /* 293 * pidfd from SCM_PIDFD should point to the client_pid. 294 * Let's read exit information and check if it's what 295 * we expect to see. 296 */ 297 if (ioctl(*res.pidfd, PIDFD_GET_INFO, &info)) { 298 log_err("%s: ioctl(PIDFD_GET_INFO) failed", __func__); 299 close(*res.pidfd); 300 return 1; 301 } 302 303 if (!(info.mask & PIDFD_INFO_EXIT)) { 304 log_err("%s: No exit information from ioctl(PIDFD_GET_INFO)", __func__); 305 close(*res.pidfd); 306 return 1; 307 } 308 309 err = WIFEXITED(info.exit_code) ? WEXITSTATUS(info.exit_code) : 1; 310 if (err != CHILD_EXIT_CODE_OK) { 311 log_err("%s: wrong exit_code %d != %d", __func__, err, CHILD_EXIT_CODE_OK); 312 close(*res.pidfd); 313 return 1; 314 } 315 316 close(*res.pidfd); 317 return 0; 318 } 319 320 struct sock_addr { 321 char sock_name[32]; 322 struct sockaddr_un listen_addr; 323 socklen_t addrlen; 324 }; 325 326 FIXTURE(scm_pidfd) 327 { 328 int server; 329 pid_t client_pid; 330 int startup_pipe[2]; 331 struct sock_addr server_addr; 332 struct sock_addr *client_addr; 333 }; 334 335 FIXTURE_VARIANT(scm_pidfd) 336 { 337 int type; 338 bool abstract; 339 }; 340 341 FIXTURE_VARIANT_ADD(scm_pidfd, stream_pathname) 342 { 343 .type = SOCK_STREAM, 344 .abstract = 0, 345 }; 346 347 FIXTURE_VARIANT_ADD(scm_pidfd, stream_abstract) 348 { 349 .type = SOCK_STREAM, 350 .abstract = 1, 351 }; 352 353 FIXTURE_VARIANT_ADD(scm_pidfd, dgram_pathname) 354 { 355 .type = SOCK_DGRAM, 356 .abstract = 0, 357 }; 358 359 FIXTURE_VARIANT_ADD(scm_pidfd, dgram_abstract) 360 { 361 .type = SOCK_DGRAM, 362 .abstract = 1, 363 }; 364 365 FIXTURE_SETUP(scm_pidfd) 366 { 367 self->client_addr = mmap(NULL, sizeof(*self->client_addr), PROT_READ | PROT_WRITE, 368 MAP_SHARED | MAP_ANONYMOUS, -1, 0); 369 ASSERT_NE(MAP_FAILED, self->client_addr); 370 } 371 372 FIXTURE_TEARDOWN(scm_pidfd) 373 { 374 close(self->server); 375 376 kill(self->client_pid, SIGKILL); 377 waitpid(self->client_pid, NULL, 0); 378 379 if (!variant->abstract) { 380 unlink(self->server_addr.sock_name); 381 unlink(self->client_addr->sock_name); 382 } 383 } 384 385 static void fill_sockaddr(struct sock_addr *addr, bool abstract) 386 { 387 char *sun_path_buf = (char *)&addr->listen_addr.sun_path; 388 389 addr->listen_addr.sun_family = AF_UNIX; 390 addr->addrlen = offsetof(struct sockaddr_un, sun_path); 391 snprintf(addr->sock_name, sizeof(addr->sock_name), "scm_pidfd_%d", getpid()); 392 addr->addrlen += strlen(addr->sock_name); 393 if (abstract) { 394 *sun_path_buf = '\0'; 395 addr->addrlen++; 396 sun_path_buf++; 397 } else { 398 unlink(addr->sock_name); 399 } 400 memcpy(sun_path_buf, addr->sock_name, strlen(addr->sock_name)); 401 } 402 403 static int sk_enable_cred_pass(int sk) 404 { 405 int on = 0; 406 407 on = 1; 408 if (setsockopt(sk, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) { 409 log_err("Failed to set SO_PASSCRED"); 410 return 1; 411 } 412 413 if (setsockopt(sk, SOL_SOCKET, SO_PASSPIDFD, &on, sizeof(on))) { 414 log_err("Failed to set SO_PASSPIDFD"); 415 return 1; 416 } 417 418 return 0; 419 } 420 421 static void client(FIXTURE_DATA(scm_pidfd) *self, 422 const FIXTURE_VARIANT(scm_pidfd) *variant) 423 { 424 int cfd; 425 socklen_t len; 426 struct ucred peer_cred; 427 int peer_pidfd; 428 pid_t peer_pid; 429 430 cfd = socket(AF_UNIX, variant->type, 0); 431 if (cfd < 0) { 432 log_err("socket"); 433 child_die(); 434 } 435 436 if (variant->type == SOCK_DGRAM) { 437 fill_sockaddr(self->client_addr, variant->abstract); 438 439 if (bind(cfd, (struct sockaddr *)&self->client_addr->listen_addr, self->client_addr->addrlen)) { 440 log_err("bind"); 441 child_die(); 442 } 443 } 444 445 if (connect(cfd, (struct sockaddr *)&self->server_addr.listen_addr, 446 self->server_addr.addrlen) != 0) { 447 log_err("connect"); 448 child_die(); 449 } 450 451 if (sk_enable_cred_pass(cfd)) { 452 log_err("sk_enable_cred_pass() failed"); 453 child_die(); 454 } 455 456 close(self->startup_pipe[1]); 457 458 if (cmsg_check(cfd)) { 459 log_err("cmsg_check failed"); 460 child_die(); 461 } 462 463 /* send something to the parent so it can receive SCM_PIDFD too and validate it */ 464 if (send(cfd, "y", sizeof(char), 0) == -1) { 465 log_err("Failed to send(cfd, \"y\", sizeof(char), 0)"); 466 child_die(); 467 } 468 469 /* skip further for SOCK_DGRAM as it's not applicable */ 470 if (variant->type == SOCK_DGRAM) 471 return; 472 473 len = sizeof(peer_cred); 474 if (getsockopt(cfd, SOL_SOCKET, SO_PEERCRED, &peer_cred, &len)) { 475 log_err("Failed to get SO_PEERCRED"); 476 child_die(); 477 } 478 479 len = sizeof(peer_pidfd); 480 if (getsockopt(cfd, SOL_SOCKET, SO_PEERPIDFD, &peer_pidfd, &len)) { 481 log_err("Failed to get SO_PEERPIDFD"); 482 child_die(); 483 } 484 485 /* pid from SO_PEERCRED should point to the parent process PID */ 486 if (peer_cred.pid != getppid()) { 487 log_err("peer_cred.pid != getppid(): %d != %d", peer_cred.pid, getppid()); 488 child_die(); 489 } 490 491 peer_pid = get_pid_from_fdinfo_file(peer_pidfd, 492 "Pid:", sizeof("Pid:") - 1); 493 if (peer_pid != peer_cred.pid) { 494 log_err("peer_pid != peer_cred.pid: %d != %d", peer_pid, peer_cred.pid); 495 child_die(); 496 } 497 } 498 499 TEST_F(scm_pidfd, test) 500 { 501 int err; 502 int pfd; 503 int child_status = 0; 504 505 self->server = socket(AF_UNIX, variant->type, 0); 506 ASSERT_NE(-1, self->server); 507 508 fill_sockaddr(&self->server_addr, variant->abstract); 509 510 err = bind(self->server, (struct sockaddr *)&self->server_addr.listen_addr, self->server_addr.addrlen); 511 ASSERT_EQ(0, err); 512 513 if (variant->type == SOCK_STREAM) { 514 err = listen(self->server, 1); 515 ASSERT_EQ(0, err); 516 } 517 518 err = pipe(self->startup_pipe); 519 ASSERT_NE(-1, err); 520 521 self->client_pid = fork(); 522 ASSERT_NE(-1, self->client_pid); 523 if (self->client_pid == 0) { 524 close(self->server); 525 close(self->startup_pipe[0]); 526 client(self, variant); 527 528 /* 529 * It's a bit unusual, but in case of success we return non-zero 530 * exit code (CHILD_EXIT_CODE_OK) and then we expect to read it 531 * from ioctl(PIDFD_GET_INFO) in cmsg_check_dead(). 532 */ 533 exit(CHILD_EXIT_CODE_OK); 534 } 535 close(self->startup_pipe[1]); 536 537 if (variant->type == SOCK_STREAM) { 538 pfd = accept(self->server, NULL, NULL); 539 ASSERT_NE(-1, pfd); 540 } else { 541 pfd = self->server; 542 } 543 544 /* wait until the child arrives at checkpoint */ 545 read(self->startup_pipe[0], &err, sizeof(int)); 546 close(self->startup_pipe[0]); 547 548 if (variant->type == SOCK_DGRAM) { 549 err = sendto(pfd, "x", sizeof(char), 0, (struct sockaddr *)&self->client_addr->listen_addr, self->client_addr->addrlen); 550 ASSERT_NE(-1, err); 551 } else { 552 err = send(pfd, "x", sizeof(char), 0); 553 ASSERT_NE(-1, err); 554 } 555 556 waitpid(self->client_pid, &child_status, 0); 557 /* see comment before exit(CHILD_EXIT_CODE_OK) */ 558 ASSERT_EQ(CHILD_EXIT_CODE_OK, WIFEXITED(child_status) ? WEXITSTATUS(child_status) : 1); 559 560 err = sk_enable_cred_pass(pfd); 561 ASSERT_EQ(0, err); 562 563 err = cmsg_check_dead(pfd, self->client_pid); 564 ASSERT_EQ(0, err); 565 566 close(pfd); 567 } 568 569 struct thread_ids { 570 pid_t pid; 571 pid_t tid; 572 }; 573 574 #define MAX_WRITERS 2 575 576 /* Used by writers to signal they've written, so we can sequence multiple writers */ 577 static int seq_pipe[2]; 578 579 static void *send_ids_thread(void *arg) 580 { 581 int fd = *(int *)arg; 582 struct thread_ids ids = { 583 .pid = getpid(), 584 .tid = gettid(), 585 }; 586 char sync; 587 588 if (send(fd, &ids, sizeof(ids), 0) != sizeof(ids)) 589 return (void *)1; 590 591 /* let the client start the next writer, so the queue order is known */ 592 if (write(seq_pipe[1], "1", 1) != 1) 593 return (void *)1; 594 595 /* stay alive until the receiver has looked at our pidfd */ 596 if (read(fd, &sync, 1) != 1) 597 return (void *)1; 598 599 return NULL; 600 } 601 602 static void *send_ids_creds_thread(void *arg) 603 { 604 int fd = *(int *)arg; 605 struct thread_ids ids = { 606 .pid = getpid(), 607 .tid = gettid(), 608 }; 609 struct ucred ucred = { 610 .pid = getpid(), 611 .uid = getuid(), 612 .gid = getgid(), 613 }; 614 char control[CMSG_SPACE(sizeof(ucred))] = { 0 }; 615 struct iovec iov; 616 struct msghdr msg = { 0 }; 617 struct cmsghdr *cmsg; 618 char sync; 619 620 iov.iov_base = &ids; 621 iov.iov_len = sizeof(ids); 622 623 msg.msg_iov = &iov; 624 msg.msg_iovlen = 1; 625 msg.msg_control = control; 626 msg.msg_controllen = sizeof(control); 627 628 cmsg = CMSG_FIRSTHDR(&msg); 629 cmsg->cmsg_level = SOL_SOCKET; 630 cmsg->cmsg_type = SCM_CREDENTIALS; 631 cmsg->cmsg_len = CMSG_LEN(sizeof(ucred)); 632 memcpy(CMSG_DATA(cmsg), &ucred, sizeof(ucred)); 633 634 if (sendmsg(fd, &msg, 0) != sizeof(ids)) 635 return (void *)1; 636 637 /* signal we've written our info */ 638 if (write(seq_pipe[1], "1", 1) != 1) 639 return (void *)1; 640 641 /* stay alive until the receiver has looked at our pidfd */ 642 if (read(fd, &sync, 1) != 1) 643 return (void *)1; 644 645 return NULL; 646 } 647 648 /* 649 * Runs @nwriters copies of @sender, each in its own non-leader thread, one 650 * at a time so the queue order is known, then tells the parent on @ackfd 651 * that everything is queued. 652 */ 653 static void thread_client(int fd, int syncfd, int ackfd, 654 void *(*sender)(void *), int nwriters) 655 { 656 pthread_t writers[MAX_WRITERS]; 657 void *ret; 658 char sync; 659 int i; 660 661 /* wait until the receiver enabled the options it wants */ 662 if (read(syncfd, &sync, 1) != 1) 663 child_die(); 664 665 for (i = 0; i < nwriters; i++) { 666 if (pthread_create(&writers[i], NULL, sender, &fd)) 667 child_die(); 668 669 if (read(seq_pipe[0], &sync, 1) != 1) 670 child_die(); 671 } 672 673 if (write(ackfd, "1", 1) != 1) 674 child_die(); 675 676 for (i = 0; i < nwriters; i++) 677 if (pthread_join(writers[i], &ret) || ret) 678 child_die(); 679 680 exit(0); 681 } 682 683 struct pidfd_msg { 684 ssize_t len; 685 struct thread_ids ids; 686 struct pidfd_info tgid_info; 687 struct pidfd_info thread_info; 688 int tgid_flags; 689 int thread_flags; 690 bool have_tgid; 691 bool have_thread; 692 }; 693 694 static int get_pidfd_info(int pidfd, struct pidfd_info *info) 695 { 696 info->mask = PIDFD_INFO_PID; 697 if (ioctl(pidfd, PIDFD_GET_INFO, info)) { 698 log_err("ioctl(PIDFD_GET_INFO)"); 699 return -1; 700 } 701 702 return 0; 703 } 704 705 /* One recvmsg(), reporting how many bytes came back and what the pidfd 706 * cmsgs that came with them say. 707 */ 708 static int read_pidfd_msg(int fd, struct pidfd_msg *out) 709 { 710 char control[CMSG_SPACE(sizeof(int)) * 2] = { 0 }; 711 int tgid_pidfd = -1, thread_pidfd = -1; 712 struct thread_ids buf[2] = { 0 }; 713 struct msghdr msg = { 0 }; 714 struct cmsghdr *cmsg; 715 struct iovec iov; 716 717 iov.iov_base = buf; 718 iov.iov_len = sizeof(buf); 719 msg.msg_iov = &iov; 720 msg.msg_iovlen = 1; 721 msg.msg_control = control; 722 msg.msg_controllen = sizeof(control); 723 724 out->len = recvmsg(fd, &msg, 0); 725 if (out->len < 0) { 726 log_err("recvmsg"); 727 return -1; 728 } 729 730 if (msg.msg_flags & MSG_CTRUNC) { 731 log_err("recvmsg: control truncated"); 732 return -1; 733 } 734 735 out->ids = buf[0]; 736 737 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 738 cmsg = CMSG_NXTHDR(&msg, cmsg)) { 739 if (cmsg->cmsg_level != SOL_SOCKET) 740 continue; 741 742 if (cmsg->cmsg_type == SCM_PIDFD) 743 memcpy(&tgid_pidfd, CMSG_DATA(cmsg), sizeof(tgid_pidfd)); 744 else if (cmsg->cmsg_type == SCM_PIDFD_THREAD) 745 memcpy(&thread_pidfd, CMSG_DATA(cmsg), sizeof(thread_pidfd)); 746 } 747 748 out->have_tgid = tgid_pidfd >= 0; 749 out->have_thread = thread_pidfd >= 0; 750 751 if (out->have_tgid) { 752 if (get_pidfd_info(tgid_pidfd, &out->tgid_info)) 753 return -1; 754 out->tgid_flags = fcntl(tgid_pidfd, F_GETFL); 755 close(tgid_pidfd); 756 } 757 758 if (out->have_thread) { 759 if (get_pidfd_info(thread_pidfd, &out->thread_info)) 760 return -1; 761 out->thread_flags = fcntl(thread_pidfd, F_GETFL); 762 close(thread_pidfd); 763 } 764 765 return 0; 766 } 767 768 /* 769 * Runs @nwriters threads of one child process against a SOCK_STREAM pair, 770 * all of them queued before the parent reads. SO_PASSPIDFD is set when 771 * @want_tgid is given, SO_PASSPIDFD_THREAD when @want_thread is. @nread 772 * reads are returned in @out. 773 */ 774 static int pidfd_flow(void *(*sender)(void *), int nwriters, bool want_tgid, 775 bool want_thread, struct pidfd_msg *out, int nread) 776 { 777 int child_status = 0; 778 int syncpipe[2]; 779 int ackpipe[2]; 780 int sk[2]; 781 int on = 1; 782 char sync; 783 pid_t child; 784 int i; 785 786 if (nwriters > MAX_WRITERS) 787 return -1; 788 789 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sk)) 790 return -1; 791 if (pipe(syncpipe) || pipe(ackpipe) || pipe(seq_pipe)) 792 return -1; 793 794 child = fork(); 795 if (child < 0) 796 return -1; 797 798 if (child == 0) { 799 close(sk[0]); 800 close(syncpipe[1]); 801 close(ackpipe[0]); 802 thread_client(sk[1], syncpipe[0], ackpipe[1], sender, nwriters); 803 } 804 close(sk[1]); 805 close(syncpipe[0]); 806 close(ackpipe[1]); 807 close(seq_pipe[0]); 808 close(seq_pipe[1]); 809 810 if (want_tgid && 811 setsockopt(sk[0], SOL_SOCKET, SO_PASSPIDFD, &on, sizeof(on))) { 812 log_err("Failed to set SO_PASSPIDFD"); 813 return -1; 814 } 815 816 if (want_thread && 817 setsockopt(sk[0], SOL_SOCKET, SO_PASSPIDFD_THREAD, &on, sizeof(on))) { 818 log_err("Failed to set SO_PASSPIDFD_THREAD"); 819 return -1; 820 } 821 822 /* let the child know the options are set, it can write now */ 823 if (write(syncpipe[1], "1", 1) != 1) 824 return -1; 825 close(syncpipe[1]); 826 827 /* wait until every writer has queued its message */ 828 if (read(ackpipe[0], &sync, 1) != 1) 829 return -1; 830 close(ackpipe[0]); 831 832 for (i = 0; i < nread; i++) 833 if (read_pidfd_msg(sk[0], &out[i])) 834 return -1; 835 836 /* release the writers */ 837 for (i = 0; i < nwriters; i++) 838 if (write(sk[0], "x", 1) != 1) 839 return -1; 840 close(sk[0]); 841 842 waitpid(child, &child_status, 0); 843 if (!WIFEXITED(child_status) || WEXITSTATUS(child_status)) 844 return -1; 845 846 return 0; 847 } 848 849 static int sockopt_set(int fd, int optname, int val) 850 { 851 return setsockopt(fd, SOL_SOCKET, optname, &val, sizeof(val)); 852 } 853 854 static int sockopt_get(int fd, int optname) 855 { 856 socklen_t len = sizeof(int); 857 int val = -1; 858 859 if (getsockopt(fd, SOL_SOCKET, optname, &val, &len)) 860 return -1; 861 862 return val; 863 } 864 865 TEST(scm_pidfd_setsockopt_values) 866 { 867 int sk[2]; 868 869 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sk)); 870 871 /* Verify that the options are truly set independently */ 872 ASSERT_EQ(0, sockopt_set(sk[0], SO_PASSPIDFD_THREAD, 1)); 873 ASSERT_EQ(1, sockopt_get(sk[0], SO_PASSPIDFD_THREAD)); 874 ASSERT_EQ(0, sockopt_get(sk[0], SO_PASSPIDFD)); 875 876 ASSERT_EQ(0, sockopt_set(sk[0], SO_PASSPIDFD, 1)); 877 ASSERT_EQ(1, sockopt_get(sk[0], SO_PASSPIDFD)); 878 ASSERT_EQ(1, sockopt_get(sk[0], SO_PASSPIDFD_THREAD)); 879 880 /* Verify that the options are truly cleared independently */ 881 ASSERT_EQ(0, sockopt_set(sk[0], SO_PASSPIDFD, 0)); 882 ASSERT_EQ(0, sockopt_get(sk[0], SO_PASSPIDFD)); 883 ASSERT_EQ(1, sockopt_get(sk[0], SO_PASSPIDFD_THREAD)); 884 885 ASSERT_EQ(0, sockopt_set(sk[0], SO_PASSPIDFD_THREAD, 0)); 886 ASSERT_EQ(0, sockopt_get(sk[0], SO_PASSPIDFD_THREAD)); 887 ASSERT_EQ(0, sockopt_get(sk[0], SO_PASSPIDFD)); 888 889 close(sk[0]); 890 close(sk[1]); 891 } 892 893 /* A receiver that only asked about the process cannot tell the two 894 * threads apart, so their writes are glued into one read. 895 */ 896 TEST(scm_pidfd_stream_glues_threads) 897 { 898 struct pidfd_msg msg[1] = { 0 }; 899 900 ASSERT_EQ(0, pidfd_flow(send_ids_thread, 2, true, false, msg, 1)); 901 EXPECT_EQ(sizeof(struct thread_ids) * 2, msg[0].len); 902 903 EXPECT_TRUE(msg[0].have_tgid); 904 EXPECT_FALSE(msg[0].have_thread); 905 EXPECT_EQ(msg[0].ids.pid, msg[0].tgid_info.pid); 906 EXPECT_EQ(msg[0].ids.pid, msg[0].tgid_info.tgid); 907 } 908 909 /* A receiver asking for both thread and process pidfd should get a unique 910 * msg for each thread writing 911 */ 912 TEST(scm_pidfd_thread_stream_splits_on_threads) 913 { 914 struct pidfd_msg msg[2] = { 0 }; 915 int i; 916 917 ASSERT_EQ(0, pidfd_flow(send_ids_thread, 2, true, true, msg, 2)); 918 919 for (i = 0; i < 2; i++) { 920 EXPECT_EQ(sizeof(struct thread_ids), msg[i].len); 921 EXPECT_TRUE(msg[i].have_tgid); 922 EXPECT_TRUE(msg[i].have_thread); 923 924 /* Make sure the info makes sense for the pidfd type */ 925 EXPECT_EQ(msg[i].ids.pid, msg[i].tgid_info.pid); 926 EXPECT_EQ(msg[i].ids.pid, msg[i].tgid_info.tgid); 927 EXPECT_EQ(msg[i].ids.tid, msg[i].thread_info.pid); 928 EXPECT_EQ(msg[i].ids.pid, msg[i].thread_info.tgid); 929 EXPECT_NE(msg[i].ids.pid, msg[i].ids.tid); 930 } 931 932 /* Make sure we really got unique threads per message */ 933 EXPECT_NE(msg[0].ids.tid, msg[1].ids.tid); 934 EXPECT_EQ(msg[0].ids.pid, msg[1].ids.pid); 935 EXPECT_EQ(msg[0].tgid_info.pid, msg[1].tgid_info.pid); 936 EXPECT_NE(msg[0].thread_info.pid, msg[1].thread_info.pid); 937 } 938 939 /* Sends from the thread-group leader */ 940 static int leader_flow(bool want_thread, struct pidfd_msg *out) 941 { 942 struct thread_ids ids = { 943 .pid = getpid(), 944 .tid = gettid(), 945 }; 946 int sk[2]; 947 int on = 1; 948 int ret; 949 950 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sk)) 951 return -1; 952 953 if (setsockopt(sk[0], SOL_SOCKET, SO_PASSPIDFD, &on, sizeof(on))) { 954 log_err("Failed to set SO_PASSPIDFD"); 955 return -1; 956 } 957 958 if (want_thread && 959 setsockopt(sk[0], SOL_SOCKET, SO_PASSPIDFD_THREAD, &on, sizeof(on))) { 960 log_err("Failed to set SO_PASSPIDFD_THREAD"); 961 return -1; 962 } 963 964 if (send(sk[1], &ids, sizeof(ids), 0) != sizeof(ids)) { 965 log_err("send"); 966 return -1; 967 } 968 969 ret = read_pidfd_msg(sk[0], out); 970 971 close(sk[0]); 972 close(sk[1]); 973 974 return ret; 975 } 976 977 TEST(scm_pidfd_leader_sender) 978 { 979 struct pidfd_msg msg = { 0 }; 980 981 ASSERT_EQ(getpid(), gettid()); 982 983 ASSERT_EQ(0, leader_flow(false, &msg)); 984 ASSERT_TRUE(msg.have_tgid); 985 EXPECT_FALSE(msg.have_thread); 986 987 EXPECT_EQ(getpid(), msg.tgid_info.pid); 988 EXPECT_EQ(getpid(), msg.tgid_info.tgid); 989 EXPECT_FALSE(msg.tgid_flags & O_EXCL); 990 } 991 992 TEST(scm_pidfd_thread_leader_sender) 993 { 994 struct pidfd_msg msg = { 0 }; 995 996 ASSERT_EQ(getpid(), gettid()); 997 998 ASSERT_EQ(0, leader_flow(true, &msg)); 999 ASSERT_TRUE(msg.have_tgid); 1000 ASSERT_TRUE(msg.have_thread); 1001 1002 EXPECT_EQ(getpid(), msg.tgid_info.pid); 1003 EXPECT_EQ(getpid(), msg.tgid_info.tgid); 1004 EXPECT_EQ(getpid(), msg.thread_info.pid); 1005 EXPECT_EQ(getpid(), msg.thread_info.tgid); 1006 1007 EXPECT_FALSE(msg.tgid_flags & O_EXCL); 1008 EXPECT_TRUE(msg.thread_flags & O_EXCL); 1009 } 1010 1011 TEST(scm_pidfd_thread_and_group) 1012 { 1013 struct pidfd_msg msg = { 0 }; 1014 1015 ASSERT_EQ(0, pidfd_flow(send_ids_thread, 1, true, true, &msg, 1)); 1016 ASSERT_NE(msg.ids.pid, msg.ids.tid); 1017 ASSERT_TRUE(msg.have_tgid); 1018 ASSERT_TRUE(msg.have_thread); 1019 1020 EXPECT_EQ(msg.ids.pid, msg.tgid_info.pid); 1021 EXPECT_EQ(msg.ids.pid, msg.tgid_info.tgid); 1022 1023 EXPECT_EQ(msg.ids.tid, msg.thread_info.pid); 1024 EXPECT_EQ(msg.ids.pid, msg.thread_info.tgid); 1025 } 1026 1027 TEST(scm_pidfd_thread) 1028 { 1029 struct pidfd_msg msg = { 0 }; 1030 1031 ASSERT_EQ(0, pidfd_flow(send_ids_thread, 1, false, true, &msg, 1)); 1032 ASSERT_NE(msg.ids.pid, msg.ids.tid); 1033 ASSERT_TRUE(msg.have_thread); 1034 EXPECT_FALSE(msg.have_tgid); 1035 EXPECT_EQ(msg.ids.tid, msg.thread_info.pid); 1036 EXPECT_EQ(msg.ids.pid, msg.thread_info.tgid); 1037 } 1038 1039 TEST(scm_pidfd_thread_group) 1040 { 1041 struct pidfd_msg msg = { 0 }; 1042 1043 ASSERT_EQ(0, pidfd_flow(send_ids_thread, 1, true, false, &msg, 1)); 1044 ASSERT_NE(msg.ids.pid, msg.ids.tid); 1045 ASSERT_TRUE(msg.have_tgid); 1046 EXPECT_FALSE(msg.have_thread); 1047 EXPECT_EQ(msg.ids.pid, msg.tgid_info.pid); 1048 EXPECT_EQ(msg.ids.pid, msg.tgid_info.tgid); 1049 } 1050 1051 TEST(scm_pidfd_thread_creds) 1052 { 1053 struct pidfd_msg msg = { 0 }; 1054 1055 ASSERT_EQ(0, pidfd_flow(send_ids_creds_thread, 1, true, true, &msg, 1)); 1056 ASSERT_NE(msg.ids.pid, msg.ids.tid); 1057 ASSERT_TRUE(msg.have_tgid); 1058 ASSERT_TRUE(msg.have_thread); 1059 EXPECT_EQ(msg.ids.pid, msg.tgid_info.pid); 1060 EXPECT_EQ(msg.ids.pid, msg.tgid_info.tgid); 1061 EXPECT_EQ(msg.ids.tid, msg.thread_info.pid); 1062 EXPECT_EQ(msg.ids.pid, msg.thread_info.tgid); 1063 } 1064 1065 static void *peer_connect_thread(void *arg) 1066 { 1067 struct sock_addr *sa = arg; 1068 struct thread_ids ids = { 1069 .pid = getpid(), 1070 .tid = gettid(), 1071 }; 1072 int fd; 1073 char sync; 1074 1075 fd = socket(AF_UNIX, SOCK_STREAM, 0); 1076 if (fd < 0) 1077 return (void *)1; 1078 1079 if (connect(fd, (struct sockaddr *)&sa->listen_addr, sa->addrlen)) 1080 return (void *)1; 1081 1082 if (send(fd, &ids, sizeof(ids), 0) != sizeof(ids)) 1083 return (void *)1; 1084 1085 /* stay alive until the server has looked at our pidfd */ 1086 if (read(fd, &sync, 1) != 1) 1087 return (void *)1; 1088 1089 close(fd); 1090 return NULL; 1091 } 1092 1093 static int peer_pidfd_info(int fd, int optname, struct pidfd_info *info) 1094 { 1095 int pidfd; 1096 socklen_t len = sizeof(pidfd); 1097 1098 if (getsockopt(fd, SOL_SOCKET, optname, &pidfd, &len)) { 1099 log_err("getsockopt(SO_PEERPIDFD*)"); 1100 return -1; 1101 } 1102 1103 info->mask = PIDFD_INFO_PID; 1104 if (ioctl(pidfd, PIDFD_GET_INFO, info)) { 1105 log_err("ioctl(PIDFD_GET_INFO)"); 1106 close(pidfd); 1107 return -1; 1108 } 1109 1110 close(pidfd); 1111 return 0; 1112 } 1113 1114 /* SO_PEERPIDFD_THREAD returns a pidfd for the peer's connecting thread. */ 1115 TEST(so_peerpidfd_thread) 1116 { 1117 struct sock_addr sa; 1118 struct thread_ids ids; 1119 struct pidfd_info info; 1120 pthread_t thread; 1121 void *tret; 1122 int server, cfd; 1123 1124 server = socket(AF_UNIX, SOCK_STREAM, 0); 1125 ASSERT_LE(0, server); 1126 1127 fill_sockaddr(&sa, true); 1128 ASSERT_EQ(0, bind(server, (struct sockaddr *)&sa.listen_addr, sa.addrlen)); 1129 ASSERT_EQ(0, listen(server, 1)); 1130 1131 ASSERT_EQ(0, pthread_create(&thread, NULL, peer_connect_thread, &sa)); 1132 1133 cfd = accept(server, NULL, NULL); 1134 ASSERT_LE(0, cfd); 1135 1136 ASSERT_EQ(sizeof(ids), recv(cfd, &ids, sizeof(ids), MSG_WAITALL)); 1137 ASSERT_NE(ids.pid, ids.tid); 1138 1139 /* SO_PEERPIDFD refers to the peer's thread-group. */ 1140 ASSERT_EQ(0, peer_pidfd_info(cfd, SO_PEERPIDFD, &info)); 1141 EXPECT_EQ(ids.pid, info.pid); 1142 EXPECT_EQ(ids.pid, info.tgid); 1143 1144 /* SO_PEERPIDFD_THREAD refers to the connecting thread. */ 1145 ASSERT_EQ(0, peer_pidfd_info(cfd, SO_PEERPIDFD_THREAD, &info)); 1146 EXPECT_EQ(ids.tid, info.pid); 1147 EXPECT_EQ(ids.pid, info.tgid); 1148 1149 /* release the connecting thread */ 1150 ASSERT_EQ(1, write(cfd, "x", 1)); 1151 ASSERT_EQ(0, pthread_join(thread, &tret)); 1152 ASSERT_EQ(NULL, tret); 1153 1154 close(cfd); 1155 close(server); 1156 } 1157 1158 TEST_HARNESS_MAIN 1159