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 {
137 # define UWRAP_LOG(...)
139 static void uwrap_log(enum uwrap_dbglvl_e dbglvl, const char *function, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
140 # define UWRAP_LOG(dbglvl, ...) uwrap_log((dbglvl), __func__, __VA_ARGS__)
142 static void uwrap_log(enum uwrap_dbglvl_e dbglvl, const char *function, const char *format, ...)
147 unsigned int lvl = 0;
149 d = getenv("UID_WRAPPER_DEBUGLEVEL");
154 va_start(va, format);
155 vsnprintf(buffer, sizeof(buffer), format, va);
159 const char *prefix = "UWRAP";
161 case UWRAP_LOG_ERROR:
162 prefix = "UWRAP_ERROR";
165 prefix = "UWRAP_WARN";
167 case UWRAP_LOG_DEBUG:
168 prefix = "UWRAP_DEBUG";
170 case UWRAP_LOG_TRACE:
171 prefix = "UWRAP_TRACE";
189 #define LIBC_NAME "libc.so"
191 typedef int (*__libc_setuid)(uid_t uid);
193 typedef uid_t (*__libc_getuid)(void);
196 typedef int (*__libc_seteuid)(uid_t euid);
200 typedef int (*__libc_setreuid)(uid_t ruid, uid_t euid);
203 #ifdef HAVE_SETRESUID
204 typedef int (*__libc_setresuid)(uid_t ruid, uid_t euid, uid_t suid);
207 #ifdef HAVE_GETRESUID
208 typedef int (*__libc_getresuid)(uid_t *ruid, uid_t *euid, uid_t *suid);
211 typedef uid_t (*__libc_geteuid)(void);
213 typedef int (*__libc_setgid)(gid_t gid);
215 typedef gid_t (*__libc_getgid)(void);
218 typedef int (*__libc_setegid)(uid_t egid);
222 typedef int (*__libc_setregid)(uid_t rgid, uid_t egid);
225 #ifdef HAVE_SETRESGID
226 typedef int (*__libc_setresgid)(uid_t rgid, uid_t egid, uid_t sgid);
229 #ifdef HAVE_GETRESGID
230 typedef int (*__libc_getresgid)(gid_t *rgid, gid_t *egid, gid_t *sgid);
233 typedef gid_t (*__libc_getegid)(void);
235 typedef int (*__libc_getgroups)(int size, gid_t list[]);
237 typedef int (*__libc_setgroups)(size_t size, const gid_t *list);
240 typedef long int (*__libc_syscall)(long int sysno, ...);
243 #define UWRAP_SYMBOL_ENTRY(i) \
249 struct uwrap_libc_symbols {
250 UWRAP_SYMBOL_ENTRY(setuid);
251 UWRAP_SYMBOL_ENTRY(getuid);
253 UWRAP_SYMBOL_ENTRY(seteuid);
256 UWRAP_SYMBOL_ENTRY(setreuid);
258 #ifdef HAVE_SETRESUID
259 UWRAP_SYMBOL_ENTRY(setresuid);
261 #ifdef HAVE_GETRESUID
262 UWRAP_SYMBOL_ENTRY(getresuid);
264 UWRAP_SYMBOL_ENTRY(geteuid);
265 UWRAP_SYMBOL_ENTRY(setgid);
266 UWRAP_SYMBOL_ENTRY(getgid);
268 UWRAP_SYMBOL_ENTRY(setegid);
271 UWRAP_SYMBOL_ENTRY(setregid);
273 #ifdef HAVE_SETRESGID
274 UWRAP_SYMBOL_ENTRY(setresgid);
276 #ifdef HAVE_GETRESGID
277 UWRAP_SYMBOL_ENTRY(getresgid);
279 UWRAP_SYMBOL_ENTRY(getegid);
280 UWRAP_SYMBOL_ENTRY(getgroups);
281 UWRAP_SYMBOL_ENTRY(setgroups);
283 UWRAP_SYMBOL_ENTRY(syscall);
286 #undef UWRAP_SYMBOL_ENTRY
291 /* Yeah... I'm pig. I overloading macro here... So what? */
292 #define UWRAP_SYMBOL_ENTRY(i) \
294 __libpthread_##i f; \
298 typedef int (*__libpthread_pthread_create)(pthread_t *thread,
299 const pthread_attr_t *attr,
300 void *(*start_routine) (void *),
302 typedef void (*__libpthread_pthread_exit)(void *retval);
304 struct uwrap_libpthread_symbols {
305 UWRAP_SYMBOL_ENTRY(pthread_create);
306 UWRAP_SYMBOL_ENTRY(pthread_exit);
308 #undef UWRAP_SYMBOL_ENTRY
311 * We keep the virtualised euid/egid/groups information here
313 struct uwrap_thread {
327 struct uwrap_thread *next;
328 struct uwrap_thread *prev;
334 struct uwrap_libc_symbols symbols;
339 struct uwrap_libpthread_symbols symbols;
344 /* Real uid and gid of user who run uid wrapper */
348 struct uwrap_thread *ids;
351 static struct uwrap uwrap;
353 /* Shortcut to the list item */
354 static UWRAP_THREAD struct uwrap_thread *uwrap_tls_id;
356 /* The mutex or accessing the id */
357 static pthread_mutex_t uwrap_id_mutex = PTHREAD_MUTEX_INITIALIZER;
359 /* The mutex for accessing the global libc.symbols */
360 static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
362 /* The mutex for accessing the global libpthread.symbols */
363 static pthread_mutex_t libpthread_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
365 /*********************************************************
367 *********************************************************/
369 bool uid_wrapper_enabled(void);
370 void uwrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
371 void uwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
373 /*********************************************************
374 * UWRAP LIBC LOADER FUNCTIONS
375 *********************************************************/
384 static void *uwrap_load_lib_handle(enum uwrap_lib lib)
386 int flags = RTLD_LAZY;
391 flags |= RTLD_DEEPBIND;
397 case UWRAP_LIBSOCKET:
400 handle = uwrap.libc.handle;
401 if (handle == NULL) {
402 for (i = 10; i >= 0; i--) {
403 char soname[256] = {0};
405 snprintf(soname, sizeof(soname), "libc.so.%d", i);
406 handle = dlopen(soname, flags);
407 if (handle != NULL) {
411 /* glibc on Alpha and IA64 is libc.so.6.1 */
412 snprintf(soname, sizeof(soname), "libc.so.%d.1", i);
413 handle = dlopen(soname, flags);
414 if (handle != NULL) {
419 uwrap.libc.handle = handle;
422 case UWRAP_LIBPTHREAD:
423 handle = uwrap.libpthread.handle;
424 if (handle == NULL) {
425 handle = dlopen("libpthread.so.0", flags);
426 if (handle != NULL) {
433 if (handle == NULL) {
435 handle = uwrap.libc.handle = RTLD_NEXT;
438 "Failed to dlopen library: %s\n",
447 static void *_uwrap_bind_symbol(enum uwrap_lib lib, const char *fn_name)
452 handle = uwrap_load_lib_handle(lib);
454 func = dlsym(handle, fn_name);
457 "Failed to find %s: %s\n",
465 #define uwrap_bind_symbol_libc(sym_name) \
466 UWRAP_LOCK(libc_symbol_binding); \
467 if (uwrap.libc.symbols._libc_##sym_name.obj == NULL) { \
468 uwrap.libc.symbols._libc_##sym_name.obj = \
469 _uwrap_bind_symbol(UWRAP_LIBC, #sym_name); \
471 UWRAP_UNLOCK(libc_symbol_binding)
473 #define uwrap_bind_symbol_libpthread(sym_name) \
474 UWRAP_LOCK(libpthread_symbol_binding); \
475 if (uwrap.libpthread.symbols._libpthread_##sym_name.obj == NULL) { \
476 uwrap.libpthread.symbols._libpthread_##sym_name.obj = \
477 _uwrap_bind_symbol(UWRAP_LIBPTHREAD, #sym_name); \
479 UWRAP_UNLOCK(libpthread_symbol_binding)
484 * Functions expeciall from libc need to be loaded individually, you can't load
485 * all at once or gdb will segfault at startup. The same applies to valgrind and
486 * has probably something todo with with the linker.
487 * So we need load each function at the point it is called the first time.
489 static int libc_setuid(uid_t uid)
491 uwrap_bind_symbol_libc(setuid);
493 return uwrap.libc.symbols._libc_setuid.f(uid);
496 static uid_t libc_getuid(void)
498 uwrap_bind_symbol_libc(getuid);
500 return uwrap.libc.symbols._libc_getuid.f();
504 static int libc_seteuid(uid_t euid)
506 uwrap_bind_symbol_libc(seteuid);
508 return uwrap.libc.symbols._libc_seteuid.f(euid);
513 static int libc_setreuid(uid_t ruid, uid_t euid)
515 uwrap_bind_symbol_libc(setreuid);
517 return uwrap.libc.symbols._libc_setreuid.f(ruid, euid);
521 #ifdef HAVE_SETRESUID
522 static int libc_setresuid(uid_t ruid, uid_t euid, uid_t suid)
524 uwrap_bind_symbol_libc(setresuid);
526 return uwrap.libc.symbols._libc_setresuid.f(ruid, euid, suid);
530 #ifdef HAVE_GETRESUID
531 static int libc_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
533 uwrap_bind_symbol_libc(getresuid);
535 return uwrap.libc.symbols._libc_getresuid.f(ruid, euid, suid);
539 static uid_t libc_geteuid(void)
541 uwrap_bind_symbol_libc(geteuid);
543 return uwrap.libc.symbols._libc_geteuid.f();
546 static int libc_setgid(gid_t gid)
548 uwrap_bind_symbol_libc(setgid);
550 return uwrap.libc.symbols._libc_setgid.f(gid);
553 static gid_t libc_getgid(void)
555 uwrap_bind_symbol_libc(getgid);
557 return uwrap.libc.symbols._libc_getgid.f();
561 static int libc_setegid(gid_t egid)
563 uwrap_bind_symbol_libc(setegid);
565 return uwrap.libc.symbols._libc_setegid.f(egid);
570 static int libc_setregid(gid_t rgid, gid_t egid)
572 uwrap_bind_symbol_libc(setregid);
574 return uwrap.libc.symbols._libc_setregid.f(rgid, egid);
578 #ifdef HAVE_SETRESGID
579 static int libc_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
581 uwrap_bind_symbol_libc(setresgid);
583 return uwrap.libc.symbols._libc_setresgid.f(rgid, egid, sgid);
587 #ifdef HAVE_GETRESGID
588 static int libc_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
590 uwrap_bind_symbol_libc(setresgid);
592 return uwrap.libc.symbols._libc_getresgid.f(rgid, egid, sgid);
596 static gid_t libc_getegid(void)
598 uwrap_bind_symbol_libc(getegid);
600 return uwrap.libc.symbols._libc_getegid.f();
603 static int libc_getgroups(int size, gid_t list[])
605 uwrap_bind_symbol_libc(getgroups);
607 return uwrap.libc.symbols._libc_getgroups.f(size, list);
610 static int libc_setgroups(size_t size, const gid_t *list)
612 uwrap_bind_symbol_libc(setgroups);
614 return uwrap.libc.symbols._libc_setgroups.f(size, list);
618 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
619 static long int libc_vsyscall(long int sysno, va_list va)
625 uwrap_bind_symbol_libc(syscall);
627 for (i = 0; i < 8; i++) {
628 args[i] = va_arg(va, long int);
631 rc = uwrap.libc.symbols._libc_syscall.f(sysno,
646 * This part is "optimistic".
647 * Thread can ends without pthread_exit call.
649 static void libpthread_pthread_exit(void *retval)
651 uwrap_bind_symbol_libpthread(pthread_exit);
653 uwrap.libpthread.symbols._libpthread_pthread_exit.f(retval);
656 static void uwrap_pthread_exit(void *retval)
658 struct uwrap_thread *id = uwrap_tls_id;
660 UWRAP_LOG(UWRAP_LOG_DEBUG, "Cleanup thread");
662 UWRAP_LOCK(uwrap_id);
664 UWRAP_UNLOCK(uwrap_id);
665 libpthread_pthread_exit(retval);
669 UWRAP_DLIST_REMOVE(uwrap.ids, id);
670 SAFE_FREE(id->groups);
674 UWRAP_UNLOCK(uwrap_id);
676 libpthread_pthread_exit(retval);
679 void pthread_exit(void *retval)
681 if (!uid_wrapper_enabled()) {
682 libpthread_pthread_exit(retval);
685 uwrap_pthread_exit(retval);
687 /* Calm down gcc warning. */
691 static int libpthread_pthread_create(pthread_t *thread,
692 const pthread_attr_t *attr,
693 void *(*start_routine) (void *),
696 uwrap_bind_symbol_libpthread(pthread_create);
697 return uwrap.libpthread.symbols._libpthread_pthread_create.f(thread,
703 struct uwrap_pthread_create_args {
704 struct uwrap_thread *id;
705 void *(*start_routine) (void *);
709 static void *uwrap_pthread_create_start(void *_a)
711 struct uwrap_pthread_create_args *a =
712 (struct uwrap_pthread_create_args *)_a;
713 void *(*start_routine) (void *) = a->start_routine;
715 struct uwrap_thread *id = a->id;
721 return start_routine(arg);
724 static int uwrap_pthread_create(pthread_t *thread,
725 const pthread_attr_t *attr,
726 void *(*start_routine) (void *),
729 struct uwrap_pthread_create_args *args;
730 struct uwrap_thread *src_id = uwrap_tls_id;
733 args = malloc(sizeof(struct uwrap_pthread_create_args));
735 UWRAP_LOG(UWRAP_LOG_ERROR,
736 "uwrap_pthread_create: Unable to allocate memory");
740 args->start_routine = start_routine;
743 args->id = calloc(1, sizeof(struct uwrap_thread));
744 if (args->id == NULL) {
746 UWRAP_LOG(UWRAP_LOG_ERROR,
747 "uwrap_pthread_create: Unable to allocate memory");
752 UWRAP_LOCK(uwrap_id);
754 args->id->groups = malloc(sizeof(gid_t) * src_id->ngroups);
755 if (args->id->groups == NULL) {
756 UWRAP_UNLOCK(uwrap_id);
759 UWRAP_LOG(UWRAP_LOG_ERROR,
760 "uwrap_pthread_create: Unable to allocate memory again");
765 args->id->ruid = src_id->ruid;
766 args->id->euid = src_id->euid;
767 args->id->suid = src_id->suid;
769 args->id->rgid = src_id->rgid;
770 args->id->egid = src_id->egid;
771 args->id->sgid = src_id->sgid;
773 args->id->enabled = src_id->enabled;
775 args->id->ngroups = src_id->ngroups;
776 if (src_id->groups != NULL) {
777 memcpy(args->id->groups, src_id->groups,
778 sizeof(gid_t) * src_id->ngroups);
780 SAFE_FREE(args->id->groups);
783 UWRAP_DLIST_ADD(uwrap.ids, args->id);
784 UWRAP_UNLOCK(uwrap_id);
786 ret = libpthread_pthread_create(thread, attr,
787 uwrap_pthread_create_start,
796 int pthread_create(pthread_t *thread,
797 const pthread_attr_t *attr,
798 void *(*start_routine) (void *),
801 if (!uid_wrapper_enabled()) {
802 return libpthread_pthread_create(thread,
808 return uwrap_pthread_create(thread,
814 /*********************************************************
816 *********************************************************/
818 #define GROUP_STRING_SIZE 16384
819 #define GROUP_MAX_COUNT (GROUP_STRING_SIZE / (10 + 1))
822 * This function exports all the IDs of the current user so if
823 * we fork and then exec we can setup uid_wrapper in the new process
826 static void uwrap_export_ids(struct uwrap_thread *id)
828 char groups_str[GROUP_STRING_SIZE] = {0};
829 size_t groups_str_size = sizeof(groups_str);
830 char unsigned_str[32] = {0};
834 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->ruid);
835 setenv("UID_WRAPPER_INITIAL_RUID", unsigned_str, 1);
837 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->euid);
838 setenv("UID_WRAPPER_INITIAL_EUID", unsigned_str, 1);
840 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->suid);
841 setenv("UID_WRAPPER_INITIAL_SUID", unsigned_str, 1);
844 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->rgid);
845 setenv("UID_WRAPPER_INITIAL_RGID", unsigned_str, 1);
847 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->egid);
848 setenv("UID_WRAPPER_INITIAL_EGID", unsigned_str, 1);
850 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->sgid);
851 setenv("UID_WRAPPER_INITIAL_SGID", unsigned_str, 1);
853 if (id->ngroups > GROUP_MAX_COUNT) {
854 UWRAP_LOG(UWRAP_LOG_ERROR,
855 "ERROR: Number of groups (%u) exceeds maximum value "
856 "uid_wrapper will handle (%u).",
863 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->ngroups);
864 setenv("UID_WRAPPER_INITIAL_GROUPS_COUNT", unsigned_str, 1);
866 for (i = 0; i < id->ngroups; i++) {
867 size_t groups_str_len = strlen(groups_str);
868 size_t groups_str_avail = groups_str_size - groups_str_len;
871 len = snprintf(unsigned_str, sizeof(unsigned_str), ",%u", id->groups[i]);
875 if (len < groups_str_avail) {
876 snprintf(groups_str + groups_str_len,
877 groups_str_size - groups_str_len,
879 i == 0 ? unsigned_str + 1 : unsigned_str);
883 if (id->ngroups > 0) {
884 setenv("UID_WRAPPER_INITIAL_GROUPS", groups_str, 1);
888 static void uwrap_thread_prepare(void)
890 struct uwrap_thread *id = uwrap_tls_id;
892 /* uid_wrapper is loaded but not enabled */
900 * What happens if another atfork prepare functions calls a uwrap
901 * function? So disable it in case another atfork prepare function
902 * calls a (s)uid function. We disable uid_wrapper only for thread
903 * (process) which called fork.
908 static void uwrap_thread_parent(void)
910 struct uwrap_thread *id = uwrap_tls_id;
912 /* uid_wrapper is loaded but not enabled */
922 static void uwrap_thread_child(void)
924 struct uwrap_thread *id = uwrap_tls_id;
925 struct uwrap_thread *u = uwrap.ids;
927 /* uid_wrapper is loaded but not enabled */
932 uwrap_export_ids(id);
935 * "Garbage collector" - Inspired by DESTRUCTOR.
936 * All threads (except one which called fork()) are dead now.. Dave
937 * That's what posix said...
941 /* Skip this item. */
946 UWRAP_DLIST_REMOVE(uwrap.ids, u);
948 SAFE_FREE(u->groups);
960 * This initializes uid_wrapper with the IDs exported to the environment. Those
961 * are normally set after we forked and executed.
963 static void uwrap_init_env(struct uwrap_thread *id)
968 env = getenv("UID_WRAPPER_INITIAL_RUID");
969 if (env != NULL && env[0] != '\0') {
970 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initialize ruid with %s", env);
971 id->ruid = strtoul(env, (char **)NULL, 10);
972 unsetenv("UID_WRAPPER_INITIAL_RUID");
975 env = getenv("UID_WRAPPER_INITIAL_EUID");
976 if (env != NULL && env[0] != '\0') {
977 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize euid with %s", env);
978 id->euid = strtoul(env, (char **)NULL, 10);
979 unsetenv("UID_WRAPPER_INITIAL_EUID");
982 env = getenv("UID_WRAPPER_INITIAL_SUID");
983 if (env != NULL && env[0] != '\0') {
984 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize suid with %s", env);
985 id->suid = strtoul(env, (char **)NULL, 10);
986 unsetenv("UID_WRAPPER_INITIAL_SUID");
989 env = getenv("UID_WRAPPER_INITIAL_RGID");
990 if (env != NULL && env[0] != '\0') {
991 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initialize ruid with %s", env);
992 id->rgid = strtoul(env, (char **)NULL, 10);
993 unsetenv("UID_WRAPPER_INITIAL_RGID");
996 env = getenv("UID_WRAPPER_INITIAL_EGID");
997 if (env != NULL && env[0] != '\0') {
998 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize egid with %s", env);
999 id->egid = strtoul(env, (char **)NULL, 10);
1000 unsetenv("UID_WRAPPER_INITIAL_EGID");
1003 env = getenv("UID_WRAPPER_INITIAL_SGID");
1004 if (env != NULL && env[0] != '\0') {
1005 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize sgid with %s", env);
1006 id->sgid = strtoul(env, (char **)NULL, 10);
1007 unsetenv("UID_WRAPPER_INITIAL_SGID");
1010 env = getenv("UID_WRAPPER_INITIAL_GROUPS_COUNT");
1011 if (env != NULL && env[0] != '\0') {
1012 ngroups = strtol(env, (char **)NULL, 10);
1013 unsetenv("UID_WRAPPER_INITIAL_GROUPS_COUNT");
1016 if (ngroups > 0 && ngroups < GROUP_MAX_COUNT) {
1022 id->groups = malloc(sizeof(gid_t) * ngroups);
1023 if (id->groups == NULL) {
1024 UWRAP_LOG(UWRAP_LOG_ERROR,
1025 "Unable to allocate memory");
1029 env = getenv("UID_WRAPPER_INITIAL_GROUPS");
1030 if (env != NULL && env[0] != '\0') {
1031 char *groups_str = NULL;
1032 char *saveptr = NULL;
1033 const char *p = NULL;
1035 groups_str = strdup(env);
1036 if (groups_str == NULL) {
1040 p = strtok_r(groups_str, ",", &saveptr);
1042 id->groups[i] = strtol(p, (char **)NULL, 10);
1045 p = strtok_r(NULL, ",", &saveptr);
1047 SAFE_FREE(groups_str);
1051 UWRAP_LOG(UWRAP_LOG_ERROR,
1052 "ERROR: The number of groups (%u) passed, "
1053 "does not the number of groups (%u) we "
1060 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize groups with %s", env);
1061 id->ngroups = ngroups;
1065 static void uwrap_init(void)
1069 UWRAP_LOCK(uwrap_id);
1071 if (uwrap.initialised) {
1072 struct uwrap_thread *id = uwrap_tls_id;
1074 if (uwrap.ids == NULL) {
1075 UWRAP_UNLOCK(uwrap_id);
1080 UWRAP_LOG(UWRAP_LOG_ERROR,
1081 "Invalid id for thread");
1085 UWRAP_UNLOCK(uwrap_id);
1089 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initialize uid_wrapper");
1091 uwrap.initialised = true;
1093 env = getenv("UID_WRAPPER");
1094 if (env != NULL && env[0] == '1') {
1095 const char *root = getenv("UID_WRAPPER_ROOT");
1096 struct uwrap_thread *id;
1098 id = calloc(1, sizeof(struct uwrap_thread));
1100 UWRAP_LOG(UWRAP_LOG_ERROR,
1101 "Unable to allocate memory for main id");
1105 UWRAP_DLIST_ADD(uwrap.ids, id);
1108 uwrap.myuid = libc_geteuid();
1109 uwrap.mygid = libc_getegid();
1111 /* put us in one group */
1112 if (root != NULL && root[0] == '1') {
1113 id->ruid = id->euid = id->suid = 0;
1114 id->rgid = id->egid = id->sgid = 0;
1116 id->groups = malloc(sizeof(gid_t) * 1);
1117 if (id->groups == NULL) {
1118 UWRAP_LOG(UWRAP_LOG_ERROR,
1119 "Unable to allocate memory");
1127 id->ruid = id->euid = id->suid = uwrap.myuid;
1128 id->rgid = id->egid = id->sgid = uwrap.mygid;
1130 id->ngroups = libc_getgroups(0, NULL);
1131 if (id->ngroups == -1) {
1132 UWRAP_LOG(UWRAP_LOG_ERROR,
1133 "Unable to call libc_getgroups in uwrap_init.");
1136 id->groups = malloc(sizeof(gid_t) * id->ngroups);
1137 if (id->groups == NULL) {
1138 UWRAP_LOG(UWRAP_LOG_ERROR, "Unable to allocate memory");
1141 if (libc_getgroups(id->ngroups, id->groups) == -1) {
1142 UWRAP_LOG(UWRAP_LOG_ERROR,
1143 "Unable to call libc_getgroups again in uwrap_init.");
1146 * Deallocation of uwrap.groups is handled by
1147 * library destructor.
1157 UWRAP_LOG(UWRAP_LOG_DEBUG,
1158 "Enabled uid_wrapper as %s (real uid=%u)",
1159 id->ruid == 0 ? "root" : "user",
1160 (unsigned int)uwrap.myuid);
1163 UWRAP_UNLOCK(uwrap_id);
1165 UWRAP_LOG(UWRAP_LOG_DEBUG, "Succeccfully initialized uid_wrapper");
1168 bool uid_wrapper_enabled(void)
1170 struct uwrap_thread *id = uwrap_tls_id;
1177 UWRAP_LOCK(uwrap_id);
1178 enabled = id->enabled;
1179 UWRAP_UNLOCK(uwrap_id);
1185 * UWRAP_SETxUID FUNCTIONS
1188 static int uwrap_setresuid_args(uid_t ruid, uid_t euid, uid_t suid)
1190 struct uwrap_thread *id = uwrap_tls_id;
1192 UWRAP_LOG(UWRAP_LOG_TRACE,
1193 "ruid %d -> %d, euid %d -> %d, suid %d -> %d",
1194 id->ruid, ruid, id->euid, euid, id->suid, suid);
1196 if (id->euid != 0) {
1197 if (ruid != (uid_t)-1 &&
1204 if (euid != (uid_t)-1 &&
1211 if (suid != (uid_t)-1 &&
1223 static int uwrap_setresuid_thread(uid_t ruid, uid_t euid, uid_t suid)
1225 struct uwrap_thread *id = uwrap_tls_id;
1228 UWRAP_LOG(UWRAP_LOG_TRACE,
1229 "ruid %d -> %d, euid %d -> %d, suid %d -> %d",
1230 id->ruid, ruid, id->euid, euid, id->suid, suid);
1232 rc = uwrap_setresuid_args(ruid, euid, suid);
1237 UWRAP_LOCK(uwrap_id);
1239 if (ruid != (uid_t)-1) {
1243 if (euid != (uid_t)-1) {
1247 if (suid != (uid_t)-1) {
1251 UWRAP_UNLOCK(uwrap_id);
1256 static int uwrap_setresuid(uid_t ruid, uid_t euid, uid_t suid)
1258 struct uwrap_thread *id = uwrap_tls_id;
1261 UWRAP_LOG(UWRAP_LOG_TRACE,
1262 "ruid %d -> %d, euid %d -> %d, suid %d -> %d",
1263 id->ruid, ruid, id->euid, euid, id->suid, suid);
1265 rc = uwrap_setresuid_args(ruid, euid, suid);
1270 UWRAP_LOCK(uwrap_id);
1272 for (id = uwrap.ids; id; id = id->next) {
1273 if (ruid != (uid_t)-1) {
1277 if (euid != (uid_t)-1) {
1281 if (suid != (uid_t)-1) {
1286 UWRAP_UNLOCK(uwrap_id);
1291 static int uwrap_setreuid_args(uid_t ruid, uid_t euid,
1296 struct uwrap_thread *id = uwrap_tls_id;
1297 uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
1299 UWRAP_LOG(UWRAP_LOG_TRACE,
1300 "ruid %d -> %d, euid %d -> %d",
1301 id->ruid, ruid, id->euid, euid);
1303 if (ruid != (uid_t)-1) {
1305 if (ruid != id->ruid &&
1313 if (euid != (uid_t)-1) {
1315 if (euid != id->ruid &&
1324 if (ruid != (uid_t) -1 ||
1325 (euid != (uid_t)-1 && id->ruid != euid)) {
1326 new_suid = new_euid;
1329 *_new_ruid = new_ruid;
1330 *_new_euid = new_euid;
1331 *_new_suid = new_suid;
1336 static int uwrap_setreuid_thread(uid_t ruid, uid_t euid)
1339 struct uwrap_thread *id = uwrap_tls_id;
1341 uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
1344 UWRAP_LOG(UWRAP_LOG_TRACE,
1345 "ruid %d -> %d, euid %d -> %d",
1346 id->ruid, ruid, id->euid, euid);
1348 rc = uwrap_setreuid_args(ruid, euid, &new_ruid, &new_euid, &new_suid);
1353 return uwrap_setresuid_thread(new_ruid, new_euid, new_suid);
1356 #ifdef HAVE_SETREUID
1357 static int uwrap_setreuid(uid_t ruid, uid_t euid)
1360 struct uwrap_thread *id = uwrap_tls_id;
1362 uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
1365 UWRAP_LOG(UWRAP_LOG_TRACE,
1366 "ruid %d -> %d, euid %d -> %d",
1367 id->ruid, ruid, id->euid, euid);
1369 rc = uwrap_setreuid_args(ruid, euid, &new_ruid, &new_euid, &new_suid);
1374 return uwrap_setresuid(new_ruid, new_euid, new_suid);
1378 static int uwrap_setuid_args(uid_t uid,
1383 struct uwrap_thread *id = uwrap_tls_id;
1385 UWRAP_LOG(UWRAP_LOG_TRACE,
1389 if (uid == (uid_t)-1) {
1394 if (id->euid == 0) {
1395 *new_suid = *new_ruid = uid;
1396 } else if (uid != id->ruid &&
1407 static int uwrap_setuid_thread(uid_t uid)
1409 uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
1412 rc = uwrap_setuid_args(uid, &new_ruid, &new_euid, &new_suid);
1417 return uwrap_setresuid_thread(new_ruid, new_euid, new_suid);
1420 static int uwrap_setuid(uid_t uid)
1422 uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
1425 rc = uwrap_setuid_args(uid, &new_ruid, &new_euid, &new_suid);
1430 return uwrap_setresuid(new_ruid, new_euid, new_suid);
1434 * UWRAP_GETxUID FUNCTIONS
1437 #ifdef HAVE_GETRESUID
1438 static int uwrap_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
1440 struct uwrap_thread *id = uwrap_tls_id;
1442 UWRAP_LOCK(uwrap_id);
1448 UWRAP_UNLOCK(uwrap_id);
1454 #ifdef HAVE_GETRESGID
1455 static int uwrap_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
1457 struct uwrap_thread *id = uwrap_tls_id;
1459 UWRAP_LOCK(uwrap_id);
1465 UWRAP_UNLOCK(uwrap_id);
1472 * UWRAP_SETxGID FUNCTIONS
1475 static int uwrap_setresgid_args(gid_t rgid, gid_t egid, gid_t sgid)
1477 struct uwrap_thread *id = uwrap_tls_id;
1479 UWRAP_LOG(UWRAP_LOG_TRACE,
1480 "rgid %d -> %d, egid %d -> %d, sgid %d -> %d",
1481 id->rgid, rgid, id->egid, egid, id->sgid, sgid);
1483 if (id->euid != 0) {
1484 if (rgid != (gid_t)-1 &&
1491 if (egid != (gid_t)-1 &&
1498 if (sgid != (gid_t)-1 &&
1510 static int uwrap_setresgid_thread(gid_t rgid, gid_t egid, gid_t sgid)
1512 struct uwrap_thread *id = uwrap_tls_id;
1515 UWRAP_LOG(UWRAP_LOG_TRACE,
1516 "rgid %d -> %d, egid %d -> %d, sgid %d -> %d",
1517 id->rgid, rgid, id->egid, egid, id->sgid, sgid);
1519 rc = uwrap_setresgid_args(rgid, egid, sgid);
1524 UWRAP_LOCK(uwrap_id);
1526 if (rgid != (gid_t)-1) {
1530 if (egid != (gid_t)-1) {
1534 if (sgid != (gid_t)-1) {
1538 UWRAP_UNLOCK(uwrap_id);
1543 static int uwrap_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
1545 struct uwrap_thread *id = uwrap_tls_id;
1548 UWRAP_LOG(UWRAP_LOG_TRACE,
1549 "rgid %d -> %d, egid %d -> %d, sgid %d -> %d",
1550 id->rgid, rgid, id->egid, egid, id->sgid, sgid);
1552 rc = uwrap_setresgid_args(rgid, egid, sgid);
1557 UWRAP_LOCK(uwrap_id);
1559 for (id = uwrap.ids; id; id = id->next) {
1560 if (rgid != (gid_t)-1) {
1564 if (egid != (gid_t)-1) {
1568 if (sgid != (gid_t)-1) {
1573 UWRAP_UNLOCK(uwrap_id);
1578 static int uwrap_setregid_args(gid_t rgid, gid_t egid,
1583 struct uwrap_thread *id = uwrap_tls_id;
1584 gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
1586 UWRAP_LOG(UWRAP_LOG_TRACE,
1587 "rgid %d -> %d, egid %d -> %d",
1588 id->rgid, rgid, id->egid, egid);
1590 if (rgid != (gid_t)-1) {
1592 if (rgid != id->rgid &&
1600 if (egid != (gid_t)-1) {
1602 if (egid != id->rgid &&
1611 if (rgid != (gid_t) -1 ||
1612 (egid != (gid_t)-1 && id->rgid != egid)) {
1613 new_sgid = new_egid;
1616 *_new_rgid = new_rgid;
1617 *_new_egid = new_egid;
1618 *_new_sgid = new_sgid;
1623 static int uwrap_setregid_thread(gid_t rgid, gid_t egid)
1626 struct uwrap_thread *id = uwrap_tls_id;
1628 gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
1631 UWRAP_LOG(UWRAP_LOG_TRACE,
1632 "rgid %d -> %d, egid %d -> %d",
1633 id->rgid, rgid, id->egid, egid);
1635 rc = uwrap_setregid_args(rgid, egid, &new_rgid, &new_egid, &new_sgid);
1640 return uwrap_setresgid_thread(new_rgid, new_egid, new_sgid);
1643 #ifdef HAVE_SETREGID
1644 static int uwrap_setregid(gid_t rgid, gid_t egid)
1647 struct uwrap_thread *id = uwrap_tls_id;
1649 gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
1652 UWRAP_LOG(UWRAP_LOG_TRACE,
1653 "rgid %d -> %d, egid %d -> %d",
1654 id->rgid, rgid, id->egid, egid);
1656 rc = uwrap_setregid_args(rgid, egid, &new_rgid, &new_egid, &new_sgid);
1661 return uwrap_setresgid(new_rgid, new_egid, new_sgid);
1665 static int uwrap_setgid_args(gid_t gid,
1670 struct uwrap_thread *id = uwrap_tls_id;
1672 UWRAP_LOG(UWRAP_LOG_TRACE,
1676 if (gid == (gid_t)-1) {
1681 if (id->euid == 0) {
1682 *new_sgid = *new_rgid = gid;
1683 } else if (gid != id->rgid &&
1694 static int uwrap_setgid_thread(gid_t gid)
1696 gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
1699 rc = uwrap_setgid_args(gid, &new_rgid, &new_egid, &new_sgid);
1704 return uwrap_setresgid_thread(new_rgid, new_egid, new_sgid);
1707 static int uwrap_setgid(gid_t gid)
1709 gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
1712 rc = uwrap_setgid_args(gid, &new_rgid, &new_egid, &new_sgid);
1717 return uwrap_setresgid(new_rgid, new_egid, new_sgid);
1723 int setuid(uid_t uid)
1725 if (!uid_wrapper_enabled()) {
1726 return libc_setuid(uid);
1730 return uwrap_setuid(uid);
1734 int seteuid(uid_t euid)
1736 if (!uid_wrapper_enabled()) {
1737 return libc_seteuid(euid);
1740 /* On FreeBSD the uid_t -1 is set and doesn't produce and error */
1741 if (euid == (uid_t)-1) {
1747 return uwrap_setresuid(-1, euid, -1);
1751 #ifdef HAVE_SETREUID
1752 int setreuid(uid_t ruid, uid_t euid)
1754 if (!uid_wrapper_enabled()) {
1755 return libc_setreuid(ruid, euid);
1759 return uwrap_setreuid(ruid, euid);
1763 #ifdef HAVE_SETRESUID
1764 int setresuid(uid_t ruid, uid_t euid, uid_t suid)
1766 if (!uid_wrapper_enabled()) {
1767 return libc_setresuid(ruid, euid, suid);
1771 return uwrap_setresuid(ruid, euid, suid);
1775 #ifdef HAVE_GETRESUID
1776 int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
1778 if (!uid_wrapper_enabled()) {
1779 return libc_getresuid(ruid, euid, suid);
1783 return uwrap_getresuid(ruid, euid, suid);
1790 static uid_t uwrap_getuid(void)
1792 struct uwrap_thread *id = uwrap_tls_id;
1795 UWRAP_LOCK(uwrap_id);
1797 UWRAP_UNLOCK(uwrap_id);
1804 if (!uid_wrapper_enabled()) {
1805 return libc_getuid();
1809 return uwrap_getuid();
1815 static uid_t uwrap_geteuid(void)
1817 const char *env = getenv("UID_WRAPPER_MYUID");
1818 struct uwrap_thread *id = uwrap_tls_id;
1821 UWRAP_LOCK(uwrap_id);
1823 UWRAP_UNLOCK(uwrap_id);
1825 /* Disable root and return myuid */
1826 if (env != NULL && env[0] == '1') {
1835 if (!uid_wrapper_enabled()) {
1836 return libc_geteuid();
1840 return uwrap_geteuid();
1846 int setgid(gid_t gid)
1848 if (!uid_wrapper_enabled()) {
1849 return libc_setgid(gid);
1853 return uwrap_setgid(gid);
1857 int setegid(gid_t egid)
1859 if (!uid_wrapper_enabled()) {
1860 return libc_setegid(egid);
1863 /* On FreeBSD the uid_t -1 is set and doesn't produce and error */
1864 if (egid == (gid_t)-1) {
1870 return uwrap_setresgid(-1, egid, -1);
1874 #ifdef HAVE_SETREGID
1875 int setregid(gid_t rgid, gid_t egid)
1877 if (!uid_wrapper_enabled()) {
1878 return libc_setregid(rgid, egid);
1882 return uwrap_setregid(rgid, egid);
1886 #ifdef HAVE_SETRESGID
1887 int setresgid(gid_t rgid, gid_t egid, gid_t sgid)
1889 if (!uid_wrapper_enabled()) {
1890 return libc_setresgid(rgid, egid, sgid);
1894 return uwrap_setresgid(rgid, egid, sgid);
1898 #ifdef HAVE_GETRESGID
1899 int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
1901 if (!uid_wrapper_enabled()) {
1902 return libc_getresgid(rgid, egid, sgid);
1906 return uwrap_getresgid(rgid, egid, sgid);
1913 static gid_t uwrap_getgid(void)
1915 struct uwrap_thread *id = uwrap_tls_id;
1918 UWRAP_LOCK(uwrap_id);
1920 UWRAP_UNLOCK(uwrap_id);
1927 if (!uid_wrapper_enabled()) {
1928 return libc_getgid();
1932 return uwrap_getgid();
1938 static uid_t uwrap_getegid(void)
1940 struct uwrap_thread *id = uwrap_tls_id;
1943 UWRAP_LOCK(uwrap_id);
1945 UWRAP_UNLOCK(uwrap_id);
1952 if (!uid_wrapper_enabled()) {
1953 return libc_getegid();
1957 return uwrap_getegid();
1960 static int uwrap_setgroups_thread(size_t size, const gid_t *list)
1962 struct uwrap_thread *id = uwrap_tls_id;
1965 UWRAP_LOCK(uwrap_id);
1968 SAFE_FREE(id->groups);
1970 } else if (size > 0) {
1973 tmp = realloc(id->groups, sizeof(gid_t) * size);
1980 memcpy(id->groups, list, size * sizeof(gid_t));
1985 UWRAP_UNLOCK(uwrap_id);
1990 static int uwrap_setgroups(size_t size, const gid_t *list)
1992 struct uwrap_thread *id;
1995 UWRAP_LOCK(uwrap_id);
1998 for (id = uwrap.ids; id; id = id->next) {
1999 SAFE_FREE(id->groups);
2003 } else if (size > 0) {
2006 for (id = uwrap.ids; id; id = id->next) {
2007 tmp = realloc(id->groups, sizeof(gid_t) * size);
2015 memcpy(id->groups, list, size * sizeof(gid_t));
2021 UWRAP_UNLOCK(uwrap_id);
2026 #ifdef HAVE_SETGROUPS_INT
2027 int setgroups(int size, const gid_t *list)
2029 int setgroups(size_t size, const gid_t *list)
2032 if (!uid_wrapper_enabled()) {
2033 return libc_setgroups(size, list);
2037 return uwrap_setgroups(size, list);
2040 static int uwrap_getgroups(int size, gid_t *list)
2042 struct uwrap_thread *id = uwrap_tls_id;
2045 UWRAP_LOCK(uwrap_id);
2046 ngroups = id->ngroups;
2048 if (size > ngroups) {
2054 if (size < ngroups) {
2058 memcpy(list, id->groups, size * sizeof(gid_t));
2061 UWRAP_UNLOCK(uwrap_id);
2066 int getgroups(int size, gid_t *list)
2068 if (!uid_wrapper_enabled()) {
2069 return libc_getgroups(size, list);
2073 return uwrap_getgroups(size, list);
2076 #if (defined(HAVE_SYS_SYSCALL_H) || defined(HAVE_SYSCALL_H)) \
2077 && (defined(SYS_setreuid) || defined(SYS_setreuid32))
2078 static long int uwrap_syscall (long int sysno, va_list vp)
2089 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2093 rc = uwrap_getgid();
2098 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2102 rc = uwrap_getegid();
2105 #endif /* SYS_getegid */
2107 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2111 gid_t gid = (gid_t) va_arg(vp, gid_t);
2113 rc = uwrap_setgid_thread(gid);
2117 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2118 case SYS_setregid32:
2121 gid_t rgid = (gid_t) va_arg(vp, gid_t);
2122 gid_t egid = (gid_t) va_arg(vp, gid_t);
2124 rc = uwrap_setregid_thread(rgid, egid);
2127 #ifdef SYS_setresgid
2129 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2130 case SYS_setresgid32:
2133 gid_t rgid = (gid_t) va_arg(vp, gid_t);
2134 gid_t egid = (gid_t) va_arg(vp, gid_t);
2135 gid_t sgid = (gid_t) va_arg(vp, gid_t);
2137 rc = uwrap_setresgid_thread(rgid, egid, sgid);
2140 #endif /* SYS_setresgid */
2141 #if defined(SYS_getresgid) && defined(HAVE_GETRESGID)
2143 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2144 case SYS_getresgid32:
2147 gid_t *rgid = (gid_t *) va_arg(vp, gid_t *);
2148 gid_t *egid = (gid_t *) va_arg(vp, gid_t *);
2149 gid_t *sgid = (gid_t *) va_arg(vp, gid_t *);
2151 rc = uwrap_getresgid(rgid, egid, sgid);
2154 #endif /* SYS_getresgid && HAVE_GETRESGID */
2162 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2166 rc = uwrap_getuid();
2171 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2175 rc = uwrap_geteuid();
2178 #endif /* SYS_geteuid */
2180 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2184 uid_t uid = (uid_t) va_arg(vp, uid_t);
2186 rc = uwrap_setuid_thread(uid);
2190 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2191 case SYS_setreuid32:
2194 uid_t ruid = (uid_t) va_arg(vp, uid_t);
2195 uid_t euid = (uid_t) va_arg(vp, uid_t);
2197 rc = uwrap_setreuid_thread(ruid, euid);
2200 #ifdef SYS_setresuid
2202 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2203 case SYS_setresuid32:
2206 uid_t ruid = (uid_t) va_arg(vp, uid_t);
2207 uid_t euid = (uid_t) va_arg(vp, uid_t);
2208 uid_t suid = (uid_t) va_arg(vp, uid_t);
2210 rc = uwrap_setresuid_thread(ruid, euid, suid);
2213 #endif /* SYS_setresuid */
2214 #if defined(SYS_getresuid) && defined(HAVE_GETRESUID)
2216 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2217 case SYS_getresuid32:
2220 uid_t *ruid = (uid_t *) va_arg(vp, uid_t *);
2221 uid_t *euid = (uid_t *) va_arg(vp, uid_t *);
2222 uid_t *suid = (uid_t *) va_arg(vp, uid_t *);
2224 rc = uwrap_getresuid(ruid, euid, suid);
2227 #endif /* SYS_getresuid && HAVE_GETRESUID*/
2230 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2231 case SYS_setgroups32:
2234 size_t size = (size_t) va_arg(vp, size_t);
2235 gid_t *list = (gid_t *) va_arg(vp, int *);
2237 rc = uwrap_setgroups_thread(size, list);
2241 UWRAP_LOG(UWRAP_LOG_DEBUG,
2242 "UID_WRAPPER calling non-wrapped syscall %lu",
2245 rc = libc_vsyscall(sysno, vp);
2253 #ifdef HAVE_SYSCALL_INT
2254 int syscall (int sysno, ...)
2256 long int syscall (long int sysno, ...)
2259 #ifdef HAVE_SYSCALL_INT
2266 va_start(va, sysno);
2268 if (!uid_wrapper_enabled()) {
2269 rc = libc_vsyscall(sysno, va);
2275 rc = uwrap_syscall(sysno, va);
2280 #endif /* HAVE_SYSCALL */
2281 #endif /* HAVE_SYS_SYSCALL_H || HAVE_SYSCALL_H */
2283 /****************************
2285 ***************************/
2286 void uwrap_constructor(void)
2289 * If we hold a lock and the application forks, then the child
2290 * is not able to unlock the mutex and we are in a deadlock.
2291 * This should prevent such deadlocks.
2293 pthread_atfork(&uwrap_thread_prepare,
2294 &uwrap_thread_parent,
2295 &uwrap_thread_child);
2297 /* Here is safe place to call uwrap_init() and initialize data
2303 /****************************
2305 ***************************/
2308 * This function is called when the library is unloaded and makes sure that
2309 * resources are freed.
2311 void uwrap_destructor(void)
2313 struct uwrap_thread *u = uwrap.ids;
2318 UWRAP_DLIST_REMOVE(uwrap.ids, u);
2320 SAFE_FREE(u->groups);
2327 if (uwrap.libc.handle != NULL) {
2328 dlclose(uwrap.libc.handle);
2331 if (uwrap.libpthread.handle != NULL) {
2332 dlclose(uwrap.libpthread.handle);