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 *format, ...) PRINTF_ATTRIBUTE(2, 3);
140 # define UWRAP_LOG(dbglvl, ...) uwrap_log((dbglvl), __VA_ARGS__)
142 static void uwrap_log(enum uwrap_dbglvl_e dbglvl, 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);
160 case UWRAP_LOG_ERROR:
162 "UWRAP_ERROR(%d): %s\n",
163 (int)getpid(), buffer);
167 "UWRAP_WARN(%d): %s\n",
168 (int)getpid(), buffer);
170 case UWRAP_LOG_DEBUG:
172 "UWRAP_DEBUG(%d): %s\n",
173 (int)getpid(), buffer);
175 case UWRAP_LOG_TRACE:
177 "UWRAP_TRACE(%d): %s\n",
178 (int)getpid(), buffer);
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) {
412 uwrap.libc.handle = handle;
415 case UWRAP_LIBPTHREAD:
416 handle = uwrap.libpthread.handle;
417 if (handle == NULL) {
418 handle = dlopen("libpthread.so.0", flags);
419 if (handle != NULL) {
426 if (handle == NULL) {
428 handle = uwrap.libc.handle = RTLD_NEXT;
431 "Failed to dlopen library: %s\n",
440 static void *_uwrap_bind_symbol(enum uwrap_lib lib, const char *fn_name)
445 handle = uwrap_load_lib_handle(lib);
447 func = dlsym(handle, fn_name);
450 "Failed to find %s: %s\n",
458 #define uwrap_bind_symbol_libc(sym_name) \
459 UWRAP_LOCK(libc_symbol_binding); \
460 if (uwrap.libc.symbols._libc_##sym_name.obj == NULL) { \
461 uwrap.libc.symbols._libc_##sym_name.obj = \
462 _uwrap_bind_symbol(UWRAP_LIBC, #sym_name); \
464 UWRAP_UNLOCK(libc_symbol_binding)
466 #define uwrap_bind_symbol_libpthread(sym_name) \
467 UWRAP_LOCK(libpthread_symbol_binding); \
468 if (uwrap.libpthread.symbols._libpthread_##sym_name.obj == NULL) { \
469 uwrap.libpthread.symbols._libpthread_##sym_name.obj = \
470 _uwrap_bind_symbol(UWRAP_LIBPTHREAD, #sym_name); \
472 UWRAP_UNLOCK(libpthread_symbol_binding)
477 * Functions expeciall from libc need to be loaded individually, you can't load
478 * all at once or gdb will segfault at startup. The same applies to valgrind and
479 * has probably something todo with with the linker.
480 * So we need load each function at the point it is called the first time.
482 static int libc_setuid(uid_t uid)
484 uwrap_bind_symbol_libc(setuid);
486 return uwrap.libc.symbols._libc_setuid.f(uid);
489 static uid_t libc_getuid(void)
491 uwrap_bind_symbol_libc(getuid);
493 return uwrap.libc.symbols._libc_getuid.f();
497 static int libc_seteuid(uid_t euid)
499 uwrap_bind_symbol_libc(seteuid);
501 return uwrap.libc.symbols._libc_seteuid.f(euid);
506 static int libc_setreuid(uid_t ruid, uid_t euid)
508 uwrap_bind_symbol_libc(setreuid);
510 return uwrap.libc.symbols._libc_setreuid.f(ruid, euid);
514 #ifdef HAVE_SETRESUID
515 static int libc_setresuid(uid_t ruid, uid_t euid, uid_t suid)
517 uwrap_bind_symbol_libc(setresuid);
519 return uwrap.libc.symbols._libc_setresuid.f(ruid, euid, suid);
523 #ifdef HAVE_GETRESUID
524 static int libc_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
526 uwrap_bind_symbol_libc(getresuid);
528 return uwrap.libc.symbols._libc_getresuid.f(ruid, euid, suid);
532 static uid_t libc_geteuid(void)
534 uwrap_bind_symbol_libc(geteuid);
536 return uwrap.libc.symbols._libc_geteuid.f();
539 static int libc_setgid(gid_t gid)
541 uwrap_bind_symbol_libc(setgid);
543 return uwrap.libc.symbols._libc_setgid.f(gid);
546 static gid_t libc_getgid(void)
548 uwrap_bind_symbol_libc(getgid);
550 return uwrap.libc.symbols._libc_getgid.f();
554 static int libc_setegid(gid_t egid)
556 uwrap_bind_symbol_libc(setegid);
558 return uwrap.libc.symbols._libc_setegid.f(egid);
563 static int libc_setregid(gid_t rgid, gid_t egid)
565 uwrap_bind_symbol_libc(setregid);
567 return uwrap.libc.symbols._libc_setregid.f(rgid, egid);
571 #ifdef HAVE_SETRESGID
572 static int libc_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
574 uwrap_bind_symbol_libc(setresgid);
576 return uwrap.libc.symbols._libc_setresgid.f(rgid, egid, sgid);
580 #ifdef HAVE_GETRESGID
581 static int libc_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
583 uwrap_bind_symbol_libc(setresgid);
585 return uwrap.libc.symbols._libc_getresgid.f(rgid, egid, sgid);
589 static gid_t libc_getegid(void)
591 uwrap_bind_symbol_libc(getegid);
593 return uwrap.libc.symbols._libc_getegid.f();
596 static int libc_getgroups(int size, gid_t list[])
598 uwrap_bind_symbol_libc(getgroups);
600 return uwrap.libc.symbols._libc_getgroups.f(size, list);
603 static int libc_setgroups(size_t size, const gid_t *list)
605 uwrap_bind_symbol_libc(setgroups);
607 return uwrap.libc.symbols._libc_setgroups.f(size, list);
611 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
612 static long int libc_vsyscall(long int sysno, va_list va)
618 uwrap_bind_symbol_libc(syscall);
620 for (i = 0; i < 8; i++) {
621 args[i] = va_arg(va, long int);
624 rc = uwrap.libc.symbols._libc_syscall.f(sysno,
639 * This part is "optimistic".
640 * Thread can ends without pthread_exit call.
642 static void libpthread_pthread_exit(void *retval)
644 uwrap_bind_symbol_libpthread(pthread_exit);
646 uwrap.libpthread.symbols._libpthread_pthread_exit.f(retval);
649 static void uwrap_pthread_exit(void *retval)
651 struct uwrap_thread *id = uwrap_tls_id;
653 UWRAP_LOG(UWRAP_LOG_DEBUG, "Cleanup thread");
655 UWRAP_LOCK(uwrap_id);
657 UWRAP_UNLOCK(uwrap_id);
658 libpthread_pthread_exit(retval);
661 UWRAP_DLIST_REMOVE(uwrap.ids, id);
662 SAFE_FREE(id->groups);
666 UWRAP_UNLOCK(uwrap_id);
668 libpthread_pthread_exit(retval);
671 void pthread_exit(void *retval)
673 if (!uid_wrapper_enabled()) {
674 libpthread_pthread_exit(retval);
677 uwrap_pthread_exit(retval);
679 /* Calm down gcc warning. */
683 static int libpthread_pthread_create(pthread_t *thread,
684 const pthread_attr_t *attr,
685 void *(*start_routine) (void *),
688 uwrap_bind_symbol_libpthread(pthread_create);
689 return uwrap.libpthread.symbols._libpthread_pthread_create.f(thread,
695 struct uwrap_pthread_create_args {
696 struct uwrap_thread *id;
697 void *(*start_routine) (void *);
701 static void *uwrap_pthread_create_start(void *_a)
703 struct uwrap_pthread_create_args *a =
704 (struct uwrap_pthread_create_args *)_a;
705 void *(*start_routine) (void *) = a->start_routine;
707 struct uwrap_thread *id = a->id;
713 return start_routine(arg);
716 static int uwrap_pthread_create(pthread_t *thread,
717 const pthread_attr_t *attr,
718 void *(*start_routine) (void *),
721 struct uwrap_pthread_create_args *args;
722 struct uwrap_thread *src_id = uwrap_tls_id;
725 args = malloc(sizeof(struct uwrap_pthread_create_args));
727 UWRAP_LOG(UWRAP_LOG_ERROR,
728 "uwrap_pthread_create: Unable to allocate memory");
732 args->start_routine = start_routine;
735 args->id = calloc(1, sizeof(struct uwrap_thread));
736 if (args->id == NULL) {
738 UWRAP_LOG(UWRAP_LOG_ERROR,
739 "uwrap_pthread_create: Unable to allocate memory");
744 UWRAP_LOCK(uwrap_id);
746 args->id->groups = malloc(sizeof(gid_t) * src_id->ngroups);
747 if (args->id->groups == NULL) {
748 UWRAP_UNLOCK(uwrap_id);
751 UWRAP_LOG(UWRAP_LOG_ERROR,
752 "uwrap_pthread_create: Unable to allocate memory again");
757 args->id->ruid = src_id->ruid;
758 args->id->euid = src_id->euid;
759 args->id->suid = src_id->suid;
761 args->id->rgid = src_id->rgid;
762 args->id->egid = src_id->egid;
763 args->id->sgid = src_id->sgid;
765 args->id->enabled = src_id->enabled;
767 args->id->ngroups = src_id->ngroups;
768 if (src_id->groups != NULL) {
769 memcpy(args->id->groups, src_id->groups,
770 sizeof(gid_t) * src_id->ngroups);
772 SAFE_FREE(args->id->groups);
775 UWRAP_DLIST_ADD(uwrap.ids, args->id);
776 UWRAP_UNLOCK(uwrap_id);
778 ret = libpthread_pthread_create(thread, attr,
779 uwrap_pthread_create_start,
788 int pthread_create(pthread_t *thread,
789 const pthread_attr_t *attr,
790 void *(*start_routine) (void *),
793 if (!uid_wrapper_enabled()) {
794 return libpthread_pthread_create(thread,
800 return uwrap_pthread_create(thread,
806 /*********************************************************
808 *********************************************************/
810 static void uwrap_thread_prepare(void)
812 struct uwrap_thread *id = uwrap_tls_id;
817 * What happens if another atfork prepare functions calls a uwrap
818 * function? So disable it in case another atfork prepare function
819 * calls a (s)uid function. We disable uid_wrapper only for thread
820 * (process) which called fork.
825 static void uwrap_thread_parent(void)
827 struct uwrap_thread *id = uwrap_tls_id;
833 static void uwrap_thread_child(void)
835 struct uwrap_thread *id = uwrap_tls_id;
836 struct uwrap_thread *u = uwrap.ids;
839 * "Garbage collector" - Inspired by DESTRUCTOR.
840 * All threads (except one which called fork()) are dead now.. Dave
841 * That's what posix said...
845 /* Skip this item. */
850 UWRAP_DLIST_REMOVE(uwrap.ids, u);
852 SAFE_FREE(u->groups);
863 static void uwrap_init(void)
867 UWRAP_LOCK(uwrap_id);
869 if (uwrap.initialised) {
870 struct uwrap_thread *id = uwrap_tls_id;
872 if (uwrap.ids == NULL) {
873 UWRAP_UNLOCK(uwrap_id);
878 UWRAP_LOG(UWRAP_LOG_ERROR,
879 "Invalid id for thread");
883 UWRAP_UNLOCK(uwrap_id);
887 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initialize uid_wrapper");
889 uwrap.initialised = true;
891 env = getenv("UID_WRAPPER");
892 if (env != NULL && env[0] == '1') {
893 const char *root = getenv("UID_WRAPPER_ROOT");
894 struct uwrap_thread *id;
896 id = calloc(1, sizeof(struct uwrap_thread));
898 UWRAP_LOG(UWRAP_LOG_ERROR,
899 "Unable to allocate memory for main id");
903 UWRAP_DLIST_ADD(uwrap.ids, id);
906 uwrap.myuid = libc_geteuid();
907 uwrap.mygid = libc_getegid();
909 /* put us in one group */
910 if (root != NULL && root[0] == '1') {
911 id->ruid = id->euid = id->suid = 0;
912 id->rgid = id->egid = id->sgid = 0;
914 id->groups = malloc(sizeof(gid_t) * 1);
915 if (id->groups == NULL) {
916 UWRAP_LOG(UWRAP_LOG_ERROR,
917 "Unable to allocate memory");
925 id->ruid = id->euid = id->suid = uwrap.myuid;
926 id->rgid = id->egid = id->sgid = uwrap.mygid;
928 id->ngroups = libc_getgroups(0, NULL);
929 if (id->ngroups == -1) {
930 UWRAP_LOG(UWRAP_LOG_ERROR,
931 "Unable to call libc_getgroups in uwrap_init.");
934 id->groups = malloc(sizeof(gid_t) * id->ngroups);
935 if (id->groups == NULL) {
936 UWRAP_LOG(UWRAP_LOG_ERROR, "Unable to allocate memory");
939 if (libc_getgroups(id->ngroups, id->groups) == -1) {
940 UWRAP_LOG(UWRAP_LOG_ERROR,
941 "Unable to call libc_getgroups again in uwrap_init.");
944 * Deallocation of uwrap.groups is handled by
945 * library destructor.
953 UWRAP_LOG(UWRAP_LOG_DEBUG,
954 "Enabled uid_wrapper as %s",
955 uwrap.myuid == 0 ? "root" : "user");
958 UWRAP_UNLOCK(uwrap_id);
960 UWRAP_LOG(UWRAP_LOG_DEBUG, "Succeccfully initialized uid_wrapper");
963 bool uid_wrapper_enabled(void)
965 struct uwrap_thread *id = uwrap_tls_id;
972 UWRAP_LOCK(uwrap_id);
973 enabled = id->enabled;
974 UWRAP_UNLOCK(uwrap_id);
979 #ifdef HAVE_GETRESUID
980 static int uwrap_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
982 struct uwrap_thread *id = uwrap_tls_id;
984 UWRAP_LOCK(uwrap_id);
990 UWRAP_UNLOCK(uwrap_id);
996 static int uwrap_setresuid_thread(uid_t ruid, uid_t euid, uid_t suid)
998 struct uwrap_thread *id = uwrap_tls_id;
1000 if (ruid == (uid_t)-1 && euid == (uid_t)-1 && suid == (uid_t)-1) {
1005 UWRAP_LOCK(uwrap_id);
1006 if (ruid != (uid_t)-1) {
1010 if (euid != (uid_t)-1) {
1014 if (suid != (uid_t)-1) {
1018 UWRAP_UNLOCK(uwrap_id);
1023 #ifdef HAVE_GETRESGID
1024 static int uwrap_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
1026 struct uwrap_thread *id = uwrap_tls_id;
1028 UWRAP_LOCK(uwrap_id);
1034 UWRAP_UNLOCK(uwrap_id);
1040 static int uwrap_setresuid(uid_t ruid, uid_t euid, uid_t suid)
1042 struct uwrap_thread *id;
1044 if (ruid == (uid_t)-1 && euid == (uid_t)-1 && suid == (uid_t)-1) {
1049 UWRAP_LOCK(uwrap_id);
1050 for (id = uwrap.ids; id; id = id->next) {
1051 if (ruid != (uid_t)-1) {
1055 if (euid != (uid_t)-1) {
1059 if (suid != (uid_t)-1) {
1064 UWRAP_UNLOCK(uwrap_id);
1072 int setuid(uid_t uid)
1074 if (!uid_wrapper_enabled()) {
1075 return libc_setuid(uid);
1079 return uwrap_setresuid(uid, -1, -1);
1083 int seteuid(uid_t euid)
1085 if (euid == (uid_t)-1) {
1090 if (!uid_wrapper_enabled()) {
1091 return libc_seteuid(euid);
1095 return uwrap_setresuid(-1, euid, -1);
1099 #ifdef HAVE_SETREUID
1100 int setreuid(uid_t ruid, uid_t euid)
1102 if (ruid == (uid_t)-1 && euid == (uid_t)-1) {
1107 if (!uid_wrapper_enabled()) {
1108 return libc_setreuid(ruid, euid);
1112 return uwrap_setresuid(ruid, euid, -1);
1116 #ifdef HAVE_SETRESUID
1117 int setresuid(uid_t ruid, uid_t euid, uid_t suid)
1119 if (!uid_wrapper_enabled()) {
1120 return libc_setresuid(ruid, euid, suid);
1124 return uwrap_setresuid(ruid, euid, suid);
1128 #ifdef HAVE_GETRESUID
1129 int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
1131 if (!uid_wrapper_enabled()) {
1132 return libc_getresuid(ruid, euid, suid);
1136 return uwrap_getresuid(ruid, euid, suid);
1143 static uid_t uwrap_getuid(void)
1145 struct uwrap_thread *id = uwrap_tls_id;
1148 UWRAP_LOCK(uwrap_id);
1150 UWRAP_UNLOCK(uwrap_id);
1157 if (!uid_wrapper_enabled()) {
1158 return libc_getuid();
1162 return uwrap_getuid();
1168 static uid_t uwrap_geteuid(void)
1170 const char *env = getenv("UID_WRAPPER_MYUID");
1171 struct uwrap_thread *id = uwrap_tls_id;
1174 UWRAP_LOCK(uwrap_id);
1176 UWRAP_UNLOCK(uwrap_id);
1178 /* Disable root and return myuid */
1179 if (env != NULL && env[0] == '1') {
1188 if (!uid_wrapper_enabled()) {
1189 return libc_geteuid();
1193 return uwrap_geteuid();
1196 static int uwrap_setresgid_thread(gid_t rgid, gid_t egid, gid_t sgid)
1198 struct uwrap_thread *id = uwrap_tls_id;
1200 if (rgid == (gid_t)-1 && egid == (gid_t)-1 && sgid == (gid_t)-1) {
1205 UWRAP_LOCK(uwrap_id);
1206 if (rgid != (gid_t)-1) {
1210 if (egid != (gid_t)-1) {
1214 if (sgid != (gid_t)-1) {
1218 UWRAP_UNLOCK(uwrap_id);
1223 static int uwrap_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
1225 struct uwrap_thread *id;
1227 if (rgid == (gid_t)-1 && egid == (gid_t)-1 && sgid == (gid_t)-1) {
1232 UWRAP_LOCK(uwrap_id);
1233 for (id = uwrap.ids; id; id = id->next) {
1234 if (rgid != (gid_t)-1) {
1238 if (egid != (gid_t)-1) {
1242 if (sgid != (gid_t)-1) {
1246 UWRAP_UNLOCK(uwrap_id);
1254 int setgid(gid_t gid)
1256 if (!uid_wrapper_enabled()) {
1257 return libc_setgid(gid);
1261 return uwrap_setresgid(gid, -1, -1);
1265 int setegid(gid_t egid)
1267 if (!uid_wrapper_enabled()) {
1268 return libc_setegid(egid);
1272 return uwrap_setresgid(-1, egid, -1);
1276 #ifdef HAVE_SETREGID
1277 int setregid(gid_t rgid, gid_t egid)
1279 if (!uid_wrapper_enabled()) {
1280 return libc_setregid(rgid, egid);
1284 return uwrap_setresgid(rgid, egid, -1);
1288 #ifdef HAVE_SETRESGID
1289 int setresgid(gid_t rgid, gid_t egid, gid_t sgid)
1291 if (!uid_wrapper_enabled()) {
1292 return libc_setresgid(rgid, egid, sgid);
1296 return uwrap_setresgid(rgid, egid, sgid);
1300 #ifdef HAVE_GETRESGID
1301 int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
1303 if (!uid_wrapper_enabled()) {
1304 return libc_getresgid(rgid, egid, sgid);
1308 return uwrap_getresgid(rgid, egid, sgid);
1315 static gid_t uwrap_getgid(void)
1317 struct uwrap_thread *id = uwrap_tls_id;
1320 UWRAP_LOCK(uwrap_id);
1322 UWRAP_UNLOCK(uwrap_id);
1329 if (!uid_wrapper_enabled()) {
1330 return libc_getgid();
1334 return uwrap_getgid();
1340 static uid_t uwrap_getegid(void)
1342 struct uwrap_thread *id = uwrap_tls_id;
1345 UWRAP_LOCK(uwrap_id);
1347 UWRAP_UNLOCK(uwrap_id);
1354 if (!uid_wrapper_enabled()) {
1355 return libc_getegid();
1359 return uwrap_getegid();
1362 static int uwrap_setgroups_thread(size_t size, const gid_t *list)
1364 struct uwrap_thread *id = uwrap_tls_id;
1367 UWRAP_LOCK(uwrap_id);
1370 SAFE_FREE(id->groups);
1372 } else if (size > 0) {
1375 tmp = realloc(id->groups, sizeof(gid_t) * size);
1382 memcpy(id->groups, list, size * sizeof(gid_t));
1387 UWRAP_UNLOCK(uwrap_id);
1392 static int uwrap_setgroups(size_t size, const gid_t *list)
1394 struct uwrap_thread *id;
1397 UWRAP_LOCK(uwrap_id);
1400 for (id = uwrap.ids; id; id = id->next) {
1401 SAFE_FREE(id->groups);
1405 } else if (size > 0) {
1408 for (id = uwrap.ids; id; id = id->next) {
1409 tmp = realloc(id->groups, sizeof(gid_t) * size);
1417 memcpy(id->groups, list, size * sizeof(gid_t));
1423 UWRAP_UNLOCK(uwrap_id);
1428 #ifdef HAVE_SETGROUPS_INT
1429 int setgroups(int size, const gid_t *list)
1431 int setgroups(size_t size, const gid_t *list)
1434 if (!uid_wrapper_enabled()) {
1435 return libc_setgroups(size, list);
1439 return uwrap_setgroups(size, list);
1442 static int uwrap_getgroups(int size, gid_t *list)
1444 struct uwrap_thread *id = uwrap_tls_id;
1447 UWRAP_LOCK(uwrap_id);
1448 ngroups = id->ngroups;
1450 if (size > ngroups) {
1456 if (size < ngroups) {
1460 memcpy(list, id->groups, size * sizeof(gid_t));
1463 UWRAP_UNLOCK(uwrap_id);
1468 int getgroups(int size, gid_t *list)
1470 if (!uid_wrapper_enabled()) {
1471 return libc_getgroups(size, list);
1475 return uwrap_getgroups(size, list);
1478 #if (defined(HAVE_SYS_SYSCALL_H) || defined(HAVE_SYSCALL_H)) \
1479 && (defined(SYS_setreuid) || defined(SYS_setreuid32))
1480 static long int uwrap_syscall (long int sysno, va_list vp)
1487 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1491 rc = uwrap_getgid();
1496 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1500 rc = uwrap_getegid();
1503 #endif /* SYS_getegid */
1505 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1509 gid_t gid = (gid_t) va_arg(vp, gid_t);
1511 rc = uwrap_setresgid_thread(gid, -1, -1);
1515 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1516 case SYS_setregid32:
1519 gid_t rgid = (gid_t) va_arg(vp, gid_t);
1520 gid_t egid = (gid_t) va_arg(vp, gid_t);
1522 rc = uwrap_setresgid_thread(rgid, egid, -1);
1525 #ifdef SYS_setresgid
1527 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1528 case SYS_setresgid32:
1531 gid_t rgid = (gid_t) va_arg(vp, gid_t);
1532 gid_t egid = (gid_t) va_arg(vp, gid_t);
1533 gid_t sgid = (gid_t) va_arg(vp, gid_t);
1535 rc = uwrap_setresgid_thread(rgid, egid, sgid);
1538 #endif /* SYS_setresgid */
1539 #ifdef SYS_getresgid
1541 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1542 case SYS_getresgid32:
1545 gid_t *rgid = (gid_t *) va_arg(vp, gid_t *);
1546 gid_t *egid = (gid_t *) va_arg(vp, gid_t *);
1547 gid_t *sgid = (gid_t *) va_arg(vp, gid_t *);
1549 rc = uwrap_getresgid(rgid, egid, sgid);
1552 #endif /* SYS_getresgid */
1556 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1560 rc = uwrap_getuid();
1565 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1569 rc = uwrap_geteuid();
1572 #endif /* SYS_geteuid */
1574 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1578 uid_t uid = (uid_t) va_arg(vp, uid_t);
1580 rc = uwrap_setresuid_thread(uid, -1, -1);
1584 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1585 case SYS_setreuid32:
1588 uid_t ruid = (uid_t) va_arg(vp, uid_t);
1589 uid_t euid = (uid_t) va_arg(vp, uid_t);
1591 rc = uwrap_setresuid_thread(ruid, euid, -1);
1594 #ifdef SYS_setresuid
1596 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1597 case SYS_setresuid32:
1600 uid_t ruid = (uid_t) va_arg(vp, uid_t);
1601 uid_t euid = (uid_t) va_arg(vp, uid_t);
1602 uid_t suid = (uid_t) va_arg(vp, uid_t);
1604 rc = uwrap_setresuid_thread(ruid, euid, suid);
1607 #endif /* SYS_setresuid */
1608 #ifdef SYS_getresuid
1610 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1611 case SYS_getresuid32:
1614 uid_t *ruid = (uid_t *) va_arg(vp, uid_t *);
1615 uid_t *euid = (uid_t *) va_arg(vp, uid_t *);
1616 uid_t *suid = (uid_t *) va_arg(vp, uid_t *);
1618 rc = uwrap_getresuid(ruid, euid, suid);
1621 #endif /* SYS_getresuid */
1624 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1625 case SYS_setgroups32:
1628 size_t size = (size_t) va_arg(vp, size_t);
1629 gid_t *list = (gid_t *) va_arg(vp, int *);
1631 rc = uwrap_setgroups_thread(size, list);
1635 UWRAP_LOG(UWRAP_LOG_DEBUG,
1636 "UID_WRAPPER calling non-wrapped syscall %lu\n",
1639 rc = libc_vsyscall(sysno, vp);
1647 #ifdef HAVE_SYSCALL_INT
1648 int syscall (int sysno, ...)
1650 long int syscall (long int sysno, ...)
1653 #ifdef HAVE_SYSCALL_INT
1660 va_start(va, sysno);
1662 if (!uid_wrapper_enabled()) {
1663 rc = libc_vsyscall(sysno, va);
1669 rc = uwrap_syscall(sysno, va);
1674 #endif /* HAVE_SYSCALL */
1675 #endif /* HAVE_SYS_SYSCALL_H || HAVE_SYSCALL_H */
1677 /****************************
1679 ***************************/
1680 void uwrap_constructor(void)
1683 * If we hold a lock and the application forks, then the child
1684 * is not able to unlock the mutex and we are in a deadlock.
1685 * This should prevent such deadlocks.
1687 pthread_atfork(&uwrap_thread_prepare,
1688 &uwrap_thread_parent,
1689 &uwrap_thread_child);
1691 /* Here is safe place to call uwrap_init() and initialize data
1697 /****************************
1699 ***************************/
1702 * This function is called when the library is unloaded and makes sure that
1703 * resources are freed.
1705 void uwrap_destructor(void)
1707 struct uwrap_thread *u = uwrap.ids;
1712 UWRAP_DLIST_REMOVE(uwrap.ids, u);
1714 SAFE_FREE(u->groups);
1721 if (uwrap.libc.handle != NULL) {
1722 dlclose(uwrap.libc.handle);
1725 if (uwrap.libpthread.handle != NULL) {
1726 dlclose(uwrap.libpthread.handle);