xref: /aosp_15_r20/external/libcap/psx/psx_syscall.h (revision 2810ac1b38eead2603277920c78344c84ddf3aff)
1*2810ac1bSKiyoung Kim /*
2*2810ac1bSKiyoung Kim  * Copyright (c) 2019 Andrew G. Morgan <[email protected]>
3*2810ac1bSKiyoung Kim  *
4*2810ac1bSKiyoung Kim  * This header, and the -lpsx library, provide a number of things to
5*2810ac1bSKiyoung Kim  * support POSIX semantics for syscalls associated with the pthread
6*2810ac1bSKiyoung Kim  * library. Linking this code is tricky and is done as follows:
7*2810ac1bSKiyoung Kim  *
8*2810ac1bSKiyoung Kim  *     ld ... -lpsx -lpthread --wrap=pthread_create
9*2810ac1bSKiyoung Kim  * or, gcc ... -lpsx -lpthread -Wl,-wrap,pthread_create
10*2810ac1bSKiyoung Kim  *
11*2810ac1bSKiyoung Kim  * glibc provides a subset of this functionality natively through the
12*2810ac1bSKiyoung Kim  * nptl:setxid mechanism and could implement psx_syscall() directly
13*2810ac1bSKiyoung Kim  * using that style of functionality but, as of 2019-11-30, the setxid
14*2810ac1bSKiyoung Kim  * mechanism is limited to 9 specific set*() syscalls that do not
15*2810ac1bSKiyoung Kim  * support the syscall6 API (needed for prctl functions and the ambient
16*2810ac1bSKiyoung Kim  * capabilities set for example).
17*2810ac1bSKiyoung Kim  */
18*2810ac1bSKiyoung Kim 
19*2810ac1bSKiyoung Kim #ifndef _SYS_PSX_SYSCALL_H
20*2810ac1bSKiyoung Kim #define _SYS_PSX_SYSCALL_H
21*2810ac1bSKiyoung Kim 
22*2810ac1bSKiyoung Kim #ifdef __cplusplus
23*2810ac1bSKiyoung Kim extern "C" {
24*2810ac1bSKiyoung Kim #endif
25*2810ac1bSKiyoung Kim 
26*2810ac1bSKiyoung Kim #include <pthread.h>
27*2810ac1bSKiyoung Kim 
28*2810ac1bSKiyoung Kim /*
29*2810ac1bSKiyoung Kim  * psx_syscall performs the specified syscall on all psx registered
30*2810ac1bSKiyoung Kim  * threads. The mechanism by which this occurs is much less efficient
31*2810ac1bSKiyoung Kim  * than a standard system call on Linux, so it should only be used
32*2810ac1bSKiyoung Kim  * when POSIX semantics are required to change process relevant
33*2810ac1bSKiyoung Kim  * security state.
34*2810ac1bSKiyoung Kim  *
35*2810ac1bSKiyoung Kim  * Glibc has native support for POSIX semantics on setgroups() and the
36*2810ac1bSKiyoung Kim  * 8 set*[gu]id() functions. So, there is no need to use psx_syscall()
37*2810ac1bSKiyoung Kim  * for these calls. This call exists for all the other system calls
38*2810ac1bSKiyoung Kim  * that need to maintain parity on all pthreads of a program.
39*2810ac1bSKiyoung Kim  *
40*2810ac1bSKiyoung Kim  * Some macrology is used to allow the caller to provide only as many
41*2810ac1bSKiyoung Kim  * arguments as needed, thus psx_syscall() cannot be used as a
42*2810ac1bSKiyoung Kim  * function pointer. For those situations, we define psx_syscall3()
43*2810ac1bSKiyoung Kim  * and psx_syscall6().
44*2810ac1bSKiyoung Kim  */
45*2810ac1bSKiyoung Kim #define psx_syscall(syscall_nr, ...) \
46*2810ac1bSKiyoung Kim     __psx_syscall(syscall_nr, __VA_ARGS__, (long int) 6, (long int) 5, \
47*2810ac1bSKiyoung Kim 		  (long int) 4, (long int) 3, (long int) 2, \
48*2810ac1bSKiyoung Kim 		  (long int) 1, (long int) 0)
49*2810ac1bSKiyoung Kim long int __psx_syscall(long int syscall_nr, ...);
50*2810ac1bSKiyoung Kim long int psx_syscall3(long int syscall_nr,
51*2810ac1bSKiyoung Kim 		      long int arg1, long int arg2, long int arg3);
52*2810ac1bSKiyoung Kim long int psx_syscall6(long int syscall_nr,
53*2810ac1bSKiyoung Kim 		      long int arg1, long int arg2, long int arg3,
54*2810ac1bSKiyoung Kim 		      long int arg4, long int arg5, long int arg6);
55*2810ac1bSKiyoung Kim 
56*2810ac1bSKiyoung Kim /*
57*2810ac1bSKiyoung Kim  * This function should be used by systems to obtain pointers to the
58*2810ac1bSKiyoung Kim  * two syscall functions provided by the PSX library. A linkage trick
59*2810ac1bSKiyoung Kim  * is to define this function as weak in a library that can optionally
60*2810ac1bSKiyoung Kim  * use libpsx and then, should the caller link -lpsx, that library can
61*2810ac1bSKiyoung Kim  * implicitly use these POSIX semantics syscalls. See libcap for an
62*2810ac1bSKiyoung Kim  * example of this usage.
63*2810ac1bSKiyoung Kim  */
64*2810ac1bSKiyoung Kim void psx_load_syscalls(long int (**syscall_fn)(long int,
65*2810ac1bSKiyoung Kim 					       long int, long int, long int),
66*2810ac1bSKiyoung Kim 		       long int (**syscall6_fn)(long int,
67*2810ac1bSKiyoung Kim 						long int, long int, long int,
68*2810ac1bSKiyoung Kim 						long int, long int, long int));
69*2810ac1bSKiyoung Kim 
70*2810ac1bSKiyoung Kim /*
71*2810ac1bSKiyoung Kim  * psx_sensitivity_t holds the level of paranoia for non-POSIX syscall
72*2810ac1bSKiyoung Kim  * behavior. The default is PSX_IGNORE: which is best effort - no
73*2810ac1bSKiyoung Kim  * enforcement; PSX_WARNING will dump to stderr a warning when a
74*2810ac1bSKiyoung Kim  * syscall's results differ; PSX_ERROR will dump info as per
75*2810ac1bSKiyoung Kim  * PSX_WARNING and generate a SIGSYS. The current mode can be set with
76*2810ac1bSKiyoung Kim  * psx_set_sensitivity().
77*2810ac1bSKiyoung Kim  */
78*2810ac1bSKiyoung Kim typedef enum {
79*2810ac1bSKiyoung Kim     PSX_IGNORE = 0,
80*2810ac1bSKiyoung Kim     PSX_WARNING = 1,
81*2810ac1bSKiyoung Kim     PSX_ERROR = 2,
82*2810ac1bSKiyoung Kim } psx_sensitivity_t;
83*2810ac1bSKiyoung Kim 
84*2810ac1bSKiyoung Kim /*
85*2810ac1bSKiyoung Kim  * psx_set_sensitivity sets the current sensitivity of the PSX
86*2810ac1bSKiyoung Kim  * mechanism.  The function returns 0 on success and -1 if the
87*2810ac1bSKiyoung Kim  * requested level is invalid.
88*2810ac1bSKiyoung Kim  */
89*2810ac1bSKiyoung Kim int psx_set_sensitivity(psx_sensitivity_t level);
90*2810ac1bSKiyoung Kim 
91*2810ac1bSKiyoung Kim #ifdef __cplusplus
92*2810ac1bSKiyoung Kim }
93*2810ac1bSKiyoung Kim #endif
94*2810ac1bSKiyoung Kim 
95*2810ac1bSKiyoung Kim #endif /* _SYS_PSX_SYSCALL_H */
96