2 * Copyright (c) 2009 Andrew Tridgell
3 * Copyright (c) 2011-2013 Andreas Schneider <asn@samba.org>
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include <sys/types.h>
30 #ifdef HAVE_SYS_SYSCALL_H
31 #include <sys/syscall.h>
40 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
41 # define UWRAP_THREAD __thread
46 # define UWRAP_LOCK(m) do { \
47 pthread_mutex_lock(&( m ## _mutex)); \
50 # define UWRAP_UNLOCK(m) do { \
51 pthread_mutex_unlock(&( m ## _mutex)); \
54 /* Add new global locks here please */
55 # define UWRAP_LOCK_ALL \
56 UWRAP_LOCK(uwrap_id); \
57 UWRAP_LOCK(libc_symbol_binding); \
58 UWRAP_LOCK(libpthread_symbol_binding)
60 # define UWRAP_UNLOCK_ALL \
61 UWRAP_UNLOCK(libpthread_symbol_binding); \
62 UWRAP_UNLOCK(libc_symbol_binding); \
63 UWRAP_UNLOCK(uwrap_id)
65 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
66 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
68 #define CONSTRUCTOR_ATTRIBUTE
69 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
71 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
72 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
74 #define DESTRUCTOR_ATTRIBUTE
75 #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
77 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
78 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
79 #else /* DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE */
80 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
81 #endif /* DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE */
83 /* GCC have printf type attribute check. */
84 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
85 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
87 #define PRINTF_ATTRIBUTE(a,b)
88 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
90 #define UWRAP_DLIST_ADD(list,item) do { \
92 (item)->prev = NULL; \
93 (item)->next = NULL; \
96 (item)->prev = NULL; \
97 (item)->next = (list); \
98 (list)->prev = (item); \
103 #define UWRAP_DLIST_REMOVE(list,item) do { \
104 if ((list) == (item)) { \
105 (list) = (item)->next; \
107 (list)->prev = NULL; \
110 if ((item)->prev) { \
111 (item)->prev->next = (item)->next; \
113 if ((item)->next) { \
114 (item)->next->prev = (item)->prev; \
117 (item)->prev = NULL; \
118 (item)->next = NULL; \
122 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
129 enum uwrap_dbglvl_e {
136 static void uwrap_log(enum uwrap_dbglvl_e dbglvl, const char *function, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
137 # define UWRAP_LOG(dbglvl, ...) uwrap_log((dbglvl), __func__, __VA_ARGS__)
139 static void uwrap_log(enum uwrap_dbglvl_e dbglvl, const char *function, const char *format, ...)
144 unsigned int lvl = 0;
146 d = getenv("UID_WRAPPER_DEBUGLEVEL");
151 va_start(va, format);
152 vsnprintf(buffer, sizeof(buffer), format, va);
156 const char *prefix = "UWRAP";
158 case UWRAP_LOG_ERROR:
159 prefix = "UWRAP_ERROR";
162 prefix = "UWRAP_WARN";
164 case UWRAP_LOG_DEBUG:
165 prefix = "UWRAP_DEBUG";
167 case UWRAP_LOG_TRACE:
168 prefix = "UWRAP_TRACE";
185 #define LIBC_NAME "libc.so"
187 typedef int (*__libc_setuid)(uid_t uid);
189 typedef uid_t (*__libc_getuid)(void);
192 typedef int (*__libc_seteuid)(uid_t euid);
196 typedef int (*__libc_setreuid)(uid_t ruid, uid_t euid);
199 #ifdef HAVE_SETRESUID
200 typedef int (*__libc_setresuid)(uid_t ruid, uid_t euid, uid_t suid);
203 #ifdef HAVE_GETRESUID
204 typedef int (*__libc_getresuid)(uid_t *ruid, uid_t *euid, uid_t *suid);
207 typedef uid_t (*__libc_geteuid)(void);
209 typedef int (*__libc_setgid)(gid_t gid);
211 typedef gid_t (*__libc_getgid)(void);
214 typedef int (*__libc_setegid)(uid_t egid);
218 typedef int (*__libc_setregid)(uid_t rgid, uid_t egid);
221 #ifdef HAVE_SETRESGID
222 typedef int (*__libc_setresgid)(uid_t rgid, uid_t egid, uid_t sgid);
225 #ifdef HAVE_GETRESGID
226 typedef int (*__libc_getresgid)(gid_t *rgid, gid_t *egid, gid_t *sgid);
229 typedef gid_t (*__libc_getegid)(void);
231 typedef int (*__libc_getgroups)(int size, gid_t list[]);
233 typedef int (*__libc_setgroups)(size_t size, const gid_t *list);
236 typedef long int (*__libc_syscall)(long int sysno, ...);
239 #define UWRAP_SYMBOL_ENTRY(i) \
245 struct uwrap_libc_symbols {
246 UWRAP_SYMBOL_ENTRY(setuid);
247 UWRAP_SYMBOL_ENTRY(getuid);
249 UWRAP_SYMBOL_ENTRY(seteuid);
252 UWRAP_SYMBOL_ENTRY(setreuid);
254 #ifdef HAVE_SETRESUID
255 UWRAP_SYMBOL_ENTRY(setresuid);
257 #ifdef HAVE_GETRESUID
258 UWRAP_SYMBOL_ENTRY(getresuid);
260 UWRAP_SYMBOL_ENTRY(geteuid);
261 UWRAP_SYMBOL_ENTRY(setgid);
262 UWRAP_SYMBOL_ENTRY(getgid);
264 UWRAP_SYMBOL_ENTRY(setegid);
267 UWRAP_SYMBOL_ENTRY(setregid);
269 #ifdef HAVE_SETRESGID
270 UWRAP_SYMBOL_ENTRY(setresgid);
272 #ifdef HAVE_GETRESGID
273 UWRAP_SYMBOL_ENTRY(getresgid);
275 UWRAP_SYMBOL_ENTRY(getegid);
276 UWRAP_SYMBOL_ENTRY(getgroups);
277 UWRAP_SYMBOL_ENTRY(setgroups);
279 UWRAP_SYMBOL_ENTRY(syscall);
282 #undef UWRAP_SYMBOL_ENTRY
287 /* Yeah... I'm pig. I overloading macro here... So what? */
288 #define UWRAP_SYMBOL_ENTRY(i) \
290 __libpthread_##i f; \
294 typedef int (*__libpthread_pthread_create)(pthread_t *thread,
295 const pthread_attr_t *attr,
296 void *(*start_routine) (void *),
298 typedef void (*__libpthread_pthread_exit)(void *retval);
300 struct uwrap_libpthread_symbols {
301 UWRAP_SYMBOL_ENTRY(pthread_create);
302 UWRAP_SYMBOL_ENTRY(pthread_exit);
304 #undef UWRAP_SYMBOL_ENTRY
307 * We keep the virtualised euid/egid/groups information here
309 struct uwrap_thread {
323 struct uwrap_thread *next;
324 struct uwrap_thread *prev;
330 struct uwrap_libc_symbols symbols;
335 struct uwrap_libpthread_symbols symbols;
340 /* Real uid and gid of user who run uid wrapper */
344 struct uwrap_thread *ids;
347 static struct uwrap uwrap;
349 /* Shortcut to the list item */
350 static UWRAP_THREAD struct uwrap_thread *uwrap_tls_id;
352 /* The mutex or accessing the id */
353 static pthread_mutex_t uwrap_id_mutex = PTHREAD_MUTEX_INITIALIZER;
355 /* The mutex for accessing the global libc.symbols */
356 static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
358 /* The mutex for accessing the global libpthread.symbols */
359 static pthread_mutex_t libpthread_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
361 /*********************************************************
363 *********************************************************/
365 bool uid_wrapper_enabled(void);
366 void uwrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
367 void uwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
369 /*********************************************************
370 * UWRAP LIBC LOADER FUNCTIONS
371 *********************************************************/
380 static void *uwrap_load_lib_handle(enum uwrap_lib lib)
382 int flags = RTLD_LAZY;
387 flags |= RTLD_DEEPBIND;
393 case UWRAP_LIBSOCKET:
396 handle = uwrap.libc.handle;
397 if (handle == NULL) {
398 for (i = 10; i >= 0; i--) {
399 char soname[256] = {0};
401 snprintf(soname, sizeof(soname), "libc.so.%d", i);
402 handle = dlopen(soname, flags);
403 if (handle != NULL) {
407 /* glibc on Alpha and IA64 is libc.so.6.1 */
408 snprintf(soname, sizeof(soname), "libc.so.%d.1", i);
409 handle = dlopen(soname, flags);
410 if (handle != NULL) {
415 uwrap.libc.handle = handle;
418 case UWRAP_LIBPTHREAD:
419 handle = uwrap.libpthread.handle;
420 if (handle == NULL) {
421 handle = dlopen("libpthread.so.0", flags);
422 if (handle != NULL) {
429 if (handle == NULL) {
431 handle = uwrap.libc.handle = RTLD_NEXT;
434 "Failed to dlopen library: %s\n",
443 static void *_uwrap_bind_symbol(enum uwrap_lib lib, const char *fn_name)
448 handle = uwrap_load_lib_handle(lib);
450 func = dlsym(handle, fn_name);
453 "Failed to find %s: %s\n",
461 #define uwrap_bind_symbol_libc(sym_name) \
462 UWRAP_LOCK(libc_symbol_binding); \
463 if (uwrap.libc.symbols._libc_##sym_name.obj == NULL) { \
464 uwrap.libc.symbols._libc_##sym_name.obj = \
465 _uwrap_bind_symbol(UWRAP_LIBC, #sym_name); \
467 UWRAP_UNLOCK(libc_symbol_binding)
469 #define uwrap_bind_symbol_libpthread(sym_name) \
470 UWRAP_LOCK(libpthread_symbol_binding); \
471 if (uwrap.libpthread.symbols._libpthread_##sym_name.obj == NULL) { \
472 uwrap.libpthread.symbols._libpthread_##sym_name.obj = \
473 _uwrap_bind_symbol(UWRAP_LIBPTHREAD, #sym_name); \
475 UWRAP_UNLOCK(libpthread_symbol_binding)
480 * Functions expeciall from libc need to be loaded individually, you can't load
481 * all at once or gdb will segfault at startup. The same applies to valgrind and
482 * has probably something todo with with the linker.
483 * So we need load each function at the point it is called the first time.
485 static int libc_setuid(uid_t uid)
487 uwrap_bind_symbol_libc(setuid);
489 return uwrap.libc.symbols._libc_setuid.f(uid);
492 static uid_t libc_getuid(void)
494 uwrap_bind_symbol_libc(getuid);
496 return uwrap.libc.symbols._libc_getuid.f();
500 static int libc_seteuid(uid_t euid)
502 uwrap_bind_symbol_libc(seteuid);
504 return uwrap.libc.symbols._libc_seteuid.f(euid);
509 static int libc_setreuid(uid_t ruid, uid_t euid)
511 uwrap_bind_symbol_libc(setreuid);
513 return uwrap.libc.symbols._libc_setreuid.f(ruid, euid);
517 #ifdef HAVE_SETRESUID
518 static int libc_setresuid(uid_t ruid, uid_t euid, uid_t suid)
520 uwrap_bind_symbol_libc(setresuid);
522 return uwrap.libc.symbols._libc_setresuid.f(ruid, euid, suid);
526 #ifdef HAVE_GETRESUID
527 static int libc_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
529 uwrap_bind_symbol_libc(getresuid);
531 return uwrap.libc.symbols._libc_getresuid.f(ruid, euid, suid);
535 static uid_t libc_geteuid(void)
537 uwrap_bind_symbol_libc(geteuid);
539 return uwrap.libc.symbols._libc_geteuid.f();
542 static int libc_setgid(gid_t gid)
544 uwrap_bind_symbol_libc(setgid);
546 return uwrap.libc.symbols._libc_setgid.f(gid);
549 static gid_t libc_getgid(void)
551 uwrap_bind_symbol_libc(getgid);
553 return uwrap.libc.symbols._libc_getgid.f();
557 static int libc_setegid(gid_t egid)
559 uwrap_bind_symbol_libc(setegid);
561 return uwrap.libc.symbols._libc_setegid.f(egid);
566 static int libc_setregid(gid_t rgid, gid_t egid)
568 uwrap_bind_symbol_libc(setregid);
570 return uwrap.libc.symbols._libc_setregid.f(rgid, egid);
574 #ifdef HAVE_SETRESGID
575 static int libc_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
577 uwrap_bind_symbol_libc(setresgid);
579 return uwrap.libc.symbols._libc_setresgid.f(rgid, egid, sgid);
583 #ifdef HAVE_GETRESGID
584 static int libc_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
586 uwrap_bind_symbol_libc(setresgid);
588 return uwrap.libc.symbols._libc_getresgid.f(rgid, egid, sgid);
592 static gid_t libc_getegid(void)
594 uwrap_bind_symbol_libc(getegid);
596 return uwrap.libc.symbols._libc_getegid.f();
599 static int libc_getgroups(int size, gid_t list[])
601 uwrap_bind_symbol_libc(getgroups);
603 return uwrap.libc.symbols._libc_getgroups.f(size, list);
606 static int libc_setgroups(size_t size, const gid_t *list)
608 uwrap_bind_symbol_libc(setgroups);
610 return uwrap.libc.symbols._libc_setgroups.f(size, list);
614 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
615 static long int libc_vsyscall(long int sysno, va_list va)
621 uwrap_bind_symbol_libc(syscall);
623 for (i = 0; i < 8; i++) {
624 args[i] = va_arg(va, long int);
627 rc = uwrap.libc.symbols._libc_syscall.f(sysno,
642 * This part is "optimistic".
643 * Thread can ends without pthread_exit call.
645 static void libpthread_pthread_exit(void *retval)
647 uwrap_bind_symbol_libpthread(pthread_exit);
649 uwrap.libpthread.symbols._libpthread_pthread_exit.f(retval);
652 static void uwrap_pthread_exit(void *retval)
654 struct uwrap_thread *id = uwrap_tls_id;
656 UWRAP_LOG(UWRAP_LOG_DEBUG, "Cleanup thread");
658 UWRAP_LOCK(uwrap_id);
660 UWRAP_UNLOCK(uwrap_id);
661 libpthread_pthread_exit(retval);
665 UWRAP_DLIST_REMOVE(uwrap.ids, id);
666 SAFE_FREE(id->groups);
670 UWRAP_UNLOCK(uwrap_id);
672 libpthread_pthread_exit(retval);
675 void pthread_exit(void *retval)
677 if (!uid_wrapper_enabled()) {
678 libpthread_pthread_exit(retval);
681 uwrap_pthread_exit(retval);
683 /* Calm down gcc warning. */
687 static int libpthread_pthread_create(pthread_t *thread,
688 const pthread_attr_t *attr,
689 void *(*start_routine) (void *),
692 uwrap_bind_symbol_libpthread(pthread_create);
693 return uwrap.libpthread.symbols._libpthread_pthread_create.f(thread,
699 struct uwrap_pthread_create_args {
700 struct uwrap_thread *id;
701 void *(*start_routine) (void *);
705 static void *uwrap_pthread_create_start(void *_a)
707 struct uwrap_pthread_create_args *a =
708 (struct uwrap_pthread_create_args *)_a;
709 void *(*start_routine) (void *) = a->start_routine;
711 struct uwrap_thread *id = a->id;
717 return start_routine(arg);
720 static int uwrap_pthread_create(pthread_t *thread,
721 const pthread_attr_t *attr,
722 void *(*start_routine) (void *),
725 struct uwrap_pthread_create_args *args;
726 struct uwrap_thread *src_id = uwrap_tls_id;
729 args = malloc(sizeof(struct uwrap_pthread_create_args));
731 UWRAP_LOG(UWRAP_LOG_ERROR,
732 "uwrap_pthread_create: Unable to allocate memory");
736 args->start_routine = start_routine;
739 args->id = calloc(1, sizeof(struct uwrap_thread));
740 if (args->id == NULL) {
742 UWRAP_LOG(UWRAP_LOG_ERROR,
743 "uwrap_pthread_create: Unable to allocate memory");
748 UWRAP_LOCK(uwrap_id);
750 args->id->groups = malloc(sizeof(gid_t) * src_id->ngroups);
751 if (args->id->groups == NULL) {
752 UWRAP_UNLOCK(uwrap_id);
755 UWRAP_LOG(UWRAP_LOG_ERROR,
756 "uwrap_pthread_create: Unable to allocate memory again");
761 args->id->ruid = src_id->ruid;
762 args->id->euid = src_id->euid;
763 args->id->suid = src_id->suid;
765 args->id->rgid = src_id->rgid;
766 args->id->egid = src_id->egid;
767 args->id->sgid = src_id->sgid;
769 args->id->enabled = src_id->enabled;
771 args->id->ngroups = src_id->ngroups;
772 if (src_id->groups != NULL) {
773 memcpy(args->id->groups, src_id->groups,
774 sizeof(gid_t) * src_id->ngroups);
776 SAFE_FREE(args->id->groups);
779 UWRAP_DLIST_ADD(uwrap.ids, args->id);
780 UWRAP_UNLOCK(uwrap_id);
782 ret = libpthread_pthread_create(thread, attr,
783 uwrap_pthread_create_start,
792 int pthread_create(pthread_t *thread,
793 const pthread_attr_t *attr,
794 void *(*start_routine) (void *),
797 if (!uid_wrapper_enabled()) {
798 return libpthread_pthread_create(thread,
804 return uwrap_pthread_create(thread,
810 /*********************************************************
812 *********************************************************/
814 #define GROUP_STRING_SIZE 16384
815 #define GROUP_MAX_COUNT (GROUP_STRING_SIZE / (10 + 1))
818 * This function exports all the IDs of the current user so if
819 * we fork and then exec we can setup uid_wrapper in the new process
822 static void uwrap_export_ids(struct uwrap_thread *id)
824 char groups_str[GROUP_STRING_SIZE] = {0};
825 size_t groups_str_size = sizeof(groups_str);
826 char unsigned_str[32] = {0};
830 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->ruid);
831 setenv("UID_WRAPPER_INITIAL_RUID", unsigned_str, 1);
833 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->euid);
834 setenv("UID_WRAPPER_INITIAL_EUID", unsigned_str, 1);
836 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->suid);
837 setenv("UID_WRAPPER_INITIAL_SUID", unsigned_str, 1);
840 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->rgid);
841 setenv("UID_WRAPPER_INITIAL_RGID", unsigned_str, 1);
843 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->egid);
844 setenv("UID_WRAPPER_INITIAL_EGID", unsigned_str, 1);
846 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->sgid);
847 setenv("UID_WRAPPER_INITIAL_SGID", unsigned_str, 1);
849 if (id->ngroups > GROUP_MAX_COUNT) {
850 UWRAP_LOG(UWRAP_LOG_ERROR,
851 "ERROR: Number of groups (%u) exceeds maximum value "
852 "uid_wrapper will handle (%u).",
859 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->ngroups);
860 setenv("UID_WRAPPER_INITIAL_GROUPS_COUNT", unsigned_str, 1);
862 for (i = 0; i < id->ngroups; i++) {
863 size_t groups_str_len = strlen(groups_str);
864 size_t groups_str_avail = groups_str_size - groups_str_len;
867 len = snprintf(unsigned_str, sizeof(unsigned_str), ",%u", id->groups[i]);
871 if (len < groups_str_avail) {
872 snprintf(groups_str + groups_str_len,
873 groups_str_size - groups_str_len,
875 i == 0 ? unsigned_str + 1 : unsigned_str);
879 if (id->ngroups > 0) {
880 setenv("UID_WRAPPER_INITIAL_GROUPS", groups_str, 1);
884 static void uwrap_thread_prepare(void)
886 struct uwrap_thread *id = uwrap_tls_id;
888 /* uid_wrapper is loaded but not enabled */
896 * What happens if another atfork prepare functions calls a uwrap
897 * function? So disable it in case another atfork prepare function
898 * calls a (s)uid function. We disable uid_wrapper only for thread
899 * (process) which called fork.
904 static void uwrap_thread_parent(void)
906 struct uwrap_thread *id = uwrap_tls_id;
908 /* uid_wrapper is loaded but not enabled */
918 static void uwrap_thread_child(void)
920 struct uwrap_thread *id = uwrap_tls_id;
921 struct uwrap_thread *u = uwrap.ids;
923 /* uid_wrapper is loaded but not enabled */
928 uwrap_export_ids(id);
931 * "Garbage collector" - Inspired by DESTRUCTOR.
932 * All threads (except one which called fork()) are dead now.. Dave
933 * That's what posix said...
937 /* Skip this item. */
942 UWRAP_DLIST_REMOVE(uwrap.ids, u);
944 SAFE_FREE(u->groups);
956 * This initializes uid_wrapper with the IDs exported to the environment. Those
957 * are normally set after we forked and executed.
959 static void uwrap_init_env(struct uwrap_thread *id)
964 env = getenv("UID_WRAPPER_INITIAL_RUID");
965 if (env != NULL && env[0] != '\0') {
966 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initialize ruid with %s", env);
967 id->ruid = strtoul(env, (char **)NULL, 10);
968 unsetenv("UID_WRAPPER_INITIAL_RUID");
971 env = getenv("UID_WRAPPER_INITIAL_EUID");
972 if (env != NULL && env[0] != '\0') {
973 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize euid with %s", env);
974 id->euid = strtoul(env, (char **)NULL, 10);
975 unsetenv("UID_WRAPPER_INITIAL_EUID");
978 env = getenv("UID_WRAPPER_INITIAL_SUID");
979 if (env != NULL && env[0] != '\0') {
980 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize suid with %s", env);
981 id->suid = strtoul(env, (char **)NULL, 10);
982 unsetenv("UID_WRAPPER_INITIAL_SUID");
985 env = getenv("UID_WRAPPER_INITIAL_RGID");
986 if (env != NULL && env[0] != '\0') {
987 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initialize ruid with %s", env);
988 id->rgid = strtoul(env, (char **)NULL, 10);
989 unsetenv("UID_WRAPPER_INITIAL_RGID");
992 env = getenv("UID_WRAPPER_INITIAL_EGID");
993 if (env != NULL && env[0] != '\0') {
994 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize egid with %s", env);
995 id->egid = strtoul(env, (char **)NULL, 10);
996 unsetenv("UID_WRAPPER_INITIAL_EGID");
999 env = getenv("UID_WRAPPER_INITIAL_SGID");
1000 if (env != NULL && env[0] != '\0') {
1001 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize sgid with %s", env);
1002 id->sgid = strtoul(env, (char **)NULL, 10);
1003 unsetenv("UID_WRAPPER_INITIAL_SGID");
1006 env = getenv("UID_WRAPPER_INITIAL_GROUPS_COUNT");
1007 if (env != NULL && env[0] != '\0') {
1008 ngroups = strtol(env, (char **)NULL, 10);
1009 unsetenv("UID_WRAPPER_INITIAL_GROUPS_COUNT");
1012 if (ngroups > 0 && ngroups < GROUP_MAX_COUNT) {
1018 id->groups = malloc(sizeof(gid_t) * ngroups);
1019 if (id->groups == NULL) {
1020 UWRAP_LOG(UWRAP_LOG_ERROR,
1021 "Unable to allocate memory");
1025 env = getenv("UID_WRAPPER_INITIAL_GROUPS");
1026 if (env != NULL && env[0] != '\0') {
1027 char *groups_str = NULL;
1028 char *saveptr = NULL;
1029 const char *p = NULL;
1031 groups_str = strdup(env);
1032 if (groups_str == NULL) {
1036 p = strtok_r(groups_str, ",", &saveptr);
1038 id->groups[i] = strtol(p, (char **)NULL, 10);
1041 p = strtok_r(NULL, ",", &saveptr);
1043 SAFE_FREE(groups_str);
1047 UWRAP_LOG(UWRAP_LOG_ERROR,
1048 "ERROR: The number of groups (%u) passed, "
1049 "does not the number of groups (%u) we "
1056 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize groups with %s", env);
1057 id->ngroups = ngroups;
1061 static void uwrap_init(void)
1065 UWRAP_LOCK(uwrap_id);
1067 if (uwrap.initialised) {
1068 struct uwrap_thread *id = uwrap_tls_id;
1070 if (uwrap.ids == NULL) {
1071 UWRAP_UNLOCK(uwrap_id);
1076 UWRAP_LOG(UWRAP_LOG_ERROR,
1077 "Invalid id for thread");
1081 UWRAP_UNLOCK(uwrap_id);
1085 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initialize uid_wrapper");
1087 uwrap.initialised = true;
1089 env = getenv("UID_WRAPPER");
1090 if (env != NULL && env[0] == '1') {
1091 const char *root = getenv("UID_WRAPPER_ROOT");
1092 struct uwrap_thread *id;
1094 id = calloc(1, sizeof(struct uwrap_thread));
1096 UWRAP_LOG(UWRAP_LOG_ERROR,
1097 "Unable to allocate memory for main id");
1101 UWRAP_DLIST_ADD(uwrap.ids, id);
1104 uwrap.myuid = libc_geteuid();
1105 uwrap.mygid = libc_getegid();
1107 /* put us in one group */
1108 if (root != NULL && root[0] == '1') {
1109 id->ruid = id->euid = id->suid = 0;
1110 id->rgid = id->egid = id->sgid = 0;
1112 id->groups = malloc(sizeof(gid_t) * 1);
1113 if (id->groups == NULL) {
1114 UWRAP_LOG(UWRAP_LOG_ERROR,
1115 "Unable to allocate memory");
1123 id->ruid = id->euid = id->suid = uwrap.myuid;
1124 id->rgid = id->egid = id->sgid = uwrap.mygid;
1126 id->ngroups = libc_getgroups(0, NULL);
1127 if (id->ngroups == -1) {
1128 UWRAP_LOG(UWRAP_LOG_ERROR,
1129 "Unable to call libc_getgroups in uwrap_init.");
1132 id->groups = malloc(sizeof(gid_t) * id->ngroups);
1133 if (id->groups == NULL) {
1134 UWRAP_LOG(UWRAP_LOG_ERROR, "Unable to allocate memory");
1137 if (libc_getgroups(id->ngroups, id->groups) == -1) {
1138 UWRAP_LOG(UWRAP_LOG_ERROR,
1139 "Unable to call libc_getgroups again in uwrap_init.");
1142 * Deallocation of uwrap.groups is handled by
1143 * library destructor.
1153 UWRAP_LOG(UWRAP_LOG_DEBUG,
1154 "Enabled uid_wrapper as %s (real uid=%u)",
1155 id->ruid == 0 ? "root" : "user",
1156 (unsigned int)uwrap.myuid);
1159 UWRAP_UNLOCK(uwrap_id);
1161 UWRAP_LOG(UWRAP_LOG_DEBUG, "Succeccfully initialized uid_wrapper");
1164 bool uid_wrapper_enabled(void)
1166 struct uwrap_thread *id = uwrap_tls_id;
1173 UWRAP_LOCK(uwrap_id);
1174 enabled = id->enabled;
1175 UWRAP_UNLOCK(uwrap_id);
1181 * UWRAP_SETxUID FUNCTIONS
1184 static int uwrap_setresuid_args(uid_t ruid, uid_t euid, uid_t suid)
1186 struct uwrap_thread *id = uwrap_tls_id;
1188 UWRAP_LOG(UWRAP_LOG_TRACE,
1189 "ruid %d -> %d, euid %d -> %d, suid %d -> %d",
1190 id->ruid, ruid, id->euid, euid, id->suid, suid);
1192 if (id->euid != 0) {
1193 if (ruid != (uid_t)-1 &&
1200 if (euid != (uid_t)-1 &&
1207 if (suid != (uid_t)-1 &&
1219 static int uwrap_setresuid_thread(uid_t ruid, uid_t euid, uid_t suid)
1221 struct uwrap_thread *id = uwrap_tls_id;
1224 UWRAP_LOG(UWRAP_LOG_TRACE,
1225 "ruid %d -> %d, euid %d -> %d, suid %d -> %d",
1226 id->ruid, ruid, id->euid, euid, id->suid, suid);
1228 rc = uwrap_setresuid_args(ruid, euid, suid);
1233 UWRAP_LOCK(uwrap_id);
1235 if (ruid != (uid_t)-1) {
1239 if (euid != (uid_t)-1) {
1243 if (suid != (uid_t)-1) {
1247 UWRAP_UNLOCK(uwrap_id);
1252 static int uwrap_setresuid(uid_t ruid, uid_t euid, uid_t suid)
1254 struct uwrap_thread *id = uwrap_tls_id;
1257 UWRAP_LOG(UWRAP_LOG_TRACE,
1258 "ruid %d -> %d, euid %d -> %d, suid %d -> %d",
1259 id->ruid, ruid, id->euid, euid, id->suid, suid);
1261 rc = uwrap_setresuid_args(ruid, euid, suid);
1266 UWRAP_LOCK(uwrap_id);
1268 for (id = uwrap.ids; id; id = id->next) {
1269 if (ruid != (uid_t)-1) {
1273 if (euid != (uid_t)-1) {
1277 if (suid != (uid_t)-1) {
1282 UWRAP_UNLOCK(uwrap_id);
1287 static int uwrap_setreuid_args(uid_t ruid, uid_t euid,
1292 struct uwrap_thread *id = uwrap_tls_id;
1293 uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
1295 UWRAP_LOG(UWRAP_LOG_TRACE,
1296 "ruid %d -> %d, euid %d -> %d",
1297 id->ruid, ruid, id->euid, euid);
1299 if (ruid != (uid_t)-1) {
1301 if (ruid != id->ruid &&
1309 if (euid != (uid_t)-1) {
1311 if (euid != id->ruid &&
1320 if (ruid != (uid_t) -1 ||
1321 (euid != (uid_t)-1 && id->ruid != euid)) {
1322 new_suid = new_euid;
1325 *_new_ruid = new_ruid;
1326 *_new_euid = new_euid;
1327 *_new_suid = new_suid;
1332 static int uwrap_setreuid_thread(uid_t ruid, uid_t euid)
1335 struct uwrap_thread *id = uwrap_tls_id;
1337 uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
1340 UWRAP_LOG(UWRAP_LOG_TRACE,
1341 "ruid %d -> %d, euid %d -> %d",
1342 id->ruid, ruid, id->euid, euid);
1344 rc = uwrap_setreuid_args(ruid, euid, &new_ruid, &new_euid, &new_suid);
1349 return uwrap_setresuid_thread(new_ruid, new_euid, new_suid);
1352 #ifdef HAVE_SETREUID
1353 static int uwrap_setreuid(uid_t ruid, uid_t euid)
1356 struct uwrap_thread *id = uwrap_tls_id;
1358 uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
1361 UWRAP_LOG(UWRAP_LOG_TRACE,
1362 "ruid %d -> %d, euid %d -> %d",
1363 id->ruid, ruid, id->euid, euid);
1365 rc = uwrap_setreuid_args(ruid, euid, &new_ruid, &new_euid, &new_suid);
1370 return uwrap_setresuid(new_ruid, new_euid, new_suid);
1374 static int uwrap_setuid_args(uid_t uid,
1379 struct uwrap_thread *id = uwrap_tls_id;
1381 UWRAP_LOG(UWRAP_LOG_TRACE,
1385 if (uid == (uid_t)-1) {
1390 if (id->euid == 0) {
1391 *new_suid = *new_ruid = uid;
1392 } else if (uid != id->ruid &&
1403 static int uwrap_setuid_thread(uid_t uid)
1405 uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
1408 rc = uwrap_setuid_args(uid, &new_ruid, &new_euid, &new_suid);
1413 return uwrap_setresuid_thread(new_ruid, new_euid, new_suid);
1416 static int uwrap_setuid(uid_t uid)
1418 uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
1421 rc = uwrap_setuid_args(uid, &new_ruid, &new_euid, &new_suid);
1426 return uwrap_setresuid(new_ruid, new_euid, new_suid);
1430 * UWRAP_GETxUID FUNCTIONS
1433 #ifdef HAVE_GETRESUID
1434 static int uwrap_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
1436 struct uwrap_thread *id = uwrap_tls_id;
1438 UWRAP_LOCK(uwrap_id);
1444 UWRAP_UNLOCK(uwrap_id);
1450 #ifdef HAVE_GETRESGID
1451 static int uwrap_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
1453 struct uwrap_thread *id = uwrap_tls_id;
1455 UWRAP_LOCK(uwrap_id);
1461 UWRAP_UNLOCK(uwrap_id);
1468 * UWRAP_SETxGID FUNCTIONS
1471 static int uwrap_setresgid_args(gid_t rgid, gid_t egid, gid_t sgid)
1473 struct uwrap_thread *id = uwrap_tls_id;
1475 UWRAP_LOG(UWRAP_LOG_TRACE,
1476 "rgid %d -> %d, egid %d -> %d, sgid %d -> %d",
1477 id->rgid, rgid, id->egid, egid, id->sgid, sgid);
1479 if (id->euid != 0) {
1480 if (rgid != (gid_t)-1 &&
1487 if (egid != (gid_t)-1 &&
1494 if (sgid != (gid_t)-1 &&
1506 static int uwrap_setresgid_thread(gid_t rgid, gid_t egid, gid_t sgid)
1508 struct uwrap_thread *id = uwrap_tls_id;
1511 UWRAP_LOG(UWRAP_LOG_TRACE,
1512 "rgid %d -> %d, egid %d -> %d, sgid %d -> %d",
1513 id->rgid, rgid, id->egid, egid, id->sgid, sgid);
1515 rc = uwrap_setresgid_args(rgid, egid, sgid);
1520 UWRAP_LOCK(uwrap_id);
1522 if (rgid != (gid_t)-1) {
1526 if (egid != (gid_t)-1) {
1530 if (sgid != (gid_t)-1) {
1534 UWRAP_UNLOCK(uwrap_id);
1539 static int uwrap_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
1541 struct uwrap_thread *id = uwrap_tls_id;
1544 UWRAP_LOG(UWRAP_LOG_TRACE,
1545 "rgid %d -> %d, egid %d -> %d, sgid %d -> %d",
1546 id->rgid, rgid, id->egid, egid, id->sgid, sgid);
1548 rc = uwrap_setresgid_args(rgid, egid, sgid);
1553 UWRAP_LOCK(uwrap_id);
1555 for (id = uwrap.ids; id; id = id->next) {
1556 if (rgid != (gid_t)-1) {
1560 if (egid != (gid_t)-1) {
1564 if (sgid != (gid_t)-1) {
1569 UWRAP_UNLOCK(uwrap_id);
1574 static int uwrap_setregid_args(gid_t rgid, gid_t egid,
1579 struct uwrap_thread *id = uwrap_tls_id;
1580 gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
1582 UWRAP_LOG(UWRAP_LOG_TRACE,
1583 "rgid %d -> %d, egid %d -> %d",
1584 id->rgid, rgid, id->egid, egid);
1586 if (rgid != (gid_t)-1) {
1588 if (rgid != id->rgid &&
1596 if (egid != (gid_t)-1) {
1598 if (egid != id->rgid &&
1607 if (rgid != (gid_t) -1 ||
1608 (egid != (gid_t)-1 && id->rgid != egid)) {
1609 new_sgid = new_egid;
1612 *_new_rgid = new_rgid;
1613 *_new_egid = new_egid;
1614 *_new_sgid = new_sgid;
1619 static int uwrap_setregid_thread(gid_t rgid, gid_t egid)
1622 struct uwrap_thread *id = uwrap_tls_id;
1624 gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
1627 UWRAP_LOG(UWRAP_LOG_TRACE,
1628 "rgid %d -> %d, egid %d -> %d",
1629 id->rgid, rgid, id->egid, egid);
1631 rc = uwrap_setregid_args(rgid, egid, &new_rgid, &new_egid, &new_sgid);
1636 return uwrap_setresgid_thread(new_rgid, new_egid, new_sgid);
1639 #ifdef HAVE_SETREGID
1640 static int uwrap_setregid(gid_t rgid, gid_t egid)
1643 struct uwrap_thread *id = uwrap_tls_id;
1645 gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
1648 UWRAP_LOG(UWRAP_LOG_TRACE,
1649 "rgid %d -> %d, egid %d -> %d",
1650 id->rgid, rgid, id->egid, egid);
1652 rc = uwrap_setregid_args(rgid, egid, &new_rgid, &new_egid, &new_sgid);
1657 return uwrap_setresgid(new_rgid, new_egid, new_sgid);
1661 static int uwrap_setgid_args(gid_t gid,
1666 struct uwrap_thread *id = uwrap_tls_id;
1668 UWRAP_LOG(UWRAP_LOG_TRACE,
1672 if (gid == (gid_t)-1) {
1677 if (id->euid == 0) {
1678 *new_sgid = *new_rgid = gid;
1679 } else if (gid != id->rgid &&
1690 static int uwrap_setgid_thread(gid_t gid)
1692 gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
1695 rc = uwrap_setgid_args(gid, &new_rgid, &new_egid, &new_sgid);
1700 return uwrap_setresgid_thread(new_rgid, new_egid, new_sgid);
1703 static int uwrap_setgid(gid_t gid)
1705 gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
1708 rc = uwrap_setgid_args(gid, &new_rgid, &new_egid, &new_sgid);
1713 return uwrap_setresgid(new_rgid, new_egid, new_sgid);
1719 int setuid(uid_t uid)
1721 if (!uid_wrapper_enabled()) {
1722 return libc_setuid(uid);
1726 return uwrap_setuid(uid);
1730 int seteuid(uid_t euid)
1732 if (!uid_wrapper_enabled()) {
1733 return libc_seteuid(euid);
1736 /* On FreeBSD the uid_t -1 is set and doesn't produce and error */
1737 if (euid == (uid_t)-1) {
1743 return uwrap_setresuid(-1, euid, -1);
1747 #ifdef HAVE_SETREUID
1748 int setreuid(uid_t ruid, uid_t euid)
1750 if (!uid_wrapper_enabled()) {
1751 return libc_setreuid(ruid, euid);
1755 return uwrap_setreuid(ruid, euid);
1759 #ifdef HAVE_SETRESUID
1760 int setresuid(uid_t ruid, uid_t euid, uid_t suid)
1762 if (!uid_wrapper_enabled()) {
1763 return libc_setresuid(ruid, euid, suid);
1767 return uwrap_setresuid(ruid, euid, suid);
1771 #ifdef HAVE_GETRESUID
1772 int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
1774 if (!uid_wrapper_enabled()) {
1775 return libc_getresuid(ruid, euid, suid);
1779 return uwrap_getresuid(ruid, euid, suid);
1786 static uid_t uwrap_getuid(void)
1788 struct uwrap_thread *id = uwrap_tls_id;
1791 UWRAP_LOCK(uwrap_id);
1793 UWRAP_UNLOCK(uwrap_id);
1800 if (!uid_wrapper_enabled()) {
1801 return libc_getuid();
1805 return uwrap_getuid();
1811 static uid_t uwrap_geteuid(void)
1813 const char *env = getenv("UID_WRAPPER_MYUID");
1814 struct uwrap_thread *id = uwrap_tls_id;
1817 UWRAP_LOCK(uwrap_id);
1819 UWRAP_UNLOCK(uwrap_id);
1821 /* Disable root and return myuid */
1822 if (env != NULL && env[0] == '1') {
1831 if (!uid_wrapper_enabled()) {
1832 return libc_geteuid();
1836 return uwrap_geteuid();
1842 int setgid(gid_t gid)
1844 if (!uid_wrapper_enabled()) {
1845 return libc_setgid(gid);
1849 return uwrap_setgid(gid);
1853 int setegid(gid_t egid)
1855 if (!uid_wrapper_enabled()) {
1856 return libc_setegid(egid);
1859 /* On FreeBSD the uid_t -1 is set and doesn't produce and error */
1860 if (egid == (gid_t)-1) {
1866 return uwrap_setresgid(-1, egid, -1);
1870 #ifdef HAVE_SETREGID
1871 int setregid(gid_t rgid, gid_t egid)
1873 if (!uid_wrapper_enabled()) {
1874 return libc_setregid(rgid, egid);
1878 return uwrap_setregid(rgid, egid);
1882 #ifdef HAVE_SETRESGID
1883 int setresgid(gid_t rgid, gid_t egid, gid_t sgid)
1885 if (!uid_wrapper_enabled()) {
1886 return libc_setresgid(rgid, egid, sgid);
1890 return uwrap_setresgid(rgid, egid, sgid);
1894 #ifdef HAVE_GETRESGID
1895 int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
1897 if (!uid_wrapper_enabled()) {
1898 return libc_getresgid(rgid, egid, sgid);
1902 return uwrap_getresgid(rgid, egid, sgid);
1909 static gid_t uwrap_getgid(void)
1911 struct uwrap_thread *id = uwrap_tls_id;
1914 UWRAP_LOCK(uwrap_id);
1916 UWRAP_UNLOCK(uwrap_id);
1923 if (!uid_wrapper_enabled()) {
1924 return libc_getgid();
1928 return uwrap_getgid();
1934 static uid_t uwrap_getegid(void)
1936 struct uwrap_thread *id = uwrap_tls_id;
1939 UWRAP_LOCK(uwrap_id);
1941 UWRAP_UNLOCK(uwrap_id);
1948 if (!uid_wrapper_enabled()) {
1949 return libc_getegid();
1953 return uwrap_getegid();
1956 static int uwrap_setgroups_thread(size_t size, const gid_t *list)
1958 struct uwrap_thread *id = uwrap_tls_id;
1961 UWRAP_LOCK(uwrap_id);
1964 SAFE_FREE(id->groups);
1966 } else if (size > 0) {
1969 tmp = realloc(id->groups, sizeof(gid_t) * size);
1976 memcpy(id->groups, list, size * sizeof(gid_t));
1981 UWRAP_UNLOCK(uwrap_id);
1986 static int uwrap_setgroups(size_t size, const gid_t *list)
1988 struct uwrap_thread *id;
1991 UWRAP_LOCK(uwrap_id);
1994 for (id = uwrap.ids; id; id = id->next) {
1995 SAFE_FREE(id->groups);
1999 } else if (size > 0) {
2002 for (id = uwrap.ids; id; id = id->next) {
2003 tmp = realloc(id->groups, sizeof(gid_t) * size);
2011 memcpy(id->groups, list, size * sizeof(gid_t));
2017 UWRAP_UNLOCK(uwrap_id);
2022 #ifdef HAVE_SETGROUPS_INT
2023 int setgroups(int size, const gid_t *list)
2025 int setgroups(size_t size, const gid_t *list)
2028 if (!uid_wrapper_enabled()) {
2029 return libc_setgroups(size, list);
2033 return uwrap_setgroups(size, list);
2036 static int uwrap_getgroups(int size, gid_t *list)
2038 struct uwrap_thread *id = uwrap_tls_id;
2041 UWRAP_LOCK(uwrap_id);
2042 ngroups = id->ngroups;
2044 if (size > ngroups) {
2050 if (size < ngroups) {
2054 memcpy(list, id->groups, size * sizeof(gid_t));
2057 UWRAP_UNLOCK(uwrap_id);
2062 int getgroups(int size, gid_t *list)
2064 if (!uid_wrapper_enabled()) {
2065 return libc_getgroups(size, list);
2069 return uwrap_getgroups(size, list);
2072 #if (defined(HAVE_SYS_SYSCALL_H) || defined(HAVE_SYSCALL_H)) \
2073 && (defined(SYS_setreuid) || defined(SYS_setreuid32))
2074 static long int uwrap_syscall (long int sysno, va_list vp)
2085 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2089 rc = uwrap_getgid();
2094 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2098 rc = uwrap_getegid();
2101 #endif /* SYS_getegid */
2103 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2107 gid_t gid = (gid_t) va_arg(vp, gid_t);
2109 rc = uwrap_setgid_thread(gid);
2113 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2114 case SYS_setregid32:
2117 gid_t rgid = (gid_t) va_arg(vp, gid_t);
2118 gid_t egid = (gid_t) va_arg(vp, gid_t);
2120 rc = uwrap_setregid_thread(rgid, egid);
2123 #ifdef SYS_setresgid
2125 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2126 case SYS_setresgid32:
2129 gid_t rgid = (gid_t) va_arg(vp, gid_t);
2130 gid_t egid = (gid_t) va_arg(vp, gid_t);
2131 gid_t sgid = (gid_t) va_arg(vp, gid_t);
2133 rc = uwrap_setresgid_thread(rgid, egid, sgid);
2136 #endif /* SYS_setresgid */
2137 #if defined(SYS_getresgid) && defined(HAVE_GETRESGID)
2139 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2140 case SYS_getresgid32:
2143 gid_t *rgid = (gid_t *) va_arg(vp, gid_t *);
2144 gid_t *egid = (gid_t *) va_arg(vp, gid_t *);
2145 gid_t *sgid = (gid_t *) va_arg(vp, gid_t *);
2147 rc = uwrap_getresgid(rgid, egid, sgid);
2150 #endif /* SYS_getresgid && HAVE_GETRESGID */
2158 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2162 rc = uwrap_getuid();
2167 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2171 rc = uwrap_geteuid();
2174 #endif /* SYS_geteuid */
2176 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2180 uid_t uid = (uid_t) va_arg(vp, uid_t);
2182 rc = uwrap_setuid_thread(uid);
2186 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2187 case SYS_setreuid32:
2190 uid_t ruid = (uid_t) va_arg(vp, uid_t);
2191 uid_t euid = (uid_t) va_arg(vp, uid_t);
2193 rc = uwrap_setreuid_thread(ruid, euid);
2196 #ifdef SYS_setresuid
2198 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2199 case SYS_setresuid32:
2202 uid_t ruid = (uid_t) va_arg(vp, uid_t);
2203 uid_t euid = (uid_t) va_arg(vp, uid_t);
2204 uid_t suid = (uid_t) va_arg(vp, uid_t);
2206 rc = uwrap_setresuid_thread(ruid, euid, suid);
2209 #endif /* SYS_setresuid */
2210 #if defined(SYS_getresuid) && defined(HAVE_GETRESUID)
2212 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2213 case SYS_getresuid32:
2216 uid_t *ruid = (uid_t *) va_arg(vp, uid_t *);
2217 uid_t *euid = (uid_t *) va_arg(vp, uid_t *);
2218 uid_t *suid = (uid_t *) va_arg(vp, uid_t *);
2220 rc = uwrap_getresuid(ruid, euid, suid);
2223 #endif /* SYS_getresuid && HAVE_GETRESUID*/
2226 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2227 case SYS_setgroups32:
2230 size_t size = (size_t) va_arg(vp, size_t);
2231 gid_t *list = (gid_t *) va_arg(vp, int *);
2233 rc = uwrap_setgroups_thread(size, list);
2237 UWRAP_LOG(UWRAP_LOG_DEBUG,
2238 "UID_WRAPPER calling non-wrapped syscall %lu",
2241 rc = libc_vsyscall(sysno, vp);
2249 #ifdef HAVE_SYSCALL_INT
2250 int syscall (int sysno, ...)
2252 long int syscall (long int sysno, ...)
2255 #ifdef HAVE_SYSCALL_INT
2262 va_start(va, sysno);
2264 if (!uid_wrapper_enabled()) {
2265 rc = libc_vsyscall(sysno, va);
2271 rc = uwrap_syscall(sysno, va);
2276 #endif /* HAVE_SYSCALL */
2277 #endif /* HAVE_SYS_SYSCALL_H || HAVE_SYSCALL_H */
2279 /****************************
2281 ***************************/
2282 void uwrap_constructor(void)
2285 * If we hold a lock and the application forks, then the child
2286 * is not able to unlock the mutex and we are in a deadlock.
2287 * This should prevent such deadlocks.
2289 pthread_atfork(&uwrap_thread_prepare,
2290 &uwrap_thread_parent,
2291 &uwrap_thread_child);
2293 /* Here is safe place to call uwrap_init() and initialize data
2299 /****************************
2301 ***************************/
2304 * This function is called when the library is unloaded and makes sure that
2305 * resources are freed.
2307 void uwrap_destructor(void)
2309 struct uwrap_thread *u = uwrap.ids;
2314 UWRAP_DLIST_REMOVE(uwrap.ids, u);
2316 SAFE_FREE(u->groups);
2323 if (uwrap.libc.handle != NULL) {
2324 dlclose(uwrap.libc.handle);
2327 if (uwrap.libpthread.handle != NULL) {
2328 dlclose(uwrap.libpthread.handle);