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;
145 const char *prefix = "UWRAP";
147 d = getenv("UID_WRAPPER_DEBUGLEVEL");
156 va_start(va, format);
157 vsnprintf(buffer, sizeof(buffer), format, va);
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";
187 #define LIBC_NAME "libc.so"
189 typedef int (*__libc_setuid)(uid_t uid);
191 typedef uid_t (*__libc_getuid)(void);
194 typedef int (*__libc_seteuid)(uid_t euid);
198 typedef int (*__libc_setreuid)(uid_t ruid, uid_t euid);
201 #ifdef HAVE_SETRESUID
202 typedef int (*__libc_setresuid)(uid_t ruid, uid_t euid, uid_t suid);
205 #ifdef HAVE_GETRESUID
206 typedef int (*__libc_getresuid)(uid_t *ruid, uid_t *euid, uid_t *suid);
209 typedef uid_t (*__libc_geteuid)(void);
211 typedef int (*__libc_setgid)(gid_t gid);
213 typedef gid_t (*__libc_getgid)(void);
216 typedef int (*__libc_setegid)(uid_t egid);
220 typedef int (*__libc_setregid)(uid_t rgid, uid_t egid);
223 #ifdef HAVE_SETRESGID
224 typedef int (*__libc_setresgid)(uid_t rgid, uid_t egid, uid_t sgid);
227 #ifdef HAVE_GETRESGID
228 typedef int (*__libc_getresgid)(gid_t *rgid, gid_t *egid, gid_t *sgid);
231 typedef gid_t (*__libc_getegid)(void);
233 typedef int (*__libc_getgroups)(int size, gid_t list[]);
235 typedef int (*__libc_setgroups)(size_t size, const gid_t *list);
238 typedef long int (*__libc_syscall)(long int sysno, ...);
241 #define UWRAP_SYMBOL_ENTRY(i) \
247 struct uwrap_libc_symbols {
248 UWRAP_SYMBOL_ENTRY(setuid);
249 UWRAP_SYMBOL_ENTRY(getuid);
251 UWRAP_SYMBOL_ENTRY(seteuid);
254 UWRAP_SYMBOL_ENTRY(setreuid);
256 #ifdef HAVE_SETRESUID
257 UWRAP_SYMBOL_ENTRY(setresuid);
259 #ifdef HAVE_GETRESUID
260 UWRAP_SYMBOL_ENTRY(getresuid);
262 UWRAP_SYMBOL_ENTRY(geteuid);
263 UWRAP_SYMBOL_ENTRY(setgid);
264 UWRAP_SYMBOL_ENTRY(getgid);
266 UWRAP_SYMBOL_ENTRY(setegid);
269 UWRAP_SYMBOL_ENTRY(setregid);
271 #ifdef HAVE_SETRESGID
272 UWRAP_SYMBOL_ENTRY(setresgid);
274 #ifdef HAVE_GETRESGID
275 UWRAP_SYMBOL_ENTRY(getresgid);
277 UWRAP_SYMBOL_ENTRY(getegid);
278 UWRAP_SYMBOL_ENTRY(getgroups);
279 UWRAP_SYMBOL_ENTRY(setgroups);
281 UWRAP_SYMBOL_ENTRY(syscall);
284 #undef UWRAP_SYMBOL_ENTRY
289 /* Yeah... I'm pig. I overloading macro here... So what? */
290 #define UWRAP_SYMBOL_ENTRY(i) \
292 __libpthread_##i f; \
296 typedef int (*__libpthread_pthread_create)(pthread_t *thread,
297 const pthread_attr_t *attr,
298 void *(*start_routine) (void *),
300 typedef void (*__libpthread_pthread_exit)(void *retval);
302 struct uwrap_libpthread_symbols {
303 UWRAP_SYMBOL_ENTRY(pthread_create);
304 UWRAP_SYMBOL_ENTRY(pthread_exit);
306 #undef UWRAP_SYMBOL_ENTRY
309 * We keep the virtualised euid/egid/groups information here
311 struct uwrap_thread {
325 struct uwrap_thread *next;
326 struct uwrap_thread *prev;
332 struct uwrap_libc_symbols symbols;
337 struct uwrap_libpthread_symbols symbols;
342 /* Real uid and gid of user who run uid wrapper */
346 struct uwrap_thread *ids;
349 static struct uwrap uwrap;
351 /* Shortcut to the list item */
352 static UWRAP_THREAD struct uwrap_thread *uwrap_tls_id;
354 /* The mutex or accessing the id */
355 static pthread_mutex_t uwrap_id_mutex = PTHREAD_MUTEX_INITIALIZER;
357 /* The mutex for accessing the global libc.symbols */
358 static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
360 /* The mutex for accessing the global libpthread.symbols */
361 static pthread_mutex_t libpthread_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
363 /*********************************************************
365 *********************************************************/
367 bool uid_wrapper_enabled(void);
368 void uwrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
369 void uwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
371 /*********************************************************
372 * UWRAP LIBC LOADER FUNCTIONS
373 *********************************************************/
382 static void *uwrap_load_lib_handle(enum uwrap_lib lib)
384 int flags = RTLD_LAZY;
389 flags |= RTLD_DEEPBIND;
395 case UWRAP_LIBSOCKET:
398 handle = uwrap.libc.handle;
399 if (handle == NULL) {
400 for (i = 10; i >= 0; i--) {
401 char soname[256] = {0};
403 snprintf(soname, sizeof(soname), "libc.so.%d", i);
404 handle = dlopen(soname, flags);
405 if (handle != NULL) {
409 /* glibc on Alpha and IA64 is libc.so.6.1 */
410 snprintf(soname, sizeof(soname), "libc.so.%d.1", i);
411 handle = dlopen(soname, flags);
412 if (handle != NULL) {
417 uwrap.libc.handle = handle;
420 case UWRAP_LIBPTHREAD:
421 handle = uwrap.libpthread.handle;
422 if (handle == NULL) {
423 handle = dlopen("libpthread.so.0", flags);
424 if (handle != NULL) {
431 if (handle == NULL) {
433 handle = uwrap.libc.handle = RTLD_NEXT;
436 "Failed to dlopen library: %s\n",
445 static void *_uwrap_bind_symbol(enum uwrap_lib lib, const char *fn_name)
450 handle = uwrap_load_lib_handle(lib);
452 func = dlsym(handle, fn_name);
455 "Failed to find %s: %s\n",
463 #define uwrap_bind_symbol_libc(sym_name) \
464 UWRAP_LOCK(libc_symbol_binding); \
465 if (uwrap.libc.symbols._libc_##sym_name.obj == NULL) { \
466 uwrap.libc.symbols._libc_##sym_name.obj = \
467 _uwrap_bind_symbol(UWRAP_LIBC, #sym_name); \
469 UWRAP_UNLOCK(libc_symbol_binding)
471 #define uwrap_bind_symbol_libpthread(sym_name) \
472 UWRAP_LOCK(libpthread_symbol_binding); \
473 if (uwrap.libpthread.symbols._libpthread_##sym_name.obj == NULL) { \
474 uwrap.libpthread.symbols._libpthread_##sym_name.obj = \
475 _uwrap_bind_symbol(UWRAP_LIBPTHREAD, #sym_name); \
477 UWRAP_UNLOCK(libpthread_symbol_binding)
482 * Functions expeciall from libc need to be loaded individually, you can't load
483 * all at once or gdb will segfault at startup. The same applies to valgrind and
484 * has probably something todo with with the linker.
485 * So we need load each function at the point it is called the first time.
487 static int libc_setuid(uid_t uid)
489 uwrap_bind_symbol_libc(setuid);
491 return uwrap.libc.symbols._libc_setuid.f(uid);
494 static uid_t libc_getuid(void)
496 uwrap_bind_symbol_libc(getuid);
498 return uwrap.libc.symbols._libc_getuid.f();
502 static int libc_seteuid(uid_t euid)
504 uwrap_bind_symbol_libc(seteuid);
506 return uwrap.libc.symbols._libc_seteuid.f(euid);
511 static int libc_setreuid(uid_t ruid, uid_t euid)
513 uwrap_bind_symbol_libc(setreuid);
515 return uwrap.libc.symbols._libc_setreuid.f(ruid, euid);
519 #ifdef HAVE_SETRESUID
520 static int libc_setresuid(uid_t ruid, uid_t euid, uid_t suid)
522 uwrap_bind_symbol_libc(setresuid);
524 return uwrap.libc.symbols._libc_setresuid.f(ruid, euid, suid);
528 #ifdef HAVE_GETRESUID
529 static int libc_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
531 uwrap_bind_symbol_libc(getresuid);
533 return uwrap.libc.symbols._libc_getresuid.f(ruid, euid, suid);
537 static uid_t libc_geteuid(void)
539 uwrap_bind_symbol_libc(geteuid);
541 return uwrap.libc.symbols._libc_geteuid.f();
544 static int libc_setgid(gid_t gid)
546 uwrap_bind_symbol_libc(setgid);
548 return uwrap.libc.symbols._libc_setgid.f(gid);
551 static gid_t libc_getgid(void)
553 uwrap_bind_symbol_libc(getgid);
555 return uwrap.libc.symbols._libc_getgid.f();
559 static int libc_setegid(gid_t egid)
561 uwrap_bind_symbol_libc(setegid);
563 return uwrap.libc.symbols._libc_setegid.f(egid);
568 static int libc_setregid(gid_t rgid, gid_t egid)
570 uwrap_bind_symbol_libc(setregid);
572 return uwrap.libc.symbols._libc_setregid.f(rgid, egid);
576 #ifdef HAVE_SETRESGID
577 static int libc_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
579 uwrap_bind_symbol_libc(setresgid);
581 return uwrap.libc.symbols._libc_setresgid.f(rgid, egid, sgid);
585 #ifdef HAVE_GETRESGID
586 static int libc_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
588 uwrap_bind_symbol_libc(setresgid);
590 return uwrap.libc.symbols._libc_getresgid.f(rgid, egid, sgid);
594 static gid_t libc_getegid(void)
596 uwrap_bind_symbol_libc(getegid);
598 return uwrap.libc.symbols._libc_getegid.f();
601 static int libc_getgroups(int size, gid_t list[])
603 uwrap_bind_symbol_libc(getgroups);
605 return uwrap.libc.symbols._libc_getgroups.f(size, list);
608 static int libc_setgroups(size_t size, const gid_t *list)
610 uwrap_bind_symbol_libc(setgroups);
612 return uwrap.libc.symbols._libc_setgroups.f(size, list);
616 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
617 static long int libc_vsyscall(long int sysno, va_list va)
623 uwrap_bind_symbol_libc(syscall);
625 for (i = 0; i < 8; i++) {
626 args[i] = va_arg(va, long int);
629 rc = uwrap.libc.symbols._libc_syscall.f(sysno,
644 * This part is "optimistic".
645 * Thread can ends without pthread_exit call.
647 static void libpthread_pthread_exit(void *retval)
649 uwrap_bind_symbol_libpthread(pthread_exit);
651 uwrap.libpthread.symbols._libpthread_pthread_exit.f(retval);
654 static void uwrap_pthread_exit(void *retval)
656 struct uwrap_thread *id = uwrap_tls_id;
658 UWRAP_LOG(UWRAP_LOG_DEBUG, "Cleanup thread");
660 UWRAP_LOCK(uwrap_id);
662 UWRAP_UNLOCK(uwrap_id);
663 libpthread_pthread_exit(retval);
667 UWRAP_DLIST_REMOVE(uwrap.ids, id);
668 SAFE_FREE(id->groups);
672 UWRAP_UNLOCK(uwrap_id);
674 libpthread_pthread_exit(retval);
677 void pthread_exit(void *retval)
679 if (!uid_wrapper_enabled()) {
680 libpthread_pthread_exit(retval);
683 uwrap_pthread_exit(retval);
685 /* Calm down gcc warning. */
689 static int libpthread_pthread_create(pthread_t *thread,
690 const pthread_attr_t *attr,
691 void *(*start_routine) (void *),
694 uwrap_bind_symbol_libpthread(pthread_create);
695 return uwrap.libpthread.symbols._libpthread_pthread_create.f(thread,
701 struct uwrap_pthread_create_args {
702 struct uwrap_thread *id;
703 void *(*start_routine) (void *);
707 static void *uwrap_pthread_create_start(void *_a)
709 struct uwrap_pthread_create_args *a =
710 (struct uwrap_pthread_create_args *)_a;
711 void *(*start_routine) (void *) = a->start_routine;
713 struct uwrap_thread *id = a->id;
719 return start_routine(arg);
722 static int uwrap_pthread_create(pthread_t *thread,
723 const pthread_attr_t *attr,
724 void *(*start_routine) (void *),
727 struct uwrap_pthread_create_args *args;
728 struct uwrap_thread *src_id = uwrap_tls_id;
731 args = malloc(sizeof(struct uwrap_pthread_create_args));
733 UWRAP_LOG(UWRAP_LOG_ERROR,
734 "uwrap_pthread_create: Unable to allocate memory");
738 args->start_routine = start_routine;
741 args->id = calloc(1, sizeof(struct uwrap_thread));
742 if (args->id == NULL) {
744 UWRAP_LOG(UWRAP_LOG_ERROR,
745 "uwrap_pthread_create: Unable to allocate memory");
750 UWRAP_LOCK(uwrap_id);
752 args->id->groups = malloc(sizeof(gid_t) * src_id->ngroups);
753 if (args->id->groups == NULL) {
754 UWRAP_UNLOCK(uwrap_id);
757 UWRAP_LOG(UWRAP_LOG_ERROR,
758 "uwrap_pthread_create: Unable to allocate memory again");
763 args->id->ruid = src_id->ruid;
764 args->id->euid = src_id->euid;
765 args->id->suid = src_id->suid;
767 args->id->rgid = src_id->rgid;
768 args->id->egid = src_id->egid;
769 args->id->sgid = src_id->sgid;
771 args->id->enabled = src_id->enabled;
773 args->id->ngroups = src_id->ngroups;
774 if (src_id->groups != NULL) {
775 memcpy(args->id->groups, src_id->groups,
776 sizeof(gid_t) * src_id->ngroups);
778 SAFE_FREE(args->id->groups);
781 UWRAP_DLIST_ADD(uwrap.ids, args->id);
782 UWRAP_UNLOCK(uwrap_id);
784 ret = libpthread_pthread_create(thread, attr,
785 uwrap_pthread_create_start,
794 int pthread_create(pthread_t *thread,
795 const pthread_attr_t *attr,
796 void *(*start_routine) (void *),
799 if (!uid_wrapper_enabled()) {
800 return libpthread_pthread_create(thread,
806 return uwrap_pthread_create(thread,
812 /*********************************************************
814 *********************************************************/
816 #define GROUP_STRING_SIZE 16384
817 #define GROUP_MAX_COUNT (GROUP_STRING_SIZE / (10 + 1))
820 * This function exports all the IDs of the current user so if
821 * we fork and then exec we can setup uid_wrapper in the new process
824 static void uwrap_export_ids(struct uwrap_thread *id)
826 char groups_str[GROUP_STRING_SIZE] = {0};
827 size_t groups_str_size = sizeof(groups_str);
828 char unsigned_str[32] = {0};
832 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->ruid);
833 setenv("UID_WRAPPER_INITIAL_RUID", unsigned_str, 1);
835 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->euid);
836 setenv("UID_WRAPPER_INITIAL_EUID", unsigned_str, 1);
838 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->suid);
839 setenv("UID_WRAPPER_INITIAL_SUID", unsigned_str, 1);
842 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->rgid);
843 setenv("UID_WRAPPER_INITIAL_RGID", unsigned_str, 1);
845 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->egid);
846 setenv("UID_WRAPPER_INITIAL_EGID", unsigned_str, 1);
848 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->sgid);
849 setenv("UID_WRAPPER_INITIAL_SGID", unsigned_str, 1);
851 if (id->ngroups > GROUP_MAX_COUNT) {
852 UWRAP_LOG(UWRAP_LOG_ERROR,
853 "ERROR: Number of groups (%u) exceeds maximum value "
854 "uid_wrapper will handle (%u).",
861 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->ngroups);
862 setenv("UID_WRAPPER_INITIAL_GROUPS_COUNT", unsigned_str, 1);
864 for (i = 0; i < id->ngroups; i++) {
865 size_t groups_str_len = strlen(groups_str);
866 size_t groups_str_avail = groups_str_size - groups_str_len;
869 len = snprintf(unsigned_str, sizeof(unsigned_str), ",%u", id->groups[i]);
873 if (len < groups_str_avail) {
874 snprintf(groups_str + groups_str_len,
875 groups_str_size - groups_str_len,
877 i == 0 ? unsigned_str + 1 : unsigned_str);
881 if (id->ngroups > 0) {
882 setenv("UID_WRAPPER_INITIAL_GROUPS", groups_str, 1);
886 static void uwrap_thread_prepare(void)
888 struct uwrap_thread *id = uwrap_tls_id;
890 /* uid_wrapper is loaded but not enabled */
898 * What happens if another atfork prepare functions calls a uwrap
899 * function? So disable it in case another atfork prepare function
900 * calls a (s)uid function. We disable uid_wrapper only for thread
901 * (process) which called fork.
906 static void uwrap_thread_parent(void)
908 struct uwrap_thread *id = uwrap_tls_id;
910 /* uid_wrapper is loaded but not enabled */
920 static void uwrap_thread_child(void)
922 struct uwrap_thread *id = uwrap_tls_id;
923 struct uwrap_thread *u = uwrap.ids;
925 /* uid_wrapper is loaded but not enabled */
930 uwrap_export_ids(id);
933 * "Garbage collector" - Inspired by DESTRUCTOR.
934 * All threads (except one which called fork()) are dead now.. Dave
935 * That's what posix said...
939 /* Skip this item. */
944 UWRAP_DLIST_REMOVE(uwrap.ids, u);
946 SAFE_FREE(u->groups);
958 * This initializes uid_wrapper with the IDs exported to the environment. Those
959 * are normally set after we forked and executed.
961 static void uwrap_init_env(struct uwrap_thread *id)
966 env = getenv("UID_WRAPPER_INITIAL_RUID");
967 if (env != NULL && env[0] != '\0') {
968 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initialize ruid with %s", env);
969 id->ruid = strtoul(env, (char **)NULL, 10);
970 unsetenv("UID_WRAPPER_INITIAL_RUID");
973 env = getenv("UID_WRAPPER_INITIAL_EUID");
974 if (env != NULL && env[0] != '\0') {
975 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize euid with %s", env);
976 id->euid = strtoul(env, (char **)NULL, 10);
977 unsetenv("UID_WRAPPER_INITIAL_EUID");
980 env = getenv("UID_WRAPPER_INITIAL_SUID");
981 if (env != NULL && env[0] != '\0') {
982 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize suid with %s", env);
983 id->suid = strtoul(env, (char **)NULL, 10);
984 unsetenv("UID_WRAPPER_INITIAL_SUID");
987 env = getenv("UID_WRAPPER_INITIAL_RGID");
988 if (env != NULL && env[0] != '\0') {
989 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initialize ruid with %s", env);
990 id->rgid = strtoul(env, (char **)NULL, 10);
991 unsetenv("UID_WRAPPER_INITIAL_RGID");
994 env = getenv("UID_WRAPPER_INITIAL_EGID");
995 if (env != NULL && env[0] != '\0') {
996 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize egid with %s", env);
997 id->egid = strtoul(env, (char **)NULL, 10);
998 unsetenv("UID_WRAPPER_INITIAL_EGID");
1001 env = getenv("UID_WRAPPER_INITIAL_SGID");
1002 if (env != NULL && env[0] != '\0') {
1003 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize sgid with %s", env);
1004 id->sgid = strtoul(env, (char **)NULL, 10);
1005 unsetenv("UID_WRAPPER_INITIAL_SGID");
1008 env = getenv("UID_WRAPPER_INITIAL_GROUPS_COUNT");
1009 if (env != NULL && env[0] != '\0') {
1010 ngroups = strtol(env, (char **)NULL, 10);
1011 unsetenv("UID_WRAPPER_INITIAL_GROUPS_COUNT");
1014 if (ngroups > 0 && ngroups < GROUP_MAX_COUNT) {
1020 id->groups = malloc(sizeof(gid_t) * ngroups);
1021 if (id->groups == NULL) {
1022 UWRAP_LOG(UWRAP_LOG_ERROR,
1023 "Unable to allocate memory");
1027 env = getenv("UID_WRAPPER_INITIAL_GROUPS");
1028 if (env != NULL && env[0] != '\0') {
1029 char *groups_str = NULL;
1030 char *saveptr = NULL;
1031 const char *p = NULL;
1033 groups_str = strdup(env);
1034 if (groups_str == NULL) {
1038 p = strtok_r(groups_str, ",", &saveptr);
1040 id->groups[i] = strtol(p, (char **)NULL, 10);
1043 p = strtok_r(NULL, ",", &saveptr);
1045 SAFE_FREE(groups_str);
1049 UWRAP_LOG(UWRAP_LOG_ERROR,
1050 "ERROR: The number of groups (%u) passed, "
1051 "does not the number of groups (%u) we "
1058 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize groups with %s", env);
1059 id->ngroups = ngroups;
1063 static void uwrap_init(void)
1067 UWRAP_LOCK(uwrap_id);
1069 if (uwrap.initialised) {
1070 struct uwrap_thread *id = uwrap_tls_id;
1072 if (uwrap.ids == NULL) {
1073 UWRAP_UNLOCK(uwrap_id);
1078 UWRAP_LOG(UWRAP_LOG_ERROR,
1079 "Invalid id for thread");
1083 UWRAP_UNLOCK(uwrap_id);
1087 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initialize uid_wrapper");
1089 uwrap.initialised = true;
1091 env = getenv("UID_WRAPPER");
1092 if (env != NULL && env[0] == '1') {
1093 const char *root = getenv("UID_WRAPPER_ROOT");
1094 struct uwrap_thread *id;
1096 id = calloc(1, sizeof(struct uwrap_thread));
1098 UWRAP_LOG(UWRAP_LOG_ERROR,
1099 "Unable to allocate memory for main id");
1103 UWRAP_DLIST_ADD(uwrap.ids, id);
1106 uwrap.myuid = libc_geteuid();
1107 uwrap.mygid = libc_getegid();
1109 /* put us in one group */
1110 if (root != NULL && root[0] == '1') {
1111 id->ruid = id->euid = id->suid = 0;
1112 id->rgid = id->egid = id->sgid = 0;
1114 id->groups = malloc(sizeof(gid_t) * 1);
1115 if (id->groups == NULL) {
1116 UWRAP_LOG(UWRAP_LOG_ERROR,
1117 "Unable to allocate memory");
1125 id->ruid = id->euid = id->suid = uwrap.myuid;
1126 id->rgid = id->egid = id->sgid = uwrap.mygid;
1128 id->ngroups = libc_getgroups(0, NULL);
1129 if (id->ngroups == -1) {
1130 UWRAP_LOG(UWRAP_LOG_ERROR,
1131 "Unable to call libc_getgroups in uwrap_init.");
1134 id->groups = malloc(sizeof(gid_t) * id->ngroups);
1135 if (id->groups == NULL) {
1136 UWRAP_LOG(UWRAP_LOG_ERROR, "Unable to allocate memory");
1139 if (libc_getgroups(id->ngroups, id->groups) == -1) {
1140 UWRAP_LOG(UWRAP_LOG_ERROR,
1141 "Unable to call libc_getgroups again in uwrap_init.");
1144 * Deallocation of uwrap.groups is handled by
1145 * library destructor.
1155 UWRAP_LOG(UWRAP_LOG_DEBUG,
1156 "Enabled uid_wrapper as %s (real uid=%u)",
1157 id->ruid == 0 ? "root" : "user",
1158 (unsigned int)uwrap.myuid);
1161 UWRAP_UNLOCK(uwrap_id);
1163 UWRAP_LOG(UWRAP_LOG_DEBUG, "Succeccfully initialized uid_wrapper");
1166 bool uid_wrapper_enabled(void)
1168 struct uwrap_thread *id = uwrap_tls_id;
1175 UWRAP_LOCK(uwrap_id);
1176 enabled = id->enabled;
1177 UWRAP_UNLOCK(uwrap_id);
1183 * UWRAP_SETxUID FUNCTIONS
1186 static int uwrap_setresuid_args(uid_t ruid, uid_t euid, uid_t suid)
1188 struct uwrap_thread *id = uwrap_tls_id;
1190 UWRAP_LOG(UWRAP_LOG_TRACE,
1191 "ruid %d -> %d, euid %d -> %d, suid %d -> %d",
1192 id->ruid, ruid, id->euid, euid, id->suid, suid);
1194 if (id->euid != 0) {
1195 if (ruid != (uid_t)-1 &&
1202 if (euid != (uid_t)-1 &&
1209 if (suid != (uid_t)-1 &&
1221 static int uwrap_setresuid_thread(uid_t ruid, uid_t euid, uid_t suid)
1223 struct uwrap_thread *id = uwrap_tls_id;
1226 UWRAP_LOG(UWRAP_LOG_TRACE,
1227 "ruid %d -> %d, euid %d -> %d, suid %d -> %d",
1228 id->ruid, ruid, id->euid, euid, id->suid, suid);
1230 rc = uwrap_setresuid_args(ruid, euid, suid);
1235 UWRAP_LOCK(uwrap_id);
1237 if (ruid != (uid_t)-1) {
1241 if (euid != (uid_t)-1) {
1245 if (suid != (uid_t)-1) {
1249 UWRAP_UNLOCK(uwrap_id);
1254 static int uwrap_setresuid(uid_t ruid, uid_t euid, uid_t suid)
1256 struct uwrap_thread *id = uwrap_tls_id;
1259 UWRAP_LOG(UWRAP_LOG_TRACE,
1260 "ruid %d -> %d, euid %d -> %d, suid %d -> %d",
1261 id->ruid, ruid, id->euid, euid, id->suid, suid);
1263 rc = uwrap_setresuid_args(ruid, euid, suid);
1268 UWRAP_LOCK(uwrap_id);
1270 for (id = uwrap.ids; id; id = id->next) {
1271 if (ruid != (uid_t)-1) {
1275 if (euid != (uid_t)-1) {
1279 if (suid != (uid_t)-1) {
1284 UWRAP_UNLOCK(uwrap_id);
1289 static int uwrap_setreuid_args(uid_t ruid, uid_t euid,
1294 struct uwrap_thread *id = uwrap_tls_id;
1295 uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
1297 UWRAP_LOG(UWRAP_LOG_TRACE,
1298 "ruid %d -> %d, euid %d -> %d",
1299 id->ruid, ruid, id->euid, euid);
1301 if (ruid != (uid_t)-1) {
1303 if (ruid != id->ruid &&
1311 if (euid != (uid_t)-1) {
1313 if (euid != id->ruid &&
1322 if (ruid != (uid_t) -1 ||
1323 (euid != (uid_t)-1 && id->ruid != euid)) {
1324 new_suid = new_euid;
1327 *_new_ruid = new_ruid;
1328 *_new_euid = new_euid;
1329 *_new_suid = new_suid;
1334 static int uwrap_setreuid_thread(uid_t ruid, uid_t euid)
1337 struct uwrap_thread *id = uwrap_tls_id;
1339 uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
1342 UWRAP_LOG(UWRAP_LOG_TRACE,
1343 "ruid %d -> %d, euid %d -> %d",
1344 id->ruid, ruid, id->euid, euid);
1346 rc = uwrap_setreuid_args(ruid, euid, &new_ruid, &new_euid, &new_suid);
1351 return uwrap_setresuid_thread(new_ruid, new_euid, new_suid);
1354 #ifdef HAVE_SETREUID
1355 static int uwrap_setreuid(uid_t ruid, uid_t euid)
1358 struct uwrap_thread *id = uwrap_tls_id;
1360 uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
1363 UWRAP_LOG(UWRAP_LOG_TRACE,
1364 "ruid %d -> %d, euid %d -> %d",
1365 id->ruid, ruid, id->euid, euid);
1367 rc = uwrap_setreuid_args(ruid, euid, &new_ruid, &new_euid, &new_suid);
1372 return uwrap_setresuid(new_ruid, new_euid, new_suid);
1376 static int uwrap_setuid_args(uid_t uid,
1381 struct uwrap_thread *id = uwrap_tls_id;
1383 UWRAP_LOG(UWRAP_LOG_TRACE,
1387 if (uid == (uid_t)-1) {
1392 if (id->euid == 0) {
1393 *new_suid = *new_ruid = uid;
1394 } else if (uid != id->ruid &&
1405 static int uwrap_setuid_thread(uid_t uid)
1407 uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
1410 rc = uwrap_setuid_args(uid, &new_ruid, &new_euid, &new_suid);
1415 return uwrap_setresuid_thread(new_ruid, new_euid, new_suid);
1418 static int uwrap_setuid(uid_t uid)
1420 uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
1423 rc = uwrap_setuid_args(uid, &new_ruid, &new_euid, &new_suid);
1428 return uwrap_setresuid(new_ruid, new_euid, new_suid);
1432 * UWRAP_GETxUID FUNCTIONS
1435 #ifdef HAVE_GETRESUID
1436 static int uwrap_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
1438 struct uwrap_thread *id = uwrap_tls_id;
1440 UWRAP_LOCK(uwrap_id);
1446 UWRAP_UNLOCK(uwrap_id);
1452 #ifdef HAVE_GETRESGID
1453 static int uwrap_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
1455 struct uwrap_thread *id = uwrap_tls_id;
1457 UWRAP_LOCK(uwrap_id);
1463 UWRAP_UNLOCK(uwrap_id);
1470 * UWRAP_SETxGID FUNCTIONS
1473 static int uwrap_setresgid_args(gid_t rgid, gid_t egid, gid_t sgid)
1475 struct uwrap_thread *id = uwrap_tls_id;
1477 UWRAP_LOG(UWRAP_LOG_TRACE,
1478 "rgid %d -> %d, egid %d -> %d, sgid %d -> %d",
1479 id->rgid, rgid, id->egid, egid, id->sgid, sgid);
1481 if (id->euid != 0) {
1482 if (rgid != (gid_t)-1 &&
1489 if (egid != (gid_t)-1 &&
1496 if (sgid != (gid_t)-1 &&
1508 static int uwrap_setresgid_thread(gid_t rgid, gid_t egid, gid_t sgid)
1510 struct uwrap_thread *id = uwrap_tls_id;
1513 UWRAP_LOG(UWRAP_LOG_TRACE,
1514 "rgid %d -> %d, egid %d -> %d, sgid %d -> %d",
1515 id->rgid, rgid, id->egid, egid, id->sgid, sgid);
1517 rc = uwrap_setresgid_args(rgid, egid, sgid);
1522 UWRAP_LOCK(uwrap_id);
1524 if (rgid != (gid_t)-1) {
1528 if (egid != (gid_t)-1) {
1532 if (sgid != (gid_t)-1) {
1536 UWRAP_UNLOCK(uwrap_id);
1541 static int uwrap_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
1543 struct uwrap_thread *id = uwrap_tls_id;
1546 UWRAP_LOG(UWRAP_LOG_TRACE,
1547 "rgid %d -> %d, egid %d -> %d, sgid %d -> %d",
1548 id->rgid, rgid, id->egid, egid, id->sgid, sgid);
1550 rc = uwrap_setresgid_args(rgid, egid, sgid);
1555 UWRAP_LOCK(uwrap_id);
1557 for (id = uwrap.ids; id; id = id->next) {
1558 if (rgid != (gid_t)-1) {
1562 if (egid != (gid_t)-1) {
1566 if (sgid != (gid_t)-1) {
1571 UWRAP_UNLOCK(uwrap_id);
1576 static int uwrap_setregid_args(gid_t rgid, gid_t egid,
1581 struct uwrap_thread *id = uwrap_tls_id;
1582 gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
1584 UWRAP_LOG(UWRAP_LOG_TRACE,
1585 "rgid %d -> %d, egid %d -> %d",
1586 id->rgid, rgid, id->egid, egid);
1588 if (rgid != (gid_t)-1) {
1590 if (rgid != id->rgid &&
1598 if (egid != (gid_t)-1) {
1600 if (egid != id->rgid &&
1609 if (rgid != (gid_t) -1 ||
1610 (egid != (gid_t)-1 && id->rgid != egid)) {
1611 new_sgid = new_egid;
1614 *_new_rgid = new_rgid;
1615 *_new_egid = new_egid;
1616 *_new_sgid = new_sgid;
1621 static int uwrap_setregid_thread(gid_t rgid, gid_t egid)
1624 struct uwrap_thread *id = uwrap_tls_id;
1626 gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
1629 UWRAP_LOG(UWRAP_LOG_TRACE,
1630 "rgid %d -> %d, egid %d -> %d",
1631 id->rgid, rgid, id->egid, egid);
1633 rc = uwrap_setregid_args(rgid, egid, &new_rgid, &new_egid, &new_sgid);
1638 return uwrap_setresgid_thread(new_rgid, new_egid, new_sgid);
1641 #ifdef HAVE_SETREGID
1642 static int uwrap_setregid(gid_t rgid, gid_t egid)
1645 struct uwrap_thread *id = uwrap_tls_id;
1647 gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
1650 UWRAP_LOG(UWRAP_LOG_TRACE,
1651 "rgid %d -> %d, egid %d -> %d",
1652 id->rgid, rgid, id->egid, egid);
1654 rc = uwrap_setregid_args(rgid, egid, &new_rgid, &new_egid, &new_sgid);
1659 return uwrap_setresgid(new_rgid, new_egid, new_sgid);
1663 static int uwrap_setgid_args(gid_t gid,
1668 struct uwrap_thread *id = uwrap_tls_id;
1670 UWRAP_LOG(UWRAP_LOG_TRACE,
1674 if (gid == (gid_t)-1) {
1679 if (id->euid == 0) {
1680 *new_sgid = *new_rgid = gid;
1681 } else if (gid != id->rgid &&
1692 static int uwrap_setgid_thread(gid_t gid)
1694 gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
1697 rc = uwrap_setgid_args(gid, &new_rgid, &new_egid, &new_sgid);
1702 return uwrap_setresgid_thread(new_rgid, new_egid, new_sgid);
1705 static int uwrap_setgid(gid_t gid)
1707 gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
1710 rc = uwrap_setgid_args(gid, &new_rgid, &new_egid, &new_sgid);
1715 return uwrap_setresgid(new_rgid, new_egid, new_sgid);
1721 int setuid(uid_t uid)
1723 if (!uid_wrapper_enabled()) {
1724 return libc_setuid(uid);
1728 return uwrap_setuid(uid);
1732 int seteuid(uid_t euid)
1734 if (!uid_wrapper_enabled()) {
1735 return libc_seteuid(euid);
1738 /* On FreeBSD the uid_t -1 is set and doesn't produce and error */
1739 if (euid == (uid_t)-1) {
1745 return uwrap_setresuid(-1, euid, -1);
1749 #ifdef HAVE_SETREUID
1750 int setreuid(uid_t ruid, uid_t euid)
1752 if (!uid_wrapper_enabled()) {
1753 return libc_setreuid(ruid, euid);
1757 return uwrap_setreuid(ruid, euid);
1761 #ifdef HAVE_SETRESUID
1762 int setresuid(uid_t ruid, uid_t euid, uid_t suid)
1764 if (!uid_wrapper_enabled()) {
1765 return libc_setresuid(ruid, euid, suid);
1769 return uwrap_setresuid(ruid, euid, suid);
1773 #ifdef HAVE_GETRESUID
1774 int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
1776 if (!uid_wrapper_enabled()) {
1777 return libc_getresuid(ruid, euid, suid);
1781 return uwrap_getresuid(ruid, euid, suid);
1788 static uid_t uwrap_getuid(void)
1790 struct uwrap_thread *id = uwrap_tls_id;
1793 UWRAP_LOCK(uwrap_id);
1795 UWRAP_UNLOCK(uwrap_id);
1802 if (!uid_wrapper_enabled()) {
1803 return libc_getuid();
1807 return uwrap_getuid();
1813 static uid_t uwrap_geteuid(void)
1815 const char *env = getenv("UID_WRAPPER_MYUID");
1816 struct uwrap_thread *id = uwrap_tls_id;
1819 UWRAP_LOCK(uwrap_id);
1821 UWRAP_UNLOCK(uwrap_id);
1823 /* Disable root and return myuid */
1824 if (env != NULL && env[0] == '1') {
1833 if (!uid_wrapper_enabled()) {
1834 return libc_geteuid();
1838 return uwrap_geteuid();
1844 int setgid(gid_t gid)
1846 if (!uid_wrapper_enabled()) {
1847 return libc_setgid(gid);
1851 return uwrap_setgid(gid);
1855 int setegid(gid_t egid)
1857 if (!uid_wrapper_enabled()) {
1858 return libc_setegid(egid);
1861 /* On FreeBSD the uid_t -1 is set and doesn't produce and error */
1862 if (egid == (gid_t)-1) {
1868 return uwrap_setresgid(-1, egid, -1);
1872 #ifdef HAVE_SETREGID
1873 int setregid(gid_t rgid, gid_t egid)
1875 if (!uid_wrapper_enabled()) {
1876 return libc_setregid(rgid, egid);
1880 return uwrap_setregid(rgid, egid);
1884 #ifdef HAVE_SETRESGID
1885 int setresgid(gid_t rgid, gid_t egid, gid_t sgid)
1887 if (!uid_wrapper_enabled()) {
1888 return libc_setresgid(rgid, egid, sgid);
1892 return uwrap_setresgid(rgid, egid, sgid);
1896 #ifdef HAVE_GETRESGID
1897 int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
1899 if (!uid_wrapper_enabled()) {
1900 return libc_getresgid(rgid, egid, sgid);
1904 return uwrap_getresgid(rgid, egid, sgid);
1911 static gid_t uwrap_getgid(void)
1913 struct uwrap_thread *id = uwrap_tls_id;
1916 UWRAP_LOCK(uwrap_id);
1918 UWRAP_UNLOCK(uwrap_id);
1925 if (!uid_wrapper_enabled()) {
1926 return libc_getgid();
1930 return uwrap_getgid();
1936 static uid_t uwrap_getegid(void)
1938 struct uwrap_thread *id = uwrap_tls_id;
1941 UWRAP_LOCK(uwrap_id);
1943 UWRAP_UNLOCK(uwrap_id);
1950 if (!uid_wrapper_enabled()) {
1951 return libc_getegid();
1955 return uwrap_getegid();
1958 static int uwrap_setgroups_thread(size_t size, const gid_t *list)
1960 struct uwrap_thread *id = uwrap_tls_id;
1963 UWRAP_LOCK(uwrap_id);
1966 SAFE_FREE(id->groups);
1968 } else if (size > 0) {
1971 tmp = realloc(id->groups, sizeof(gid_t) * size);
1978 memcpy(id->groups, list, size * sizeof(gid_t));
1983 UWRAP_UNLOCK(uwrap_id);
1988 static int uwrap_setgroups(size_t size, const gid_t *list)
1990 struct uwrap_thread *id;
1993 UWRAP_LOCK(uwrap_id);
1996 for (id = uwrap.ids; id; id = id->next) {
1997 SAFE_FREE(id->groups);
2001 } else if (size > 0) {
2004 for (id = uwrap.ids; id; id = id->next) {
2005 tmp = realloc(id->groups, sizeof(gid_t) * size);
2013 memcpy(id->groups, list, size * sizeof(gid_t));
2019 UWRAP_UNLOCK(uwrap_id);
2024 #ifdef HAVE_SETGROUPS_INT
2025 int setgroups(int size, const gid_t *list)
2027 int setgroups(size_t size, const gid_t *list)
2030 if (!uid_wrapper_enabled()) {
2031 return libc_setgroups(size, list);
2035 return uwrap_setgroups(size, list);
2038 static int uwrap_getgroups(int size, gid_t *list)
2040 struct uwrap_thread *id = uwrap_tls_id;
2043 UWRAP_LOCK(uwrap_id);
2044 ngroups = id->ngroups;
2046 if (size > ngroups) {
2052 if (size < ngroups) {
2056 memcpy(list, id->groups, size * sizeof(gid_t));
2059 UWRAP_UNLOCK(uwrap_id);
2064 int getgroups(int size, gid_t *list)
2066 if (!uid_wrapper_enabled()) {
2067 return libc_getgroups(size, list);
2071 return uwrap_getgroups(size, list);
2074 #if (defined(HAVE_SYS_SYSCALL_H) || defined(HAVE_SYSCALL_H)) \
2075 && (defined(SYS_setreuid) || defined(SYS_setreuid32))
2076 static long int uwrap_syscall (long int sysno, va_list vp)
2087 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2091 rc = uwrap_getgid();
2096 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2100 rc = uwrap_getegid();
2103 #endif /* SYS_getegid */
2105 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2109 gid_t gid = (gid_t) va_arg(vp, gid_t);
2111 rc = uwrap_setgid_thread(gid);
2115 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2116 case SYS_setregid32:
2119 gid_t rgid = (gid_t) va_arg(vp, gid_t);
2120 gid_t egid = (gid_t) va_arg(vp, gid_t);
2122 rc = uwrap_setregid_thread(rgid, egid);
2125 #ifdef SYS_setresgid
2127 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2128 case SYS_setresgid32:
2131 gid_t rgid = (gid_t) va_arg(vp, gid_t);
2132 gid_t egid = (gid_t) va_arg(vp, gid_t);
2133 gid_t sgid = (gid_t) va_arg(vp, gid_t);
2135 rc = uwrap_setresgid_thread(rgid, egid, sgid);
2138 #endif /* SYS_setresgid */
2139 #if defined(SYS_getresgid) && defined(HAVE_GETRESGID)
2141 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2142 case SYS_getresgid32:
2145 gid_t *rgid = (gid_t *) va_arg(vp, gid_t *);
2146 gid_t *egid = (gid_t *) va_arg(vp, gid_t *);
2147 gid_t *sgid = (gid_t *) va_arg(vp, gid_t *);
2149 rc = uwrap_getresgid(rgid, egid, sgid);
2152 #endif /* SYS_getresgid && HAVE_GETRESGID */
2160 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2164 rc = uwrap_getuid();
2169 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2173 rc = uwrap_geteuid();
2176 #endif /* SYS_geteuid */
2178 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2182 uid_t uid = (uid_t) va_arg(vp, uid_t);
2184 rc = uwrap_setuid_thread(uid);
2188 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2189 case SYS_setreuid32:
2192 uid_t ruid = (uid_t) va_arg(vp, uid_t);
2193 uid_t euid = (uid_t) va_arg(vp, uid_t);
2195 rc = uwrap_setreuid_thread(ruid, euid);
2198 #ifdef SYS_setresuid
2200 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2201 case SYS_setresuid32:
2204 uid_t ruid = (uid_t) va_arg(vp, uid_t);
2205 uid_t euid = (uid_t) va_arg(vp, uid_t);
2206 uid_t suid = (uid_t) va_arg(vp, uid_t);
2208 rc = uwrap_setresuid_thread(ruid, euid, suid);
2211 #endif /* SYS_setresuid */
2212 #if defined(SYS_getresuid) && defined(HAVE_GETRESUID)
2214 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2215 case SYS_getresuid32:
2218 uid_t *ruid = (uid_t *) va_arg(vp, uid_t *);
2219 uid_t *euid = (uid_t *) va_arg(vp, uid_t *);
2220 uid_t *suid = (uid_t *) va_arg(vp, uid_t *);
2222 rc = uwrap_getresuid(ruid, euid, suid);
2225 #endif /* SYS_getresuid && HAVE_GETRESUID*/
2228 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2229 case SYS_setgroups32:
2232 size_t size = (size_t) va_arg(vp, size_t);
2233 gid_t *list = (gid_t *) va_arg(vp, int *);
2235 rc = uwrap_setgroups_thread(size, list);
2239 UWRAP_LOG(UWRAP_LOG_DEBUG,
2240 "UID_WRAPPER calling non-wrapped syscall %lu",
2243 rc = libc_vsyscall(sysno, vp);
2251 #ifdef HAVE_SYSCALL_INT
2252 int syscall (int sysno, ...)
2254 long int syscall (long int sysno, ...)
2257 #ifdef HAVE_SYSCALL_INT
2264 va_start(va, sysno);
2266 if (!uid_wrapper_enabled()) {
2267 rc = libc_vsyscall(sysno, va);
2273 rc = uwrap_syscall(sysno, va);
2278 #endif /* HAVE_SYSCALL */
2279 #endif /* HAVE_SYS_SYSCALL_H || HAVE_SYSCALL_H */
2281 /****************************
2283 ***************************/
2284 void uwrap_constructor(void)
2287 * If we hold a lock and the application forks, then the child
2288 * is not able to unlock the mutex and we are in a deadlock.
2289 * This should prevent such deadlocks.
2291 pthread_atfork(&uwrap_thread_prepare,
2292 &uwrap_thread_parent,
2293 &uwrap_thread_child);
2295 /* Here is safe place to call uwrap_init() and initialize data
2301 /****************************
2303 ***************************/
2306 * This function is called when the library is unloaded and makes sure that
2307 * resources are freed.
2309 void uwrap_destructor(void)
2311 struct uwrap_thread *u = uwrap.ids;
2316 UWRAP_DLIST_REMOVE(uwrap.ids, u);
2318 SAFE_FREE(u->groups);
2325 if (uwrap.libc.handle != NULL) {
2326 dlclose(uwrap.libc.handle);
2329 if (uwrap.libpthread.handle != NULL) {
2330 dlclose(uwrap.libpthread.handle);