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 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
55 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
57 #define CONSTRUCTOR_ATTRIBUTE
58 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
60 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
61 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
63 #define DESTRUCTOR_ATTRIBUTE
64 #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
66 /* GCC have printf type attribute check. */
67 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
68 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
70 #define PRINTF_ATTRIBUTE(a,b)
71 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
73 #define UWRAP_DLIST_ADD(list,item) do { \
75 (item)->prev = NULL; \
76 (item)->next = NULL; \
79 (item)->prev = NULL; \
80 (item)->next = (list); \
81 (list)->prev = (item); \
86 #define UWRAP_DLIST_REMOVE(list,item) do { \
87 if ((list) == (item)) { \
88 (list) = (item)->next; \
90 (list)->prev = NULL; \
94 (item)->prev->next = (item)->next; \
97 (item)->next->prev = (item)->prev; \
100 (item)->prev = NULL; \
101 (item)->next = NULL; \
105 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
112 enum uwrap_dbglvl_e {
120 # define UWRAP_LOG(...)
122 static void uwrap_log(enum uwrap_dbglvl_e dbglvl, const char *format, ...) PRINTF_ATTRIBUTE(2, 3);
123 # define UWRAP_LOG(dbglvl, ...) uwrap_log((dbglvl), __VA_ARGS__)
125 static void uwrap_log(enum uwrap_dbglvl_e dbglvl, const char *format, ...)
130 unsigned int lvl = 0;
132 d = getenv("UID_WRAPPER_DEBUGLEVEL");
137 va_start(va, format);
138 vsnprintf(buffer, sizeof(buffer), format, va);
143 case UWRAP_LOG_ERROR:
145 "UWRAP_ERROR(%d): %s\n",
146 (int)getpid(), buffer);
150 "UWRAP_WARN(%d): %s\n",
151 (int)getpid(), buffer);
153 case UWRAP_LOG_DEBUG:
155 "UWRAP_DEBUG(%d): %s\n",
156 (int)getpid(), buffer);
158 case UWRAP_LOG_TRACE:
160 "UWRAP_TRACE(%d): %s\n",
161 (int)getpid(), buffer);
172 #define LIBC_NAME "libc.so"
174 struct uwrap_libc_fns {
175 int (*_libc_setuid)(uid_t uid);
176 uid_t (*_libc_getuid)(void);
179 int (*_libc_seteuid)(uid_t euid);
182 int (*_libc_setreuid)(uid_t ruid, uid_t euid);
184 #ifdef HAVE_SETRESUID
185 int (*_libc_setresuid)(uid_t ruid, uid_t euid, uid_t suid);
187 uid_t (*_libc_geteuid)(void);
189 int (*_libc_setgid)(gid_t gid);
190 gid_t (*_libc_getgid)(void);
192 int (*_libc_setegid)(uid_t egid);
195 int (*_libc_setregid)(uid_t rgid, uid_t egid);
197 #ifdef HAVE_SETRESGID
198 int (*_libc_setresgid)(uid_t rgid, uid_t egid, uid_t sgid);
200 gid_t (*_libc_getegid)(void);
201 int (*_libc_getgroups)(int size, gid_t list[]);
202 int (*_libc_setgroups)(size_t size, const gid_t *list);
204 long int (*_libc_syscall)(long int sysno, ...);
209 * We keep the virtualised euid/egid/groups information here
211 struct uwrap_thread {
226 struct uwrap_thread *next;
227 struct uwrap_thread *prev;
233 struct uwrap_libc_fns fns;
242 struct uwrap_thread *ids;
245 static struct uwrap uwrap;
247 /* Shortcut to the list item */
248 static UWRAP_THREAD struct uwrap_thread *uwrap_tls_id;
250 /* The mutex or accessing the id */
251 static pthread_mutex_t uwrap_id_mutex = PTHREAD_MUTEX_INITIALIZER;
253 /* The mutex for accessing the global libc.fns */
254 static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
256 /*********************************************************
258 *********************************************************/
260 bool uid_wrapper_enabled(void);
261 void uwrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
262 void uwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
264 /*********************************************************
265 * UWRAP LIBC LOADER FUNCTIONS
266 *********************************************************/
274 static void *uwrap_load_lib_handle(enum uwrap_lib lib)
276 int flags = RTLD_LAZY;
281 flags |= RTLD_DEEPBIND;
287 case UWRAP_LIBSOCKET:
290 handle = uwrap.libc.handle;
291 if (handle == NULL) {
292 for (i = 10; i >= 0; i--) {
293 char soname[256] = {0};
295 snprintf(soname, sizeof(soname), "libc.so.%d", i);
296 handle = dlopen(soname, flags);
297 if (handle != NULL) {
302 uwrap.libc.handle = handle;
307 if (handle == NULL) {
309 handle = uwrap.libc.handle = RTLD_NEXT;
312 "Failed to dlopen library: %s\n",
321 static void *_uwrap_load_lib_function(enum uwrap_lib lib, const char *fn_name)
326 handle = uwrap_load_lib_handle(lib);
328 func = dlsym(handle, fn_name);
331 "Failed to find %s: %s\n",
339 #define uwrap_load_lib_function(lib, fn_name) \
340 UWRAP_LOCK(libc_symbol_binding); \
341 if (uwrap.libc.fns._libc_##fn_name == NULL) { \
342 *(void **) (&uwrap.libc.fns._libc_##fn_name) = \
343 _uwrap_load_lib_function(lib, #fn_name); \
345 UWRAP_UNLOCK(libc_symbol_binding)
350 * Functions expeciall from libc need to be loaded individually, you can't load
351 * all at once or gdb will segfault at startup. The same applies to valgrind and
352 * has probably something todo with with the linker.
353 * So we need load each function at the point it is called the first time.
355 static int libc_setuid(uid_t uid)
357 uwrap_load_lib_function(UWRAP_LIBC, setuid);
359 return uwrap.libc.fns._libc_setuid(uid);
362 static uid_t libc_getuid(void)
364 uwrap_load_lib_function(UWRAP_LIBC, getuid);
366 return uwrap.libc.fns._libc_getuid();
370 static int libc_seteuid(uid_t euid)
372 uwrap_load_lib_function(UWRAP_LIBC, seteuid);
374 return uwrap.libc.fns._libc_seteuid(euid);
379 static int libc_setreuid(uid_t ruid, uid_t euid)
381 uwrap_load_lib_function(UWRAP_LIBC, setreuid);
383 return uwrap.libc.fns._libc_setreuid(ruid, euid);
387 #ifdef HAVE_SETRESUID
388 static int libc_setresuid(uid_t ruid, uid_t euid, uid_t suid)
390 uwrap_load_lib_function(UWRAP_LIBC, setresuid);
392 return uwrap.libc.fns._libc_setresuid(ruid, euid, suid);
396 static uid_t libc_geteuid(void)
398 uwrap_load_lib_function(UWRAP_LIBC, geteuid);
400 return uwrap.libc.fns._libc_geteuid();
403 static int libc_setgid(gid_t gid)
405 uwrap_load_lib_function(UWRAP_LIBC, setgid);
407 return uwrap.libc.fns._libc_setgid(gid);
410 static gid_t libc_getgid(void)
412 uwrap_load_lib_function(UWRAP_LIBC, getgid);
414 return uwrap.libc.fns._libc_getgid();
418 static int libc_setegid(gid_t egid)
420 uwrap_load_lib_function(UWRAP_LIBC, setegid);
422 return uwrap.libc.fns._libc_setegid(egid);
427 static int libc_setregid(gid_t rgid, gid_t egid)
429 uwrap_load_lib_function(UWRAP_LIBC, setregid);
431 return uwrap.libc.fns._libc_setregid(rgid, egid);
435 #ifdef HAVE_SETRESGID
436 static int libc_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
438 uwrap_load_lib_function(UWRAP_LIBC, setresgid);
440 return uwrap.libc.fns._libc_setresgid(rgid, egid, sgid);
444 static gid_t libc_getegid(void)
446 uwrap_load_lib_function(UWRAP_LIBC, getegid);
448 return uwrap.libc.fns._libc_getegid();
451 static int libc_getgroups(int size, gid_t list[])
453 uwrap_load_lib_function(UWRAP_LIBC, getgroups);
455 return uwrap.libc.fns._libc_getgroups(size, list);
458 static int libc_setgroups(size_t size, const gid_t *list)
460 uwrap_load_lib_function(UWRAP_LIBC, setgroups);
462 return uwrap.libc.fns._libc_setgroups(size, list);
466 static long int libc_vsyscall(long int sysno, va_list va)
472 uwrap_load_lib_function(UWRAP_LIBC, syscall);
474 for (i = 0; i < 8; i++) {
475 args[i] = va_arg(va, long int);
478 rc = uwrap.libc.fns._libc_syscall(sysno,
492 /*********************************************************
494 *********************************************************/
496 static struct uwrap_thread *find_uwrap_id(pthread_t tid)
498 struct uwrap_thread *id;
500 for (id = uwrap.ids; id; id = id->next) {
501 if (pthread_equal(id->tid, tid)) {
509 static int uwrap_new_id(pthread_t tid, bool do_alloc)
511 struct uwrap_thread *id = uwrap_tls_id;
514 id = malloc(sizeof(struct uwrap_thread));
516 UWRAP_LOG(UWRAP_LOG_ERROR, "Unable to allocate memory");
521 id->groups = malloc(sizeof(gid_t) * 1);
522 if (id->groups == NULL) {
523 UWRAP_LOG(UWRAP_LOG_ERROR, "Unable to allocate memory");
529 UWRAP_DLIST_ADD(uwrap.ids, id);
536 id->ruid = id->euid = id->suid = uwrap.myuid;
537 id->rgid = id->egid = id->sgid = uwrap.mygid;
540 id->groups[0] = uwrap.mygid;
545 static void uwrap_thread_prepare(void)
547 UWRAP_LOCK(uwrap_id);
548 UWRAP_LOCK(libc_symbol_binding);
550 * What happens if another atfork prepare functions calls a uwrap
551 * function? So disable it in case another atfork prepare function
552 * calls a (s)uid function.
554 uwrap.enabled = false;
557 static void uwrap_thread_parent(void)
559 uwrap.enabled = true;
561 UWRAP_UNLOCK(libc_symbol_binding);
562 UWRAP_UNLOCK(uwrap_id);
565 static void uwrap_thread_child(void)
567 uwrap.enabled = true;
569 UWRAP_UNLOCK(libc_symbol_binding);
570 UWRAP_UNLOCK(uwrap_id);
573 static void uwrap_init(void)
575 const char *env = getenv("UID_WRAPPER");
576 pthread_t tid = pthread_self();
578 UWRAP_LOCK(uwrap_id);
579 if (uwrap.initialised) {
580 struct uwrap_thread *id = uwrap_tls_id;
584 UWRAP_UNLOCK(uwrap_id);
588 id = find_uwrap_id(tid);
590 rc = uwrap_new_id(tid, true);
595 /* We reuse an old thread id */
598 uwrap_new_id(tid, false);
600 UWRAP_UNLOCK(uwrap_id);
605 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initialize uid_wrapper");
607 uwrap.initialised = true;
608 uwrap.enabled = false;
610 if (env != NULL && env[0] == '1') {
611 const char *root = getenv("UID_WRAPPER_ROOT");
614 /* put us in one group */
615 if (root != NULL && root[0] == '1') {
619 uwrap.myuid = libc_geteuid();
620 uwrap.mygid = libc_getegid();
623 rc = uwrap_new_id(tid, true);
628 uwrap.enabled = true;
630 UWRAP_LOG(UWRAP_LOG_DEBUG,
631 "Enabled uid_wrapper as %s",
632 uwrap.myuid == 0 ? "root" : "user");
635 UWRAP_UNLOCK(uwrap_id);
637 UWRAP_LOG(UWRAP_LOG_DEBUG, "Succeccfully initialized uid_wrapper");
640 bool uid_wrapper_enabled(void)
642 bool enabled = false;
643 #ifdef HAVE_GCC_ATOMIC_BUILTINS
644 __atomic_load(&uwrap.enabled, &enabled, __ATOMIC_RELAXED);
646 UWRAP_LOCK(uwrap_id);
647 enabled = uwrap.enabled;
648 UWRAP_UNLOCK(uwrap_id);
653 static int uwrap_setresuid_thread(uid_t ruid, uid_t euid, uid_t suid)
655 struct uwrap_thread *id = uwrap_tls_id;
657 if (ruid == (uid_t)-1 && euid == (uid_t)-1 && suid == (uid_t)-1) {
662 UWRAP_LOCK(uwrap_id);
663 if (ruid != (uid_t)-1) {
667 if (euid != (uid_t)-1) {
671 if (suid != (uid_t)-1) {
674 UWRAP_UNLOCK(uwrap_id);
679 static int uwrap_setresuid(uid_t ruid, uid_t euid, uid_t suid)
681 struct uwrap_thread *id;
683 if (ruid == (uid_t)-1 && euid == (uid_t)-1 && suid == (uid_t)-1) {
688 UWRAP_LOCK(uwrap_id);
689 for (id = uwrap.ids; id; id = id->next) {
694 if (ruid != (uid_t)-1) {
698 if (euid != (uid_t)-1) {
702 if (suid != (uid_t)-1) {
706 UWRAP_UNLOCK(uwrap_id);
714 int setuid(uid_t uid)
716 if (!uid_wrapper_enabled()) {
717 return libc_setuid(uid);
721 return uwrap_setresuid(uid, -1, -1);
725 int seteuid(uid_t euid)
727 if (euid == (uid_t)-1) {
732 if (!uid_wrapper_enabled()) {
733 return libc_seteuid(euid);
737 return uwrap_setresuid(-1, euid, -1);
742 int setreuid(uid_t ruid, uid_t euid)
744 if (ruid == (uid_t)-1 && euid == (uid_t)-1) {
749 if (!uid_wrapper_enabled()) {
750 return libc_setreuid(ruid, euid);
754 return uwrap_setresuid(ruid, euid, -1);
758 #ifdef HAVE_SETRESUID
759 int setresuid(uid_t ruid, uid_t euid, uid_t suid)
761 if (!uid_wrapper_enabled()) {
762 return libc_setresuid(ruid, euid, suid);
766 return uwrap_setresuid(ruid, euid, suid);
773 static uid_t uwrap_getuid(void)
775 struct uwrap_thread *id = uwrap_tls_id;
778 UWRAP_LOCK(uwrap_id);
780 UWRAP_UNLOCK(uwrap_id);
787 if (!uid_wrapper_enabled()) {
788 return libc_getuid();
792 return uwrap_getuid();
798 static uid_t uwrap_geteuid(void)
800 const char *env = getenv("UID_WRAPPER_MYUID");
801 struct uwrap_thread *id = uwrap_tls_id;
804 UWRAP_LOCK(uwrap_id);
806 UWRAP_UNLOCK(uwrap_id);
808 /* Disable root and return myuid */
809 if (env != NULL && env[0] == '1') {
818 if (!uid_wrapper_enabled()) {
819 return libc_geteuid();
823 return uwrap_geteuid();
826 static int uwrap_setresgid_thread(gid_t rgid, gid_t egid, gid_t sgid)
828 struct uwrap_thread *id = uwrap_tls_id;
830 if (rgid == (gid_t)-1 && egid == (gid_t)-1 && sgid == (gid_t)-1) {
835 UWRAP_LOCK(uwrap_id);
836 if (rgid != (gid_t)-1) {
840 if (egid != (gid_t)-1) {
844 if (sgid != (gid_t)-1) {
847 UWRAP_UNLOCK(uwrap_id);
852 static int uwrap_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
854 struct uwrap_thread *id;
856 if (rgid == (gid_t)-1 && egid == (gid_t)-1 && sgid == (gid_t)-1) {
861 UWRAP_LOCK(uwrap_id);
862 for (id = uwrap.ids; id; id = id->next) {
867 if (rgid != (gid_t)-1) {
871 if (egid != (gid_t)-1) {
875 if (sgid != (gid_t)-1) {
879 UWRAP_UNLOCK(uwrap_id);
887 int setgid(gid_t gid)
889 if (!uid_wrapper_enabled()) {
890 return libc_setgid(gid);
894 return uwrap_setresgid(gid, -1, -1);
898 int setegid(gid_t egid)
900 if (!uid_wrapper_enabled()) {
901 return libc_setegid(egid);
905 return uwrap_setresgid(-1, egid, -1);
910 int setregid(gid_t rgid, gid_t egid)
912 if (!uid_wrapper_enabled()) {
913 return libc_setregid(rgid, egid);
917 return uwrap_setresgid(rgid, egid, -1);
921 #ifdef HAVE_SETRESGID
922 int setresgid(gid_t rgid, gid_t egid, gid_t sgid)
924 if (!uid_wrapper_enabled()) {
925 return libc_setresgid(rgid, egid, sgid);
929 return uwrap_setresgid(rgid, egid, sgid);
936 static gid_t uwrap_getgid(void)
938 struct uwrap_thread *id = uwrap_tls_id;
941 UWRAP_LOCK(uwrap_id);
943 UWRAP_UNLOCK(uwrap_id);
950 if (!uid_wrapper_enabled()) {
951 return libc_getgid();
955 return uwrap_getgid();
961 static uid_t uwrap_getegid(void)
963 struct uwrap_thread *id = uwrap_tls_id;
966 UWRAP_LOCK(uwrap_id);
968 UWRAP_UNLOCK(uwrap_id);
975 if (!uid_wrapper_enabled()) {
976 return libc_getegid();
980 return uwrap_getegid();
983 static int uwrap_setgroups_thread(size_t size, const gid_t *list)
985 struct uwrap_thread *id = uwrap_tls_id;
988 UWRAP_LOCK(uwrap_id);
994 } else if (size > 0) {
997 tmp = realloc(id->groups, sizeof(gid_t) * size);
1005 memcpy(id->groups, list, size * sizeof(gid_t));
1010 UWRAP_UNLOCK(uwrap_id);
1015 static int uwrap_setgroups(size_t size, const gid_t *list)
1017 struct uwrap_thread *id;
1020 UWRAP_LOCK(uwrap_id);
1023 for (id = uwrap.ids; id; id = id->next) {
1028 } else if (size > 0) {
1029 for (id = uwrap.ids; id; id = id->next) {
1032 tmp = realloc(id->groups, sizeof(gid_t) * size);
1040 memcpy(id->groups, list, size * sizeof(gid_t));
1046 UWRAP_UNLOCK(uwrap_id);
1051 #ifdef HAVE_SETGROUPS_INT
1052 int setgroups(int size, const gid_t *list)
1054 int setgroups(size_t size, const gid_t *list)
1057 if (!uid_wrapper_enabled()) {
1058 return libc_setgroups(size, list);
1062 return uwrap_setgroups(size, list);
1065 static int uwrap_getgroups(int size, gid_t *list)
1067 struct uwrap_thread *id = uwrap_tls_id;
1070 UWRAP_LOCK(uwrap_id);
1071 ngroups = id->ngroups;
1073 if (size > ngroups) {
1079 if (size < ngroups) {
1083 memcpy(list, id->groups, size * sizeof(gid_t));
1086 UWRAP_UNLOCK(uwrap_id);
1091 int getgroups(int size, gid_t *list)
1093 if (!uid_wrapper_enabled()) {
1094 return libc_getgroups(size, list);
1098 return uwrap_getgroups(size, list);
1101 #if (defined(HAVE_SYS_SYSCALL_H) || defined(HAVE_SYSCALL_H)) \
1102 && (defined(SYS_setreuid) || defined(SYS_setreuid32))
1103 static long int uwrap_syscall (long int sysno, va_list vp)
1110 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1114 rc = uwrap_getgid();
1119 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1123 rc = uwrap_getegid();
1126 #endif /* SYS_getegid */
1128 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1132 gid_t gid = (gid_t) va_arg(vp, int);
1134 rc = uwrap_setresgid_thread(gid, -1, -1);
1138 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1139 case SYS_setregid32:
1142 uid_t rgid = (uid_t) va_arg(vp, int);
1143 uid_t egid = (uid_t) va_arg(vp, int);
1145 rc = uwrap_setresgid_thread(rgid, egid, -1);
1148 #ifdef SYS_setresgid
1150 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1151 case SYS_setresgid32:
1154 uid_t rgid = (uid_t) va_arg(vp, int);
1155 uid_t egid = (uid_t) va_arg(vp, int);
1156 uid_t sgid = (uid_t) va_arg(vp, int);
1158 rc = uwrap_setresgid_thread(rgid, egid, sgid);
1161 #endif /* SYS_setresgid */
1165 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1169 rc = uwrap_getuid();
1174 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1178 rc = uwrap_geteuid();
1181 #endif /* SYS_geteuid */
1183 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1187 uid_t uid = (uid_t) va_arg(vp, int);
1189 rc = uwrap_setresuid_thread(uid, -1, -1);
1193 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1194 case SYS_setreuid32:
1197 uid_t ruid = (uid_t) va_arg(vp, int);
1198 uid_t euid = (uid_t) va_arg(vp, int);
1200 rc = uwrap_setresuid_thread(ruid, euid, -1);
1203 #ifdef SYS_setresuid
1205 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1206 case SYS_setresuid32:
1209 uid_t ruid = (uid_t) va_arg(vp, int);
1210 uid_t euid = (uid_t) va_arg(vp, int);
1211 uid_t suid = (uid_t) va_arg(vp, int);
1213 rc = uwrap_setresuid_thread(ruid, euid, suid);
1216 #endif /* SYS_setresuid */
1220 #ifdef HAVE_LINUX_32BIT_SYSCALLS
1221 case SYS_setgroups32:
1224 size_t size = (size_t) va_arg(vp, size_t);
1225 gid_t *list = (gid_t *) va_arg(vp, int *);
1227 rc = uwrap_setgroups_thread(size, list);
1231 UWRAP_LOG(UWRAP_LOG_DEBUG,
1232 "UID_WRAPPER calling non-wrapped syscall %lu\n",
1235 rc = libc_vsyscall(sysno, vp);
1243 #ifdef HAVE_SYSCALL_INT
1244 int syscall (int sysno, ...)
1246 long int syscall (long int sysno, ...)
1249 #ifdef HAVE_SYSCALL_INT
1256 va_start(va, sysno);
1258 if (!uid_wrapper_enabled()) {
1259 rc = libc_vsyscall(sysno, va);
1265 rc = uwrap_syscall(sysno, va);
1270 #endif /* HAVE_SYSCALL */
1271 #endif /* HAVE_SYS_SYSCALL_H || HAVE_SYSCALL_H */
1273 /****************************
1275 ***************************/
1276 void uwrap_constructor(void)
1279 * If we hold a lock and the application forks, then the child
1280 * is not able to unlock the mutex and we are in a deadlock.
1281 * This should prevent such deadlocks.
1283 pthread_atfork(&uwrap_thread_prepare,
1284 &uwrap_thread_parent,
1285 &uwrap_thread_child);
1287 /* Here is safe place to call uwrap_init() and initialize data
1293 /****************************
1295 ***************************/
1298 * This function is called when the library is unloaded and makes sure that
1299 * resources are freed.
1301 void uwrap_destructor(void)
1303 struct uwrap_thread *u = uwrap.ids;
1305 UWRAP_LOCK(uwrap_id);
1306 UWRAP_LOCK(libc_symbol_binding);
1309 UWRAP_DLIST_REMOVE(uwrap.ids, u);
1311 SAFE_FREE(u->groups);
1317 if (uwrap.libc.handle != NULL) {
1318 dlclose(uwrap.libc.handle);
1321 UWRAP_UNLOCK(libc_symbol_binding);
1322 UWRAP_UNLOCK(uwrap_id);