1 /* $NetBSD: pthread_cancelstub.c,v 1.51 2025/04/04 20:53:38 riastradh Exp $ */ 2 3 /*- 4 * Copyright (c) 2002, 2007 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Nathan J. Williams and Andrew Doran. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* Disable namespace mangling, Fortification is useless here anyway. */ 33 #undef _FORTIFY_SOURCE 34 35 #include <sys/cdefs.h> 36 __RCSID("$NetBSD: pthread_cancelstub.c,v 1.51 2025/04/04 20:53:38 riastradh Exp $"); 37 38 /* Need to use libc-private names for atomic operations. */ 39 #include "../../common/lib/libc/atomic/atomic_op_namespace.h" 40 41 #ifndef lint 42 43 44 /* 45 * This is necessary because the names are always weak (they are not 46 * POSIX functions). 47 */ 48 #define fsync_range _fsync_range 49 #define pollts _pollts 50 51 /* 52 * XXX this is necessary to get the prototypes for the __sigsuspend14 53 * XXX and __msync13 internal names, instead of the application-visible 54 * XXX sigsuspend and msync names. It's kind of gross, but we're pretty 55 * XXX intimate with libc already. 56 */ 57 #define __LIBC12_SOURCE__ 58 59 #include <sys/msg.h> 60 #include <sys/types.h> 61 #include <sys/uio.h> 62 #include <sys/wait.h> 63 #include <aio.h> 64 #include <errno.h> 65 #include <fcntl.h> 66 #include <mqueue.h> 67 #include <poll.h> 68 #include <stdatomic.h> 69 #include <stdarg.h> 70 #include <termios.h> 71 #include <unistd.h> 72 73 #include <signal.h> 74 #include <sys/mman.h> 75 #include <sys/select.h> 76 #include <sys/socket.h> 77 #include <sys/event.h> 78 #include <sys/resource.h> 79 80 #include <compat/sys/mman.h> 81 #include <compat/sys/poll.h> 82 #include <compat/sys/select.h> 83 #include <compat/sys/event.h> 84 #include <compat/sys/wait.h> 85 #include <compat/sys/resource.h> 86 #include <compat/include/aio.h> 87 #include <compat/include/mqueue.h> 88 #include <compat/include/signal.h> 89 #include <compat/include/time.h> 90 91 #include "pthread.h" 92 #include "pthread_int.h" 93 #include "reentrant.h" 94 95 #define atomic_load_relaxed(p) \ 96 atomic_load_explicit(p, memory_order_relaxed) 97 98 int pthread__cancel_stub_binder; 99 100 /* 101 * Provide declarations for the underlying libc syscall stubs. These 102 * _sys_* functions are symbols defined by libc which invoke the system 103 * call, without testing for cancellation. Below, we define non-_sys_* 104 * wrappers which surround calls to _sys_* by the equivalent of 105 * pthread_testcancel(). Both libc and libpthread define the 106 * non-_sys_* wrappers, but they are weak in libc and strong in 107 * libpthread, so programs linked against both will get the libpthread 108 * wrappers that test for cancellation. 109 */ 110 __typeof(accept) _sys_accept; 111 __typeof(__aio_suspend50) _sys___aio_suspend50; 112 __typeof(clock_nanosleep) _sys_clock_nanosleep; 113 __typeof(close) _sys_close; 114 __typeof(connect) _sys_connect; 115 __typeof(fcntl) _sys_fcntl; 116 __typeof(fdatasync) _sys_fdatasync; 117 __typeof(fsync) _sys_fsync; 118 __typeof(fsync_range) _sys_fsync_range; 119 __typeof(__kevent100) _sys___kevent100; 120 __typeof(mq_receive) _sys_mq_receive; 121 __typeof(mq_send) _sys_mq_send; 122 __typeof(__mq_timedreceive50) _sys___mq_timedreceive50; 123 __typeof(__mq_timedsend50) _sys___mq_timedsend50; 124 __typeof(msgrcv) _sys_msgrcv; 125 __typeof(msgsnd) _sys_msgsnd; 126 __typeof(__msync13) _sys___msync13; 127 __typeof(__nanosleep50) _sys___nanosleep50; 128 __typeof(open) _sys_open; 129 __typeof(openat) _sys_openat; 130 __typeof(paccept) _sys_paccept; 131 __typeof(poll) _sys_poll; 132 __typeof(__pollts50) _sys___pollts50; 133 __typeof(pread) _sys_pread; 134 __typeof(__pselect50) _sys___pselect50; 135 __typeof(pwrite) _sys_pwrite; 136 __typeof(read) _sys_read; 137 __typeof(readv) _sys_readv; 138 __typeof(recvfrom) _sys_recvfrom; 139 __typeof(recvmmsg) _sys_recvmmsg; 140 __typeof(recvmsg) _sys_recvmsg; 141 __typeof(__select50) _sys___select50; 142 __typeof(sendmmsg) _sys_sendmmsg; 143 __typeof(sendmsg) _sys_sendmsg; 144 __typeof(sendto) _sys_sendto; 145 __typeof(__sigsuspend14) _sys___sigsuspend14; 146 __typeof(__wait450) _sys___wait450; 147 __typeof(write) _sys_write; 148 __typeof(writev) _sys_writev; 149 150 #define TESTCANCEL(id) do { \ 151 if (__predict_true(!__uselibcstub) && \ 152 __predict_false(atomic_load_relaxed(&(id)->pt_cancel) & \ 153 PT_CANCEL_CANCELLED)) { \ 154 membar_acquire(); \ 155 pthread__cancelled(); \ 156 } \ 157 } while (0) 158 159 160 int 161 accept(int s, struct sockaddr *addr, socklen_t *addrlen) 162 { 163 int retval; 164 pthread_t self; 165 166 self = pthread__self(); 167 TESTCANCEL(self); 168 retval = _sys_accept(s, addr, addrlen); 169 TESTCANCEL(self); 170 171 return retval; 172 } 173 174 int 175 accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags) 176 { 177 int retval; 178 pthread_t self; 179 180 self = pthread__self(); 181 TESTCANCEL(self); 182 retval = _sys_paccept(s, addr, addrlen, NULL, flags); 183 TESTCANCEL(self); 184 185 return retval; 186 } 187 188 int 189 __aio_suspend50(const struct aiocb * const list[], int nent, 190 const struct timespec *timeout) 191 { 192 int retval; 193 pthread_t self; 194 195 self = pthread__self(); 196 TESTCANCEL(self); 197 retval = _sys___aio_suspend50(list, nent, timeout); 198 TESTCANCEL(self); 199 200 return retval; 201 } 202 203 int 204 clock_nanosleep(clockid_t clock_id, int flags, 205 const struct timespec *rqtp, struct timespec *rmtp) 206 { 207 int retval; 208 pthread_t self; 209 210 self = pthread__self(); 211 TESTCANCEL(self); 212 retval = _sys_clock_nanosleep(clock_id, flags, rqtp, rmtp); 213 TESTCANCEL(self); 214 215 return retval; 216 } 217 218 int 219 close(int d) 220 { 221 int retval; 222 pthread_t self; 223 224 self = pthread__self(); 225 TESTCANCEL(self); 226 retval = _sys_close(d); 227 TESTCANCEL(self); 228 229 return retval; 230 } 231 232 int 233 connect(int s, const struct sockaddr *addr, socklen_t namelen) 234 { 235 int retval; 236 pthread_t self; 237 238 self = pthread__self(); 239 TESTCANCEL(self); 240 retval = _sys_connect(s, addr, namelen); 241 TESTCANCEL(self); 242 243 return retval; 244 } 245 246 int 247 fcntl(int fd, int cmd, ...) 248 { 249 int retval; 250 pthread_t self; 251 va_list ap; 252 253 self = pthread__self(); 254 TESTCANCEL(self); 255 va_start(ap, cmd); 256 retval = _sys_fcntl(fd, cmd, va_arg(ap, void *)); 257 va_end(ap); 258 TESTCANCEL(self); 259 260 return retval; 261 } 262 263 int 264 fdatasync(int d) 265 { 266 int retval; 267 pthread_t self; 268 269 self = pthread__self(); 270 TESTCANCEL(self); 271 retval = _sys_fdatasync(d); 272 TESTCANCEL(self); 273 274 return retval; 275 } 276 277 int 278 fsync(int d) 279 { 280 int retval; 281 pthread_t self; 282 283 self = pthread__self(); 284 TESTCANCEL(self); 285 retval = _sys_fsync(d); 286 TESTCANCEL(self); 287 288 return retval; 289 } 290 291 int 292 fsync_range(int d, int f, off_t s, off_t e) 293 { 294 int retval; 295 pthread_t self; 296 297 self = pthread__self(); 298 TESTCANCEL(self); 299 retval = _sys_fsync_range(d, f, s, e); 300 TESTCANCEL(self); 301 302 return retval; 303 } 304 305 int 306 __kevent100(int fd, const struct kevent *ev, size_t nev, struct kevent *rev, 307 size_t nrev, const struct timespec *ts) 308 { 309 int retval; 310 pthread_t self; 311 312 self = pthread__self(); 313 TESTCANCEL(self); 314 retval = _sys___kevent100(fd, ev, nev, rev, nrev, ts); 315 TESTCANCEL(self); 316 317 return retval; 318 } 319 320 ssize_t 321 mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio) 322 { 323 ssize_t retval; 324 pthread_t self; 325 326 self = pthread__self(); 327 TESTCANCEL(self); 328 retval = _sys_mq_receive(mqdes, msg_ptr, msg_len, msg_prio); 329 TESTCANCEL(self); 330 331 return retval; 332 } 333 334 int 335 mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio) 336 { 337 int retval; 338 pthread_t self; 339 340 self = pthread__self(); 341 TESTCANCEL(self); 342 retval = _sys_mq_send(mqdes, msg_ptr, msg_len, msg_prio); 343 TESTCANCEL(self); 344 345 return retval; 346 } 347 348 ssize_t 349 __mq_timedreceive50(mqd_t mqdes, char *msg_ptr, size_t msg_len, 350 unsigned *msg_prio, const struct timespec *abst) 351 { 352 ssize_t retval; 353 pthread_t self; 354 355 self = pthread__self(); 356 TESTCANCEL(self); 357 retval = _sys___mq_timedreceive50(mqdes, msg_ptr, msg_len, msg_prio, 358 abst); 359 TESTCANCEL(self); 360 361 return retval; 362 } 363 364 int 365 __mq_timedsend50(mqd_t mqdes, const char *msg_ptr, size_t msg_len, 366 unsigned msg_prio, const struct timespec *abst) 367 { 368 int retval; 369 pthread_t self; 370 371 self = pthread__self(); 372 TESTCANCEL(self); 373 retval = _sys___mq_timedsend50(mqdes, msg_ptr, msg_len, msg_prio, 374 abst); 375 TESTCANCEL(self); 376 377 return retval; 378 } 379 380 ssize_t 381 msgrcv(int msgid, void *msgp, size_t msgsz, long msgtyp, int msgflg) 382 { 383 ssize_t retval; 384 pthread_t self; 385 386 self = pthread__self(); 387 TESTCANCEL(self); 388 retval = _sys_msgrcv(msgid, msgp, msgsz, msgtyp, msgflg); 389 TESTCANCEL(self); 390 391 return retval; 392 } 393 394 int 395 msgsnd(int msgid, const void *msgp, size_t msgsz, int msgflg) 396 { 397 int retval; 398 pthread_t self; 399 400 self = pthread__self(); 401 TESTCANCEL(self); 402 retval = _sys_msgsnd(msgid, msgp, msgsz, msgflg); 403 TESTCANCEL(self); 404 405 return retval; 406 } 407 408 int 409 __msync13(void *addr, size_t len, int flags) 410 { 411 int retval; 412 pthread_t self; 413 414 self = pthread__self(); 415 TESTCANCEL(self); 416 retval = _sys___msync13(addr, len, flags); 417 TESTCANCEL(self); 418 419 return retval; 420 } 421 422 int 423 __nanosleep50(const struct timespec *rqtp, struct timespec *rmtp) 424 { 425 int retval; 426 pthread_t self; 427 428 self = pthread__self(); 429 TESTCANCEL(self); 430 /* 431 * For now, just nanosleep. In the future, maybe pass a ucontext_t 432 * to _lwp_nanosleep() and allow it to recycle our kernel stack. 433 */ 434 retval = _sys___nanosleep50(rqtp, rmtp); 435 TESTCANCEL(self); 436 437 return retval; 438 } 439 440 int 441 open(const char *path, int flags, ...) 442 { 443 int retval; 444 pthread_t self; 445 va_list ap; 446 447 self = pthread__self(); 448 TESTCANCEL(self); 449 va_start(ap, flags); 450 retval = _sys_open(path, flags, va_arg(ap, mode_t)); 451 va_end(ap); 452 TESTCANCEL(self); 453 454 return retval; 455 } 456 457 int 458 openat(int fd, const char *path, int flags, ...) 459 { 460 int retval; 461 pthread_t self; 462 va_list ap; 463 464 self = pthread__self(); 465 TESTCANCEL(self); 466 va_start(ap, flags); 467 retval = _sys_openat(fd, path, flags, va_arg(ap, mode_t)); 468 va_end(ap); 469 TESTCANCEL(self); 470 471 return retval; 472 } 473 474 int 475 poll(struct pollfd *fds, nfds_t nfds, int timeout) 476 { 477 int retval; 478 pthread_t self; 479 480 self = pthread__self(); 481 TESTCANCEL(self); 482 retval = _sys_poll(fds, nfds, timeout); 483 TESTCANCEL(self); 484 485 return retval; 486 } 487 488 int 489 __pollts50(struct pollfd *fds, nfds_t nfds, const struct timespec *ts, 490 const sigset_t *sigmask) 491 { 492 int retval; 493 pthread_t self; 494 495 self = pthread__self(); 496 TESTCANCEL(self); 497 retval = _sys___pollts50(fds, nfds, ts, sigmask); 498 TESTCANCEL(self); 499 500 return retval; 501 } 502 503 ssize_t 504 pread(int d, void *buf, size_t nbytes, off_t offset) 505 { 506 ssize_t retval; 507 pthread_t self; 508 509 self = pthread__self(); 510 TESTCANCEL(self); 511 retval = _sys_pread(d, buf, nbytes, offset); 512 TESTCANCEL(self); 513 514 return retval; 515 } 516 517 int 518 __pselect50(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, 519 const struct timespec *timeout, const sigset_t *sigmask) 520 { 521 int retval; 522 pthread_t self; 523 524 self = pthread__self(); 525 TESTCANCEL(self); 526 retval = _sys___pselect50(nfds, readfds, writefds, exceptfds, timeout, 527 sigmask); 528 TESTCANCEL(self); 529 530 return retval; 531 } 532 533 ssize_t 534 pwrite(int d, const void *buf, size_t nbytes, off_t offset) 535 { 536 ssize_t retval; 537 pthread_t self; 538 539 self = pthread__self(); 540 TESTCANCEL(self); 541 retval = _sys_pwrite(d, buf, nbytes, offset); 542 TESTCANCEL(self); 543 544 return retval; 545 } 546 547 ssize_t 548 read(int d, void *buf, size_t nbytes) 549 { 550 ssize_t retval; 551 pthread_t self; 552 553 self = pthread__self(); 554 TESTCANCEL(self); 555 retval = _sys_read(d, buf, nbytes); 556 TESTCANCEL(self); 557 558 return retval; 559 } 560 561 ssize_t 562 readv(int d, const struct iovec *iov, int iovcnt) 563 { 564 ssize_t retval; 565 pthread_t self; 566 567 self = pthread__self(); 568 TESTCANCEL(self); 569 retval = _sys_readv(d, iov, iovcnt); 570 TESTCANCEL(self); 571 572 return retval; 573 } 574 575 ssize_t 576 recvfrom(int s, void * restrict buf, size_t len, int flags, 577 struct sockaddr * restrict from, socklen_t * restrict fromlen) 578 { 579 ssize_t retval; 580 pthread_t self; 581 582 self = pthread__self(); 583 TESTCANCEL(self); 584 retval = _sys_recvfrom(s, buf, len, flags, from, fromlen); 585 TESTCANCEL(self); 586 587 return retval; 588 } 589 590 int 591 recvmmsg(int s, struct mmsghdr *mmsg, unsigned int vlen, 592 unsigned int flags, struct timespec *timeout) 593 { 594 ssize_t retval; 595 pthread_t self; 596 597 self = pthread__self(); 598 TESTCANCEL(self); 599 retval = _sys_recvmmsg(s, mmsg, vlen, flags, timeout); 600 TESTCANCEL(self); 601 602 return retval; 603 } 604 605 ssize_t 606 recvmsg(int s, struct msghdr *msg, int flags) 607 { 608 ssize_t retval; 609 pthread_t self; 610 611 self = pthread__self(); 612 TESTCANCEL(self); 613 retval = _sys_recvmsg(s, msg, flags); 614 TESTCANCEL(self); 615 616 return retval; 617 } 618 619 int 620 __select50(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, 621 struct timeval *timeout) 622 { 623 int retval; 624 pthread_t self; 625 626 self = pthread__self(); 627 TESTCANCEL(self); 628 retval = _sys___select50(nfds, readfds, writefds, exceptfds, timeout); 629 TESTCANCEL(self); 630 631 return retval; 632 } 633 634 int 635 sendmmsg(int s, struct mmsghdr *mmsg, unsigned int vlen, 636 unsigned int flags) 637 { 638 int retval; 639 pthread_t self; 640 641 self = pthread__self(); 642 TESTCANCEL(self); 643 retval = _sys_sendmmsg(s, mmsg, vlen, flags); 644 TESTCANCEL(self); 645 646 return retval; 647 } 648 649 ssize_t 650 sendmsg(int s, const struct msghdr *msg, int flags) 651 { 652 int retval; 653 pthread_t self; 654 655 self = pthread__self(); 656 TESTCANCEL(self); 657 retval = _sys_sendmsg(s, msg, flags); 658 TESTCANCEL(self); 659 660 return retval; 661 } 662 663 ssize_t 664 sendto(int s, const void *msg, size_t len, int flags, 665 const struct sockaddr *to, socklen_t tolen) 666 { 667 int retval; 668 pthread_t self; 669 670 self = pthread__self(); 671 TESTCANCEL(self); 672 retval = _sys_sendto(s, msg, len, flags, to, tolen); 673 TESTCANCEL(self); 674 675 return retval; 676 } 677 678 int 679 __sigsuspend14(const sigset_t *sigmask) 680 { 681 pthread_t self; 682 int retval; 683 684 self = pthread__self(); 685 TESTCANCEL(self); 686 retval = _sys___sigsuspend14(sigmask); 687 TESTCANCEL(self); 688 689 return retval; 690 } 691 692 int 693 __sigtimedwait50(const sigset_t * restrict set, siginfo_t * restrict info, 694 const struct timespec * restrict timeout) 695 { 696 pthread_t self; 697 int retval; 698 struct timespec tout, *tp; 699 700 if (timeout) { 701 tout = *timeout; 702 tp = &tout; 703 } else 704 tp = NULL; 705 706 self = pthread__self(); 707 TESTCANCEL(self); 708 retval = ____sigtimedwait50(set, info, tp); 709 TESTCANCEL(self); 710 711 return retval; 712 } 713 714 int 715 sigwait(const sigset_t * restrict set, int * restrict sig) 716 { 717 pthread_t self; 718 int saved_errno; 719 int new_errno; 720 int retval; 721 722 self = pthread__self(); 723 saved_errno = errno; 724 TESTCANCEL(self); 725 retval = ____sigtimedwait50(set, NULL, NULL); 726 TESTCANCEL(self); 727 new_errno = errno; 728 errno = saved_errno; 729 if (retval < 0) { 730 return new_errno; 731 } 732 *sig = retval; 733 return 0; 734 } 735 736 int 737 tcdrain(int fd) 738 { 739 int retval; 740 pthread_t self; 741 742 self = pthread__self(); 743 TESTCANCEL(self); 744 retval = ioctl(fd, TIOCDRAIN, 0); 745 TESTCANCEL(self); 746 747 return retval; 748 } 749 750 pid_t 751 __wait450(pid_t wpid, int *status, int options, struct rusage *rusage) 752 { 753 pid_t retval; 754 pthread_t self; 755 756 self = pthread__self(); 757 TESTCANCEL(self); 758 retval = _sys___wait450(wpid, status, options, rusage); 759 TESTCANCEL(self); 760 761 return retval; 762 } 763 764 ssize_t 765 write(int d, const void *buf, size_t nbytes) 766 { 767 ssize_t retval; 768 pthread_t self; 769 770 self = pthread__self(); 771 TESTCANCEL(self); 772 retval = _sys_write(d, buf, nbytes); 773 TESTCANCEL(self); 774 775 return retval; 776 } 777 778 ssize_t 779 writev(int d, const struct iovec *iov, int iovcnt) 780 { 781 ssize_t retval; 782 pthread_t self; 783 784 self = pthread__self(); 785 TESTCANCEL(self); 786 retval = _sys_writev(d, iov, iovcnt); 787 TESTCANCEL(self); 788 789 return retval; 790 } 791 792 __strong_alias(_clock_nanosleep, clock_nanosleep) 793 __strong_alias(_close, close) 794 __strong_alias(_fcntl, fcntl) 795 __strong_alias(_fdatasync, fdatasync) 796 __strong_alias(_fsync, fsync) 797 __weak_alias(fsync_range, _fsync_range) 798 __strong_alias(_mq_receive, mq_receive) 799 __strong_alias(_mq_send, mq_send) 800 __strong_alias(_msgrcv, msgrcv) 801 __strong_alias(_msgsnd, msgsnd) 802 __strong_alias(___msync13, __msync13) 803 __strong_alias(___nanosleep50, __nanosleep50) 804 __strong_alias(_open, open) 805 __strong_alias(_openat, openat) 806 __strong_alias(_poll, poll) 807 __strong_alias(_pread, pread) 808 __strong_alias(_pwrite, pwrite) 809 __strong_alias(_read, read) 810 __strong_alias(_readv, readv) 811 __strong_alias(_recvfrom, recvfrom) 812 __strong_alias(_recvmmsg, recvmmsg) 813 __strong_alias(_recvmsg, recvmsg) 814 __strong_alias(_sendmmsg, sendmmsg) 815 __strong_alias(_sendmsg, sendmsg) 816 __strong_alias(_sendto, sendto) 817 __strong_alias(_sigwait, sigwait) 818 __strong_alias(_write, write) 819 __strong_alias(_writev, writev) 820 821 #endif /* !lint */ 822