xref: /freebsd-src/lib/libthr/thread/thr_syscalls.c (revision 2b15cb3d0922bd70ea592f0da9b4a5b167f4d53f)
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  * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
38  * All rights reserved.
39  *
40  * Redistribution and use in source and binary forms, with or without
41  * modification, are permitted provided that the following conditions
42  * are met:
43  * 1. Redistributions of source code must retain the above copyright
44  *    notice, this list of conditions and the following disclaimer.
45  * 2. Redistributions in binary form must reproduce the above copyright
46  *    notice, this list of conditions and the following disclaimer in the
47  *    documentation and/or other materials provided with the distribution.
48  * 3. Neither the name of the author nor the names of any co-contributors
49  *    may be used to endorse or promote products derived from this software
50  *    without specific prior written permission.
51  *
52  * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
53  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
56  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62  * SUCH DAMAGE.
63  *
64  */
65 
66 #include <sys/cdefs.h>
67 __FBSDID("$FreeBSD$");
68 
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 #ifdef SYSCALL_COMPAT
99 extern int __fcntl_compat(int, int, ...);
100 #endif
101 
102 static int
103 __thr_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
104 {
105 	struct pthread *curthread;
106 	int ret;
107 
108 	curthread = _get_curthread();
109 	_thr_cancel_enter(curthread);
110 	ret = __sys_accept(s, addr, addrlen);
111 	_thr_cancel_leave(curthread, ret == -1);
112 
113  	return (ret);
114 }
115 
116 /*
117  * Cancellation behavior:
118  *   If thread is canceled, no socket is created.
119  */
120 static int
121 __thr_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
122 {
123 	struct pthread *curthread;
124 	int ret;
125 
126 	curthread = _get_curthread();
127 	_thr_cancel_enter(curthread);
128 	ret = __sys_accept4(s, addr, addrlen, flags);
129 	_thr_cancel_leave(curthread, ret == -1);
130 
131  	return (ret);
132 }
133 
134 static int
135 __thr_aio_suspend(const struct aiocb * const iocbs[], int niocb, const struct
136     timespec *timeout)
137 {
138 	struct pthread *curthread;
139 	int ret;
140 
141 	curthread = _get_curthread();
142 	_thr_cancel_enter(curthread);
143 	ret = __sys_aio_suspend(iocbs, niocb, timeout);
144 	_thr_cancel_leave(curthread, 1);
145 
146 	return (ret);
147 }
148 
149 /*
150  * Cancellation behavior:
151  *   According to manual of close(), the file descriptor is always deleted.
152  *   Here, thread is only canceled after the system call, so the file
153  *   descriptor is always deleted despite whether the thread is canceled
154  *   or not.
155  */
156 static int
157 __thr_close(int fd)
158 {
159 	struct pthread *curthread;
160 	int ret;
161 
162 	curthread = _get_curthread();
163 	_thr_cancel_enter2(curthread, 0);
164 	ret = __sys_close(fd);
165 	_thr_cancel_leave(curthread, 1);
166 
167 	return (ret);
168 }
169 
170 /*
171  * Cancellation behavior:
172  *   If the thread is canceled, connection is not made.
173  */
174 static int
175 __thr_connect(int fd, const struct sockaddr *name, socklen_t namelen)
176 {
177 	struct pthread *curthread;
178 	int ret;
179 
180 	curthread = _get_curthread();
181 	_thr_cancel_enter(curthread);
182 	ret = __sys_connect(fd, name, namelen);
183 	_thr_cancel_leave(curthread, ret == -1);
184 
185  	return (ret);
186 }
187 
188 /*
189  * Cancellation behavior:
190  *   According to specification, only F_SETLKW is a cancellation point.
191  *   Thread is only canceled at start, or canceled if the system call
192  *   is failure, this means the function does not generate side effect
193  *   if it is canceled.
194  */
195 static int
196 __thr_fcntl(int fd, int cmd, ...)
197 {
198 	struct pthread *curthread;
199 	int ret;
200 	va_list	ap;
201 
202 	curthread = _get_curthread();
203 	va_start(ap, cmd);
204 	if (cmd == F_OSETLKW || cmd == F_SETLKW) {
205 		_thr_cancel_enter(curthread);
206 #ifdef SYSCALL_COMPAT
207 		ret = __fcntl_compat(fd, cmd, va_arg(ap, void *));
208 #else
209 		ret = __sys_fcntl(fd, cmd, va_arg(ap, void *));
210 #endif
211 		_thr_cancel_leave(curthread, ret == -1);
212 	} else {
213 #ifdef SYSCALL_COMPAT
214 		ret = __fcntl_compat(fd, cmd, va_arg(ap, void *));
215 #else
216 		ret = __sys_fcntl(fd, cmd, va_arg(ap, void *));
217 #endif
218 	}
219 	va_end(ap);
220 
221 	return (ret);
222 }
223 
224 /*
225  * Cancellation behavior:
226  *   Thread may be canceled after system call.
227  */
228 static int
229 __thr_fsync(int fd)
230 {
231 	struct pthread *curthread;
232 	int ret;
233 
234 	curthread = _get_curthread();
235 	_thr_cancel_enter2(curthread, 0);
236 	ret = __sys_fsync(fd);
237 	_thr_cancel_leave(curthread, 1);
238 
239 	return (ret);
240 }
241 
242 /*
243  * Cancellation behavior:
244  *   Thread may be canceled after system call.
245  */
246 static int
247 __thr_msync(void *addr, size_t len, int flags)
248 {
249 	struct pthread *curthread;
250 	int ret;
251 
252 	curthread = _get_curthread();
253 	_thr_cancel_enter2(curthread, 0);
254 	ret = __sys_msync(addr, len, flags);
255 	_thr_cancel_leave(curthread, 1);
256 
257 	return (ret);
258 }
259 
260 static int
261 __thr_nanosleep(const struct timespec *time_to_sleep,
262     struct timespec *time_remaining)
263 {
264 	struct pthread *curthread;
265 	int ret;
266 
267 	curthread = _get_curthread();
268 	_thr_cancel_enter(curthread);
269 	ret = __sys_nanosleep(time_to_sleep, time_remaining);
270 	_thr_cancel_leave(curthread, 1);
271 
272 	return (ret);
273 }
274 
275 /*
276  * Cancellation behavior:
277  *   If the thread is canceled, file is not opened.
278  */
279 static int
280 __thr_openat(int fd, const char *path, int flags, ...)
281 {
282 	struct pthread *curthread;
283 	int mode, ret;
284 	va_list	ap;
285 
286 
287 	/* Check if the file is being created: */
288 	if ((flags & O_CREAT) != 0) {
289 		/* Get the creation mode: */
290 		va_start(ap, flags);
291 		mode = va_arg(ap, int);
292 		va_end(ap);
293 	} else {
294 		mode = 0;
295 	}
296 
297 	curthread = _get_curthread();
298 	_thr_cancel_enter(curthread);
299 	ret = __sys_openat(fd, path, flags, mode);
300 	_thr_cancel_leave(curthread, ret == -1);
301 
302 	return (ret);
303 }
304 
305 /*
306  * Cancellation behavior:
307  *   Thread may be canceled at start, but if the system call returns something,
308  *   the thread is not canceled.
309  */
310 static int
311 __thr_poll(struct pollfd *fds, unsigned int nfds, int timeout)
312 {
313 	struct pthread *curthread;
314 	int ret;
315 
316 	curthread = _get_curthread();
317 	_thr_cancel_enter(curthread);
318 	ret = __sys_poll(fds, nfds, timeout);
319 	_thr_cancel_leave(curthread, ret == -1);
320 
321 	return (ret);
322 }
323 
324 /*
325  * Cancellation behavior:
326  *   Thread may be canceled at start, but if the system call returns something,
327  *   the thread is not canceled.
328  */
329 static int
330 __thr_pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
331 	const struct timespec *timo, const sigset_t *mask)
332 {
333 	struct pthread *curthread;
334 	int ret;
335 
336 	curthread = _get_curthread();
337 	_thr_cancel_enter(curthread);
338 	ret = __sys_pselect(count, rfds, wfds, efds, timo, mask);
339 	_thr_cancel_leave(curthread, ret == -1);
340 
341 	return (ret);
342 }
343 
344 static int
345 __thr_kevent(int kq, const struct kevent *changelist, int nchanges,
346     struct kevent *eventlist, int nevents, const struct timespec *timeout)
347 {
348 	struct pthread *curthread;
349 	int ret;
350 
351 	if (nevents == 0) {
352 		/*
353 		 * No blocking, do not make the call cancellable.
354 		 */
355 		return (__sys_kevent(kq, changelist, nchanges, eventlist,
356 		    nevents, timeout));
357 	}
358 	curthread = _get_curthread();
359 	_thr_cancel_enter(curthread);
360 	ret = __sys_kevent(kq, changelist, nchanges, eventlist, nevents,
361 	    timeout);
362 	_thr_cancel_leave(curthread, ret == -1 && nchanges == 0);
363 
364 	return (ret);
365 }
366 
367 /*
368  * Cancellation behavior:
369  *   Thread may be canceled at start, but if the system call got some data,
370  *   the thread is not canceled.
371  */
372 static ssize_t
373 __thr_read(int fd, void *buf, size_t nbytes)
374 {
375 	struct pthread *curthread;
376 	ssize_t	ret;
377 
378 	curthread = _get_curthread();
379 	_thr_cancel_enter(curthread);
380 	ret = __sys_read(fd, buf, nbytes);
381 	_thr_cancel_leave(curthread, ret == -1);
382 
383 	return (ret);
384 }
385 
386 /*
387  * Cancellation behavior:
388  *   Thread may be canceled at start, but if the system call got some data,
389  *   the thread is not canceled.
390  */
391 static ssize_t
392 __thr_readv(int fd, const struct iovec *iov, int iovcnt)
393 {
394 	struct pthread *curthread;
395 	ssize_t ret;
396 
397 	curthread = _get_curthread();
398 	_thr_cancel_enter(curthread);
399 	ret = __sys_readv(fd, iov, iovcnt);
400 	_thr_cancel_leave(curthread, ret == -1);
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_recvfrom(int s, void *b, size_t l, int f, struct sockaddr *from,
411     socklen_t *fl)
412 {
413 	struct pthread *curthread;
414 	ssize_t ret;
415 
416 	curthread = _get_curthread();
417 	_thr_cancel_enter(curthread);
418 	ret = __sys_recvfrom(s, b, l, f, from, fl);
419 	_thr_cancel_leave(curthread, ret == -1);
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_recvmsg(int s, struct msghdr *m, int f)
430 {
431 	struct pthread *curthread;
432 	ssize_t ret;
433 
434 	curthread = _get_curthread();
435 	_thr_cancel_enter(curthread);
436 	ret = __sys_recvmsg(s, m, f);
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 returns something,
444  *   the thread is not canceled.
445  */
446 static int
447 __thr_select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
448 	struct timeval *timeout)
449 {
450 	struct pthread *curthread;
451 	int ret;
452 
453 	curthread = _get_curthread();
454 	_thr_cancel_enter(curthread);
455 	ret = __sys_select(numfds, readfds, writefds, exceptfds, timeout);
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 sent
463  *   data, the thread is not canceled.
464  */
465 static ssize_t
466 __thr_sendmsg(int s, const 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_sendmsg(s, m, f);
474 	_thr_cancel_leave(curthread, ret <= 0);
475 	return (ret);
476 }
477 
478 /*
479  * Cancellation behavior:
480  *   Thread may be canceled at start, but if the system call sent some
481  *   data, the thread is not canceled.
482  */
483 static ssize_t
484 __thr_sendto(int s, const void *m, size_t l, int f, const struct sockaddr *t,
485     socklen_t tl)
486 {
487 	struct pthread *curthread;
488 	ssize_t ret;
489 
490 	curthread = _get_curthread();
491 	_thr_cancel_enter(curthread);
492 	ret = __sys_sendto(s, m, l, f, t, tl);
493 	_thr_cancel_leave(curthread, ret <= 0);
494 	return (ret);
495 }
496 
497 static int
498 __thr_system(const char *string)
499 {
500 	struct pthread *curthread;
501 	int ret;
502 
503 	curthread = _get_curthread();
504 	_thr_cancel_enter(curthread);
505 	ret = __libc_system(string);
506 	_thr_cancel_leave(curthread, 1);
507 	return (ret);
508 }
509 
510 /*
511  * Cancellation behavior:
512  *   If thread is canceled, the system call is not completed,
513  *   this means not all bytes were drained.
514  */
515 static int
516 __thr_tcdrain(int fd)
517 {
518 	struct pthread *curthread;
519 	int ret;
520 
521 	curthread = _get_curthread();
522 	_thr_cancel_enter(curthread);
523 	ret = __libc_tcdrain(fd);
524 	_thr_cancel_leave(curthread, ret == -1);
525 	return (ret);
526 }
527 
528 /*
529  * Cancellation behavior:
530  *   Thread may be canceled at start, but if the system call returns
531  *   a child pid, the thread is not canceled.
532  */
533 static pid_t
534 __thr_wait4(pid_t pid, int *status, int options, struct rusage *rusage)
535 {
536 	struct pthread *curthread;
537 	pid_t ret;
538 
539 	curthread = _get_curthread();
540 	_thr_cancel_enter(curthread);
541 	ret = __sys_wait4(pid, status, options, rusage);
542 	_thr_cancel_leave(curthread, ret <= 0);
543 	return (ret);
544 }
545 
546 /*
547  * Cancellation behavior:
548  *   Thread may be canceled at start, but if the thread wrote some data,
549  *   it is not canceled.
550  */
551 static ssize_t
552 __thr_write(int fd, const void *buf, size_t nbytes)
553 {
554 	struct pthread *curthread;
555 	ssize_t	ret;
556 
557 	curthread = _get_curthread();
558 	_thr_cancel_enter(curthread);
559 	ret = __sys_write(fd, buf, nbytes);
560 	_thr_cancel_leave(curthread, (ret <= 0));
561 	return (ret);
562 }
563 
564 /*
565  * Cancellation behavior:
566  *   Thread may be canceled at start, but if the thread wrote some data,
567  *   it is not canceled.
568  */
569 static ssize_t
570 __thr_writev(int fd, const struct iovec *iov, int iovcnt)
571 {
572 	struct pthread *curthread;
573 	ssize_t ret;
574 
575 	curthread = _get_curthread();
576 	_thr_cancel_enter(curthread);
577 	ret = __sys_writev(fd, iov, iovcnt);
578 	_thr_cancel_leave(curthread, (ret <= 0));
579 	return (ret);
580 }
581 
582 void
583 __thr_interpose_libc(void)
584 {
585 
586 	__set_error_selector(__error_threaded);
587 #define	SLOT(name)					\
588 	*(__libc_interposing_slot(INTERPOS_##name)) =	\
589 	    (interpos_func_t)__thr_##name;
590 	SLOT(accept);
591 	SLOT(accept4);
592 	SLOT(aio_suspend);
593 	SLOT(close);
594 	SLOT(connect);
595 	SLOT(fcntl);
596 	SLOT(fsync);
597 	SLOT(fork);
598 	SLOT(msync);
599 	SLOT(nanosleep);
600 	SLOT(openat);
601 	SLOT(poll);
602 	SLOT(pselect);
603 	SLOT(read);
604 	SLOT(readv);
605 	SLOT(recvfrom);
606 	SLOT(recvmsg);
607 	SLOT(select);
608 	SLOT(sendmsg);
609 	SLOT(sendto);
610 	SLOT(setcontext);
611 	SLOT(sigaction);
612 	SLOT(sigprocmask);
613 	SLOT(sigsuspend);
614 	SLOT(sigwait);
615 	SLOT(sigtimedwait);
616 	SLOT(sigwaitinfo);
617 	SLOT(swapcontext);
618 	SLOT(system);
619 	SLOT(tcdrain);
620 	SLOT(wait4);
621 	SLOT(write);
622 	SLOT(writev);
623 	SLOT(spinlock);
624 	SLOT(spinunlock);
625 	SLOT(kevent);
626 #undef SLOT
627 	*(__libc_interposing_slot(
628 	    INTERPOS__pthread_mutex_init_calloc_cb)) =
629 	    (interpos_func_t)_pthread_mutex_init_calloc_cb;
630 }
631