| /* |
| * Copyright (c) 2019 Andrew G. Morgan <morgan@kernel.org> |
| * |
| * This header, and the -lpsx library, provide a number of things to |
| * support POSIX semantics for syscalls associated with the pthread |
| * library. Linking this code is tricky and is done as follows: |
| * |
| * ld ... -lpsx -lpthread --wrap=pthread_create |
| * or, gcc ... -lpsx -lpthread -Wl,-wrap,pthread_create |
| * |
| * glibc provides a subset of this functionality natively through the |
| * nptl:setxid mechanism and could implement psx_syscall() directly |
| * using that style of functionality but, as of 2019-11-30, the setxid |
| * mechanism is limited to 9 specific set*() syscalls that do not |
| * support the syscall6 API (needed for prctl functions and the ambient |
| * capabilities set for example). |
| * |
| * This psx library API also includes explicit registration of threads |
| * if implicit wrapping the pthread_create() function is problematic |
| * for your application via the psx_pthread_create() function. To use |
| * the library in that way, you should include this line in the file |
| * containing your main() function: |
| * |
| * ----------- |
| * #include <sys/psx_syscall.h> |
| * |
| * int main(...) { |
| * |
| * .... |
| * |
| * } |
| * PSX_NO_LINKER_WRAPPING |
| * ----------- |
| * |
| * This will ensure that your binary can link. |
| */ |
| |
| #ifndef _SYS_PSX_SYSCALL_H |
| #define _SYS_PSX_SYSCALL_H |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #include <pthread.h> |
| |
| /* |
| * This function is actually provided by the linker trick: |
| * |
| * gcc ... -lpsx -lpthread -Wl,-wrap,pthread_create |
| */ |
| int __real_pthread_create(pthread_t *thread, const pthread_attr_t *attr, |
| void *(*start_routine) (void *), void *arg); |
| |
| #define PSX_NO_LINKER_WRAPPING int \ |
| __real_pthread_create(pthread_t *thread, const pthread_attr_t *attr, \ |
| void *(*start_routine) (void *), void *arg) { \ |
| return -1; \ |
| } |
| |
| /* |
| * psx_syscall performs the specified syscall on all psx registered |
| * threads. The mecanism by which this occurs is much less efficient |
| * than a standard system call on Linux, so it should only be used |
| * when POSIX semantics are required to change process relevant |
| * security state. |
| * |
| * Glibc has native support for POSIX semantics on setgroups() and the |
| * 8 set*[gu]id() functions. So, there is no need to use psx_syscall() |
| * for these calls. This call exists for all the other system calls |
| * that need to maintain parity on all pthreads of a program. |
| * |
| * Some macrology is used to allow the caller to provide only as many |
| * arguments as needed, thus psx_syscall() cannot be used as a |
| * function pointer. For those situations, we define psx_syscall3() |
| * and psx_syscall6(). |
| */ |
| #define psx_syscall(syscall_nr, ...) \ |
| __psx_syscall(syscall_nr, __VA_ARGS__, 6, 5, 4, 3, 2, 1, 0) |
| long int __psx_syscall(long int syscall_nr, ...); |
| long int psx_syscall3(long int syscall_nr, |
| long int arg1, long int arg2, long int arg3); |
| long int psx_syscall6(long int syscall_nr, |
| long int arg1, long int arg2, long int arg3, |
| long int arg4, long int arg5, long int arg6); |
| |
| /* |
| * psx_register registers the current pthread with the psx abstraction |
| * of system calls. Typically, there is never any need to call this |
| * explicitly because the way the library is linked it is implicitly |
| * called when pthread_create() is called. |
| */ |
| void psx_register(void); |
| |
| /* |
| * psx_pthread_create() wraps the -lpthread pthread_create() function |
| * call and registers the generated thread with the psx_syscall |
| * infrastructure. |
| * |
| * Note, to transparently redirect all the pthread_create() calls in |
| * your binary to psx_pthread_create(), link with: |
| * |
| * gcc ... -lpsx -lpthread -Wl,-wrap,pthread_create |
| * |
| * [That is, libpsx contains an internal definition for the |
| * __wrap_pthread_create function to invoke psx_pthread_create |
| * functionality instead.] |
| */ |
| int psx_pthread_create(pthread_t *thread, const pthread_attr_t *attr, |
| void *(*start_routine) (void *), void *arg); |
| |
| /* |
| * This function should be used by systems to obtain pointers to the |
| * two syscall functions provided by the PSX library. A linkage trick |
| * is to define this function as weak in a library that can optionally |
| * use libpsx and then, should the caller link -lpsx, that library can |
| * implicitly use these POSIX semantics syscalls. See libcap for an |
| * example of this useage. |
| */ |
| void psx_load_syscalls(long int (**syscall_fn)(long int, |
| long int, long int, long int), |
| long int (**syscall6_fn)(long int, |
| long int, long int, long int, |
| long int, long int, long int)); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* _SYS_PSX_SYSCALL_H */ |