xref: /freebsd/lib/libthr/thread/thr_syscalls.c (revision 02e9120893770924227138ba49df1edb3896112a)
1 /*
2  * Copyright (c) 2014 The FreeBSD Foundation.
3  * Copyright (C) 2005 David Xu <davidxu@freebsd.org>.
4  * Copyright (c) 2003 Daniel Eischen <deischen@freebsd.org>.
5  * Copyright (C) 2000 Jason Evans <jasone@freebsd.org>.
6  * All rights reserved.
7  *
8  * Portions of this software were developed by Konstantin Belousov
9  * under sponsorship from the FreeBSD Foundation.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice(s), this list of conditions and the following disclaimer as
16  *    the first lines of this file unmodified other than the possible
17  *    addition of one or more copyright notices.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice(s), this list of conditions and the following disclaimer in
20  *    the documentation and/or other materials provided with the
21  *    distribution.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
24  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
32  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
33  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 /*-
37  * SPDX-License-Identifier: BSD-3-Clause
38  *
39  * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
40  * All rights reserved.
41  *
42  * Redistribution and use in source and binary forms, with or without
43  * modification, are permitted provided that the following conditions
44  * are met:
45  * 1. Redistributions of source code must retain the above copyright
46  *    notice, this list of conditions and the following disclaimer.
47  * 2. Redistributions in binary form must reproduce the above copyright
48  *    notice, this list of conditions and the following disclaimer in the
49  *    documentation and/or other materials provided with the distribution.
50  * 3. Neither the name of the author nor the names of any co-contributors
51  *    may be used to endorse or promote products derived from this software
52  *    without specific prior written permission.
53  *
54  * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
55  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
58  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64  * SUCH DAMAGE.
65  *
66  */
67 
68 #include <sys/cdefs.h>
69 #include "namespace.h"
70 #include <sys/types.h>
71 #include <sys/mman.h>
72 #include <sys/param.h>
73 #include <sys/select.h>
74 #include <sys/signalvar.h>
75 #include <sys/socket.h>
76 #include <sys/stat.h>
77 #include <sys/time.h>
78 #include <sys/uio.h>
79 #include <sys/wait.h>
80 #include <aio.h>
81 #include <dirent.h>
82 #include <errno.h>
83 #include <fcntl.h>
84 #include <poll.h>
85 #include <signal.h>
86 #include <stdarg.h>
87 #include <stdio.h>
88 #include <stdlib.h>
89 #include <string.h>
90 #include <termios.h>
91 #include <unistd.h>
92 #include <pthread.h>
93 #include "un-namespace.h"
94 
95 #include "libc_private.h"
96 #include "thr_private.h"
97 
98 static int
99 __thr_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
100 {
101 	struct pthread *curthread;
102 	int ret;
103 
104 	curthread = _get_curthread();
105 	_thr_cancel_enter(curthread);
106 	ret = __sys_accept(s, addr, addrlen);
107 	_thr_cancel_leave(curthread, ret == -1);
108 
109  	return (ret);
110 }
111 
112 /*
113  * Cancellation behavior:
114  *   If thread is canceled, no socket is created.
115  */
116 static int
117 __thr_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
118 {
119 	struct pthread *curthread;
120 	int ret;
121 
122 	curthread = _get_curthread();
123 	_thr_cancel_enter(curthread);
124 	ret = __sys_accept4(s, addr, addrlen, flags);
125 	_thr_cancel_leave(curthread, ret == -1);
126 
127  	return (ret);
128 }
129 
130 static int
131 __thr_aio_suspend(const struct aiocb * const iocbs[], int niocb, const struct
132     timespec *timeout)
133 {
134 	struct pthread *curthread;
135 	int ret;
136 
137 	curthread = _get_curthread();
138 	_thr_cancel_enter(curthread);
139 	ret = __sys_aio_suspend(iocbs, niocb, timeout);
140 	_thr_cancel_leave(curthread, 1);
141 
142 	return (ret);
143 }
144 
145 /*
146  * Cancellation behavior:
147  *   According to manual of close(), the file descriptor is always deleted.
148  *   Here, thread is only canceled after the system call, so the file
149  *   descriptor is always deleted despite whether the thread is canceled
150  *   or not.
151  */
152 static int
153 __thr_close(int fd)
154 {
155 	struct pthread *curthread;
156 	int ret;
157 
158 	curthread = _get_curthread();
159 	_thr_cancel_enter2(curthread, 0);
160 	ret = __sys_close(fd);
161 	_thr_cancel_leave(curthread, 1);
162 
163 	return (ret);
164 }
165 
166 /*
167  * Cancellation behavior:
168  *   If the thread is canceled, connection is not made.
169  */
170 static int
171 __thr_connect(int fd, const struct sockaddr *name, socklen_t namelen)
172 {
173 	struct pthread *curthread;
174 	int ret;
175 
176 	curthread = _get_curthread();
177 	_thr_cancel_enter(curthread);
178 	ret = __sys_connect(fd, name, namelen);
179 	_thr_cancel_leave(curthread, ret == -1);
180 
181  	return (ret);
182 }
183 
184 /*
185  * Cancellation behavior:
186  *   According to specification, only F_SETLKW is a cancellation point.
187  *   Thread is only canceled at start, or canceled if the system call
188  *   is failure, this means the function does not generate side effect
189  *   if it is canceled.
190  */
191 static int
192 __thr_fcntl(int fd, int cmd, ...)
193 {
194 	struct pthread *curthread;
195 	int ret;
196 	va_list	ap;
197 
198 	curthread = _get_curthread();
199 	va_start(ap, cmd);
200 	if (cmd == F_OSETLKW || cmd == F_SETLKW) {
201 		_thr_cancel_enter(curthread);
202 		ret = __sys_fcntl(fd, cmd, va_arg(ap, void *));
203 		_thr_cancel_leave(curthread, ret == -1);
204 	} else {
205 		ret = __sys_fcntl(fd, cmd, va_arg(ap, void *));
206 	}
207 	va_end(ap);
208 
209 	return (ret);
210 }
211 
212 /*
213  * Cancellation behavior:
214  *   Thread may be canceled after system call.
215  */
216 static int
217 __thr_fsync(int fd)
218 {
219 	struct pthread *curthread;
220 	int ret;
221 
222 	curthread = _get_curthread();
223 	_thr_cancel_enter2(curthread, 0);
224 	ret = __sys_fsync(fd);
225 	_thr_cancel_leave(curthread, 1);
226 
227 	return (ret);
228 }
229 
230 static int
231 __thr_fdatasync(int fd)
232 {
233 	struct pthread *curthread;
234 	int ret;
235 
236 	curthread = _get_curthread();
237 	_thr_cancel_enter2(curthread, 0);
238 	ret = __sys_fdatasync(fd);
239 	_thr_cancel_leave(curthread, 1);
240 
241 	return (ret);
242 }
243 
244 /*
245  * Cancellation behavior:
246  *   Thread may be canceled after system call.
247  */
248 static int
249 __thr_msync(void *addr, size_t len, int flags)
250 {
251 	struct pthread *curthread;
252 	int ret;
253 
254 	curthread = _get_curthread();
255 	_thr_cancel_enter2(curthread, 0);
256 	ret = __sys_msync(addr, len, flags);
257 	_thr_cancel_leave(curthread, 1);
258 
259 	return (ret);
260 }
261 
262 static int
263 __thr_clock_nanosleep(clockid_t clock_id, int flags,
264     const struct timespec *time_to_sleep, struct timespec *time_remaining)
265 {
266 	struct pthread *curthread;
267 	int ret;
268 
269 	curthread = _get_curthread();
270 	_thr_cancel_enter(curthread);
271 	ret = __sys_clock_nanosleep(clock_id, flags, time_to_sleep,
272 	    time_remaining);
273 	_thr_cancel_leave(curthread, 1);
274 
275 	return (ret);
276 }
277 
278 static int
279 __thr_nanosleep(const struct timespec *time_to_sleep,
280     struct timespec *time_remaining)
281 {
282 	struct pthread *curthread;
283 	int ret;
284 
285 	curthread = _get_curthread();
286 	_thr_cancel_enter(curthread);
287 	ret = __sys_nanosleep(time_to_sleep, time_remaining);
288 	_thr_cancel_leave(curthread, 1);
289 
290 	return (ret);
291 }
292 
293 /*
294  * Cancellation behavior:
295  *   If the thread is canceled, file is not opened.
296  */
297 static int
298 __thr_openat(int fd, const char *path, int flags, ...)
299 {
300 	struct pthread *curthread;
301 	int mode, ret;
302 	va_list	ap;
303 
304 
305 	/* Check if the file is being created: */
306 	if ((flags & O_CREAT) != 0) {
307 		/* Get the creation mode: */
308 		va_start(ap, flags);
309 		mode = va_arg(ap, int);
310 		va_end(ap);
311 	} else {
312 		mode = 0;
313 	}
314 
315 	curthread = _get_curthread();
316 	_thr_cancel_enter(curthread);
317 	ret = __sys_openat(fd, path, flags, mode);
318 	_thr_cancel_leave(curthread, ret == -1);
319 
320 	return (ret);
321 }
322 
323 /*
324  * Cancellation behavior:
325  *   Thread may be canceled at start, but if the system call returns something,
326  *   the thread is not canceled.
327  */
328 static int
329 __thr_poll(struct pollfd *fds, unsigned int nfds, int timeout)
330 {
331 	struct pthread *curthread;
332 	int ret;
333 
334 	curthread = _get_curthread();
335 	_thr_cancel_enter(curthread);
336 	ret = __sys_poll(fds, nfds, timeout);
337 	_thr_cancel_leave(curthread, ret == -1);
338 
339 	return (ret);
340 }
341 
342 /*
343  * Cancellation behavior:
344  *   Thread may be canceled at start, but if the system call returns something,
345  *   the thread is not canceled.
346  */
347 static int
348 __thr_ppoll(struct pollfd pfd[], nfds_t nfds, const struct timespec *
349     timeout, const sigset_t *newsigmask)
350 {
351 	struct pthread *curthread;
352 	int ret;
353 
354 	curthread = _get_curthread();
355 	_thr_cancel_enter(curthread);
356 	ret = __sys_ppoll(pfd, nfds, timeout, newsigmask);
357 	_thr_cancel_leave(curthread, ret == -1);
358 
359 	return (ret);
360 }
361 
362 /*
363  * Cancellation behavior:
364  *   Thread may be canceled at start, but if the system call returns something,
365  *   the thread is not canceled.
366  */
367 static int
368 __thr_pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
369 	const struct timespec *timo, const sigset_t *mask)
370 {
371 	struct pthread *curthread;
372 	int ret;
373 
374 	curthread = _get_curthread();
375 	_thr_cancel_enter(curthread);
376 	ret = __sys_pselect(count, rfds, wfds, efds, timo, mask);
377 	_thr_cancel_leave(curthread, ret == -1);
378 
379 	return (ret);
380 }
381 
382 static int
383 __thr_kevent(int kq, const struct kevent *changelist, int nchanges,
384     struct kevent *eventlist, int nevents, const struct timespec *timeout)
385 {
386 	struct pthread *curthread;
387 	int ret;
388 
389 	if (nevents == 0) {
390 		/*
391 		 * No blocking, do not make the call cancellable.
392 		 */
393 		return (__sys_kevent(kq, changelist, nchanges, eventlist,
394 		    nevents, timeout));
395 	}
396 	curthread = _get_curthread();
397 	_thr_cancel_enter(curthread);
398 	ret = __sys_kevent(kq, changelist, nchanges, eventlist, nevents,
399 	    timeout);
400 	_thr_cancel_leave(curthread, ret == -1 && nchanges == 0);
401 
402 	return (ret);
403 }
404 
405 /*
406  * Cancellation behavior:
407  *   Thread may be canceled at start, but if the system call got some data,
408  *   the thread is not canceled.
409  */
410 static ssize_t
411 __thr_read(int fd, void *buf, size_t nbytes)
412 {
413 	struct pthread *curthread;
414 	ssize_t	ret;
415 
416 	curthread = _get_curthread();
417 	_thr_cancel_enter(curthread);
418 	ret = __sys_read(fd, buf, nbytes);
419 	_thr_cancel_leave(curthread, ret == -1);
420 
421 	return (ret);
422 }
423 
424 /*
425  * Cancellation behavior:
426  *   Thread may be canceled at start, but if the system call got some data,
427  *   the thread is not canceled.
428  */
429 static ssize_t
430 __thr_readv(int fd, const struct iovec *iov, int iovcnt)
431 {
432 	struct pthread *curthread;
433 	ssize_t ret;
434 
435 	curthread = _get_curthread();
436 	_thr_cancel_enter(curthread);
437 	ret = __sys_readv(fd, iov, iovcnt);
438 	_thr_cancel_leave(curthread, ret == -1);
439 	return (ret);
440 }
441 
442 /*
443  * Cancellation behavior:
444  *   Thread may be canceled at start, but if the system call got some data,
445  *   the thread is not canceled.
446  */
447 static ssize_t
448 __thr_recvfrom(int s, void *b, size_t l, int f, struct sockaddr *from,
449     socklen_t *fl)
450 {
451 	struct pthread *curthread;
452 	ssize_t ret;
453 
454 	curthread = _get_curthread();
455 	_thr_cancel_enter(curthread);
456 	ret = __sys_recvfrom(s, b, l, f, from, fl);
457 	_thr_cancel_leave(curthread, ret == -1);
458 	return (ret);
459 }
460 
461 /*
462  * Cancellation behavior:
463  *   Thread may be canceled at start, but if the system call got some data,
464  *   the thread is not canceled.
465  */
466 static ssize_t
467 __thr_recvmsg(int s, struct msghdr *m, int f)
468 {
469 	struct pthread *curthread;
470 	ssize_t ret;
471 
472 	curthread = _get_curthread();
473 	_thr_cancel_enter(curthread);
474 	ret = __sys_recvmsg(s, m, f);
475 	_thr_cancel_leave(curthread, ret == -1);
476 	return (ret);
477 }
478 
479 /*
480  * Cancellation behavior:
481  *   Thread may be canceled at start, but if the system call returns something,
482  *   the thread is not canceled.
483  */
484 static int
485 __thr_select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
486 	struct timeval *timeout)
487 {
488 	struct pthread *curthread;
489 	int ret;
490 
491 	curthread = _get_curthread();
492 	_thr_cancel_enter(curthread);
493 	ret = __sys_select(numfds, readfds, writefds, exceptfds, timeout);
494 	_thr_cancel_leave(curthread, ret == -1);
495 	return (ret);
496 }
497 
498 /*
499  * Cancellation behavior:
500  *   Thread may be canceled at start, but if the system call sent
501  *   data, the thread is not canceled.
502  */
503 static ssize_t
504 __thr_sendmsg(int s, const struct msghdr *m, int f)
505 {
506 	struct pthread *curthread;
507 	ssize_t ret;
508 
509 	curthread = _get_curthread();
510 	_thr_cancel_enter(curthread);
511 	ret = __sys_sendmsg(s, m, f);
512 	_thr_cancel_leave(curthread, ret <= 0);
513 	return (ret);
514 }
515 
516 /*
517  * Cancellation behavior:
518  *   Thread may be canceled at start, but if the system call sent some
519  *   data, the thread is not canceled.
520  */
521 static ssize_t
522 __thr_sendto(int s, const void *m, size_t l, int f, const struct sockaddr *t,
523     socklen_t tl)
524 {
525 	struct pthread *curthread;
526 	ssize_t ret;
527 
528 	curthread = _get_curthread();
529 	_thr_cancel_enter(curthread);
530 	ret = __sys_sendto(s, m, l, f, t, tl);
531 	_thr_cancel_leave(curthread, ret <= 0);
532 	return (ret);
533 }
534 
535 static int
536 __thr_system(const char *string)
537 {
538 	struct pthread *curthread;
539 	int ret;
540 
541 	curthread = _get_curthread();
542 	_thr_cancel_enter(curthread);
543 	ret = __libc_system(string);
544 	_thr_cancel_leave(curthread, 1);
545 	return (ret);
546 }
547 
548 /*
549  * Cancellation behavior:
550  *   If thread is canceled, the system call is not completed,
551  *   this means not all bytes were drained.
552  */
553 static int
554 __thr_tcdrain(int fd)
555 {
556 	struct pthread *curthread;
557 	int ret;
558 
559 	curthread = _get_curthread();
560 	_thr_cancel_enter(curthread);
561 	ret = __libc_tcdrain(fd);
562 	_thr_cancel_leave(curthread, ret == -1);
563 	return (ret);
564 }
565 
566 /*
567  * Cancellation behavior:
568  *   Thread may be canceled at start, but if the system call returns
569  *   a child pid, the thread is not canceled.
570  */
571 static pid_t
572 __thr_wait4(pid_t pid, int *status, int options, struct rusage *rusage)
573 {
574 	struct pthread *curthread;
575 	pid_t ret;
576 
577 	curthread = _get_curthread();
578 	_thr_cancel_enter(curthread);
579 	ret = __sys_wait4(pid, status, options, rusage);
580 	_thr_cancel_leave(curthread, ret <= 0);
581 	return (ret);
582 }
583 
584 /*
585  * Cancellation behavior:
586  *   Thread may be canceled at start, but if the system call returns
587  *   a child pid, the thread is not canceled.
588  */
589 static pid_t
590 __thr_wait6(idtype_t idtype, id_t id, int *status, int options,
591     struct __wrusage *ru, siginfo_t *infop)
592 {
593 	struct pthread *curthread;
594 	pid_t ret;
595 
596 	curthread = _get_curthread();
597 	_thr_cancel_enter(curthread);
598 	ret = __sys_wait6(idtype, id, status, options, ru, infop);
599 	_thr_cancel_leave(curthread, ret <= 0);
600 	return (ret);
601 }
602 
603 /*
604  * Cancellation behavior:
605  *   Thread may be canceled at start, but if the thread wrote some data,
606  *   it is not canceled.
607  */
608 static ssize_t
609 __thr_write(int fd, const void *buf, size_t nbytes)
610 {
611 	struct pthread *curthread;
612 	ssize_t	ret;
613 
614 	curthread = _get_curthread();
615 	_thr_cancel_enter(curthread);
616 	ret = __sys_write(fd, buf, nbytes);
617 	_thr_cancel_leave(curthread, (ret <= 0));
618 	return (ret);
619 }
620 
621 /*
622  * Cancellation behavior:
623  *   Thread may be canceled at start, but if the thread wrote some data,
624  *   it is not canceled.
625  */
626 static ssize_t
627 __thr_writev(int fd, const struct iovec *iov, int iovcnt)
628 {
629 	struct pthread *curthread;
630 	ssize_t ret;
631 
632 	curthread = _get_curthread();
633 	_thr_cancel_enter(curthread);
634 	ret = __sys_writev(fd, iov, iovcnt);
635 	_thr_cancel_leave(curthread, (ret <= 0));
636 	return (ret);
637 }
638 
639 void
640 __thr_interpose_libc(void)
641 {
642 
643 	__set_error_selector(__error_threaded);
644 #define	SLOT(name)					\
645 	*(__libc_interposing_slot(INTERPOS_##name)) =	\
646 	    (interpos_func_t)__thr_##name;
647 	SLOT(accept);
648 	SLOT(accept4);
649 	SLOT(aio_suspend);
650 	SLOT(close);
651 	SLOT(connect);
652 	SLOT(fcntl);
653 	SLOT(fsync);
654 	SLOT(fork);
655 	SLOT(msync);
656 	SLOT(nanosleep);
657 	SLOT(openat);
658 	SLOT(poll);
659 	SLOT(pselect);
660 	SLOT(read);
661 	SLOT(readv);
662 	SLOT(recvfrom);
663 	SLOT(recvmsg);
664 	SLOT(select);
665 	SLOT(sendmsg);
666 	SLOT(sendto);
667 	SLOT(setcontext);
668 	SLOT(sigaction);
669 	SLOT(sigprocmask);
670 	SLOT(sigsuspend);
671 	SLOT(sigwait);
672 	SLOT(sigtimedwait);
673 	SLOT(sigwaitinfo);
674 	SLOT(swapcontext);
675 	SLOT(system);
676 	SLOT(tcdrain);
677 	SLOT(wait4);
678 	SLOT(write);
679 	SLOT(writev);
680 	SLOT(spinlock);
681 	SLOT(spinunlock);
682 	SLOT(kevent);
683 	SLOT(wait6);
684 	SLOT(ppoll);
685 	SLOT(map_stacks_exec);
686 	SLOT(fdatasync);
687 	SLOT(clock_nanosleep);
688 	SLOT(pdfork);
689 #undef SLOT
690 	*(__libc_interposing_slot(
691 	    INTERPOS__pthread_mutex_init_calloc_cb)) =
692 	    (interpos_func_t)_pthread_mutex_init_calloc_cb;
693 }
694