autorid: introduce idmap_autorid_domsid_is_for_alloc()
[Samba.git] / lib / uid_wrapper / uid_wrapper.c
blobcb99481993a3104d5fda02620d5b32cb8682147e
1 /*
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/>.
19 #include "config.h"
21 #include <errno.h>
22 #include <stdarg.h>
23 #include <stdbool.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29 #include <grp.h>
30 #ifdef HAVE_SYS_SYSCALL_H
31 #include <sys/syscall.h>
32 #endif
33 #ifdef HAVE_SYSCALL_H
34 #include <syscall.h>
35 #endif
36 #include <dlfcn.h>
38 #include <pthread.h>
40 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
41 # define UWRAP_THREAD __thread
42 #else
43 # define UWRAP_THREAD
44 #endif
46 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
47 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
48 #else
49 #define DESTRUCTOR_ATTRIBUTE
50 #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
52 #ifdef NDEBUG
53 #define UWRAP_DEBUG(...)
54 #else
55 #define UWRAP_DEBUG(...) fprintf(stderr, __VA_ARGS__)
56 #endif
58 #define UWRAP_DLIST_ADD(list,item) do { \
59 if (!(list)) { \
60 (item)->prev = NULL; \
61 (item)->next = NULL; \
62 (list) = (item); \
63 } else { \
64 (item)->prev = NULL; \
65 (item)->next = (list); \
66 (list)->prev = (item); \
67 (list) = (item); \
68 } \
69 } while (0)
71 #define UWRAP_DLIST_REMOVE(list,item) do { \
72 if ((list) == (item)) { \
73 (list) = (item)->next; \
74 if (list) { \
75 (list)->prev = NULL; \
76 } \
77 } else { \
78 if ((item)->prev) { \
79 (item)->prev->next = (item)->next; \
80 } \
81 if ((item)->next) { \
82 (item)->next->prev = (item)->prev; \
83 } \
84 } \
85 (item)->prev = NULL; \
86 (item)->next = NULL; \
87 } while (0)
89 #ifndef SAFE_FREE
90 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
91 #endif
93 #define LIBC_NAME "libc.so"
95 struct uwrap_libc_fns {
96 int (*_libc_setuid)(uid_t uid);
97 uid_t (*_libc_getuid)(void);
99 #ifdef HAVE_SETEUID
100 int (*_libc_seteuid)(uid_t euid);
101 #endif
102 #ifdef HAVE_SETREUID
103 int (*_libc_setreuid)(uid_t ruid, uid_t euid);
104 #endif
105 #ifdef HAVE_SETRESUID
106 int (*_libc_setresuid)(uid_t ruid, uid_t euid, uid_t suid);
107 #endif
108 uid_t (*_libc_geteuid)(void);
110 int (*_libc_setgid)(gid_t gid);
111 gid_t (*_libc_getgid)(void);
112 #ifdef HAVE_SETEGID
113 int (*_libc_setegid)(uid_t egid);
114 #endif
115 #ifdef HAVE_SETREGID
116 int (*_libc_setregid)(uid_t rgid, uid_t egid);
117 #endif
118 #ifdef HAVE_SETRESGID
119 int (*_libc_setresgid)(uid_t rgid, uid_t egid, uid_t sgid);
120 #endif
121 gid_t (*_libc_getegid)(void);
122 int (*_libc_getgroups)(int size, gid_t list[]);
123 int (*_libc_setgroups)(size_t size, const gid_t *list);
124 #ifdef HAVE_SYSCALL
125 long int (*_libc_syscall)(long int sysno, ...);
126 #endif
130 * We keep the virtualised euid/egid/groups information here
132 struct uwrap_thread {
133 pthread_t tid;
134 bool dead;
136 uid_t ruid;
137 uid_t euid;
138 uid_t suid;
140 gid_t rgid;
141 gid_t egid;
142 gid_t sgid;
144 gid_t *groups;
145 int ngroups;
147 struct uwrap_thread *next;
148 struct uwrap_thread *prev;
151 struct uwrap {
152 struct {
153 void *handle;
154 struct uwrap_libc_fns fns;
155 } libc;
157 bool initialised;
158 bool enabled;
160 uid_t myuid;
161 uid_t mygid;
163 struct uwrap_thread *ids;
166 static struct uwrap uwrap;
168 /* Shortcut to the list item */
169 static UWRAP_THREAD struct uwrap_thread *uwrap_tls_id;
171 /* The mutex or accessing the id */
172 static pthread_mutex_t uwrap_id_mutex = PTHREAD_MUTEX_INITIALIZER;
174 /*********************************************************
175 * UWRAP PROTOTYPES
176 *********************************************************/
178 bool uid_wrapper_enabled(void);
179 void uwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
181 /*********************************************************
182 * UWRAP LIBC LOADER FUNCTIONS
183 *********************************************************/
185 enum uwrap_lib {
186 UWRAP_LIBC,
187 UWRAP_LIBNSL,
188 UWRAP_LIBSOCKET,
191 static void *uwrap_load_lib_handle(enum uwrap_lib lib)
193 int flags = RTLD_LAZY;
194 void *handle = NULL;
195 int i;
197 #ifdef HAVE_APPLE
198 return RTLD_NEXT;
199 #endif
201 #ifdef RTLD_DEEPBIND
202 flags |= RTLD_DEEPBIND;
203 #endif
205 switch (lib) {
206 case UWRAP_LIBNSL:
207 /* FALL TROUGH */
208 case UWRAP_LIBSOCKET:
209 /* FALL TROUGH */
210 case UWRAP_LIBC:
211 handle = uwrap.libc.handle;
212 if (handle == NULL) {
213 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
214 char soname[256] = {0};
216 snprintf(soname, sizeof(soname), "libc.so.%d", i);
217 handle = dlopen(soname, flags);
220 uwrap.libc.handle = handle;
222 break;
225 if (handle == NULL) {
226 fprintf(stderr,
227 "Failed to dlopen library: %s\n",
228 dlerror());
229 exit(-1);
232 return handle;
235 static void *_uwrap_load_lib_function(enum uwrap_lib lib, const char *fn_name)
237 void *handle;
238 void *func;
240 handle = uwrap_load_lib_handle(lib);
242 func = dlsym(handle, fn_name);
243 if (func == NULL) {
244 fprintf(stderr,
245 "Failed to find %s: %s\n",
246 fn_name, dlerror());
247 exit(-1);
250 return func;
253 #define uwrap_load_lib_function(lib, fn_name) \
254 if (uwrap.libc.fns._libc_##fn_name == NULL) { \
255 *(void **) (&uwrap.libc.fns._libc_##fn_name) = \
256 _uwrap_load_lib_function(lib, #fn_name); \
260 * IMPORTANT
262 * Functions expeciall from libc need to be loaded individually, you can't load
263 * all at once or gdb will segfault at startup. The same applies to valgrind and
264 * has probably something todo with with the linker.
265 * So we need load each function at the point it is called the first time.
267 static int libc_setuid(uid_t uid)
269 uwrap_load_lib_function(UWRAP_LIBC, setuid);
271 return uwrap.libc.fns._libc_setuid(uid);
274 static uid_t libc_getuid(void)
276 uwrap_load_lib_function(UWRAP_LIBC, getuid);
278 return uwrap.libc.fns._libc_getuid();
281 #ifdef HAVE_SETEUID
282 static int libc_seteuid(uid_t euid)
284 uwrap_load_lib_function(UWRAP_LIBC, seteuid);
286 return uwrap.libc.fns._libc_seteuid(euid);
288 #endif
290 #ifdef HAVE_SETREUID
291 static int libc_setreuid(uid_t ruid, uid_t euid)
293 uwrap_load_lib_function(UWRAP_LIBC, setreuid);
295 return uwrap.libc.fns._libc_setreuid(ruid, euid);
297 #endif
299 #ifdef HAVE_SETRESUID
300 static int libc_setresuid(uid_t ruid, uid_t euid, uid_t suid)
302 uwrap_load_lib_function(UWRAP_LIBC, setresuid);
304 return uwrap.libc.fns._libc_setresuid(ruid, euid, suid);
306 #endif
308 static uid_t libc_geteuid(void)
310 uwrap_load_lib_function(UWRAP_LIBC, geteuid);
312 return uwrap.libc.fns._libc_geteuid();
315 static int libc_setgid(gid_t gid)
317 uwrap_load_lib_function(UWRAP_LIBC, setgid);
319 return uwrap.libc.fns._libc_setgid(gid);
322 static gid_t libc_getgid(void)
324 uwrap_load_lib_function(UWRAP_LIBC, getgid);
326 return uwrap.libc.fns._libc_getgid();
329 #ifdef HAVE_SETEGID
330 static int libc_setegid(gid_t egid)
332 uwrap_load_lib_function(UWRAP_LIBC, setegid);
334 return uwrap.libc.fns._libc_setegid(egid);
336 #endif
338 #ifdef HAVE_SETREGID
339 static int libc_setregid(gid_t rgid, gid_t egid)
341 uwrap_load_lib_function(UWRAP_LIBC, setregid);
343 return uwrap.libc.fns._libc_setregid(rgid, egid);
345 #endif
347 #ifdef HAVE_SETRESGID
348 static int libc_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
350 uwrap_load_lib_function(UWRAP_LIBC, setresgid);
352 return uwrap.libc.fns._libc_setresgid(rgid, egid, sgid);
354 #endif
356 static gid_t libc_getegid(void)
358 uwrap_load_lib_function(UWRAP_LIBC, getegid);
360 return uwrap.libc.fns._libc_getegid();
363 static int libc_getgroups(int size, gid_t list[])
365 uwrap_load_lib_function(UWRAP_LIBC, getgroups);
367 return uwrap.libc.fns._libc_getgroups(size, list);
370 static int libc_setgroups(size_t size, const gid_t *list)
372 uwrap_load_lib_function(UWRAP_LIBC, setgroups);
374 return uwrap.libc.fns._libc_setgroups(size, list);
377 #ifdef HAVE_SYSCALL
378 static long int libc_vsyscall(long int sysno, va_list va)
380 long int args[8];
381 long int rc;
382 int i;
384 uwrap_load_lib_function(UWRAP_LIBC, syscall);
386 for (i = 0; i < 8; i++) {
387 args[i] = va_arg(va, long int);
390 rc = uwrap.libc.fns._libc_syscall(sysno,
391 args[0],
392 args[1],
393 args[2],
394 args[3],
395 args[4],
396 args[5],
397 args[6],
398 args[7]);
400 return rc;
402 #endif
404 /*********************************************************
405 * UWRAP ID HANDLING
406 *********************************************************/
408 static struct uwrap_thread *find_uwrap_id(pthread_t tid)
410 struct uwrap_thread *id;
412 for (id = uwrap.ids; id; id = id->next) {
413 if (pthread_equal(id->tid, tid)) {
414 return id;
418 return NULL;
421 static int uwrap_new_id(pthread_t tid, bool do_alloc)
423 struct uwrap_thread *id = uwrap_tls_id;
425 if (do_alloc) {
426 id = malloc(sizeof(struct uwrap_thread));
427 if (id == NULL) {
428 errno = ENOMEM;
429 return -1;
432 id->groups = malloc(sizeof(gid_t) * 1);
433 if (id->groups == NULL) {
434 errno = ENOMEM;
435 return -1;
438 UWRAP_DLIST_ADD(uwrap.ids, id);
439 uwrap_tls_id = id;
442 id->tid = tid;
443 id->dead = false;
445 id->ruid = id->euid = id->suid = uwrap.myuid;
446 id->rgid = id->egid = id->sgid = uwrap.mygid;
448 id->ngroups = 1;
449 id->groups[0] = uwrap.mygid;
451 return 0;
454 static void uwrap_thread_prepare(void)
456 pthread_mutex_lock(&uwrap_id_mutex);
459 * What happens if another atfork prepare functions calls a uwrap
460 * function? So disable it in case another atfork prepare function
461 * calls a (s)uid function.
463 uwrap.enabled = false;
466 static void uwrap_thread_parent(void)
468 uwrap.enabled = true;
470 pthread_mutex_unlock(&uwrap_id_mutex);
473 static void uwrap_thread_child(void)
475 uwrap.enabled = true;
477 pthread_mutex_unlock(&uwrap_id_mutex);
480 static void uwrap_init(void)
482 const char *env = getenv("UID_WRAPPER");
483 pthread_t tid = pthread_self();
487 if (uwrap.initialised) {
488 struct uwrap_thread *id = uwrap_tls_id;
489 int rc;
491 if (id != NULL) {
492 return;
495 pthread_mutex_lock(&uwrap_id_mutex);
496 id = find_uwrap_id(tid);
497 if (id == NULL) {
498 rc = uwrap_new_id(tid, true);
499 if (rc < 0) {
500 exit(-1);
502 } else {
503 /* We reuse an old thread id */
504 uwrap_tls_id = id;
506 uwrap_new_id(tid, false);
508 pthread_mutex_unlock(&uwrap_id_mutex);
510 return;
514 * If we hold a lock and the application forks, then the child
515 * is not able to unlock the mutex and we are in a deadlock.
516 * This should prevent such deadlocks.
518 pthread_atfork(&uwrap_thread_prepare,
519 &uwrap_thread_parent,
520 &uwrap_thread_child);
522 pthread_mutex_lock(&uwrap_id_mutex);
524 uwrap.initialised = true;
525 uwrap.enabled = false;
527 if (env != NULL && env[0] == '1') {
528 const char *root = getenv("UID_WRAPPER_ROOT");
529 int rc;
531 /* put us in one group */
532 if (root != NULL && root[0] == '1') {
533 uwrap.myuid = 0;
534 uwrap.mygid = 0;
535 } else {
536 uwrap.myuid = libc_geteuid();
537 uwrap.mygid = libc_getegid();
540 rc = uwrap_new_id(tid, true);
541 if (rc < 0) {
542 exit(-1);
545 uwrap.enabled = true;
548 pthread_mutex_unlock(&uwrap_id_mutex);
551 bool uid_wrapper_enabled(void)
553 uwrap_init();
555 return uwrap.enabled ? true : false;
558 static int uwrap_setresuid_thread(uid_t ruid, uid_t euid, uid_t suid)
560 struct uwrap_thread *id = uwrap_tls_id;
562 if (ruid == (uid_t)-1 && euid == (uid_t)-1 && suid == (uid_t)-1) {
563 errno = EINVAL;
564 return -1;
567 pthread_mutex_lock(&uwrap_id_mutex);
568 if (ruid != (uid_t)-1) {
569 id->ruid = ruid;
572 if (euid != (uid_t)-1) {
573 id->euid = euid;
576 if (suid != (uid_t)-1) {
577 id->suid = suid;
579 pthread_mutex_unlock(&uwrap_id_mutex);
581 return 0;
584 static int uwrap_setresuid(uid_t ruid, uid_t euid, uid_t suid)
586 struct uwrap_thread *id;
588 if (ruid == (uid_t)-1 && euid == (uid_t)-1 && suid == (uid_t)-1) {
589 errno = EINVAL;
590 return -1;
593 pthread_mutex_lock(&uwrap_id_mutex);
594 for (id = uwrap.ids; id; id = id->next) {
595 if (id->dead) {
596 continue;
599 if (ruid != (uid_t)-1) {
600 id->ruid = ruid;
603 if (euid != (uid_t)-1) {
604 id->euid = euid;
607 if (suid != (uid_t)-1) {
608 id->suid = suid;
611 pthread_mutex_unlock(&uwrap_id_mutex);
613 return 0;
617 * SETUID
619 int setuid(uid_t uid)
621 if (!uid_wrapper_enabled()) {
622 return libc_setuid(uid);
625 return uwrap_setresuid(uid, -1, -1);
628 #ifdef HAVE_SETEUID
629 int seteuid(uid_t euid)
631 if (euid == (uid_t)-1) {
632 errno = EINVAL;
633 return -1;
636 if (!uid_wrapper_enabled()) {
637 return libc_seteuid(euid);
640 return uwrap_setresuid(-1, euid, -1);
642 #endif
644 #ifdef HAVE_SETREUID
645 int setreuid(uid_t ruid, uid_t euid)
647 if (ruid == (uid_t)-1 && euid == (uid_t)-1) {
648 errno = EINVAL;
649 return -1;
652 if (!uid_wrapper_enabled()) {
653 return libc_setreuid(ruid, euid);
656 return uwrap_setresuid(ruid, euid, -1);
658 #endif
660 #ifdef HAVE_SETRESUID
661 int setresuid(uid_t ruid, uid_t euid, uid_t suid)
663 if (!uid_wrapper_enabled()) {
664 return libc_setresuid(ruid, euid, suid);
667 return uwrap_setresuid(ruid, euid, suid);
669 #endif
672 * GETUID
674 static uid_t uwrap_getuid(void)
676 struct uwrap_thread *id = uwrap_tls_id;
677 uid_t uid;
679 pthread_mutex_lock(&uwrap_id_mutex);
680 uid = id->ruid;
681 pthread_mutex_unlock(&uwrap_id_mutex);
683 return uid;
686 uid_t getuid(void)
688 if (!uid_wrapper_enabled()) {
689 return libc_getuid();
692 return uwrap_getuid();
696 * GETEUID
698 static uid_t uwrap_geteuid(void)
700 const char *env = getenv("UID_WRAPPER_MYUID");
701 struct uwrap_thread *id = uwrap_tls_id;
702 uid_t uid;
704 pthread_mutex_lock(&uwrap_id_mutex);
705 uid = id->euid;
706 pthread_mutex_unlock(&uwrap_id_mutex);
708 /* Disable root and return myuid */
709 if (env != NULL && env[0] == '1') {
710 uid = uwrap.myuid;
713 return uid;
716 uid_t geteuid(void)
718 if (!uid_wrapper_enabled()) {
719 return libc_geteuid();
722 return uwrap_geteuid();
725 static int uwrap_setresgid_thread(gid_t rgid, gid_t egid, gid_t sgid)
727 struct uwrap_thread *id = uwrap_tls_id;
729 if (rgid == (gid_t)-1 && egid == (gid_t)-1 && sgid == (gid_t)-1) {
730 errno = EINVAL;
731 return -1;
734 pthread_mutex_lock(&uwrap_id_mutex);
735 if (rgid != (gid_t)-1) {
736 id->rgid = rgid;
739 if (egid != (gid_t)-1) {
740 id->egid = egid;
743 if (sgid != (gid_t)-1) {
744 id->sgid = sgid;
746 pthread_mutex_unlock(&uwrap_id_mutex);
748 return 0;
751 static int uwrap_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
753 struct uwrap_thread *id;
755 if (rgid == (gid_t)-1 && egid == (gid_t)-1 && sgid == (gid_t)-1) {
756 errno = EINVAL;
757 return -1;
760 pthread_mutex_lock(&uwrap_id_mutex);
761 for (id = uwrap.ids; id; id = id->next) {
762 if (id->dead) {
763 continue;
766 if (rgid != (gid_t)-1) {
767 id->rgid = rgid;
770 if (egid != (gid_t)-1) {
771 id->egid = egid;
774 if (sgid != (gid_t)-1) {
775 id->sgid = sgid;
778 pthread_mutex_unlock(&uwrap_id_mutex);
780 return 0;
784 * SETGID
786 int setgid(gid_t gid)
788 if (!uid_wrapper_enabled()) {
789 return libc_setgid(gid);
792 return uwrap_setresgid(gid, -1, -1);
795 #ifdef HAVE_SETEGID
796 int setegid(gid_t egid)
798 if (!uid_wrapper_enabled()) {
799 return libc_setegid(egid);
802 return uwrap_setresgid(-1, egid, -1);
804 #endif
806 #ifdef HAVE_SETREGID
807 int setregid(gid_t rgid, gid_t egid)
809 if (!uid_wrapper_enabled()) {
810 return libc_setregid(rgid, egid);
813 return uwrap_setresgid(rgid, egid, -1);
815 #endif
817 #ifdef HAVE_SETRESGID
818 int setresgid(gid_t rgid, gid_t egid, gid_t sgid)
820 if (!uid_wrapper_enabled()) {
821 return libc_setresgid(rgid, egid, sgid);
824 return uwrap_setresgid(rgid, egid, sgid);
826 #endif
829 * GETGID
831 static gid_t uwrap_getgid(void)
833 struct uwrap_thread *id = uwrap_tls_id;
834 gid_t gid;
836 pthread_mutex_lock(&uwrap_id_mutex);
837 gid = id->rgid;
838 pthread_mutex_unlock(&uwrap_id_mutex);
840 return gid;
843 gid_t getgid(void)
845 if (!uid_wrapper_enabled()) {
846 return libc_getgid();
849 return uwrap_getgid();
853 * GETEGID
855 static uid_t uwrap_getegid(void)
857 struct uwrap_thread *id = uwrap_tls_id;
858 gid_t gid;
860 pthread_mutex_lock(&uwrap_id_mutex);
861 gid = id->egid;
862 pthread_mutex_unlock(&uwrap_id_mutex);
864 return gid;
867 uid_t getegid(void)
869 if (!uid_wrapper_enabled()) {
870 return libc_getegid();
873 return uwrap_getegid();
876 static int uwrap_setgroups_thread(size_t size, const gid_t *list)
878 struct uwrap_thread *id = uwrap_tls_id;
879 int rc = -1;
881 pthread_mutex_lock(&uwrap_id_mutex);
883 if (size > 0) {
884 gid_t *tmp;
886 tmp = realloc(id->groups, sizeof(gid_t) * size);
887 if (tmp == NULL) {
888 errno = ENOMEM;
889 goto out;
891 id->groups = tmp;
893 id->ngroups = size;
894 memcpy(id->groups, list, size * sizeof(gid_t));
897 rc = 0;
898 out:
899 pthread_mutex_unlock(&uwrap_id_mutex);
901 return rc;
904 static int uwrap_setgroups(size_t size, const gid_t *list)
906 struct uwrap_thread *id;
907 int rc = -1;
909 pthread_mutex_lock(&uwrap_id_mutex);
911 if (size > 0) {
912 for (id = uwrap.ids; id; id = id->next) {
913 gid_t *tmp;
915 tmp = realloc(id->groups, sizeof(gid_t) * size);
916 if (tmp == NULL) {
917 errno = ENOMEM;
918 goto out;
920 id->groups = tmp;
922 id->ngroups = size;
923 memcpy(id->groups, list, size * sizeof(gid_t));
927 rc = 0;
928 out:
929 pthread_mutex_unlock(&uwrap_id_mutex);
931 return rc;
934 #ifdef HAVE_SETGROUPS_INT
935 int setgroups(int size, const gid_t *list)
936 #else
937 int setgroups(size_t size, const gid_t *list)
938 #endif
940 if (!uid_wrapper_enabled()) {
941 return libc_setgroups(size, list);
944 return uwrap_setgroups(size, list);
947 static int uwrap_getgroups(int size, gid_t *list)
949 struct uwrap_thread *id = uwrap_tls_id;
950 int ngroups;
952 pthread_mutex_lock(&uwrap_id_mutex);
953 ngroups = id->ngroups;
955 if (size > ngroups) {
956 size = ngroups;
958 if (size == 0) {
959 goto out;
961 if (size < ngroups) {
962 errno = EINVAL;
963 ngroups = -1;
965 memcpy(list, id->groups, size * sizeof(gid_t));
967 out:
968 pthread_mutex_unlock(&uwrap_id_mutex);
970 return ngroups;
973 int getgroups(int size, gid_t *list)
975 if (!uid_wrapper_enabled()) {
976 return libc_getgroups(size, list);
979 return uwrap_getgroups(size, list);
982 #if (defined(HAVE_SYS_SYSCALL_H) || defined(HAVE_SYSCALL_H)) \
983 && (defined(SYS_setreuid) || defined(SYS_setreuid32))
984 static long int uwrap_syscall (long int sysno, va_list vp)
986 long int rc;
988 switch (sysno) {
989 /* gid */
990 case SYS_getgid:
991 #ifdef HAVE_LINUX_32BIT_SYSCALLS
992 case SYS_getgid32:
993 #endif
995 rc = uwrap_getgid();
997 break;
998 #ifdef SYS_getegid
999 case SYS_getegid:
1000 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1001 case SYS_getegid32:
1002 #endif
1004 rc = uwrap_getegid();
1006 break;
1007 #endif /* SYS_getegid */
1008 case SYS_setgid:
1009 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1010 case SYS_setgid32:
1011 #endif
1013 gid_t gid = (gid_t) va_arg(vp, int);
1015 rc = uwrap_setresgid_thread(gid, -1, -1);
1017 break;
1018 case SYS_setregid:
1019 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1020 case SYS_setregid32:
1021 #endif
1023 uid_t rgid = (uid_t) va_arg(vp, int);
1024 uid_t egid = (uid_t) va_arg(vp, int);
1026 rc = uwrap_setresgid_thread(rgid, egid, -1);
1028 break;
1029 #ifdef SYS_setresgid
1030 case SYS_setresgid:
1031 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1032 case SYS_setresgid32:
1033 #endif
1035 uid_t rgid = (uid_t) va_arg(vp, int);
1036 uid_t egid = (uid_t) va_arg(vp, int);
1037 uid_t sgid = (uid_t) va_arg(vp, int);
1039 rc = uwrap_setresgid_thread(rgid, egid, sgid);
1041 break;
1042 #endif /* SYS_setresgid */
1044 /* uid */
1045 case SYS_getuid:
1046 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1047 case SYS_getuid32:
1048 #endif
1050 rc = uwrap_getuid();
1052 break;
1053 #ifdef SYS_geteuid
1054 case SYS_geteuid:
1055 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1056 case SYS_geteuid32:
1057 #endif
1059 rc = uwrap_geteuid();
1061 break;
1062 #endif /* SYS_geteuid */
1063 case SYS_setuid:
1064 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1065 case SYS_setuid32:
1066 #endif
1068 uid_t uid = (uid_t) va_arg(vp, int);
1070 rc = uwrap_setresuid_thread(uid, -1, -1);
1072 break;
1073 case SYS_setreuid:
1074 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1075 case SYS_setreuid32:
1076 #endif
1078 uid_t ruid = (uid_t) va_arg(vp, int);
1079 uid_t euid = (uid_t) va_arg(vp, int);
1081 rc = uwrap_setresuid_thread(ruid, euid, -1);
1083 break;
1084 #ifdef SYS_setresuid
1085 case SYS_setresuid:
1086 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1087 case SYS_setresuid32:
1088 #endif
1090 uid_t ruid = (uid_t) va_arg(vp, int);
1091 uid_t euid = (uid_t) va_arg(vp, int);
1092 uid_t suid = (uid_t) va_arg(vp, int);
1094 rc = uwrap_setresuid_thread(ruid, euid, suid);
1096 break;
1097 #endif /* SYS_setresuid */
1099 /* groups */
1100 case SYS_setgroups:
1101 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1102 case SYS_setgroups32:
1103 #endif
1105 size_t size = (size_t) va_arg(vp, size_t);
1106 gid_t *list = (gid_t *) va_arg(vp, int *);
1108 rc = uwrap_setgroups_thread(size, list);
1110 break;
1111 default:
1112 UWRAP_DEBUG("UID_WRAPPER calling non-wrapped syscall "
1113 "%lu\n", sysno);
1115 rc = libc_vsyscall(sysno, vp);
1116 break;
1119 return rc;
1122 #ifdef HAVE_SYSCALL
1123 #ifdef HAVE_SYSCALL_INT
1124 int syscall (int sysno, ...)
1125 #else
1126 long int syscall (long int sysno, ...)
1127 #endif
1129 #ifdef HAVE_SYSCALL_INT
1130 int rc;
1131 #else
1132 long int rc;
1133 #endif
1134 va_list va;
1136 va_start(va, sysno);
1138 if (!uid_wrapper_enabled()) {
1139 rc = libc_vsyscall(sysno, va);
1140 va_end(va);
1141 return rc;
1144 rc = uwrap_syscall(sysno, va);
1145 va_end(va);
1147 return rc;
1149 #endif /* HAVE_SYSCALL */
1150 #endif /* HAVE_SYS_SYSCALL_H || HAVE_SYSCALL_H */
1152 /****************************
1153 * DESTRUCTOR
1154 ***************************/
1157 * This function is called when the library is unloaded and makes sure that
1158 * resources are freed.
1160 void uwrap_destructor(void)
1162 struct uwrap_thread *u = uwrap.ids;
1164 while (u != NULL) {
1165 UWRAP_DLIST_REMOVE(uwrap.ids, u);
1167 SAFE_FREE(u->groups);
1168 SAFE_FREE(u);
1170 u = uwrap.ids;
1173 if (uwrap.libc.handle != NULL) {
1174 dlclose(uwrap.libc.handle);