xref: /freebsd/lib/libthr/thread/thr_syscalls.c (revision b985c9ca)
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 "namespace.h"
69 #include <sys/types.h>
70 #include <sys/mman.h>
71 #include <sys/param.h>
72 #include <sys/select.h>
73 #include <sys/signalvar.h>
74 #include <sys/socket.h>
75 #include <sys/stat.h>
76 #include <sys/time.h>
77 #include <sys/uio.h>
78 #include <sys/wait.h>
79 #include <aio.h>
80 #include <dirent.h>
81 #include <errno.h>
82 #include <fcntl.h>
83 #include <poll.h>
84 #include <signal.h>
85 #include <stdarg.h>
86 #include <stdio.h>
87 #include <stdlib.h>
88 #include <string.h>
89 #include <termios.h>
90 #include <unistd.h>
91 #include <pthread.h>
92 #include "un-namespace.h"
93 
94 #include "libc_private.h"
95 #include "thr_private.h"
96 
97 static int
98 __thr_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
99 {
100 	struct pthread *curthread;
101 	int ret;
102 
103 	curthread = _get_curthread();
104 	_thr_cancel_enter(curthread);
105 	ret = __sys_accept(s, addr, addrlen);
106 	_thr_cancel_leave(curthread, ret == -1);
107 
108  	return (ret);
109 }
110 
111 /*
112  * Cancellation behavior:
113  *   If thread is canceled, no socket is created.
114  */
115 static int
116 __thr_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
117 {
118 	struct pthread *curthread;
119 	int ret;
120 
121 	curthread = _get_curthread();
122 	_thr_cancel_enter(curthread);
123 	ret = __sys_accept4(s, addr, addrlen, flags);
124 	_thr_cancel_leave(curthread, ret == -1);
125 
126  	return (ret);
127 }
128 
129 static int
130 __thr_aio_suspend(const struct aiocb * const iocbs[], int niocb, const struct
131     timespec *timeout)
132 {
133 	struct pthread *curthread;
134 	int ret;
135 
136 	curthread = _get_curthread();
137 	_thr_cancel_enter(curthread);
138 	ret = __sys_aio_suspend(iocbs, niocb, timeout);
139 	_thr_cancel_leave(curthread, 1);
140 
141 	return (ret);
142 }
143 
144 /*
145  * Cancellation behavior:
146  *   According to manual of close(), the file descriptor is always deleted.
147  *   Here, thread is only canceled after the system call, so the file
148  *   descriptor is always deleted despite whether the thread is canceled
149  *   or not.
150  */
151 static int
152 __thr_close(int fd)
153 {
154 	struct pthread *curthread;
155 	int ret;
156 
157 	curthread = _get_curthread();
158 	_thr_cancel_enter2(curthread, 0);
159 	ret = __sys_close(fd);
160 	_thr_cancel_leave(curthread, 1);
161 
162 	return (ret);
163 }
164 
165 /*
166  * Cancellation behavior:
167  *   If the thread is canceled, connection is not made.
168  */
169 static int
170 __thr_connect(int fd, const struct sockaddr *name, socklen_t namelen)
171 {
172 	struct pthread *curthread;
173 	int ret;
174 
175 	curthread = _get_curthread();
176 	_thr_cancel_enter(curthread);
177 	ret = __sys_connect(fd, name, namelen);
178 	_thr_cancel_leave(curthread, ret == -1);
179 
180  	return (ret);
181 }
182 
183 /*
184  * Cancellation behavior:
185  *   According to specification, only F_SETLKW is a cancellation point.
186  *   Thread is only canceled at start, or canceled if the system call
187  *   is failure, this means the function does not generate side effect
188  *   if it is canceled.
189  */
190 static int
191 __thr_fcntl(int fd, int cmd, ...)
192 {
193 	struct pthread *curthread;
194 	int ret;
195 	va_list	ap;
196 
197 	curthread = _get_curthread();
198 	va_start(ap, cmd);
199 	if (cmd == F_OSETLKW || cmd == F_SETLKW) {
200 		_thr_cancel_enter(curthread);
201 		ret = __sys_fcntl(fd, cmd, (intptr_t)va_arg(ap, void *));
202 		_thr_cancel_leave(curthread, ret == -1);
203 	} else {
204 		ret = __sys_fcntl(fd, cmd, (intptr_t)va_arg(ap, void *));
205 	}
206 	va_end(ap);
207 
208 	return (ret);
209 }
210 
211 /*
212  * Cancellation behavior:
213  *   Thread may be canceled after system call.
214  */
215 static int
216 __thr_fsync(int fd)
217 {
218 	struct pthread *curthread;
219 	int ret;
220 
221 	curthread = _get_curthread();
222 	_thr_cancel_enter2(curthread, 0);
223 	ret = __sys_fsync(fd);
224 	_thr_cancel_leave(curthread, 1);
225 
226 	return (ret);
227 }
228 
229 static int
230 __thr_fdatasync(int fd)
231 {
232 	struct pthread *curthread;
233 	int ret;
234 
235 	curthread = _get_curthread();
236 	_thr_cancel_enter2(curthread, 0);
237 	ret = __sys_fdatasync(fd);
238 	_thr_cancel_leave(curthread, 1);
239 
240 	return (ret);
241 }
242 
243 /*
244  * Cancellation behavior:
245  *   Thread may be canceled after system call.
246  */
247 static int
248 __thr_msync(void *addr, size_t len, int flags)
249 {
250 	struct pthread *curthread;
251 	int ret;
252 
253 	curthread = _get_curthread();
254 	_thr_cancel_enter2(curthread, 0);
255 	ret = __sys_msync(addr, len, flags);
256 	_thr_cancel_leave(curthread, 1);
257 
258 	return (ret);
259 }
260 
261 static int
262 __thr_clock_nanosleep(clockid_t clock_id, int flags,
263     const struct timespec *time_to_sleep, struct timespec *time_remaining)
264 {
265 	struct pthread *curthread;
266 	int ret;
267 
268 	curthread = _get_curthread();
269 	_thr_cancel_enter(curthread);
270 	ret = __sys_clock_nanosleep(clock_id, flags, time_to_sleep,
271 	    time_remaining);
272 	_thr_cancel_leave(curthread, 1);
273 
274 	return (ret);
275 }
276 
277 static int
278 __thr_nanosleep(const struct timespec *time_to_sleep,
279     struct timespec *time_remaining)
280 {
281 	struct pthread *curthread;
282 	int ret;
283 
284 	curthread = _get_curthread();
285 	_thr_cancel_enter(curthread);
286 	ret = __sys_nanosleep(time_to_sleep, time_remaining);
287 	_thr_cancel_leave(curthread, 1);
288 
289 	return (ret);
290 }
291 
292 /*
293  * Cancellation behavior:
294  *   If the thread is canceled, file is not opened.
295  */
296 static int
297 __thr_openat(int fd, const char *path, int flags, ...)
298 {
299 	struct pthread *curthread;
300 	int mode, ret;
301 	va_list	ap;
302 
303 
304 	/* Check if the file is being created: */
305 	if ((flags & O_CREAT) != 0) {
306 		/* Get the creation mode: */
307 		va_start(ap, flags);
308 		mode = va_arg(ap, int);
309 		va_end(ap);
310 	} else {
311 		mode = 0;
312 	}
313 
314 	curthread = _get_curthread();
315 	_thr_cancel_enter(curthread);
316 	ret = __sys_openat(fd, path, flags, mode);
317 	_thr_cancel_leave(curthread, ret == -1);
318 
319 	return (ret);
320 }
321 
322 /*
323  * Cancellation behavior:
324  *   Thread may be canceled at start, but if the system call returns something,
325  *   the thread is not canceled.
326  */
327 static int
328 __thr_poll(struct pollfd *fds, unsigned int nfds, int timeout)
329 {
330 	struct pthread *curthread;
331 	int ret;
332 
333 	curthread = _get_curthread();
334 	_thr_cancel_enter(curthread);
335 	ret = __sys_poll(fds, nfds, timeout);
336 	_thr_cancel_leave(curthread, ret == -1);
337 
338 	return (ret);
339 }
340 
341 /*
342  * Cancellation behavior:
343  *   Thread may be canceled at start, but if the system call returns something,
344  *   the thread is not canceled.
345  */
346 static int
347 __thr_ppoll(struct pollfd pfd[], nfds_t nfds, const struct timespec *
348     timeout, const sigset_t *newsigmask)
349 {
350 	struct pthread *curthread;
351 	int ret;
352 
353 	curthread = _get_curthread();
354 	_thr_cancel_enter(curthread);
355 	ret = __sys_ppoll(pfd, nfds, timeout, newsigmask);
356 	_thr_cancel_leave(curthread, ret == -1);
357 
358 	return (ret);
359 }
360 
361 /*
362  * Cancellation behavior:
363  *   Thread may be canceled at start, but if the system call returns something,
364  *   the thread is not canceled.
365  */
366 static int
367 __thr_pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
368 	const struct timespec *timo, const sigset_t *mask)
369 {
370 	struct pthread *curthread;
371 	int ret;
372 
373 	curthread = _get_curthread();
374 	_thr_cancel_enter(curthread);
375 	ret = __sys_pselect(count, rfds, wfds, efds, timo, mask);
376 	_thr_cancel_leave(curthread, ret == -1);
377 
378 	return (ret);
379 }
380 
381 static int
382 __thr_kevent(int kq, const struct kevent *changelist, int nchanges,
383     struct kevent *eventlist, int nevents, const struct timespec *timeout)
384 {
385 	struct pthread *curthread;
386 	int ret;
387 
388 	if (nevents == 0) {
389 		/*
390 		 * No blocking, do not make the call cancellable.
391 		 */
392 		return (__sys_kevent(kq, changelist, nchanges, eventlist,
393 		    nevents, timeout));
394 	}
395 	curthread = _get_curthread();
396 	_thr_cancel_enter(curthread);
397 	ret = __sys_kevent(kq, changelist, nchanges, eventlist, nevents,
398 	    timeout);
399 	_thr_cancel_leave(curthread, ret == -1 && nchanges == 0);
400 
401 	return (ret);
402 }
403 
404 /*
405  * Cancellation behavior:
406  *   Thread may be canceled at start, but if the system call got some data,
407  *   the thread is not canceled.
408  */
409 static ssize_t
410 __thr_read(int fd, void *buf, size_t nbytes)
411 {
412 	struct pthread *curthread;
413 	ssize_t	ret;
414 
415 	curthread = _get_curthread();
416 	_thr_cancel_enter(curthread);
417 	ret = __sys_read(fd, buf, nbytes);
418 	_thr_cancel_leave(curthread, ret == -1);
419 
420 	return (ret);
421 }
422 
423 /*
424  * Cancellation behavior:
425  *   Thread may be canceled at start, but if the system call got some data,
426  *   the thread is not canceled.
427  */
428 static ssize_t
429 __thr_readv(int fd, const struct iovec *iov, int iovcnt)
430 {
431 	struct pthread *curthread;
432 	ssize_t ret;
433 
434 	curthread = _get_curthread();
435 	_thr_cancel_enter(curthread);
436 	ret = __sys_readv(fd, iov, iovcnt);
437 	_thr_cancel_leave(curthread, ret == -1);
438 	return (ret);
439 }
440 
441 /*
442  * Cancellation behavior:
443  *   Thread may be canceled at start, but if the system call got some data,
444  *   the thread is not canceled.
445  */
446 static ssize_t
447 __thr_recvfrom(int s, void *b, size_t l, int f, struct sockaddr *from,
448     socklen_t *fl)
449 {
450 	struct pthread *curthread;
451 	ssize_t ret;
452 
453 	curthread = _get_curthread();
454 	_thr_cancel_enter(curthread);
455 	ret = __sys_recvfrom(s, b, l, f, from, fl);
456 	_thr_cancel_leave(curthread, ret == -1);
457 	return (ret);
458 }
459 
460 /*
461  * Cancellation behavior:
462  *   Thread may be canceled at start, but if the system call got some data,
463  *   the thread is not canceled.
464  */
465 static ssize_t
466 __thr_recvmsg(int s, struct msghdr *m, int f)
467 {
468 	struct pthread *curthread;
469 	ssize_t ret;
470 
471 	curthread = _get_curthread();
472 	_thr_cancel_enter(curthread);
473 	ret = __sys_recvmsg(s, m, f);
474 	_thr_cancel_leave(curthread, ret == -1);
475 	return (ret);
476 }
477 
478 /*
479  * Cancellation behavior:
480  *   Thread may be canceled at start, but if the system call returns something,
481  *   the thread is not canceled.
482  */
483 static int
484 __thr_select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
485 	struct timeval *timeout)
486 {
487 	struct pthread *curthread;
488 	int ret;
489 
490 	curthread = _get_curthread();
491 	_thr_cancel_enter(curthread);
492 	ret = __sys_select(numfds, readfds, writefds, exceptfds, timeout);
493 	_thr_cancel_leave(curthread, ret == -1);
494 	return (ret);
495 }
496 
497 /*
498  * Cancellation behavior:
499  *   Thread may be canceled at start, but if the system call sent
500  *   data, the thread is not canceled.
501  */
502 static ssize_t
503 __thr_sendmsg(int s, const struct msghdr *m, int f)
504 {
505 	struct pthread *curthread;
506 	ssize_t ret;
507 
508 	curthread = _get_curthread();
509 	_thr_cancel_enter(curthread);
510 	ret = __sys_sendmsg(s, m, f);
511 	_thr_cancel_leave(curthread, ret <= 0);
512 	return (ret);
513 }
514 
515 /*
516  * Cancellation behavior:
517  *   Thread may be canceled at start, but if the system call sent some
518  *   data, the thread is not canceled.
519  */
520 static ssize_t
521 __thr_sendto(int s, const void *m, size_t l, int f, const struct sockaddr *t,
522     socklen_t tl)
523 {
524 	struct pthread *curthread;
525 	ssize_t ret;
526 
527 	curthread = _get_curthread();
528 	_thr_cancel_enter(curthread);
529 	ret = __sys_sendto(s, m, l, f, t, tl);
530 	_thr_cancel_leave(curthread, ret <= 0);
531 	return (ret);
532 }
533 
534 static int
535 __thr_system(const char *string)
536 {
537 	struct pthread *curthread;
538 	int ret;
539 
540 	curthread = _get_curthread();
541 	_thr_cancel_enter(curthread);
542 	ret = __libc_system(string);
543 	_thr_cancel_leave(curthread, 1);
544 	return (ret);
545 }
546 
547 /*
548  * Cancellation behavior:
549  *   If thread is canceled, the system call is not completed,
550  *   this means not all bytes were drained.
551  */
552 static int
553 __thr_tcdrain(int fd)
554 {
555 	struct pthread *curthread;
556 	int ret;
557 
558 	curthread = _get_curthread();
559 	_thr_cancel_enter(curthread);
560 	ret = __libc_tcdrain(fd);
561 	_thr_cancel_leave(curthread, ret == -1);
562 	return (ret);
563 }
564 
565 /*
566  * Cancellation behavior:
567  *   Thread may be canceled at start, but if the system call returns
568  *   a child pid, the thread is not canceled.
569  */
570 static pid_t
571 __thr_wait4(pid_t pid, int *status, int options, struct rusage *rusage)
572 {
573 	struct pthread *curthread;
574 	pid_t ret;
575 
576 	curthread = _get_curthread();
577 	_thr_cancel_enter(curthread);
578 	ret = __sys_wait4(pid, status, options, rusage);
579 	_thr_cancel_leave(curthread, ret <= 0);
580 	return (ret);
581 }
582 
583 /*
584  * Cancellation behavior:
585  *   Thread may be canceled at start, but if the system call returns
586  *   a child pid, the thread is not canceled.
587  */
588 static pid_t
589 __thr_wait6(idtype_t idtype, id_t id, int *status, int options,
590     struct __wrusage *ru, siginfo_t *infop)
591 {
592 	struct pthread *curthread;
593 	pid_t ret;
594 
595 	curthread = _get_curthread();
596 	_thr_cancel_enter(curthread);
597 	ret = __sys_wait6(idtype, id, status, options, ru, infop);
598 	_thr_cancel_leave(curthread, ret <= 0);
599 	return (ret);
600 }
601 
602 /*
603  * Cancellation behavior:
604  *   Thread may be canceled at start, but if the thread wrote some data,
605  *   it is not canceled.
606  */
607 static ssize_t
608 __thr_write(int fd, const void *buf, size_t nbytes)
609 {
610 	struct pthread *curthread;
611 	ssize_t	ret;
612 
613 	curthread = _get_curthread();
614 	_thr_cancel_enter(curthread);
615 	ret = __sys_write(fd, buf, nbytes);
616 	_thr_cancel_leave(curthread, (ret <= 0));
617 	return (ret);
618 }
619 
620 /*
621  * Cancellation behavior:
622  *   Thread may be canceled at start, but if the thread wrote some data,
623  *   it is not canceled.
624  */
625 static ssize_t
626 __thr_writev(int fd, const struct iovec *iov, int iovcnt)
627 {
628 	struct pthread *curthread;
629 	ssize_t ret;
630 
631 	curthread = _get_curthread();
632 	_thr_cancel_enter(curthread);
633 	ret = __sys_writev(fd, iov, iovcnt);
634 	_thr_cancel_leave(curthread, (ret <= 0));
635 	return (ret);
636 }
637 
638 void
639 __thr_interpose_libc(void)
640 {
641 
642 	__set_error_selector(__error_threaded);
643 #define	SLOT(name)					\
644 	*(__libc_interposing_slot(INTERPOS_##name)) =	\
645 	    (interpos_func_t)__thr_##name;
646 	SLOT(system);
647 	SLOT(tcdrain);
648 	SLOT(spinlock);
649 	SLOT(spinunlock);
650 	SLOT(map_stacks_exec);
651 #undef SLOT
652 
653 #define	SLOT(name)					\
654 	*(__libc_interposing_slot(INTERPOS_##name)) =	\
655 	    (interpos_func_t)__thr_##name;
656 	SLOT(accept);
657 	SLOT(accept4);
658 	SLOT(aio_suspend);
659 	SLOT(close);
660 	SLOT(connect);
661 	SLOT(fcntl);
662 	SLOT(fsync);
663 	SLOT(fork);
664 	SLOT(msync);
665 	SLOT(nanosleep);
666 	SLOT(openat);
667 	SLOT(poll);
668 	SLOT(pselect);
669 	SLOT(read);
670 	SLOT(readv);
671 	SLOT(recvfrom);
672 	SLOT(recvmsg);
673 	SLOT(select);
674 	SLOT(sendmsg);
675 	SLOT(sendto);
676 	SLOT(setcontext);
677 	SLOT(sigaction);
678 	SLOT(sigprocmask);
679 	SLOT(sigsuspend);
680 	SLOT(sigwait);
681 	SLOT(sigtimedwait);
682 	SLOT(sigwaitinfo);
683 	SLOT(swapcontext);
684 	SLOT(wait4);
685 	SLOT(write);
686 	SLOT(writev);
687 	SLOT(kevent);
688 	SLOT(wait6);
689 	SLOT(ppoll);
690 	SLOT(fdatasync);
691 	SLOT(clock_nanosleep);
692 	SLOT(pdfork);
693 #undef SLOT
694 	*(__libc_interposing_slot(
695 	    INTERPOS__pthread_mutex_init_calloc_cb)) =
696 	    (interpos_func_t)_pthread_mutex_init_calloc_cb;
697 }
698