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