xref: /aosp_15_r20/external/libcap/psx/psx_syscall.h (revision 2810ac1b38eead2603277920c78344c84ddf3aff)
1 /*
2  * Copyright (c) 2019 Andrew G. Morgan <[email protected]>
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 usage.
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 /*
71  * psx_sensitivity_t holds the level of paranoia for non-POSIX syscall
72  * behavior. The default is PSX_IGNORE: which is best effort - no
73  * enforcement; PSX_WARNING will dump to stderr a warning when a
74  * syscall's results differ; PSX_ERROR will dump info as per
75  * PSX_WARNING and generate a SIGSYS. The current mode can be set with
76  * psx_set_sensitivity().
77  */
78 typedef enum {
79     PSX_IGNORE = 0,
80     PSX_WARNING = 1,
81     PSX_ERROR = 2,
82 } psx_sensitivity_t;
83 
84 /*
85  * psx_set_sensitivity sets the current sensitivity of the PSX
86  * mechanism.  The function returns 0 on success and -1 if the
87  * requested level is invalid.
88  */
89 int psx_set_sensitivity(psx_sensitivity_t level);
90 
91 #ifdef __cplusplus
92 }
93 #endif
94 
95 #endif /* _SYS_PSX_SYSCALL_H */
96