thr_syscalls.c revision 296732
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: stable/10/lib/libthr/thread/thr_syscalls.c 296732 2016-03-12 17:33:40Z kib $");
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
99extern int __fcntl_compat(int, int, ...);
100#endif
101
102static 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 */
120static 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
134static 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 */
156static 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 */
174static 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 */
195static 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 */
228static 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 */
246static 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
260static 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 */
279static 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 */
310static 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 */
329static int
330__thr_ppoll(struct pollfd pfd[], nfds_t nfds, const struct timespec *
331    timeout, const sigset_t *newsigmask)
332{
333	struct pthread *curthread;
334	int ret;
335
336	curthread = _get_curthread();
337	_thr_cancel_enter(curthread);
338	ret = __sys_ppoll(pfd, nfds, timeout, newsigmask);
339	_thr_cancel_leave(curthread, ret == -1);
340
341	return (ret);
342}
343
344/*
345 * Cancellation behavior:
346 *   Thread may be canceled at start, but if the system call returns something,
347 *   the thread is not canceled.
348 */
349static int
350__thr_pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
351	const struct timespec *timo, const sigset_t *mask)
352{
353	struct pthread *curthread;
354	int ret;
355
356	curthread = _get_curthread();
357	_thr_cancel_enter(curthread);
358	ret = __sys_pselect(count, rfds, wfds, efds, timo, mask);
359	_thr_cancel_leave(curthread, ret == -1);
360
361	return (ret);
362}
363
364static int
365__thr_kevent(int kq, const struct kevent *changelist, int nchanges,
366    struct kevent *eventlist, int nevents, const struct timespec *timeout)
367{
368	struct pthread *curthread;
369	int ret;
370
371	if (nevents == 0) {
372		/*
373		 * No blocking, do not make the call cancellable.
374		 */
375		return (__sys_kevent(kq, changelist, nchanges, eventlist,
376		    nevents, timeout));
377	}
378	curthread = _get_curthread();
379	_thr_cancel_enter(curthread);
380	ret = __sys_kevent(kq, changelist, nchanges, eventlist, nevents,
381	    timeout);
382	_thr_cancel_leave(curthread, ret == -1 && nchanges == 0);
383
384	return (ret);
385}
386
387/*
388 * Cancellation behavior:
389 *   Thread may be canceled at start, but if the system call got some data,
390 *   the thread is not canceled.
391 */
392static ssize_t
393__thr_read(int fd, void *buf, size_t nbytes)
394{
395	struct pthread *curthread;
396	ssize_t	ret;
397
398	curthread = _get_curthread();
399	_thr_cancel_enter(curthread);
400	ret = __sys_read(fd, buf, nbytes);
401	_thr_cancel_leave(curthread, ret == -1);
402
403	return (ret);
404}
405
406/*
407 * Cancellation behavior:
408 *   Thread may be canceled at start, but if the system call got some data,
409 *   the thread is not canceled.
410 */
411static ssize_t
412__thr_readv(int fd, const struct iovec *iov, int iovcnt)
413{
414	struct pthread *curthread;
415	ssize_t ret;
416
417	curthread = _get_curthread();
418	_thr_cancel_enter(curthread);
419	ret = __sys_readv(fd, iov, iovcnt);
420	_thr_cancel_leave(curthread, ret == -1);
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 */
429static ssize_t
430__thr_recvfrom(int s, void *b, size_t l, int f, struct sockaddr *from,
431    socklen_t *fl)
432{
433	struct pthread *curthread;
434	ssize_t ret;
435
436	curthread = _get_curthread();
437	_thr_cancel_enter(curthread);
438	ret = __sys_recvfrom(s, b, l, f, from, fl);
439	_thr_cancel_leave(curthread, ret == -1);
440	return (ret);
441}
442
443/*
444 * Cancellation behavior:
445 *   Thread may be canceled at start, but if the system call got some data,
446 *   the thread is not canceled.
447 */
448static ssize_t
449__thr_recvmsg(int s, struct msghdr *m, int f)
450{
451	struct pthread *curthread;
452	ssize_t ret;
453
454	curthread = _get_curthread();
455	_thr_cancel_enter(curthread);
456	ret = __sys_recvmsg(s, m, f);
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 returns something,
464 *   the thread is not canceled.
465 */
466static int
467__thr_select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
468	struct timeval *timeout)
469{
470	struct pthread *curthread;
471	int ret;
472
473	curthread = _get_curthread();
474	_thr_cancel_enter(curthread);
475	ret = __sys_select(numfds, readfds, writefds, exceptfds, timeout);
476	_thr_cancel_leave(curthread, ret == -1);
477	return (ret);
478}
479
480/*
481 * Cancellation behavior:
482 *   Thread may be canceled at start, but if the system call sent
483 *   data, the thread is not canceled.
484 */
485static ssize_t
486__thr_sendmsg(int s, const struct msghdr *m, int f)
487{
488	struct pthread *curthread;
489	ssize_t ret;
490
491	curthread = _get_curthread();
492	_thr_cancel_enter(curthread);
493	ret = __sys_sendmsg(s, m, f);
494	_thr_cancel_leave(curthread, ret <= 0);
495	return (ret);
496}
497
498/*
499 * Cancellation behavior:
500 *   Thread may be canceled at start, but if the system call sent some
501 *   data, the thread is not canceled.
502 */
503static ssize_t
504__thr_sendto(int s, const void *m, size_t l, int f, const struct sockaddr *t,
505    socklen_t tl)
506{
507	struct pthread *curthread;
508	ssize_t ret;
509
510	curthread = _get_curthread();
511	_thr_cancel_enter(curthread);
512	ret = __sys_sendto(s, m, l, f, t, tl);
513	_thr_cancel_leave(curthread, ret <= 0);
514	return (ret);
515}
516
517static int
518__thr_system(const char *string)
519{
520	struct pthread *curthread;
521	int ret;
522
523	curthread = _get_curthread();
524	_thr_cancel_enter(curthread);
525	ret = __libc_system(string);
526	_thr_cancel_leave(curthread, 1);
527	return (ret);
528}
529
530/*
531 * Cancellation behavior:
532 *   If thread is canceled, the system call is not completed,
533 *   this means not all bytes were drained.
534 */
535static int
536__thr_tcdrain(int fd)
537{
538	struct pthread *curthread;
539	int ret;
540
541	curthread = _get_curthread();
542	_thr_cancel_enter(curthread);
543	ret = __libc_tcdrain(fd);
544	_thr_cancel_leave(curthread, ret == -1);
545	return (ret);
546}
547
548/*
549 * Cancellation behavior:
550 *   Thread may be canceled at start, but if the system call returns
551 *   a child pid, the thread is not canceled.
552 */
553static pid_t
554__thr_wait4(pid_t pid, int *status, int options, struct rusage *rusage)
555{
556	struct pthread *curthread;
557	pid_t ret;
558
559	curthread = _get_curthread();
560	_thr_cancel_enter(curthread);
561	ret = __sys_wait4(pid, status, options, rusage);
562	_thr_cancel_leave(curthread, ret <= 0);
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 */
571static pid_t
572__thr_wait6(idtype_t idtype, id_t id, int *status, int options,
573    struct __wrusage *ru, siginfo_t *infop)
574{
575	struct pthread *curthread;
576	pid_t ret;
577
578	curthread = _get_curthread();
579	_thr_cancel_enter(curthread);
580	ret = __sys_wait6(idtype, id, status, options, ru, infop);
581	_thr_cancel_leave(curthread, ret <= 0);
582	return (ret);
583}
584
585/*
586 * Cancellation behavior:
587 *   Thread may be canceled at start, but if the thread wrote some data,
588 *   it is not canceled.
589 */
590static ssize_t
591__thr_write(int fd, const void *buf, size_t nbytes)
592{
593	struct pthread *curthread;
594	ssize_t	ret;
595
596	curthread = _get_curthread();
597	_thr_cancel_enter(curthread);
598	ret = __sys_write(fd, buf, nbytes);
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 */
608static ssize_t
609__thr_writev(int fd, const struct iovec *iov, int iovcnt)
610{
611	struct pthread *curthread;
612	ssize_t ret;
613
614	curthread = _get_curthread();
615	_thr_cancel_enter(curthread);
616	ret = __sys_writev(fd, iov, iovcnt);
617	_thr_cancel_leave(curthread, (ret <= 0));
618	return (ret);
619}
620
621void
622__thr_interpose_libc(void)
623{
624
625	__set_error_selector(__error_threaded);
626#define	SLOT(name)					\
627	*(__libc_interposing_slot(INTERPOS_##name)) =	\
628	    (interpos_func_t)__thr_##name;
629	SLOT(accept);
630	SLOT(accept4);
631	SLOT(aio_suspend);
632	SLOT(close);
633	SLOT(connect);
634	SLOT(fcntl);
635	SLOT(fsync);
636	SLOT(fork);
637	SLOT(msync);
638	SLOT(nanosleep);
639	SLOT(openat);
640	SLOT(poll);
641	SLOT(pselect);
642	SLOT(read);
643	SLOT(readv);
644	SLOT(recvfrom);
645	SLOT(recvmsg);
646	SLOT(select);
647	SLOT(sendmsg);
648	SLOT(sendto);
649	SLOT(setcontext);
650	SLOT(sigaction);
651	SLOT(sigprocmask);
652	SLOT(sigsuspend);
653	SLOT(sigwait);
654	SLOT(sigtimedwait);
655	SLOT(sigwaitinfo);
656	SLOT(swapcontext);
657	SLOT(system);
658	SLOT(tcdrain);
659	SLOT(wait4);
660	SLOT(write);
661	SLOT(writev);
662	SLOT(spinlock);
663	SLOT(spinunlock);
664	SLOT(kevent);
665	SLOT(wait6);
666	SLOT(ppoll);
667	SLOT(map_stacks_exec);
668#undef SLOT
669	*(__libc_interposing_slot(
670	    INTERPOS__pthread_mutex_init_calloc_cb)) =
671	    (interpos_func_t)_pthread_mutex_init_calloc_cb;
672}
673