pthread_cancelstub.c revision 1.49 1 /* $NetBSD: pthread_cancelstub.c,v 1.49 2025/04/04 20:40:58 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.49 2025/04/04 20:40:58 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_send) _sys_mq_send;
121 __typeof(mq_receive) _sys_mq_receive;
122 __typeof(__mq_timedsend50) _sys___mq_timedsend50;
123 __typeof(__mq_timedreceive50) _sys___mq_timedreceive50;
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(recvmsg) _sys_recvmsg;
140 __typeof(recvmmsg) _sys_recvmmsg;
141 __typeof(sendto) _sys_sendto;
142 __typeof(sendmsg) _sys_sendmsg;
143 __typeof(sendmmsg) _sys_sendmmsg;
144 __typeof(__select50) _sys___select50;
145 __typeof(__wait450) _sys___wait450;
146 __typeof(write) _sys_write;
147 __typeof(writev) _sys_writev;
148 __typeof(__sigsuspend14) _sys___sigsuspend14;
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 __kevent100(int fd, const struct kevent *ev, size_t nev, struct kevent *rev,
205 size_t nrev, const struct timespec *ts)
206 {
207 int retval;
208 pthread_t self;
209
210 self = pthread__self();
211 TESTCANCEL(self);
212 retval = _sys___kevent100(fd, ev, nev, rev, nrev, ts);
213 TESTCANCEL(self);
214
215 return retval;
216 }
217
218 int
219 clock_nanosleep(clockid_t clock_id, int flags,
220 const struct timespec *rqtp, struct timespec *rmtp)
221 {
222 int retval;
223 pthread_t self;
224
225 self = pthread__self();
226 TESTCANCEL(self);
227 retval = _sys_clock_nanosleep(clock_id, flags, rqtp, rmtp);
228 TESTCANCEL(self);
229
230 return retval;
231 }
232
233 int
234 close(int d)
235 {
236 int retval;
237 pthread_t self;
238
239 self = pthread__self();
240 TESTCANCEL(self);
241 retval = _sys_close(d);
242 TESTCANCEL(self);
243
244 return retval;
245 }
246
247 int
248 connect(int s, const struct sockaddr *addr, socklen_t namelen)
249 {
250 int retval;
251 pthread_t self;
252
253 self = pthread__self();
254 TESTCANCEL(self);
255 retval = _sys_connect(s, addr, namelen);
256 TESTCANCEL(self);
257
258 return retval;
259 }
260
261 int
262 fcntl(int fd, int cmd, ...)
263 {
264 int retval;
265 pthread_t self;
266 va_list ap;
267
268 self = pthread__self();
269 TESTCANCEL(self);
270 va_start(ap, cmd);
271 retval = _sys_fcntl(fd, cmd, va_arg(ap, void *));
272 va_end(ap);
273 TESTCANCEL(self);
274
275 return retval;
276 }
277
278 int
279 fdatasync(int d)
280 {
281 int retval;
282 pthread_t self;
283
284 self = pthread__self();
285 TESTCANCEL(self);
286 retval = _sys_fdatasync(d);
287 TESTCANCEL(self);
288
289 return retval;
290 }
291
292 int
293 fsync(int d)
294 {
295 int retval;
296 pthread_t self;
297
298 self = pthread__self();
299 TESTCANCEL(self);
300 retval = _sys_fsync(d);
301 TESTCANCEL(self);
302
303 return retval;
304 }
305
306 int
307 fsync_range(int d, int f, off_t s, off_t e)
308 {
309 int retval;
310 pthread_t self;
311
312 self = pthread__self();
313 TESTCANCEL(self);
314 retval = _sys_fsync_range(d, f, s, e);
315 TESTCANCEL(self);
316
317 return retval;
318 }
319
320 int
321 mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio)
322 {
323 int retval;
324 pthread_t self;
325
326 self = pthread__self();
327 TESTCANCEL(self);
328 retval = _sys_mq_send(mqdes, msg_ptr, msg_len, msg_prio);
329 TESTCANCEL(self);
330
331 return retval;
332 }
333
334 ssize_t
335 mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio)
336 {
337 ssize_t retval;
338 pthread_t self;
339
340 self = pthread__self();
341 TESTCANCEL(self);
342 retval = _sys_mq_receive(mqdes, msg_ptr, msg_len, msg_prio);
343 TESTCANCEL(self);
344
345 return retval;
346 }
347
348 int
349 __mq_timedsend50(mqd_t mqdes, const char *msg_ptr, size_t msg_len,
350 unsigned msg_prio, const struct timespec *abst)
351 {
352 int retval;
353 pthread_t self;
354
355 self = pthread__self();
356 TESTCANCEL(self);
357 retval = _sys___mq_timedsend50(mqdes, msg_ptr, msg_len, msg_prio, abst);
358 TESTCANCEL(self);
359
360 return retval;
361 }
362
363 ssize_t
364 __mq_timedreceive50(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio,
365 const struct timespec *abst)
366 {
367 ssize_t retval;
368 pthread_t self;
369
370 self = pthread__self();
371 TESTCANCEL(self);
372 retval = _sys___mq_timedreceive50(mqdes, msg_ptr, msg_len, msg_prio, abst);
373 TESTCANCEL(self);
374
375 return retval;
376 }
377
378 ssize_t
379 msgrcv(int msgid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
380 {
381 ssize_t retval;
382 pthread_t self;
383
384 self = pthread__self();
385 TESTCANCEL(self);
386 retval = _sys_msgrcv(msgid, msgp, msgsz, msgtyp, msgflg);
387 TESTCANCEL(self);
388
389 return retval;
390 }
391
392 int
393 msgsnd(int msgid, const void *msgp, size_t msgsz, int msgflg)
394 {
395 int retval;
396 pthread_t self;
397
398 self = pthread__self();
399 TESTCANCEL(self);
400 retval = _sys_msgsnd(msgid, msgp, msgsz, msgflg);
401 TESTCANCEL(self);
402
403 return retval;
404 }
405
406 int
407 __msync13(void *addr, size_t len, int flags)
408 {
409 int retval;
410 pthread_t self;
411
412 self = pthread__self();
413 TESTCANCEL(self);
414 retval = _sys___msync13(addr, len, flags);
415 TESTCANCEL(self);
416
417 return retval;
418 }
419
420 int
421 open(const char *path, int flags, ...)
422 {
423 int retval;
424 pthread_t self;
425 va_list ap;
426
427 self = pthread__self();
428 TESTCANCEL(self);
429 va_start(ap, flags);
430 retval = _sys_open(path, flags, va_arg(ap, mode_t));
431 va_end(ap);
432 TESTCANCEL(self);
433
434 return retval;
435 }
436
437 int
438 openat(int fd, const char *path, int flags, ...)
439 {
440 int retval;
441 pthread_t self;
442 va_list ap;
443
444 self = pthread__self();
445 TESTCANCEL(self);
446 va_start(ap, flags);
447 retval = _sys_openat(fd, path, flags, va_arg(ap, mode_t));
448 va_end(ap);
449 TESTCANCEL(self);
450
451 return retval;
452 }
453
454 int
455 __nanosleep50(const struct timespec *rqtp, struct timespec *rmtp)
456 {
457 int retval;
458 pthread_t self;
459
460 self = pthread__self();
461 TESTCANCEL(self);
462 /*
463 * For now, just nanosleep. In the future, maybe pass a ucontext_t
464 * to _lwp_nanosleep() and allow it to recycle our kernel stack.
465 */
466 retval = _sys___nanosleep50(rqtp, rmtp);
467 TESTCANCEL(self);
468
469 return retval;
470 }
471
472 int
473 poll(struct pollfd *fds, nfds_t nfds, int timeout)
474 {
475 int retval;
476 pthread_t self;
477
478 self = pthread__self();
479 TESTCANCEL(self);
480 retval = _sys_poll(fds, nfds, timeout);
481 TESTCANCEL(self);
482
483 return retval;
484 }
485
486 int
487 __pollts50(struct pollfd *fds, nfds_t nfds, const struct timespec *ts,
488 const sigset_t *sigmask)
489 {
490 int retval;
491 pthread_t self;
492
493 self = pthread__self();
494 TESTCANCEL(self);
495 retval = _sys___pollts50(fds, nfds, ts, sigmask);
496 TESTCANCEL(self);
497
498 return retval;
499 }
500
501 ssize_t
502 pread(int d, void *buf, size_t nbytes, off_t offset)
503 {
504 ssize_t retval;
505 pthread_t self;
506
507 self = pthread__self();
508 TESTCANCEL(self);
509 retval = _sys_pread(d, buf, nbytes, offset);
510 TESTCANCEL(self);
511
512 return retval;
513 }
514
515 int
516 __pselect50(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
517 const struct timespec *timeout, const sigset_t *sigmask)
518 {
519 int retval;
520 pthread_t self;
521
522 self = pthread__self();
523 TESTCANCEL(self);
524 retval = _sys___pselect50(nfds, readfds, writefds, exceptfds, timeout,
525 sigmask);
526 TESTCANCEL(self);
527
528 return retval;
529 }
530
531 ssize_t
532 pwrite(int d, const void *buf, size_t nbytes, off_t offset)
533 {
534 ssize_t retval;
535 pthread_t self;
536
537 self = pthread__self();
538 TESTCANCEL(self);
539 retval = _sys_pwrite(d, buf, nbytes, offset);
540 TESTCANCEL(self);
541
542 return retval;
543 }
544
545 ssize_t
546 read(int d, void *buf, size_t nbytes)
547 {
548 ssize_t retval;
549 pthread_t self;
550
551 self = pthread__self();
552 TESTCANCEL(self);
553 retval = _sys_read(d, buf, nbytes);
554 TESTCANCEL(self);
555
556 return retval;
557 }
558
559 ssize_t
560 readv(int d, const struct iovec *iov, int iovcnt)
561 {
562 ssize_t retval;
563 pthread_t self;
564
565 self = pthread__self();
566 TESTCANCEL(self);
567 retval = _sys_readv(d, iov, iovcnt);
568 TESTCANCEL(self);
569
570 return retval;
571 }
572
573 ssize_t
574 recvfrom(int s, void * restrict buf, size_t len, int flags,
575 struct sockaddr * restrict from, socklen_t * restrict fromlen)
576 {
577 ssize_t retval;
578 pthread_t self;
579
580 self = pthread__self();
581 TESTCANCEL(self);
582 retval = _sys_recvfrom(s, buf, len, flags, from, fromlen);
583 TESTCANCEL(self);
584
585 return retval;
586 }
587
588 ssize_t
589 recvmsg(int s, struct msghdr *msg, int flags)
590 {
591 ssize_t retval;
592 pthread_t self;
593
594 self = pthread__self();
595 TESTCANCEL(self);
596 retval = _sys_recvmsg(s, msg, flags);
597 TESTCANCEL(self);
598
599 return retval;
600 }
601
602 int
603 recvmmsg(int s, struct mmsghdr *mmsg, unsigned int vlen,
604 unsigned int flags, struct timespec *timeout)
605 {
606 ssize_t retval;
607 pthread_t self;
608
609 self = pthread__self();
610 TESTCANCEL(self);
611 retval = _sys_recvmmsg(s, mmsg, vlen, flags, timeout);
612 TESTCANCEL(self);
613
614 return retval;
615 }
616
617 int
618 __select50(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
619 struct timeval *timeout)
620 {
621 int retval;
622 pthread_t self;
623
624 self = pthread__self();
625 TESTCANCEL(self);
626 retval = _sys___select50(nfds, readfds, writefds, exceptfds, timeout);
627 TESTCANCEL(self);
628
629 return retval;
630 }
631
632 ssize_t
633 sendto(int s, const void *msg, size_t len, int flags,
634 const struct sockaddr *to, socklen_t tolen)
635 {
636 int retval;
637 pthread_t self;
638
639 self = pthread__self();
640 TESTCANCEL(self);
641 retval = _sys_sendto(s, msg, len, flags, to, tolen);
642 TESTCANCEL(self);
643
644 return retval;
645 }
646
647 ssize_t
648 sendmsg(int s, const struct msghdr *msg, int flags)
649 {
650 int retval;
651 pthread_t self;
652
653 self = pthread__self();
654 TESTCANCEL(self);
655 retval = _sys_sendmsg(s, msg, flags);
656 TESTCANCEL(self);
657
658 return retval;
659 }
660
661 int
662 sendmmsg(int s, struct mmsghdr *mmsg, unsigned int vlen,
663 unsigned int flags)
664 {
665 int retval;
666 pthread_t self;
667
668 self = pthread__self();
669 TESTCANCEL(self);
670 retval = _sys_sendmmsg(s, mmsg, vlen, flags);
671 TESTCANCEL(self);
672
673 return retval;
674 }
675
676 int
677 tcdrain(int fd)
678 {
679 int retval;
680 pthread_t self;
681
682 self = pthread__self();
683 TESTCANCEL(self);
684 retval = ioctl(fd, TIOCDRAIN, 0);
685 TESTCANCEL(self);
686
687 return retval;
688 }
689
690 pid_t
691 __wait450(pid_t wpid, int *status, int options, struct rusage *rusage)
692 {
693 pid_t retval;
694 pthread_t self;
695
696 self = pthread__self();
697 TESTCANCEL(self);
698 retval = _sys___wait450(wpid, status, options, rusage);
699 TESTCANCEL(self);
700
701 return retval;
702 }
703
704 ssize_t
705 write(int d, const void *buf, size_t nbytes)
706 {
707 ssize_t retval;
708 pthread_t self;
709
710 self = pthread__self();
711 TESTCANCEL(self);
712 retval = _sys_write(d, buf, nbytes);
713 TESTCANCEL(self);
714
715 return retval;
716 }
717
718 ssize_t
719 writev(int d, const struct iovec *iov, int iovcnt)
720 {
721 ssize_t retval;
722 pthread_t self;
723
724 self = pthread__self();
725 TESTCANCEL(self);
726 retval = _sys_writev(d, iov, iovcnt);
727 TESTCANCEL(self);
728
729 return retval;
730 }
731
732 int
733 __sigsuspend14(const sigset_t *sigmask)
734 {
735 pthread_t self;
736 int retval;
737
738 self = pthread__self();
739 TESTCANCEL(self);
740 retval = _sys___sigsuspend14(sigmask);
741 TESTCANCEL(self);
742
743 return retval;
744 }
745
746 int
747 __sigtimedwait50(const sigset_t * __restrict set, siginfo_t * __restrict info,
748 const struct timespec * __restrict timeout)
749 {
750 pthread_t self;
751 int retval;
752 struct timespec tout, *tp;
753
754 if (timeout) {
755 tout = *timeout;
756 tp = &tout;
757 } else
758 tp = NULL;
759
760 self = pthread__self();
761 TESTCANCEL(self);
762 retval = ____sigtimedwait50(set, info, tp);
763 TESTCANCEL(self);
764
765 return retval;
766 }
767
768 int
769 sigwait(const sigset_t * __restrict set, int * __restrict sig)
770 {
771 pthread_t self;
772 int saved_errno;
773 int new_errno;
774 int retval;
775
776 self = pthread__self();
777 saved_errno = errno;
778 TESTCANCEL(self);
779 retval = ____sigtimedwait50(set, NULL, NULL);
780 TESTCANCEL(self);
781 new_errno = errno;
782 errno = saved_errno;
783 if (retval < 0) {
784 return new_errno;
785 }
786 *sig = retval;
787 return 0;
788 }
789
790 __strong_alias(_close, close)
791 __strong_alias(_clock_nanosleep, clock_nanosleep)
792 __strong_alias(_fcntl, fcntl)
793 __strong_alias(_fdatasync, fdatasync)
794 __strong_alias(_fsync, fsync)
795 __weak_alias(fsync_range, _fsync_range)
796 __strong_alias(_mq_send, mq_send)
797 __strong_alias(_mq_receive, mq_receive)
798 __strong_alias(_msgrcv, msgrcv)
799 __strong_alias(_msgsnd, msgsnd)
800 __strong_alias(___msync13, __msync13)
801 __strong_alias(___nanosleep50, __nanosleep50)
802 __strong_alias(_open, open)
803 __strong_alias(_openat, openat)
804 __strong_alias(_poll, poll)
805 __strong_alias(_pread, pread)
806 __strong_alias(_pwrite, pwrite)
807 __strong_alias(_read, read)
808 __strong_alias(_readv, readv)
809 __strong_alias(_recvfrom, recvfrom)
810 __strong_alias(_recvmsg, recvmsg)
811 __strong_alias(_recvmmsg, recvmmsg)
812 __strong_alias(_sendmsg, sendmsg)
813 __strong_alias(_sendmmsg, sendmmsg)
814 __strong_alias(_sendto, sendto)
815 __strong_alias(_sigwait, sigwait)
816 __strong_alias(_write, write)
817 __strong_alias(_writev, writev)
818
819 #endif /* !lint */
820