• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2019 Andrew G. Morgan <morgan@kernel.org>
3  *
4  * This header, and the -lpsx library, provide a number of things to
5  * support POSIX semantics for syscalls associated with the pthread
6  * library. Linking this code is tricky and is done as follows:
7  *
8  *     ld ... -lpsx -lpthread --wrap=pthread_create
9  * or, gcc ... -lpsx -lpthread -Wl,-wrap,pthread_create
10  *
11  * glibc provides a subset of this functionality natively through the
12  * nptl:setxid mechanism and could implement psx_syscall() directly
13  * using that style of functionality but, as of 2019-11-30, the setxid
14  * mechanism is limited to 9 specific set*() syscalls that do not
15  * support the syscall6 API (needed for prctl functions and the ambient
16  * capabilities set for example).
17  */
18 
19 #ifndef _SYS_PSX_SYSCALL_H
20 #define _SYS_PSX_SYSCALL_H
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 #include <pthread.h>
27 
28 /*
29  * psx_syscall performs the specified syscall on all psx registered
30  * threads. The mechanism by which this occurs is much less efficient
31  * than a standard system call on Linux, so it should only be used
32  * when POSIX semantics are required to change process relevant
33  * security state.
34  *
35  * Glibc has native support for POSIX semantics on setgroups() and the
36  * 8 set*[gu]id() functions. So, there is no need to use psx_syscall()
37  * for these calls. This call exists for all the other system calls
38  * that need to maintain parity on all pthreads of a program.
39  *
40  * Some macrology is used to allow the caller to provide only as many
41  * arguments as needed, thus psx_syscall() cannot be used as a
42  * function pointer. For those situations, we define psx_syscall3()
43  * and psx_syscall6().
44  */
45 #define psx_syscall(syscall_nr, ...) \
46     __psx_syscall(syscall_nr, __VA_ARGS__, (long int) 6, (long int) 5, \
47 		  (long int) 4, (long int) 3, (long int) 2, \
48 		  (long int) 1, (long int) 0)
49 long int __psx_syscall(long int syscall_nr, ...);
50 long int psx_syscall3(long int syscall_nr,
51 		      long int arg1, long int arg2, long int arg3);
52 long int psx_syscall6(long int syscall_nr,
53 		      long int arg1, long int arg2, long int arg3,
54 		      long int arg4, long int arg5, long int arg6);
55 
56 /*
57  * This function should be used by systems to obtain pointers to the
58  * two syscall functions provided by the PSX library. A linkage trick
59  * is to define this function as weak in a library that can optionally
60  * use libpsx and then, should the caller link -lpsx, that library can
61  * implicitly use these POSIX semantics syscalls. See libcap for an
62  * example of this useage.
63  */
64 void psx_load_syscalls(long int (**syscall_fn)(long int,
65 					       long int, long int, long int),
66 		       long int (**syscall6_fn)(long int,
67 						long int, long int, long int,
68 						long int, long int, long int));
69 
70 #ifdef __cplusplus
71 }
72 #endif
73 
74 #endif /* _SYS_PSX_SYSCALL_H */
75