LCOV - code coverage report
Current view: top level - third_party/uid_wrapper - uid_wrapper.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 504 914 55.1 %
Date: 2021-08-25 13:27:56 Functions: 37 63 58.7 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2009      Andrew Tridgell
       3             :  * Copyright (c) 2011-2013 Andreas Schneider <asn@samba.org>
       4             :  *
       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.
       9             :  *
      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.
      14             :  *
      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/>.
      17             :  */
      18             : 
      19             : #include "config.h"
      20             : 
      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>
      37             : #include <limits.h>
      38             : 
      39             : #include <pthread.h>
      40             : 
      41             : #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
      42             : # define UWRAP_THREAD __thread
      43             : #else
      44             : # define UWRAP_THREAD
      45             : #endif
      46             : 
      47             : # define UWRAP_LOCK(m) do { \
      48             :         pthread_mutex_lock(&( m ## _mutex)); \
      49             : } while(0)
      50             : 
      51             : # define UWRAP_UNLOCK(m) do { \
      52             :         pthread_mutex_unlock(&( m ## _mutex)); \
      53             : } while(0)
      54             : 
      55             : /* Add new global locks here please */
      56             : # define UWRAP_LOCK_ALL \
      57             :         UWRAP_LOCK(uwrap_id); \
      58             :         UWRAP_LOCK(libc_symbol_binding); \
      59             :         UWRAP_LOCK(libpthread_symbol_binding)
      60             : 
      61             : # define UWRAP_UNLOCK_ALL \
      62             :         UWRAP_UNLOCK(libpthread_symbol_binding); \
      63             :         UWRAP_UNLOCK(libc_symbol_binding); \
      64             :         UWRAP_UNLOCK(uwrap_id)
      65             : 
      66             : #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
      67             : #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
      68             : #else
      69             : #define CONSTRUCTOR_ATTRIBUTE
      70             : #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
      71             : 
      72             : #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
      73             : #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
      74             : #else
      75             : #define DESTRUCTOR_ATTRIBUTE
      76             : #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
      77             : 
      78             : #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
      79             : #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
      80             : #else /* DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE */
      81             : #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
      82             : #endif /* DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE */
      83             : 
      84             : /* GCC have printf type attribute check. */
      85             : #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
      86             : #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
      87             : #else
      88             : #define PRINTF_ATTRIBUTE(a,b)
      89             : #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
      90             : 
      91             : #ifndef FALL_THROUGH
      92             : # ifdef HAVE_FALLTHROUGH_ATTRIBUTE
      93             : #  define FALL_THROUGH __attribute__ ((fallthrough))
      94             : # else /* HAVE_FALLTHROUGH_ATTRIBUTE */
      95             : #  define FALL_THROUGH
      96             : # endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
      97             : #endif /* FALL_THROUGH */
      98             : 
      99             : #define UWRAP_DLIST_ADD(list,item) do { \
     100             :         if (!(list)) { \
     101             :                 (item)->prev = NULL; \
     102             :                 (item)->next = NULL; \
     103             :                 (list)          = (item); \
     104             :         } else { \
     105             :                 (item)->prev = NULL; \
     106             :                 (item)->next = (list); \
     107             :                 (list)->prev = (item); \
     108             :                 (list)          = (item); \
     109             :         } \
     110             : } while (0)
     111             : 
     112             : #define UWRAP_DLIST_REMOVE(list,item) do { \
     113             :         if ((list) == (item)) { \
     114             :                 (list)          = (item)->next; \
     115             :                 if (list) { \
     116             :                         (list)->prev = NULL; \
     117             :                 } \
     118             :         } else { \
     119             :                 if ((item)->prev) { \
     120             :                         (item)->prev->next        = (item)->next; \
     121             :                 } \
     122             :                 if ((item)->next) { \
     123             :                         (item)->next->prev        = (item)->prev; \
     124             :                 } \
     125             :         } \
     126             :         (item)->prev = NULL; \
     127             :         (item)->next = NULL; \
     128             : } while (0)
     129             : 
     130             : #ifndef SAFE_FREE
     131             : #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
     132             : #endif
     133             : 
     134             : /*****************
     135             :  * LOGGING
     136             :  *****************/
     137             : 
     138             : enum uwrap_dbglvl_e {
     139             :         UWRAP_LOG_ERROR = 0,
     140             :         UWRAP_LOG_WARN,
     141             :         UWRAP_LOG_DEBUG,
     142             :         UWRAP_LOG_TRACE
     143             : };
     144             : 
     145             : static void uwrap_log(enum uwrap_dbglvl_e dbglvl, const char *function, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
     146             : # define UWRAP_LOG(dbglvl, ...) uwrap_log((dbglvl), __func__, __VA_ARGS__)
     147             : 
     148    53340623 : static void uwrap_log(enum uwrap_dbglvl_e dbglvl, const char *function, const char *format, ...)
     149             : {
     150             :         char buffer[1024];
     151             :         va_list va;
     152             :         const char *d;
     153    53340623 :         unsigned int lvl = 0;
     154    53340623 :         const char *prefix = "UWRAP";
     155             : 
     156    53340623 :         d = getenv("UID_WRAPPER_DEBUGLEVEL");
     157    53340623 :         if (d != NULL) {
     158           0 :                 lvl = atoi(d);
     159             :         }
     160             : 
     161    53340623 :         if (lvl < dbglvl) {
     162    53340623 :                 return;
     163             :         }
     164             : 
     165           0 :         va_start(va, format);
     166           0 :         vsnprintf(buffer, sizeof(buffer), format, va);
     167           0 :         va_end(va);
     168             : 
     169           0 :         switch (dbglvl) {
     170           0 :                 case UWRAP_LOG_ERROR:
     171           0 :                         prefix = "UWRAP_ERROR";
     172           0 :                         break;
     173           0 :                 case UWRAP_LOG_WARN:
     174           0 :                         prefix = "UWRAP_WARN";
     175           0 :                         break;
     176           0 :                 case UWRAP_LOG_DEBUG:
     177           0 :                         prefix = "UWRAP_DEBUG";
     178           0 :                         break;
     179           0 :                 case UWRAP_LOG_TRACE:
     180           0 :                         prefix = "UWRAP_TRACE";
     181           0 :                         break;
     182             :         }
     183             : 
     184           0 :         fprintf(stderr,
     185             :                 "%s(%d) - %s: %s\n",
     186             :                 prefix,
     187           0 :                 (int)getpid(),
     188             :                 function,
     189             :                 buffer);
     190             : }
     191             : 
     192             : /*****************
     193             :  * LIBC
     194             :  *****************/
     195             : 
     196             : #define LIBC_NAME "libc.so"
     197             : 
     198             : typedef int (*__libc_setuid)(uid_t uid);
     199             : 
     200             : typedef uid_t (*__libc_getuid)(void);
     201             : 
     202             : #ifdef HAVE_SETEUID
     203             : typedef int (*__libc_seteuid)(uid_t euid);
     204             : #endif
     205             : 
     206             : #ifdef HAVE_SETREUID
     207             : typedef int (*__libc_setreuid)(uid_t ruid, uid_t euid);
     208             : #endif
     209             : 
     210             : #ifdef HAVE_SETRESUID
     211             : typedef int (*__libc_setresuid)(uid_t ruid, uid_t euid, uid_t suid);
     212             : #endif
     213             : 
     214             : #ifdef HAVE_GETRESUID
     215             : typedef int (*__libc_getresuid)(uid_t *ruid, uid_t *euid, uid_t *suid);
     216             : #endif
     217             : 
     218             : typedef uid_t (*__libc_geteuid)(void);
     219             : 
     220             : typedef int (*__libc_setgid)(gid_t gid);
     221             : 
     222             : typedef gid_t (*__libc_getgid)(void);
     223             : 
     224             : #ifdef HAVE_SETEGID
     225             : typedef int (*__libc_setegid)(uid_t egid);
     226             : #endif
     227             : 
     228             : #ifdef HAVE_SETREGID
     229             : typedef int (*__libc_setregid)(uid_t rgid, uid_t egid);
     230             : #endif
     231             : 
     232             : #ifdef HAVE_SETRESGID
     233             : typedef int (*__libc_setresgid)(uid_t rgid, uid_t egid, uid_t sgid);
     234             : #endif
     235             : 
     236             : #ifdef HAVE_GETRESGID
     237             : typedef int (*__libc_getresgid)(gid_t *rgid, gid_t *egid, gid_t *sgid);
     238             : #endif
     239             : 
     240             : typedef gid_t (*__libc_getegid)(void);
     241             : 
     242             : typedef int (*__libc_getgroups)(int size, gid_t list[]);
     243             : 
     244             : typedef int (*__libc_setgroups)(size_t size, const gid_t *list);
     245             : 
     246             : #ifdef HAVE_SYSCALL
     247             : typedef long int (*__libc_syscall)(long int sysno, ...);
     248             : #endif
     249             : 
     250             : #define UWRAP_SYMBOL_ENTRY(i) \
     251             :         union { \
     252             :                 __libc_##i f; \
     253             :                 void *obj; \
     254             :         } _libc_##i
     255             : 
     256             : struct uwrap_libc_symbols {
     257             :         UWRAP_SYMBOL_ENTRY(setuid);
     258             :         UWRAP_SYMBOL_ENTRY(getuid);
     259             : #ifdef HAVE_SETEUID
     260             :         UWRAP_SYMBOL_ENTRY(seteuid);
     261             : #endif
     262             : #ifdef HAVE_SETREUID
     263             :         UWRAP_SYMBOL_ENTRY(setreuid);
     264             : #endif
     265             : #ifdef HAVE_SETRESUID
     266             :         UWRAP_SYMBOL_ENTRY(setresuid);
     267             : #endif
     268             : #ifdef HAVE_GETRESUID
     269             :         UWRAP_SYMBOL_ENTRY(getresuid);
     270             : #endif
     271             :         UWRAP_SYMBOL_ENTRY(geteuid);
     272             :         UWRAP_SYMBOL_ENTRY(setgid);
     273             :         UWRAP_SYMBOL_ENTRY(getgid);
     274             : #ifdef HAVE_SETEGID
     275             :         UWRAP_SYMBOL_ENTRY(setegid);
     276             : #endif
     277             : #ifdef HAVE_SETREGID
     278             :         UWRAP_SYMBOL_ENTRY(setregid);
     279             : #endif
     280             : #ifdef HAVE_SETRESGID
     281             :         UWRAP_SYMBOL_ENTRY(setresgid);
     282             : #endif
     283             : #ifdef HAVE_GETRESGID
     284             :         UWRAP_SYMBOL_ENTRY(getresgid);
     285             : #endif
     286             :         UWRAP_SYMBOL_ENTRY(getegid);
     287             :         UWRAP_SYMBOL_ENTRY(getgroups);
     288             :         UWRAP_SYMBOL_ENTRY(setgroups);
     289             : #ifdef HAVE_SYSCALL
     290             :         UWRAP_SYMBOL_ENTRY(syscall);
     291             : #endif
     292             : };
     293             : #undef UWRAP_SYMBOL_ENTRY
     294             : 
     295             : /*****************
     296             :  * LIBPTHREAD
     297             :  *****************/
     298             : /* Yeah... I'm pig. I overloading macro here... So what? */
     299             : #define UWRAP_SYMBOL_ENTRY(i) \
     300             :         union { \
     301             :                 __libpthread_##i f; \
     302             :                 void *obj; \
     303             :         } _libpthread_##i
     304             : 
     305             : typedef int (*__libpthread_pthread_create)(pthread_t *thread,
     306             :                                     const pthread_attr_t *attr,
     307             :                                     void *(*start_routine) (void *),
     308             :                                     void *arg);
     309             : typedef void (*__libpthread_pthread_exit)(void *retval);
     310             : 
     311             : struct uwrap_libpthread_symbols {
     312             :         UWRAP_SYMBOL_ENTRY(pthread_create);
     313             :         UWRAP_SYMBOL_ENTRY(pthread_exit);
     314             : };
     315             : #undef UWRAP_SYMBOL_ENTRY
     316             : 
     317             : /*
     318             :  * We keep the virtualised euid/egid/groups information here
     319             :  */
     320             : struct uwrap_thread {
     321             :         bool enabled;
     322             : 
     323             :         uid_t ruid;
     324             :         uid_t euid;
     325             :         uid_t suid;
     326             : 
     327             :         gid_t rgid;
     328             :         gid_t egid;
     329             :         gid_t sgid;
     330             : 
     331             :         int ngroups;
     332             :         gid_t *groups;
     333             : 
     334             :         struct uwrap_thread *next;
     335             :         struct uwrap_thread *prev;
     336             : };
     337             : 
     338             : struct uwrap {
     339             :         struct {
     340             :                 void *handle;
     341             :                 struct uwrap_libc_symbols symbols;
     342             :         } libc;
     343             : 
     344             :         struct {
     345             :                 void *handle;
     346             :                 struct uwrap_libpthread_symbols symbols;
     347             :         } libpthread;
     348             : 
     349             :         bool initialised;
     350             : 
     351             :         /* Real uid and gid of user who run uid wrapper */
     352             :         uid_t myuid;
     353             :         gid_t mygid;
     354             : 
     355             :         struct uwrap_thread *ids;
     356             : };
     357             : 
     358             : static struct uwrap uwrap;
     359             : 
     360             : /* Shortcut to the list item */
     361             : static UWRAP_THREAD struct uwrap_thread *uwrap_tls_id;
     362             : 
     363             : /* The mutex or accessing the id */
     364             : static pthread_mutex_t uwrap_id_mutex = PTHREAD_MUTEX_INITIALIZER;
     365             : 
     366             : /* The mutex for accessing the global libc.symbols */
     367             : static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
     368             : 
     369             : /* The mutex for accessing the global libpthread.symbols */
     370             : static pthread_mutex_t libpthread_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
     371             : 
     372             : /*********************************************************
     373             :  * UWRAP PROTOTYPES
     374             :  *********************************************************/
     375             : 
     376             : bool uid_wrapper_enabled(void);
     377             : void uwrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
     378             : void uwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
     379             : 
     380             : /*********************************************************
     381             :  * UWRAP LIBC LOADER FUNCTIONS
     382             :  *********************************************************/
     383             : 
     384             : enum uwrap_lib {
     385             :     UWRAP_LIBC,
     386             :     UWRAP_LIBNSL,
     387             :     UWRAP_LIBSOCKET,
     388             :     UWRAP_LIBPTHREAD,
     389             : };
     390             : 
     391      379097 : static void *uwrap_load_lib_handle(enum uwrap_lib lib)
     392             : {
     393      379097 :         int flags = RTLD_LAZY;
     394      379097 :         void *handle = NULL;
     395             :         int i;
     396             : 
     397             : #ifdef RTLD_DEEPBIND
     398      379097 :         const char *env_preload = getenv("LD_PRELOAD");
     399      379097 :         const char *env_deepbind = getenv("UID_WRAPPER_DISABLE_DEEPBIND");
     400      379097 :         bool enable_deepbind = true;
     401             : 
     402             :         /* Don't do a deepbind if we run with libasan */
     403      379097 :         if (env_preload != NULL && strlen(env_preload) < 1024) {
     404      379097 :                 const char *p = strstr(env_preload, "libasan.so");
     405      379097 :                 if (p != NULL) {
     406           0 :                         enable_deepbind = false;
     407             :                 }
     408             :         }
     409             : 
     410      379097 :         if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
     411           0 :                 enable_deepbind = false;
     412             :         }
     413             : 
     414      379097 :         if (enable_deepbind) {
     415      379097 :                 flags |= RTLD_DEEPBIND;
     416             :         }
     417             : #endif
     418             : 
     419      379097 :         switch (lib) {
     420      375983 :         case UWRAP_LIBNSL:
     421             :         case UWRAP_LIBSOCKET:
     422             :         case UWRAP_LIBC:
     423      375983 :                 handle = uwrap.libc.handle;
     424      375983 :                 if (handle == NULL) {
     425     1238098 :                         for (i = 10; i >= 0; i--) {
     426      631940 :                                 char soname[256] = {0};
     427             : 
     428      631940 :                                 snprintf(soname, sizeof(soname), "libc.so.%d", i);
     429      631940 :                                 handle = dlopen(soname, flags);
     430      631940 :                                 if (handle != NULL) {
     431      244182 :                                         break;
     432             :                                 }
     433             : 
     434             :                                 /* glibc on Alpha and IA64 is libc.so.6.1 */
     435      505552 :                                 snprintf(soname, sizeof(soname), "libc.so.%d.1", i);
     436      505552 :                                 handle = dlopen(soname, flags);
     437      505552 :                                 if (handle != NULL) {
     438           0 :                                         break;
     439             :                                 }
     440             :                         }
     441             : 
     442      126388 :                         uwrap.libc.handle = handle;
     443             :                 }
     444      363187 :                 break;
     445        3114 :         case UWRAP_LIBPTHREAD:
     446        3114 :                 handle = uwrap.libpthread.handle;
     447        3114 :                 if (handle == NULL) {
     448        3114 :                         handle = dlopen("libpthread.so.0", flags);
     449        3078 :                         if (handle != NULL) {
     450        3078 :                                 break;
     451             :                         }
     452             :                 }
     453           0 :                 break;
     454             :         }
     455             : 
     456      379097 :         if (handle == NULL) {
     457             : #ifdef RTLD_NEXT
     458           0 :                 handle = uwrap.libc.handle = RTLD_NEXT;
     459             : #else
     460             :                 fprintf(stderr,
     461             :                         "Failed to dlopen library: %s\n",
     462             :                         dlerror());
     463             :                 exit(-1);
     464             : #endif
     465             :         }
     466             : 
     467      379097 :         return handle;
     468             : }
     469             : 
     470      379097 : static void *_uwrap_bind_symbol(enum uwrap_lib lib, const char *fn_name)
     471             : {
     472             :         void *handle;
     473             :         void *func;
     474             : 
     475      379097 :         handle = uwrap_load_lib_handle(lib);
     476             : 
     477      379097 :         func = dlsym(handle, fn_name);
     478      379097 :         if (func == NULL) {
     479           0 :                 fprintf(stderr,
     480             :                         "Failed to find %s: %s\n",
     481             :                         fn_name, dlerror());
     482           0 :                 exit(-1);
     483             :         }
     484             : 
     485      379097 :         return func;
     486             : }
     487             : 
     488             : #define uwrap_bind_symbol_libc(sym_name) \
     489             :         UWRAP_LOCK(libc_symbol_binding); \
     490             :         if (uwrap.libc.symbols._libc_##sym_name.obj == NULL) { \
     491             :                 uwrap.libc.symbols._libc_##sym_name.obj = \
     492             :                         _uwrap_bind_symbol(UWRAP_LIBC, #sym_name); \
     493             :         } \
     494             :         UWRAP_UNLOCK(libc_symbol_binding)
     495             : 
     496             : #define uwrap_bind_symbol_libpthread(sym_name) \
     497             :         UWRAP_LOCK(libpthread_symbol_binding); \
     498             :         if (uwrap.libpthread.symbols._libpthread_##sym_name.obj == NULL) { \
     499             :                 uwrap.libpthread.symbols._libpthread_##sym_name.obj = \
     500             :                         _uwrap_bind_symbol(UWRAP_LIBPTHREAD, #sym_name); \
     501             :         } \
     502             :         UWRAP_UNLOCK(libpthread_symbol_binding)
     503             : 
     504             : /*
     505             :  * IMPORTANT
     506             :  *
     507             :  * Functions expeciall from libc need to be loaded individually, you can't load
     508             :  * all at once or gdb will segfault at startup. The same applies to valgrind and
     509             :  * has probably something todo with with the linker.
     510             :  * So we need load each function at the point it is called the first time.
     511             :  */
     512           0 : static int libc_setuid(uid_t uid)
     513             : {
     514           0 :         uwrap_bind_symbol_libc(setuid);
     515             : 
     516           0 :         return uwrap.libc.symbols._libc_setuid.f(uid);
     517             : }
     518             : 
     519           0 : static uid_t libc_getuid(void)
     520             : {
     521           0 :         uwrap_bind_symbol_libc(getuid);
     522             : 
     523           0 :         return uwrap.libc.symbols._libc_getuid.f();
     524             : }
     525             : 
     526             : #ifdef HAVE_SETEUID
     527           0 : static int libc_seteuid(uid_t euid)
     528             : {
     529           0 :         uwrap_bind_symbol_libc(seteuid);
     530             : 
     531           0 :         return uwrap.libc.symbols._libc_seteuid.f(euid);
     532             : }
     533             : #endif
     534             : 
     535             : #ifdef HAVE_SETREUID
     536           0 : static int libc_setreuid(uid_t ruid, uid_t euid)
     537             : {
     538           0 :         uwrap_bind_symbol_libc(setreuid);
     539             : 
     540           0 :         return uwrap.libc.symbols._libc_setreuid.f(ruid, euid);
     541             : }
     542             : #endif
     543             : 
     544             : #ifdef HAVE_SETRESUID
     545           0 : static int libc_setresuid(uid_t ruid, uid_t euid, uid_t suid)
     546             : {
     547           0 :         uwrap_bind_symbol_libc(setresuid);
     548             : 
     549           0 :         return uwrap.libc.symbols._libc_setresuid.f(ruid, euid, suid);
     550             : }
     551             : #endif
     552             : 
     553             : #ifdef HAVE_GETRESUID
     554           0 : static int libc_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
     555             : {
     556           0 :         uwrap_bind_symbol_libc(getresuid);
     557             : 
     558           0 :         return uwrap.libc.symbols._libc_getresuid.f(ruid, euid, suid);
     559             : }
     560             : #endif
     561             : 
     562      126388 : static uid_t libc_geteuid(void)
     563             : {
     564      126388 :         uwrap_bind_symbol_libc(geteuid);
     565             : 
     566      126388 :         return uwrap.libc.symbols._libc_geteuid.f();
     567             : }
     568             : 
     569           0 : static int libc_setgid(gid_t gid)
     570             : {
     571           0 :         uwrap_bind_symbol_libc(setgid);
     572             : 
     573           0 :         return uwrap.libc.symbols._libc_setgid.f(gid);
     574             : }
     575             : 
     576           0 : static gid_t libc_getgid(void)
     577             : {
     578           0 :         uwrap_bind_symbol_libc(getgid);
     579             : 
     580           0 :         return uwrap.libc.symbols._libc_getgid.f();
     581             : }
     582             : 
     583             : #ifdef HAVE_SETEGID
     584           0 : static int libc_setegid(gid_t egid)
     585             : {
     586           0 :         uwrap_bind_symbol_libc(setegid);
     587             : 
     588           0 :         return uwrap.libc.symbols._libc_setegid.f(egid);
     589             : }
     590             : #endif
     591             : 
     592             : #ifdef HAVE_SETREGID
     593           0 : static int libc_setregid(gid_t rgid, gid_t egid)
     594             : {
     595           0 :         uwrap_bind_symbol_libc(setregid);
     596             : 
     597           0 :         return uwrap.libc.symbols._libc_setregid.f(rgid, egid);
     598             : }
     599             : #endif
     600             : 
     601             : #ifdef HAVE_SETRESGID
     602           0 : static int libc_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
     603             : {
     604           0 :         uwrap_bind_symbol_libc(setresgid);
     605             : 
     606           0 :         return uwrap.libc.symbols._libc_setresgid.f(rgid, egid, sgid);
     607             : }
     608             : #endif
     609             : 
     610             : #ifdef HAVE_GETRESGID
     611           0 : static int libc_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
     612             : {
     613           0 :         uwrap_bind_symbol_libc(setresgid);
     614             : 
     615           0 :         return uwrap.libc.symbols._libc_getresgid.f(rgid, egid, sgid);
     616             : }
     617             : #endif
     618             : 
     619      126388 : static gid_t libc_getegid(void)
     620             : {
     621      126388 :         uwrap_bind_symbol_libc(getegid);
     622             : 
     623      126388 :         return uwrap.libc.symbols._libc_getegid.f();
     624             : }
     625             : 
     626      213648 : static int libc_getgroups(int size, gid_t list[])
     627             : {
     628      213648 :         uwrap_bind_symbol_libc(getgroups);
     629             : 
     630      213648 :         return uwrap.libc.symbols._libc_getgroups.f(size, list);
     631             : }
     632             : 
     633           0 : static int libc_setgroups(size_t size, const gid_t *list)
     634             : {
     635           0 :         uwrap_bind_symbol_libc(setgroups);
     636             : 
     637           0 :         return uwrap.libc.symbols._libc_setgroups.f(size, list);
     638             : }
     639             : 
     640             : #ifdef HAVE_SYSCALL
     641             : DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
     642      464552 : static long int libc_vsyscall(long int sysno, va_list va)
     643             : {
     644             :         long int args[8];
     645             :         long int rc;
     646             :         int i;
     647             : 
     648      464552 :         uwrap_bind_symbol_libc(syscall);
     649             : 
     650     4180968 :         for (i = 0; i < 8; i++) {
     651     3716416 :                 args[i] = va_arg(va, long int);
     652             :         }
     653             : 
     654      464552 :         rc = uwrap.libc.symbols._libc_syscall.f(sysno,
     655             :                                           args[0],
     656             :                                           args[1],
     657             :                                           args[2],
     658             :                                           args[3],
     659             :                                           args[4],
     660             :                                           args[5],
     661             :                                           args[6],
     662             :                                           args[7]);
     663             : 
     664      464552 :         return rc;
     665             : }
     666             : #endif
     667             : 
     668             : /*
     669             :  * This part is "optimistic".
     670             :  * Thread can ends without pthread_exit call.
     671             :  */
     672         120 : static void libpthread_pthread_exit(void *retval)
     673             : {
     674         120 :         uwrap_bind_symbol_libpthread(pthread_exit);
     675             : 
     676         120 :         uwrap.libpthread.symbols._libpthread_pthread_exit.f(retval);
     677           0 : }
     678             : 
     679         120 : static void uwrap_pthread_exit(void *retval)
     680             : {
     681         120 :         struct uwrap_thread *id = uwrap_tls_id;
     682             : 
     683         120 :         UWRAP_LOG(UWRAP_LOG_DEBUG, "Cleanup thread");
     684             : 
     685         120 :         UWRAP_LOCK(uwrap_id);
     686         120 :         if (id == NULL) {
     687           0 :                 UWRAP_UNLOCK(uwrap_id);
     688           0 :                 libpthread_pthread_exit(retval);
     689           0 :                 return;
     690             :         }
     691             : 
     692         120 :         UWRAP_DLIST_REMOVE(uwrap.ids, id);
     693         120 :         SAFE_FREE(id->groups);
     694         120 :         SAFE_FREE(id);
     695         120 :         uwrap_tls_id = NULL;
     696             : 
     697         120 :         UWRAP_UNLOCK(uwrap_id);
     698             : 
     699         120 :         libpthread_pthread_exit(retval);
     700             : }
     701             : 
     702             : void pthread_exit(void *retval)
     703             : {
     704         120 :         if (!uid_wrapper_enabled()) {
     705           0 :                 libpthread_pthread_exit(retval);
     706             :         };
     707             : 
     708         120 :         uwrap_pthread_exit(retval);
     709             : 
     710             :         /* Calm down gcc warning. */
     711           0 :         exit(666);
     712             : }
     713             : 
     714        4510 : static int libpthread_pthread_create(pthread_t *thread,
     715             :                                 const pthread_attr_t *attr,
     716             :                                 void *(*start_routine) (void *),
     717             :                                 void *arg)
     718             : {
     719        4510 :         uwrap_bind_symbol_libpthread(pthread_create);
     720        4510 :         return uwrap.libpthread.symbols._libpthread_pthread_create.f(thread,
     721             :                                                                      attr,
     722             :                                                                      start_routine,
     723             :                                                                      arg);
     724             : }
     725             : 
     726             : struct uwrap_pthread_create_args {
     727             :         struct uwrap_thread *id;
     728             :         void *(*start_routine) (void *);
     729             :         void *arg;
     730             : };
     731             : 
     732        4503 : static void *uwrap_pthread_create_start(void *_a)
     733             : {
     734        4503 :         struct uwrap_pthread_create_args *a =
     735             :                 (struct uwrap_pthread_create_args *)_a;
     736        4503 :         void *(*start_routine) (void *) = a->start_routine;
     737        4503 :         void *arg = a->arg;
     738        4503 :         struct uwrap_thread *id = a->id;
     739             : 
     740        4503 :         SAFE_FREE(a);
     741             : 
     742        4503 :         uwrap_tls_id = id;
     743             : 
     744        4503 :         return start_routine(arg);
     745             : }
     746             : 
     747        4510 : static int uwrap_pthread_create(pthread_t *thread,
     748             :                                  const pthread_attr_t *attr,
     749             :                                  void *(*start_routine) (void *),
     750             :                                  void *arg)
     751             : {
     752             :         struct uwrap_pthread_create_args *args;
     753        4510 :         struct uwrap_thread *src_id = uwrap_tls_id;
     754             :         int ret;
     755             : 
     756        4510 :         args = malloc(sizeof(struct uwrap_pthread_create_args));
     757        4510 :         if (args == NULL) {
     758           0 :                 UWRAP_LOG(UWRAP_LOG_ERROR,
     759             :                           "uwrap_pthread_create: Unable to allocate memory");
     760           0 :                 errno = ENOMEM;
     761           0 :                 return -1;
     762             :         }
     763        4510 :         args->start_routine = start_routine;
     764        4510 :         args->arg = arg;
     765             : 
     766        4510 :         args->id = calloc(1, sizeof(struct uwrap_thread));
     767        4510 :         if (args->id == NULL) {
     768           0 :                 SAFE_FREE(args);
     769           0 :                 UWRAP_LOG(UWRAP_LOG_ERROR,
     770             :                           "uwrap_pthread_create: Unable to allocate memory");
     771           0 :                 errno = ENOMEM;
     772           0 :                 return -1;
     773             :         }
     774             : 
     775        4510 :         UWRAP_LOCK(uwrap_id);
     776             : 
     777        4510 :         args->id->groups = calloc(src_id->ngroups, sizeof(gid_t));
     778        4510 :         if (args->id->groups == NULL) {
     779           0 :                 UWRAP_UNLOCK(uwrap_id);
     780           0 :                 SAFE_FREE(args->id);
     781           0 :                 SAFE_FREE(args);
     782           0 :                 UWRAP_LOG(UWRAP_LOG_ERROR,
     783             :                           "uwrap_pthread_create: Unable to allocate memory again");
     784           0 :                 errno = ENOMEM;
     785           0 :                 return -1;
     786             :         }
     787             : 
     788        4510 :         args->id->ruid = src_id->ruid;
     789        4510 :         args->id->euid = src_id->euid;
     790        4510 :         args->id->suid = src_id->suid;
     791             : 
     792        4510 :         args->id->rgid = src_id->rgid;
     793        4510 :         args->id->egid = src_id->egid;
     794        4510 :         args->id->sgid = src_id->sgid;
     795             : 
     796        4510 :         args->id->enabled = src_id->enabled;
     797             : 
     798        4510 :         args->id->ngroups = src_id->ngroups;
     799        4510 :         if (src_id->groups != NULL) {
     800        4503 :                 memcpy(args->id->groups, src_id->groups,
     801        4503 :                        sizeof(gid_t) * src_id->ngroups);
     802             :         } else {
     803           7 :                 SAFE_FREE(args->id->groups);
     804             :         }
     805             : 
     806        4510 :         UWRAP_DLIST_ADD(uwrap.ids, args->id);
     807        4510 :         UWRAP_UNLOCK(uwrap_id);
     808             : 
     809        4510 :         ret = libpthread_pthread_create(thread, attr,
     810             :                                         uwrap_pthread_create_start,
     811             :                                         args);
     812        3791 :         if (ret != 0) {
     813           0 :                 return ret;
     814             :         }
     815             : 
     816        3791 :         return ret;
     817             : }
     818             : 
     819             : int pthread_create(pthread_t *thread,
     820             :                     const pthread_attr_t *attr,
     821             :                     void *(*start_routine) (void *),
     822             :                     void *arg)
     823             : {
     824        4510 :         if (!uid_wrapper_enabled()) {
     825           0 :                 return libpthread_pthread_create(thread,
     826             :                                            attr,
     827             :                                            start_routine,
     828             :                                            arg);
     829             :         };
     830             : 
     831        4510 :         return uwrap_pthread_create(thread,
     832             :                                     attr,
     833             :                                     start_routine,
     834             :                                     arg);
     835             : }
     836             : 
     837             : /*********************************************************
     838             :  * UWRAP ID HANDLING
     839             :  *********************************************************/
     840             : 
     841             : #define GROUP_STRING_SIZE 16384
     842             : #define GROUP_MAX_COUNT (GROUP_STRING_SIZE / (10 + 1))
     843             : 
     844             : /**
     845             :  * This function exports all the IDs of the current user so if
     846             :  * we fork and then exec we can setup uid_wrapper in the new process
     847             :  * with those IDs.
     848             :  */
     849       51653 : static void uwrap_export_ids(struct uwrap_thread *id)
     850             : {
     851       51653 :         char groups_str[GROUP_STRING_SIZE] = {0};
     852       51653 :         size_t groups_str_size = sizeof(groups_str);
     853       51653 :         char unsigned_str[16] = {0}; /* We need 10 + 1 (+ 1) */
     854             :         int i;
     855             : 
     856             :         /* UIDS */
     857       52522 :         snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->ruid);
     858       51653 :         setenv("UID_WRAPPER_INITIAL_RUID", unsigned_str, 1);
     859             : 
     860       52522 :         snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->euid);
     861       51653 :         setenv("UID_WRAPPER_INITIAL_EUID", unsigned_str, 1);
     862             : 
     863       52522 :         snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->suid);
     864       51653 :         setenv("UID_WRAPPER_INITIAL_SUID", unsigned_str, 1);
     865             : 
     866             :         /* GIDS */
     867       52522 :         snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->rgid);
     868       51653 :         setenv("UID_WRAPPER_INITIAL_RGID", unsigned_str, 1);
     869             : 
     870       52522 :         snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->egid);
     871       51653 :         setenv("UID_WRAPPER_INITIAL_EGID", unsigned_str, 1);
     872             : 
     873       52522 :         snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->sgid);
     874       51653 :         setenv("UID_WRAPPER_INITIAL_SGID", unsigned_str, 1);
     875             : 
     876       51653 :         if (id->ngroups > GROUP_MAX_COUNT) {
     877           0 :                 UWRAP_LOG(UWRAP_LOG_ERROR,
     878             :                           "ERROR: Number of groups (%u) exceeds maximum value "
     879             :                           "uid_wrapper can handle (%u).",
     880             :                           id->ngroups,
     881             :                           GROUP_MAX_COUNT);
     882           0 :                 exit(-1);
     883             :         }
     884             : 
     885             :         /* GROUPS */
     886      104749 :         for (i = 0; i < id->ngroups; i++) {
     887       53965 :                 size_t groups_str_len = strlen(groups_str);
     888       53965 :                 size_t groups_str_avail = groups_str_size - groups_str_len - 1;
     889             :                 int len;
     890             : 
     891       54637 :                 len = snprintf(unsigned_str, sizeof(unsigned_str), ",%u", id->groups[i]);
     892       53965 :                 if (len <= 1) {
     893           0 :                         UWRAP_LOG(UWRAP_LOG_ERROR,
     894             :                                   "snprintf failed for groups[%d]=%u",
     895             :                                   i,
     896             :                                   id->groups[i]);
     897           0 :                         break;
     898             :                 }
     899       53965 :                 if (((size_t)len) >= groups_str_avail) {
     900           0 :                         UWRAP_LOG(UWRAP_LOG_ERROR,
     901             :                                   "groups env string is to small for %d groups",
     902             :                                   i);
     903           0 :                         break;
     904             :                 }
     905             : 
     906       54637 :                 len = snprintf(groups_str + groups_str_len,
     907             :                                groups_str_size - groups_str_len,
     908             :                                "%s",
     909             :                                i == 0 ? unsigned_str + 1 : unsigned_str);
     910       53965 :                 if (len < 1) {
     911           0 :                         UWRAP_LOG(UWRAP_LOG_ERROR,
     912             :                                   "snprintf failed to create groups string at groups[%d]=%u",
     913             :                                   i,
     914             :                                   id->groups[i]);
     915           0 :                         break;
     916             :                 }
     917             :         }
     918             : 
     919       51653 :         if (id->ngroups == i) {
     920       51653 :                 setenv("UID_WRAPPER_INITIAL_GROUPS", groups_str, 1);
     921             : 
     922       52522 :                 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->ngroups);
     923       51653 :                 setenv("UID_WRAPPER_INITIAL_GROUPS_COUNT", unsigned_str, 1);
     924             :         }
     925       51653 : }
     926             : 
     927      849612 : static void uwrap_thread_prepare(void)
     928             : {
     929      849612 :         struct uwrap_thread *id = uwrap_tls_id;
     930             : 
     931      849612 :         UWRAP_LOCK_ALL;
     932             : 
     933             :         /* uid_wrapper is loaded but not enabled */
     934      849612 :         if (id == NULL) {
     935           0 :                 return;
     936             :         }
     937             : 
     938             :         /*
     939             :          * What happens if another atfork prepare functions calls a uwrap
     940             :          * function? So disable it in case another atfork prepare function
     941             :          * calls a (s)uid function. We disable uid_wrapper only for thread
     942             :          * (process) which called fork.
     943             :          */
     944      849612 :         id->enabled = false;
     945             : }
     946             : 
     947      797959 : static void uwrap_thread_parent(void)
     948             : {
     949      797959 :         struct uwrap_thread *id = uwrap_tls_id;
     950             : 
     951             :         /* uid_wrapper is loaded but not enabled */
     952      797959 :         if (id == NULL) {
     953           0 :                 UWRAP_UNLOCK_ALL;
     954           0 :                 return;
     955             :         }
     956             : 
     957      797959 :         id->enabled = true;
     958             : 
     959      797959 :         UWRAP_UNLOCK_ALL;
     960             : }
     961             : 
     962       51653 : static void uwrap_thread_child(void)
     963             : {
     964       51653 :         struct uwrap_thread *id = uwrap_tls_id;
     965       51653 :         struct uwrap_thread *u = uwrap.ids;
     966             : 
     967             :         /* uid_wrapper is loaded but not enabled */
     968       51653 :         if (id == NULL) {
     969           0 :                 UWRAP_UNLOCK_ALL;
     970           0 :                 return;
     971             :         }
     972             : 
     973             :         /*
     974             :          * "Garbage collector" - Inspired by DESTRUCTOR.
     975             :          * All threads (except one which called fork()) are dead now.. Dave
     976             :          * That's what posix said...
     977             :          */
     978      161075 :         while (u != NULL) {
     979       58638 :                 if (u == id) {
     980             :                         /* Skip this item. */
     981       53733 :                         u = uwrap.ids->next;
     982       53733 :                         continue;
     983             :                 }
     984             : 
     985        4905 :                 UWRAP_DLIST_REMOVE(uwrap.ids, u);
     986             : 
     987        4905 :                 SAFE_FREE(u->groups);
     988        4905 :                 SAFE_FREE(u);
     989             : 
     990        4905 :                 u = uwrap.ids;
     991             :         }
     992             : 
     993       51653 :         uwrap_export_ids(id);
     994             : 
     995       51653 :         id->enabled = true;
     996             : 
     997       51653 :         UWRAP_UNLOCK_ALL;
     998             : }
     999             : 
    1000      758328 : static unsigned long uwrap_get_xid_from_env(const char *envname)
    1001             : {
    1002             :         unsigned long xid;
    1003      758328 :         const char *env = NULL;
    1004      758328 :         char *endp = NULL;
    1005             : 
    1006      758328 :         env = getenv(envname);
    1007      758328 :         if (env == NULL) {
    1008      558184 :                 return ULONG_MAX;
    1009             :         }
    1010             : 
    1011      180164 :         if (env[0] == '\0') {
    1012           0 :                 unsetenv(envname);
    1013           0 :                 return ULONG_MAX;
    1014             :         }
    1015             : 
    1016      180164 :         xid = strtoul(env, &endp, 10);
    1017      180164 :         unsetenv(envname);
    1018      180164 :         if (env == endp) {
    1019           0 :                 return ULONG_MAX;
    1020             :         }
    1021             : 
    1022      180164 :         return xid;
    1023             : }
    1024             : 
    1025             : /*
    1026             :  * This initializes uid_wrapper with the IDs exported to the environment. Those
    1027             :  * are normally set after we forked and executed.
    1028             :  */
    1029      126388 : static void uwrap_init_env(struct uwrap_thread *id)
    1030             : {
    1031             :         const char *env;
    1032      126388 :         int ngroups = 0;
    1033             :         unsigned long xid;
    1034             : 
    1035             :         /* UIDs */
    1036      126388 :         xid = uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_RUID");
    1037      126388 :         if (xid != ULONG_MAX) {
    1038       30042 :                 id->ruid = (uid_t)xid;
    1039             :         }
    1040             : 
    1041      126388 :         xid = uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_EUID");
    1042      126388 :         if (xid != ULONG_MAX) {
    1043       30042 :                 id->euid = (uid_t)xid;
    1044             :         }
    1045             : 
    1046      126388 :         xid = uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_SUID");
    1047      126388 :         if (xid != ULONG_MAX) {
    1048       30020 :                 id->suid = (uid_t)xid;
    1049             :         }
    1050             : 
    1051             :         /* GIDs */
    1052      126388 :         xid = uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_RGID");
    1053      126388 :         if (xid != ULONG_MAX) {
    1054       30020 :                 id->rgid = (gid_t)xid;
    1055             :         }
    1056             : 
    1057      126388 :         xid = uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_EGID");
    1058      126388 :         if (xid != ULONG_MAX) {
    1059       30020 :                 id->egid = (gid_t)xid;
    1060             :         }
    1061             : 
    1062      126388 :         xid = uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_SGID");
    1063      126388 :         if (xid != ULONG_MAX) {
    1064       30020 :                 id->sgid = (gid_t)xid;
    1065             :         }
    1066             : 
    1067      126388 :         env = getenv("UID_WRAPPER_INITIAL_GROUPS_COUNT");
    1068      126388 :         if (env != NULL && env[0] != '\0') {
    1069       30020 :                 char *endp = NULL;
    1070             :                 long n;
    1071             : 
    1072       30020 :                 n = strtol(env, &endp, 10);
    1073       30020 :                 if (env == endp) {
    1074           0 :                         ngroups = 0;
    1075       30020 :                 } else if (n > 0 && n < GROUP_MAX_COUNT) {
    1076       13381 :                         ngroups = (int)n;
    1077             :                 }
    1078       30020 :                 unsetenv("UID_WRAPPER_INITIAL_GROUPS_COUNT");
    1079             :         }
    1080             : 
    1081      123058 :         if (ngroups > 0) {
    1082       13381 :                 int i = 0;
    1083             : 
    1084       13381 :                 id->ngroups = 0;
    1085             : 
    1086       13381 :                 free(id->groups);
    1087       13381 :                 id->groups = calloc(ngroups, sizeof(gid_t));
    1088       13381 :                 if (id->groups == NULL) {
    1089           0 :                         UWRAP_LOG(UWRAP_LOG_ERROR,
    1090             :                                   "Unable to allocate memory");
    1091           0 :                         exit(-1);
    1092             :                 }
    1093             : 
    1094       13381 :                 env = getenv("UID_WRAPPER_INITIAL_GROUPS");
    1095       13381 :                 if (env != NULL && env[0] != '\0') {
    1096       13381 :                         char *groups_str = NULL;
    1097       13381 :                         char *saveptr = NULL;
    1098       13381 :                         const char *p = NULL;
    1099             : 
    1100       13381 :                         groups_str = strdup(env);
    1101       13381 :                         if (groups_str == NULL) {
    1102           0 :                                 exit(-1);
    1103             :                         }
    1104             : 
    1105       13381 :                         p = strtok_r(groups_str, ",", &saveptr);
    1106       40143 :                         while (p != NULL) {
    1107       13381 :                                 id->groups[i] = strtol(p, (char **)NULL, 10);
    1108       13381 :                                 i++;
    1109             : 
    1110       13381 :                                 p = strtok_r(NULL, ",", &saveptr);
    1111             :                         }
    1112       13381 :                         SAFE_FREE(groups_str);
    1113             :                 }
    1114             : 
    1115       13381 :                 if (i != ngroups) {
    1116           0 :                         UWRAP_LOG(UWRAP_LOG_ERROR,
    1117             :                                   "ERROR: The number of groups (%u) passed, "
    1118             :                                   "does not match the number of groups (%u) "
    1119             :                                   "we parsed.",
    1120             :                                   ngroups,
    1121             :                                   i);
    1122           0 :                         exit(-1);
    1123             :                 }
    1124             : 
    1125       13381 :                 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize groups with %s", env);
    1126       13381 :                 id->ngroups = ngroups;
    1127             :         }
    1128      126388 : }
    1129             : 
    1130    85623066 : static void uwrap_init(void)
    1131             : {
    1132             :         const char *env;
    1133             : 
    1134    85623066 :         UWRAP_LOCK(uwrap_id);
    1135             : 
    1136    85623066 :         if (uwrap.initialised) {
    1137    85496678 :                 struct uwrap_thread *id = uwrap_tls_id;
    1138             : 
    1139    85496678 :                 if (uwrap.ids == NULL) {
    1140           0 :                         UWRAP_UNLOCK(uwrap_id);
    1141           0 :                         return;
    1142             :                 }
    1143             : 
    1144    85496678 :                 if (id == NULL) {
    1145           0 :                         UWRAP_LOG(UWRAP_LOG_ERROR,
    1146             :                                   "Invalid id for thread");
    1147           0 :                         exit(-1);
    1148             :                 }
    1149             : 
    1150    85496678 :                 UWRAP_UNLOCK(uwrap_id);
    1151    85496678 :                 return;
    1152             :         }
    1153             : 
    1154      126388 :         UWRAP_LOG(UWRAP_LOG_DEBUG, "Initialize uid_wrapper");
    1155             : 
    1156      126388 :         uwrap.initialised = true;
    1157             : 
    1158      126388 :         env = getenv("UID_WRAPPER");
    1159      126388 :         if (env != NULL && env[0] == '1') {
    1160      126388 :                 const char *root = getenv("UID_WRAPPER_ROOT");
    1161             :                 struct uwrap_thread *id;
    1162             : 
    1163      126388 :                 id = calloc(1, sizeof(struct uwrap_thread));
    1164      126388 :                 if (id == NULL) {
    1165           0 :                         UWRAP_LOG(UWRAP_LOG_ERROR,
    1166             :                                   "Unable to allocate memory for main id");
    1167           0 :                         exit(-1);
    1168             :                 }
    1169             : 
    1170      126388 :                 UWRAP_DLIST_ADD(uwrap.ids, id);
    1171      126388 :                 uwrap_tls_id = id;
    1172             : 
    1173      126388 :                 uwrap.myuid = libc_geteuid();
    1174      126388 :                 uwrap.mygid = libc_getegid();
    1175             : 
    1176             :                 /* put us in one group */
    1177      126388 :                 if (root != NULL && root[0] == '1') {
    1178       19564 :                         id->ruid = id->euid = id->suid = 0;
    1179       19564 :                         id->rgid = id->egid = id->sgid = 0;
    1180             : 
    1181       19564 :                         id->groups = malloc(sizeof(gid_t) * 1);
    1182       19564 :                         if (id->groups == NULL) {
    1183           0 :                                 UWRAP_LOG(UWRAP_LOG_ERROR,
    1184             :                                           "Unable to allocate memory");
    1185           0 :                                 exit(-1);
    1186             :                         }
    1187             : 
    1188       19564 :                         id->ngroups = 1;
    1189       19564 :                         id->groups[0] = 0;
    1190             : 
    1191             :                 } else {
    1192      106824 :                         id->ruid = id->euid = id->suid = uwrap.myuid;
    1193      106824 :                         id->rgid = id->egid = id->sgid = uwrap.mygid;
    1194             : 
    1195      106824 :                         id->ngroups = libc_getgroups(0, NULL);
    1196      106824 :                         if (id->ngroups == -1) {
    1197           0 :                                 UWRAP_LOG(UWRAP_LOG_ERROR,
    1198             :                                           "Unable to call libc_getgroups in uwrap_init.");
    1199           0 :                                 exit(-1);
    1200             :                         }
    1201      106824 :                         id->groups = malloc(sizeof(gid_t) * id->ngroups);
    1202      106824 :                         if (id->groups == NULL) {
    1203           0 :                                 UWRAP_LOG(UWRAP_LOG_ERROR, "Unable to allocate memory");
    1204           0 :                                 exit(-1);
    1205             :                         }
    1206      106824 :                         if (libc_getgroups(id->ngroups, id->groups) == -1) {
    1207           0 :                                 UWRAP_LOG(UWRAP_LOG_ERROR,
    1208             :                                           "Unable to call libc_getgroups again in uwrap_init.");
    1209           0 :                                 id->groups = 0;
    1210             :                                 /*
    1211             :                                  * Deallocation of uwrap.groups is handled by
    1212             :                                  * library destructor.
    1213             :                                  */
    1214           0 :                                 exit(-1);
    1215             :                         }
    1216             :                 }
    1217             : 
    1218      126388 :                 uwrap_init_env(id);
    1219             : 
    1220      126388 :                 id->enabled = true;
    1221             : 
    1222      126388 :                 UWRAP_LOG(UWRAP_LOG_DEBUG,
    1223             :                           "Enabled uid_wrapper as %s (real uid=%u)",
    1224             :                           id->ruid == 0 ? "root" : "user",
    1225             :                           (unsigned int)uwrap.myuid);
    1226             :         }
    1227             : 
    1228      126388 :         UWRAP_UNLOCK(uwrap_id);
    1229             : 
    1230      126388 :         UWRAP_LOG(UWRAP_LOG_DEBUG, "Successfully initialized uid_wrapper");
    1231             : }
    1232             : 
    1233    87225709 : bool uid_wrapper_enabled(void)
    1234             : {
    1235    87225709 :         struct uwrap_thread *id = uwrap_tls_id;
    1236             :         bool enabled;
    1237             : 
    1238    87225709 :         if (id == NULL) {
    1239        6890 :                 return false;
    1240             :         }
    1241             : 
    1242    87218789 :         UWRAP_LOCK(uwrap_id);
    1243    87218789 :         enabled = id->enabled;
    1244    87218789 :         UWRAP_UNLOCK(uwrap_id);
    1245             : 
    1246    87218789 :         return enabled;
    1247             : }
    1248             : 
    1249             : /*
    1250             :  * UWRAP_SETxUID FUNCTIONS
    1251             :  */
    1252             : 
    1253    13801691 : static int uwrap_setresuid_args(uid_t ruid, uid_t euid, uid_t suid)
    1254             : {
    1255    13801691 :         struct uwrap_thread *id = uwrap_tls_id;
    1256             : 
    1257    13801691 :         UWRAP_LOG(UWRAP_LOG_TRACE,
    1258             :                   "ruid %d -> %d, euid %d -> %d, suid %d -> %d",
    1259             :                   id->ruid, ruid, id->euid, euid, id->suid, suid);
    1260             : 
    1261    13801691 :         if (id->euid != 0) {
    1262    10307726 :                 if (ruid != (uid_t)-1 &&
    1263     9291102 :                     ruid != id->ruid &&
    1264     8955841 :                     ruid != id->euid &&
    1265     4479996 :                     ruid != id->suid) {
    1266           7 :                         errno = EPERM;
    1267           7 :                         return -1;
    1268             :                 }
    1269    10993226 :                 if (euid != (uid_t)-1 &&
    1270     9976602 :                     euid != id->ruid &&
    1271     8955827 :                     euid != id->euid &&
    1272     4479989 :                     euid != id->suid) {
    1273           0 :                         errno = EPERM;
    1274           0 :                         return -1;
    1275             :                 }
    1276     5498493 :                 if (suid != (uid_t)-1 &&
    1277        3760 :                     suid != id->ruid &&
    1278        3760 :                     suid != id->euid &&
    1279        1880 :                     suid != id->suid) {
    1280           0 :                         errno = EPERM;
    1281           0 :                         return -1;
    1282             :                 }
    1283             :         }
    1284             : 
    1285    13783803 :         return 0;
    1286             : }
    1287             : 
    1288    13801691 : static int uwrap_setresuid_thread(uid_t ruid, uid_t euid, uid_t suid)
    1289             : {
    1290    13801691 :         struct uwrap_thread *id = uwrap_tls_id;
    1291             :         int rc;
    1292             : 
    1293    13801691 :         UWRAP_LOG(UWRAP_LOG_TRACE,
    1294             :                   "ruid %d -> %d, euid %d -> %d, suid %d -> %d",
    1295             :                   id->ruid, ruid, id->euid, euid, id->suid, suid);
    1296             : 
    1297    13801691 :         rc = uwrap_setresuid_args(ruid, euid, suid);
    1298    13801691 :         if (rc != 0) {
    1299           7 :                 return rc;
    1300             :         }
    1301             : 
    1302    13801684 :         UWRAP_LOCK(uwrap_id);
    1303             : 
    1304    13801684 :         if (ruid != (uid_t)-1) {
    1305    11068502 :                 id->ruid = ruid;
    1306             :         }
    1307             : 
    1308    13801684 :         if (euid != (uid_t)-1) {
    1309    13801684 :                 id->euid = euid;
    1310             :         }
    1311             : 
    1312    13801684 :         if (suid != (uid_t)-1) {
    1313       13624 :                 id->suid = suid;
    1314             :         }
    1315             : 
    1316    13801684 :         UWRAP_UNLOCK(uwrap_id);
    1317             : 
    1318    13801684 :         return 0;
    1319             : }
    1320             : 
    1321           0 : static int uwrap_setresuid(uid_t ruid, uid_t euid, uid_t suid)
    1322             : {
    1323           0 :         struct uwrap_thread *id = uwrap_tls_id;
    1324             :         int rc;
    1325             : 
    1326           0 :         UWRAP_LOG(UWRAP_LOG_TRACE,
    1327             :                   "ruid %d -> %d, euid %d -> %d, suid %d -> %d",
    1328             :                   id->ruid, ruid, id->euid, euid, id->suid, suid);
    1329             : 
    1330           0 :         rc = uwrap_setresuid_args(ruid, euid, suid);
    1331           0 :         if (rc != 0) {
    1332           0 :                 return rc;
    1333             :         }
    1334             : 
    1335           0 :         UWRAP_LOCK(uwrap_id);
    1336             : 
    1337           0 :         for (id = uwrap.ids; id; id = id->next) {
    1338           0 :                 if (ruid != (uid_t)-1) {
    1339           0 :                         id->ruid = ruid;
    1340             :                 }
    1341             : 
    1342           0 :                 if (euid != (uid_t)-1) {
    1343           0 :                         id->euid = euid;
    1344             :                 }
    1345             : 
    1346           0 :                 if (suid != (uid_t)-1) {
    1347           0 :                         id->suid = suid;
    1348             :                 }
    1349             :         }
    1350             : 
    1351           0 :         UWRAP_UNLOCK(uwrap_id);
    1352             : 
    1353           0 :         return 0;
    1354             : }
    1355             : 
    1356           0 : static int uwrap_setreuid_args(uid_t ruid, uid_t euid,
    1357             :                                uid_t *_new_ruid,
    1358             :                                uid_t *_new_euid,
    1359             :                                uid_t *_new_suid)
    1360             : {
    1361           0 :         struct uwrap_thread *id = uwrap_tls_id;
    1362           0 :         uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
    1363             : 
    1364           0 :         UWRAP_LOG(UWRAP_LOG_TRACE,
    1365             :                   "ruid %d -> %d, euid %d -> %d",
    1366             :                   id->ruid, ruid, id->euid, euid);
    1367             : 
    1368           0 :         if (ruid != (uid_t)-1) {
    1369           0 :                 new_ruid = ruid;
    1370           0 :                 if (ruid != id->ruid &&
    1371           0 :                     ruid != id->euid &&
    1372           0 :                     id->euid != 0) {
    1373           0 :                         errno = EPERM;
    1374           0 :                         return -1;
    1375             :                 }
    1376             :         }
    1377             : 
    1378           0 :         if (euid != (uid_t)-1) {
    1379           0 :                 new_euid = euid;
    1380           0 :                 if (euid != id->ruid &&
    1381           0 :                     euid != id->euid &&
    1382           0 :                     euid != id->suid &&
    1383           0 :                     id->euid != 0) {
    1384           0 :                         errno = EPERM;
    1385           0 :                         return -1;
    1386             :                 }
    1387             :         }
    1388             : 
    1389           0 :         if (ruid != (uid_t) -1 ||
    1390           0 :             (euid != (uid_t)-1 && id->ruid != euid)) {
    1391           0 :                 new_suid = new_euid;
    1392             :         }
    1393             : 
    1394           0 :         *_new_ruid = new_ruid;
    1395           0 :         *_new_euid = new_euid;
    1396           0 :         *_new_suid = new_suid;
    1397             : 
    1398           0 :         return 0;
    1399             : }
    1400             : 
    1401           0 : static int uwrap_setreuid_thread(uid_t ruid, uid_t euid)
    1402             : {
    1403           0 :         struct uwrap_thread *id = uwrap_tls_id;
    1404           0 :         uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
    1405             :         int rc;
    1406             : 
    1407           0 :         UWRAP_LOG(UWRAP_LOG_TRACE,
    1408             :                   "ruid %d -> %d, euid %d -> %d",
    1409             :                   id->ruid, ruid, id->euid, euid);
    1410             : 
    1411           0 :         rc = uwrap_setreuid_args(ruid, euid, &new_ruid, &new_euid, &new_suid);
    1412           0 :         if (rc != 0) {
    1413           0 :                 return rc;
    1414             :         }
    1415             : 
    1416           0 :         return uwrap_setresuid_thread(new_ruid, new_euid, new_suid);
    1417             : }
    1418             : 
    1419             : #ifdef HAVE_SETREUID
    1420           0 : static int uwrap_setreuid(uid_t ruid, uid_t euid)
    1421             : {
    1422           0 :         struct uwrap_thread *id = uwrap_tls_id;
    1423           0 :         uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
    1424             :         int rc;
    1425             : 
    1426           0 :         UWRAP_LOG(UWRAP_LOG_TRACE,
    1427             :                   "ruid %d -> %d, euid %d -> %d",
    1428             :                   id->ruid, ruid, id->euid, euid);
    1429             : 
    1430           0 :         rc = uwrap_setreuid_args(ruid, euid, &new_ruid, &new_euid, &new_suid);
    1431           0 :         if (rc != 0) {
    1432           0 :                 return rc;
    1433             :         }
    1434             : 
    1435           0 :         return uwrap_setresuid(new_ruid, new_euid, new_suid);
    1436             : }
    1437             : #endif
    1438             : 
    1439        7752 : static int uwrap_setuid_args(uid_t uid,
    1440             :                              uid_t *new_ruid,
    1441             :                              uid_t *new_euid,
    1442             :                              uid_t *new_suid)
    1443             : {
    1444        7752 :         struct uwrap_thread *id = uwrap_tls_id;
    1445             : 
    1446        7752 :         UWRAP_LOG(UWRAP_LOG_TRACE,
    1447             :                   "uid %d -> %d",
    1448             :                   id->ruid, uid);
    1449             : 
    1450        7752 :         if (uid == (uid_t)-1) {
    1451           0 :                 errno = EINVAL;
    1452           0 :                 return -1;
    1453             :         }
    1454             : 
    1455        7752 :         if (id->euid == 0) {
    1456        5872 :                 *new_suid = *new_ruid = uid;
    1457        1880 :         } else if (uid != id->ruid &&
    1458           0 :                    uid != id->suid) {
    1459           0 :                 errno = EPERM;
    1460           0 :                 return -1;
    1461             :         }
    1462             : 
    1463        7752 :         *new_euid = uid;
    1464             : 
    1465        7752 :         return 0;
    1466             : }
    1467             : 
    1468        7752 : static int uwrap_setuid_thread(uid_t uid)
    1469             : {
    1470        7752 :         uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
    1471             :         int rc;
    1472             : 
    1473        7752 :         rc = uwrap_setuid_args(uid, &new_ruid, &new_euid, &new_suid);
    1474        7752 :         if (rc != 0) {
    1475           0 :                 return rc;
    1476             :         }
    1477             : 
    1478        7752 :         return uwrap_setresuid_thread(new_ruid, new_euid, new_suid);
    1479             : }
    1480             : 
    1481           0 : static int uwrap_setuid(uid_t uid)
    1482             : {
    1483           0 :         uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
    1484             :         int rc;
    1485             : 
    1486           0 :         rc = uwrap_setuid_args(uid, &new_ruid, &new_euid, &new_suid);
    1487           0 :         if (rc != 0) {
    1488           0 :                 return rc;
    1489             :         }
    1490             : 
    1491           0 :         return uwrap_setresuid(new_ruid, new_euid, new_suid);
    1492             : }
    1493             : 
    1494             : /*
    1495             :  * UWRAP_GETxUID FUNCTIONS
    1496             :  */
    1497             : 
    1498             : #ifdef HAVE_GETRESUID
    1499           0 : static int uwrap_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
    1500             : {
    1501           0 :         struct uwrap_thread *id = uwrap_tls_id;
    1502             : 
    1503           0 :         UWRAP_LOCK(uwrap_id);
    1504             : 
    1505           0 :         *ruid = id->ruid;
    1506           0 :         *euid = id->euid;
    1507           0 :         *suid = id->suid;
    1508             : 
    1509           0 :         UWRAP_UNLOCK(uwrap_id);
    1510             : 
    1511           0 :         return 0;
    1512             : }
    1513             : #endif
    1514             : 
    1515             : #ifdef HAVE_GETRESGID
    1516           0 : static int uwrap_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
    1517             : {
    1518           0 :         struct uwrap_thread *id = uwrap_tls_id;
    1519             : 
    1520           0 :         UWRAP_LOCK(uwrap_id);
    1521             : 
    1522           0 :         *rgid = id->rgid;
    1523           0 :         *egid = id->egid;
    1524           0 :         *sgid = id->sgid;
    1525             : 
    1526           0 :         UWRAP_UNLOCK(uwrap_id);
    1527             : 
    1528           0 :         return 0;
    1529             : }
    1530             : #endif
    1531             : 
    1532             : /*
    1533             :  * UWRAP_SETxGID FUNCTIONS
    1534             :  */
    1535             : 
    1536    12435679 : static int uwrap_setresgid_args(gid_t rgid, gid_t egid, gid_t sgid)
    1537             : {
    1538    12435679 :         struct uwrap_thread *id = uwrap_tls_id;
    1539             : 
    1540    12435679 :         UWRAP_LOG(UWRAP_LOG_TRACE,
    1541             :                   "rgid %d -> %d, egid %d -> %d, sgid %d -> %d",
    1542             :                   id->rgid, rgid, id->egid, egid, id->sgid, sgid);
    1543             : 
    1544    12435679 :         if (id->euid != 0) {
    1545     4809200 :                 if (rgid != (gid_t)-1 &&
    1546           0 :                     rgid != id->rgid &&
    1547           0 :                     rgid != id->egid &&
    1548           0 :                     rgid != id->sgid) {
    1549           0 :                         errno = EPERM;
    1550           0 :                         return -1;
    1551             :                 }
    1552     9618400 :                 if (egid != (gid_t)-1 &&
    1553     5140311 :                     egid != id->rgid &&
    1554      331118 :                     egid != id->egid &&
    1555           7 :                     egid != id->sgid) {
    1556           7 :                         errno = EPERM;
    1557           7 :                         return -1;
    1558             :                 }
    1559     4809193 :                 if (sgid != (gid_t)-1 &&
    1560           0 :                     sgid != id->rgid &&
    1561           0 :                     sgid != id->egid &&
    1562           0 :                     sgid != id->sgid) {
    1563           0 :                         errno = EPERM;
    1564           0 :                         return -1;
    1565             :                 }
    1566             :         }
    1567             : 
    1568    12417785 :         return 0;
    1569             : }
    1570             : 
    1571    12435679 : static int uwrap_setresgid_thread(gid_t rgid, gid_t egid, gid_t sgid)
    1572             : {
    1573    12435679 :         struct uwrap_thread *id = uwrap_tls_id;
    1574             :         int rc;
    1575             : 
    1576    12435679 :         UWRAP_LOG(UWRAP_LOG_TRACE,
    1577             :                   "rgid %d -> %d, egid %d -> %d, sgid %d -> %d",
    1578             :                   id->rgid, rgid, id->egid, egid, id->sgid, sgid);
    1579             : 
    1580    12435679 :         rc = uwrap_setresgid_args(rgid, egid, sgid);
    1581    12435679 :         if (rc != 0) {
    1582           7 :                 return rc;
    1583             :         }
    1584             : 
    1585    12435672 :         UWRAP_LOCK(uwrap_id);
    1586             : 
    1587    12435672 :         if (rgid != (gid_t)-1) {
    1588       15694 :                 id->rgid = rgid;
    1589             :         }
    1590             : 
    1591    12435672 :         if (egid != (gid_t)-1) {
    1592    12435672 :                 id->egid = egid;
    1593             :         }
    1594             : 
    1595    12435672 :         if (sgid != (gid_t)-1) {
    1596       15586 :                 id->sgid = sgid;
    1597             :         }
    1598             : 
    1599    12435672 :         UWRAP_UNLOCK(uwrap_id);
    1600             : 
    1601    12435672 :         return 0;
    1602             : }
    1603             : 
    1604           0 : static int uwrap_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
    1605             : {
    1606           0 :         struct uwrap_thread *id = uwrap_tls_id;
    1607             :         int rc;
    1608             : 
    1609           0 :         UWRAP_LOG(UWRAP_LOG_TRACE,
    1610             :                   "rgid %d -> %d, egid %d -> %d, sgid %d -> %d",
    1611             :                   id->rgid, rgid, id->egid, egid, id->sgid, sgid);
    1612             : 
    1613           0 :         rc = uwrap_setresgid_args(rgid, egid, sgid);
    1614           0 :         if (rc != 0) {
    1615           0 :                 return rc;
    1616             :         }
    1617             : 
    1618           0 :         UWRAP_LOCK(uwrap_id);
    1619             : 
    1620           0 :         for (id = uwrap.ids; id; id = id->next) {
    1621           0 :                 if (rgid != (gid_t)-1) {
    1622           0 :                         id->rgid = rgid;
    1623             :                 }
    1624             : 
    1625           0 :                 if (egid != (gid_t)-1) {
    1626           0 :                         id->egid = egid;
    1627             :                 }
    1628             : 
    1629           0 :                 if (sgid != (gid_t)-1) {
    1630           0 :                         id->sgid = sgid;
    1631             :                 }
    1632             :         }
    1633             : 
    1634           0 :         UWRAP_UNLOCK(uwrap_id);
    1635             : 
    1636           0 :         return 0;
    1637             : }
    1638             : 
    1639           0 : static int uwrap_setregid_args(gid_t rgid, gid_t egid,
    1640             :                                gid_t *_new_rgid,
    1641             :                                gid_t *_new_egid,
    1642             :                                gid_t *_new_sgid)
    1643             : {
    1644           0 :         struct uwrap_thread *id = uwrap_tls_id;
    1645           0 :         gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
    1646             : 
    1647           0 :         UWRAP_LOG(UWRAP_LOG_TRACE,
    1648             :                   "rgid %d -> %d, egid %d -> %d",
    1649             :                   id->rgid, rgid, id->egid, egid);
    1650             : 
    1651           0 :         if (rgid != (gid_t)-1) {
    1652           0 :                 new_rgid = rgid;
    1653           0 :                 if (rgid != id->rgid &&
    1654           0 :                     rgid != id->egid &&
    1655           0 :                     id->euid != 0) {
    1656           0 :                         errno = EPERM;
    1657           0 :                         return -1;
    1658             :                 }
    1659             :         }
    1660             : 
    1661           0 :         if (egid != (gid_t)-1) {
    1662           0 :                 new_egid = egid;
    1663           0 :                 if (egid != id->rgid &&
    1664           0 :                     egid != id->egid &&
    1665           0 :                     egid != id->sgid &&
    1666           0 :                     id->euid != 0) {
    1667           0 :                         errno = EPERM;
    1668           0 :                         return -1;
    1669             :                 }
    1670             :         }
    1671             : 
    1672           0 :         if (rgid != (gid_t) -1 ||
    1673           0 :             (egid != (gid_t)-1 && id->rgid != egid)) {
    1674           0 :                 new_sgid = new_egid;
    1675             :         }
    1676             : 
    1677           0 :         *_new_rgid = new_rgid;
    1678           0 :         *_new_egid = new_egid;
    1679           0 :         *_new_sgid = new_sgid;
    1680             : 
    1681           0 :         return 0;
    1682             : }
    1683             : 
    1684           0 : static int uwrap_setregid_thread(gid_t rgid, gid_t egid)
    1685             : {
    1686           0 :         struct uwrap_thread *id = uwrap_tls_id;
    1687           0 :         gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
    1688             :         int rc;
    1689             : 
    1690           0 :         UWRAP_LOG(UWRAP_LOG_TRACE,
    1691             :                   "rgid %d -> %d, egid %d -> %d",
    1692             :                   id->rgid, rgid, id->egid, egid);
    1693             : 
    1694           0 :         rc = uwrap_setregid_args(rgid, egid, &new_rgid, &new_egid, &new_sgid);
    1695           0 :         if (rc != 0) {
    1696           0 :                 return rc;
    1697             :         }
    1698             : 
    1699           0 :         return uwrap_setresgid_thread(new_rgid, new_egid, new_sgid);
    1700             : }
    1701             : 
    1702             : #ifdef HAVE_SETREGID
    1703           0 : static int uwrap_setregid(gid_t rgid, gid_t egid)
    1704             : {
    1705           0 :         struct uwrap_thread *id = uwrap_tls_id;
    1706           0 :         gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
    1707             :         int rc;
    1708             : 
    1709           0 :         UWRAP_LOG(UWRAP_LOG_TRACE,
    1710             :                   "rgid %d -> %d, egid %d -> %d",
    1711             :                   id->rgid, rgid, id->egid, egid);
    1712             : 
    1713           0 :         rc = uwrap_setregid_args(rgid, egid, &new_rgid, &new_egid, &new_sgid);
    1714           0 :         if (rc != 0) {
    1715           0 :                 return rc;
    1716             :         }
    1717             : 
    1718           0 :         return uwrap_setresgid(new_rgid, new_egid, new_sgid);
    1719             : }
    1720             : #endif
    1721             : 
    1722        7834 : static int uwrap_setgid_args(gid_t gid,
    1723             :                              gid_t *new_rgid,
    1724             :                              gid_t *new_egid,
    1725             :                              gid_t *new_sgid)
    1726             : {
    1727        7834 :         struct uwrap_thread *id = uwrap_tls_id;
    1728             : 
    1729        7834 :         UWRAP_LOG(UWRAP_LOG_TRACE,
    1730             :                   "gid %d -> %d",
    1731             :                   id->rgid, gid);
    1732             : 
    1733        7834 :         if (gid == (gid_t)-1) {
    1734           0 :                 errno = EINVAL;
    1735           0 :                 return -1;
    1736             :         }
    1737             : 
    1738        7834 :         if (id->euid == 0) {
    1739        7834 :                 *new_sgid = *new_rgid = gid;
    1740           0 :         } else if (gid != id->rgid &&
    1741           0 :                    gid != id->sgid) {
    1742           0 :                 errno = EPERM;
    1743           0 :                 return -1;
    1744             :         }
    1745             : 
    1746        7834 :         *new_egid = gid;
    1747             : 
    1748        7834 :         return 0;
    1749             : }
    1750             : 
    1751        7834 : static int uwrap_setgid_thread(gid_t gid)
    1752             : {
    1753        7834 :         gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
    1754             :         int rc;
    1755             : 
    1756        7834 :         rc = uwrap_setgid_args(gid, &new_rgid, &new_egid, &new_sgid);
    1757        7834 :         if (rc != 0) {
    1758           0 :                 return rc;
    1759             :         }
    1760             : 
    1761        7834 :         return uwrap_setresgid_thread(new_rgid, new_egid, new_sgid);
    1762             : }
    1763             : 
    1764           0 : static int uwrap_setgid(gid_t gid)
    1765             : {
    1766           0 :         gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
    1767             :         int rc;
    1768             : 
    1769           0 :         rc = uwrap_setgid_args(gid, &new_rgid, &new_egid, &new_sgid);
    1770           0 :         if (rc != 0) {
    1771           0 :                 return rc;
    1772             :         }
    1773             : 
    1774           0 :         return uwrap_setresgid(new_rgid, new_egid, new_sgid);
    1775             : }
    1776             : 
    1777             : /*
    1778             :  * SETUID
    1779             :  */
    1780             : int setuid(uid_t uid)
    1781             : {
    1782           0 :         if (!uid_wrapper_enabled()) {
    1783           0 :                 return libc_setuid(uid);
    1784             :         }
    1785             : 
    1786           0 :         uwrap_init();
    1787           0 :         return uwrap_setuid(uid);
    1788             : }
    1789             : 
    1790             : #ifdef HAVE_SETEUID
    1791             : int seteuid(uid_t euid)
    1792             : {
    1793           0 :         if (!uid_wrapper_enabled()) {
    1794           0 :                 return libc_seteuid(euid);
    1795             :         }
    1796             : 
    1797             :         /* On FreeBSD the uid_t -1 is set and doesn't produce and error */
    1798           0 :         if (euid == (uid_t)-1) {
    1799           0 :                 errno = EINVAL;
    1800           0 :                 return -1;
    1801             :         }
    1802             : 
    1803           0 :         uwrap_init();
    1804           0 :         return uwrap_setresuid(-1, euid, -1);
    1805             : }
    1806             : #endif
    1807             : 
    1808             : #ifdef HAVE_SETREUID
    1809             : int setreuid(uid_t ruid, uid_t euid)
    1810             : {
    1811           0 :         if (!uid_wrapper_enabled()) {
    1812           0 :                 return libc_setreuid(ruid, euid);
    1813             :         }
    1814             : 
    1815           0 :         uwrap_init();
    1816           0 :         return uwrap_setreuid(ruid, euid);
    1817             : }
    1818             : #endif
    1819             : 
    1820             : #ifdef HAVE_SETRESUID
    1821             : int setresuid(uid_t ruid, uid_t euid, uid_t suid)
    1822             : {
    1823           0 :         if (!uid_wrapper_enabled()) {
    1824           0 :                 return libc_setresuid(ruid, euid, suid);
    1825             :         }
    1826             : 
    1827           0 :         uwrap_init();
    1828           0 :         return uwrap_setresuid(ruid, euid, suid);
    1829             : }
    1830             : #endif
    1831             : 
    1832             : #ifdef HAVE_GETRESUID
    1833             : int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
    1834             : {
    1835           0 :         if (!uid_wrapper_enabled()) {
    1836           0 :                 return libc_getresuid(ruid, euid, suid);
    1837             :         }
    1838             : 
    1839           0 :         uwrap_init();
    1840           0 :         return uwrap_getresuid(ruid, euid, suid);
    1841             : }
    1842             : #endif
    1843             : 
    1844             : /*
    1845             :  * GETUID
    1846             :  */
    1847       72424 : static uid_t uwrap_getuid(void)
    1848             : {
    1849       75539 :         struct uwrap_thread *id = uwrap_tls_id;
    1850             :         uid_t uid;
    1851             : 
    1852       75539 :         UWRAP_LOCK(uwrap_id);
    1853       75539 :         uid = id->ruid;
    1854       75539 :         UWRAP_UNLOCK(uwrap_id);
    1855             : 
    1856       72424 :         return uid;
    1857             : }
    1858             : 
    1859             : uid_t getuid(void)
    1860             : {
    1861       75539 :         if (!uid_wrapper_enabled()) {
    1862           0 :                 return libc_getuid();
    1863             :         }
    1864             : 
    1865       75539 :         uwrap_init();
    1866       75539 :         return uwrap_getuid();
    1867             : }
    1868             : 
    1869             : /*
    1870             :  * GETEUID
    1871             :  */
    1872    18335345 : static uid_t uwrap_geteuid(void)
    1873             : {
    1874    18335345 :         const char *env = getenv("UID_WRAPPER_MYUID");
    1875    18335345 :         struct uwrap_thread *id = uwrap_tls_id;
    1876             :         uid_t uid;
    1877             : 
    1878    18335345 :         UWRAP_LOCK(uwrap_id);
    1879    18335345 :         uid = id->euid;
    1880    18335345 :         UWRAP_UNLOCK(uwrap_id);
    1881             : 
    1882             :         /* Disable root and return myuid */
    1883    18335345 :         if (env != NULL && env[0] == '1') {
    1884      368371 :                 uid = uwrap.myuid;
    1885             :         }
    1886             : 
    1887    18335345 :         return uid;
    1888             : }
    1889             : 
    1890             : uid_t geteuid(void)
    1891             : {
    1892    18335345 :         if (!uid_wrapper_enabled()) {
    1893           0 :                 return libc_geteuid();
    1894             :         }
    1895             : 
    1896    18335345 :         uwrap_init();
    1897    18335345 :         return uwrap_geteuid();
    1898             : }
    1899             : 
    1900             : /*
    1901             :  * SETGID
    1902             :  */
    1903             : int setgid(gid_t gid)
    1904             : {
    1905           0 :         if (!uid_wrapper_enabled()) {
    1906           0 :                 return libc_setgid(gid);
    1907             :         }
    1908             : 
    1909           0 :         uwrap_init();
    1910           0 :         return uwrap_setgid(gid);
    1911             : }
    1912             : 
    1913             : #ifdef HAVE_SETEGID
    1914             : int setegid(gid_t egid)
    1915             : {
    1916           0 :         if (!uid_wrapper_enabled()) {
    1917           0 :                 return libc_setegid(egid);
    1918             :         }
    1919             : 
    1920             :         /* On FreeBSD the uid_t -1 is set and doesn't produce and error */
    1921           0 :         if (egid == (gid_t)-1) {
    1922           0 :                 errno = EINVAL;
    1923           0 :                 return -1;
    1924             :         }
    1925             : 
    1926           0 :         uwrap_init();
    1927           0 :         return uwrap_setresgid(-1, egid, -1);
    1928             : }
    1929             : #endif
    1930             : 
    1931             : #ifdef HAVE_SETREGID
    1932             : int setregid(gid_t rgid, gid_t egid)
    1933             : {
    1934           0 :         if (!uid_wrapper_enabled()) {
    1935           0 :                 return libc_setregid(rgid, egid);
    1936             :         }
    1937             : 
    1938           0 :         uwrap_init();
    1939           0 :         return uwrap_setregid(rgid, egid);
    1940             : }
    1941             : #endif
    1942             : 
    1943             : #ifdef HAVE_SETRESGID
    1944             : int setresgid(gid_t rgid, gid_t egid, gid_t sgid)
    1945             : {
    1946           0 :         if (!uid_wrapper_enabled()) {
    1947           0 :                 return libc_setresgid(rgid, egid, sgid);
    1948             :         }
    1949             : 
    1950           0 :         uwrap_init();
    1951           0 :         return uwrap_setresgid(rgid, egid, sgid);
    1952             : }
    1953             : #endif
    1954             : 
    1955             : #ifdef HAVE_GETRESGID
    1956             : int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
    1957             : {
    1958           0 :         if (!uid_wrapper_enabled()) {
    1959           0 :                 return libc_getresgid(rgid, egid, sgid);
    1960             :         }
    1961             : 
    1962           0 :         uwrap_init();
    1963           0 :         return uwrap_getresgid(rgid, egid, sgid);
    1964             : }
    1965             : #endif
    1966             : 
    1967             : /*
    1968             :  * GETGID
    1969             :  */
    1970       29211 : static gid_t uwrap_getgid(void)
    1971             : {
    1972       30985 :         struct uwrap_thread *id = uwrap_tls_id;
    1973             :         gid_t gid;
    1974             : 
    1975       30985 :         UWRAP_LOCK(uwrap_id);
    1976       30985 :         gid = id->rgid;
    1977       30985 :         UWRAP_UNLOCK(uwrap_id);
    1978             : 
    1979       29211 :         return gid;
    1980             : }
    1981             : 
    1982             : gid_t getgid(void)
    1983             : {
    1984       30985 :         if (!uid_wrapper_enabled()) {
    1985           0 :                 return libc_getgid();
    1986             :         }
    1987             : 
    1988       30985 :         uwrap_init();
    1989       30985 :         return uwrap_getgid();
    1990             : }
    1991             : 
    1992             : /*
    1993             :  * GETEGID
    1994             :  */
    1995    16904350 : static uid_t uwrap_getegid(void)
    1996             : {
    1997    16929654 :         struct uwrap_thread *id = uwrap_tls_id;
    1998             :         gid_t gid;
    1999             : 
    2000    16929654 :         UWRAP_LOCK(uwrap_id);
    2001    16929654 :         gid = id->egid;
    2002    16929654 :         UWRAP_UNLOCK(uwrap_id);
    2003             : 
    2004    16904350 :         return gid;
    2005             : }
    2006             : 
    2007             : uid_t getegid(void)
    2008             : {
    2009    16929654 :         if (!uid_wrapper_enabled()) {
    2010           0 :                 return libc_getegid();
    2011             :         }
    2012             : 
    2013    16929654 :         uwrap_init();
    2014    16929654 :         return uwrap_getegid();
    2015             : }
    2016             : 
    2017    12419929 : static int uwrap_setgroups_thread(size_t size, const gid_t *list)
    2018             : {
    2019    12419929 :         struct uwrap_thread *id = uwrap_tls_id;
    2020    12419929 :         int rc = -1;
    2021             : 
    2022    12419929 :         UWRAP_LOCK(uwrap_id);
    2023             : 
    2024    12419929 :         if (size == 0) {
    2025     6222715 :                 SAFE_FREE(id->groups);
    2026     6222715 :                 id->ngroups = 0;
    2027     6192902 :         } else if (size > 0) {
    2028             :                 gid_t *tmp;
    2029             : 
    2030     6197214 :                 tmp = realloc(id->groups, sizeof(gid_t) * size);
    2031     6197214 :                 if (tmp == NULL) {
    2032           0 :                         errno = ENOMEM;
    2033           0 :                         goto out;
    2034             :                 }
    2035     6197214 :                 id->groups = tmp;
    2036     6197214 :                 id->ngroups = size;
    2037     6197214 :                 memcpy(id->groups, list, size * sizeof(gid_t));
    2038             :         }
    2039             : 
    2040    12402052 :         rc = 0;
    2041    12419929 : out:
    2042    12419929 :         UWRAP_UNLOCK(uwrap_id);
    2043             : 
    2044    12419929 :         return rc;
    2045             : }
    2046             : 
    2047           0 : static int uwrap_setgroups(size_t size, const gid_t *list)
    2048             : {
    2049             :         struct uwrap_thread *id;
    2050           0 :         int rc = -1;
    2051             : 
    2052           0 :         UWRAP_LOCK(uwrap_id);
    2053             : 
    2054           0 :         if (size == 0) {
    2055           0 :                 for (id = uwrap.ids; id; id = id->next) {
    2056           0 :                         SAFE_FREE(id->groups);
    2057           0 :                         id->ngroups = 0;
    2058             : 
    2059             :                 }
    2060           0 :         } else if (size > 0) {
    2061             :                 gid_t *tmp;
    2062             : 
    2063           0 :                 for (id = uwrap.ids; id; id = id->next) {
    2064           0 :                         tmp = realloc(id->groups, sizeof(gid_t) * size);
    2065           0 :                         if (tmp == NULL) {
    2066           0 :                                 errno = ENOMEM;
    2067           0 :                                 goto out;
    2068             :                         }
    2069           0 :                         id->groups = tmp;
    2070             : 
    2071           0 :                         id->ngroups = size;
    2072           0 :                         memcpy(id->groups, list, size * sizeof(gid_t));
    2073             :                 }
    2074             :         }
    2075             : 
    2076           0 :         rc = 0;
    2077           0 : out:
    2078           0 :         UWRAP_UNLOCK(uwrap_id);
    2079             : 
    2080           0 :         return rc;
    2081             : }
    2082             : 
    2083             : #ifdef HAVE_SETGROUPS_INT
    2084             : int setgroups(int size, const gid_t *list)
    2085             : #else
    2086             : int setgroups(size_t size, const gid_t *list)
    2087             : #endif
    2088             : {
    2089           0 :         if (!uid_wrapper_enabled()) {
    2090           0 :                 return libc_setgroups(size, list);
    2091             :         }
    2092             : 
    2093           0 :         uwrap_init();
    2094           0 :         return uwrap_setgroups(size, list);
    2095             : }
    2096             : 
    2097    11010229 : static int uwrap_getgroups(int size, gid_t *list)
    2098             : {
    2099    11010229 :         struct uwrap_thread *id = uwrap_tls_id;
    2100             :         int ngroups;
    2101             : 
    2102    11010229 :         UWRAP_LOCK(uwrap_id);
    2103    11010229 :         ngroups = id->ngroups;
    2104             : 
    2105    11010229 :         if (size > ngroups) {
    2106           0 :                 size = ngroups;
    2107             :         }
    2108    11010229 :         if (size == 0) {
    2109     5791447 :                 goto out;
    2110             :         }
    2111     5213702 :         if (size < ngroups) {
    2112           0 :                 errno = EINVAL;
    2113           0 :                 ngroups = -1;
    2114             :         }
    2115     5213702 :         memcpy(list, id->groups, size * sizeof(gid_t));
    2116             : 
    2117    11015309 : out:
    2118    11010229 :         UWRAP_UNLOCK(uwrap_id);
    2119             : 
    2120    11010229 :         return ngroups;
    2121             : }
    2122             : 
    2123             : int getgroups(int size, gid_t *list)
    2124             : {
    2125    11010229 :         if (!uid_wrapper_enabled()) {
    2126           0 :                 return libc_getgroups(size, list);
    2127             :         }
    2128             : 
    2129    11010229 :         uwrap_init();
    2130    11010229 :         return uwrap_getgroups(size, list);
    2131             : }
    2132             : 
    2133             : #if (defined(HAVE_SYS_SYSCALL_H) || defined(HAVE_SYSCALL_H)) \
    2134             :     && (defined(SYS_setreuid) || defined(SYS_setreuid32))
    2135    39114931 : static long int uwrap_syscall (long int sysno, va_list vp)
    2136             : {
    2137             :         long int rc;
    2138             : 
    2139    39114931 :         switch (sysno) {
    2140             :                 /* gid */
    2141             : #ifdef __alpha__
    2142             :                 case SYS_getxgid:
    2143             : #else
    2144           0 :                 case SYS_getgid:
    2145             : #endif
    2146             : #ifdef HAVE_LINUX_32BIT_SYSCALLS
    2147             :                 case SYS_getgid32:
    2148             : #endif
    2149             :                         {
    2150           0 :                                 rc = uwrap_getgid();
    2151             :                         }
    2152           0 :                         break;
    2153             : #ifdef SYS_getegid
    2154           0 :                 case SYS_getegid:
    2155             : #ifdef HAVE_LINUX_32BIT_SYSCALLS
    2156             :                 case SYS_getegid32:
    2157             : #endif
    2158             :                         {
    2159           0 :                                 rc = uwrap_getegid();
    2160             :                         }
    2161           0 :                         break;
    2162             : #endif /* SYS_getegid */
    2163        7834 :                 case SYS_setgid:
    2164             : #ifdef HAVE_LINUX_32BIT_SYSCALLS
    2165             :                 case SYS_setgid32:
    2166             : #endif
    2167             :                         {
    2168        7834 :                                 gid_t gid = (gid_t) va_arg(vp, gid_t);
    2169             : 
    2170        7834 :                                 rc = uwrap_setgid_thread(gid);
    2171             :                         }
    2172        7834 :                         break;
    2173           0 :                 case SYS_setregid:
    2174             : #ifdef HAVE_LINUX_32BIT_SYSCALLS
    2175             :                 case SYS_setregid32:
    2176             : #endif
    2177             :                         {
    2178           0 :                                 gid_t rgid = (gid_t) va_arg(vp, gid_t);
    2179           0 :                                 gid_t egid = (gid_t) va_arg(vp, gid_t);
    2180             : 
    2181           0 :                                 rc = uwrap_setregid_thread(rgid, egid);
    2182             :                         }
    2183           0 :                         break;
    2184             : #ifdef SYS_setresgid
    2185    12427845 :                 case SYS_setresgid:
    2186             : #ifdef HAVE_LINUX_32BIT_SYSCALLS
    2187             :                 case SYS_setresgid32:
    2188             : #endif
    2189             :                         {
    2190    12427845 :                                 gid_t rgid = (gid_t) va_arg(vp, gid_t);
    2191    12427845 :                                 gid_t egid = (gid_t) va_arg(vp, gid_t);
    2192    12427845 :                                 gid_t sgid = (gid_t) va_arg(vp, gid_t);
    2193             : 
    2194    12427845 :                                 rc = uwrap_setresgid_thread(rgid, egid, sgid);
    2195             :                         }
    2196    12427845 :                         break;
    2197             : #endif /* SYS_setresgid */
    2198             : #if defined(SYS_getresgid) && defined(HAVE_GETRESGID)
    2199           0 :                 case SYS_getresgid:
    2200             : #ifdef HAVE_LINUX_32BIT_SYSCALLS
    2201             :                 case SYS_getresgid32:
    2202             : #endif
    2203             :                         {
    2204           0 :                                 gid_t *rgid = (gid_t *) va_arg(vp, gid_t *);
    2205           0 :                                 gid_t *egid = (gid_t *) va_arg(vp, gid_t *);
    2206           0 :                                 gid_t *sgid = (gid_t *) va_arg(vp, gid_t *);
    2207             : 
    2208           0 :                                 rc = uwrap_getresgid(rgid, egid, sgid);
    2209             :                         }
    2210           0 :                         break;
    2211             : #endif /* SYS_getresgid && HAVE_GETRESGID */
    2212             : 
    2213             :                 /* uid */
    2214             : #ifdef __alpha__
    2215             :                 case SYS_getxuid:
    2216             : #else
    2217           0 :                 case SYS_getuid:
    2218             : #endif
    2219             : #ifdef HAVE_LINUX_32BIT_SYSCALLS
    2220             :                 case SYS_getuid32:
    2221             : #endif
    2222             :                         {
    2223           0 :                                 rc = uwrap_getuid();
    2224             :                         }
    2225           0 :                         break;
    2226             : #ifdef SYS_geteuid
    2227           0 :                 case SYS_geteuid:
    2228             : #ifdef HAVE_LINUX_32BIT_SYSCALLS
    2229             :                 case SYS_geteuid32:
    2230             : #endif
    2231             :                         {
    2232           0 :                                 rc = uwrap_geteuid();
    2233             :                         }
    2234           0 :                         break;
    2235             : #endif /* SYS_geteuid */
    2236        7752 :                 case SYS_setuid:
    2237             : #ifdef HAVE_LINUX_32BIT_SYSCALLS
    2238             :                 case SYS_setuid32:
    2239             : #endif
    2240             :                         {
    2241        7752 :                                 uid_t uid = (uid_t) va_arg(vp, uid_t);
    2242             : 
    2243        7752 :                                 rc = uwrap_setuid_thread(uid);
    2244             :                         }
    2245        7752 :                         break;
    2246           0 :                 case SYS_setreuid:
    2247             : #ifdef HAVE_LINUX_32BIT_SYSCALLS
    2248             :                 case SYS_setreuid32:
    2249             : #endif
    2250             :                         {
    2251           0 :                                 uid_t ruid = (uid_t) va_arg(vp, uid_t);
    2252           0 :                                 uid_t euid = (uid_t) va_arg(vp, uid_t);
    2253             : 
    2254           0 :                                 rc = uwrap_setreuid_thread(ruid, euid);
    2255             :                         }
    2256           0 :                         break;
    2257             : #ifdef SYS_setresuid
    2258    13793939 :                 case SYS_setresuid:
    2259             : #ifdef HAVE_LINUX_32BIT_SYSCALLS
    2260             :                 case SYS_setresuid32:
    2261             : #endif
    2262             :                         {
    2263    13793939 :                                 uid_t ruid = (uid_t) va_arg(vp, uid_t);
    2264    13793939 :                                 uid_t euid = (uid_t) va_arg(vp, uid_t);
    2265    13793939 :                                 uid_t suid = (uid_t) va_arg(vp, uid_t);
    2266             : 
    2267    13793939 :                                 rc = uwrap_setresuid_thread(ruid, euid, suid);
    2268             :                         }
    2269    13793939 :                         break;
    2270             : #endif /* SYS_setresuid */
    2271             : #if defined(SYS_getresuid) && defined(HAVE_GETRESUID)
    2272           0 :                 case SYS_getresuid:
    2273             : #ifdef HAVE_LINUX_32BIT_SYSCALLS
    2274             :                 case SYS_getresuid32:
    2275             : #endif
    2276             :                         {
    2277           0 :                                 uid_t *ruid = (uid_t *) va_arg(vp, uid_t *);
    2278           0 :                                 uid_t *euid = (uid_t *) va_arg(vp, uid_t *);
    2279           0 :                                 uid_t *suid = (uid_t *) va_arg(vp, uid_t *);
    2280             : 
    2281           0 :                                 rc = uwrap_getresuid(ruid, euid, suid);
    2282             :                         }
    2283           0 :                         break;
    2284             : #endif /* SYS_getresuid && HAVE_GETRESUID*/
    2285             :                 /* groups */
    2286    12419929 :                 case SYS_setgroups:
    2287             : #ifdef HAVE_LINUX_32BIT_SYSCALLS
    2288             :                 case SYS_setgroups32:
    2289             : #endif
    2290             :                         {
    2291    12419929 :                                 size_t size = (size_t) va_arg(vp, size_t);
    2292    12419929 :                                 gid_t *list = (gid_t *) va_arg(vp, int *);
    2293             : 
    2294    12419929 :                                 rc = uwrap_setgroups_thread(size, list);
    2295             :                         }
    2296    12419929 :                         break;
    2297      457632 :                 default:
    2298      457632 :                         UWRAP_LOG(UWRAP_LOG_DEBUG,
    2299             :                                   "UID_WRAPPER calling non-wrapped syscall %lu",
    2300             :                                   sysno);
    2301             : 
    2302      457632 :                         rc = libc_vsyscall(sysno, vp);
    2303      457632 :                         break;
    2304             :         }
    2305             : 
    2306    39114931 :         return rc;
    2307             : }
    2308             : 
    2309             : #ifdef HAVE_SYSCALL
    2310             : #ifdef HAVE_SYSCALL_INT
    2311             : int syscall (int sysno, ...)
    2312             : #else
    2313             : long int syscall (long int sysno, ...)
    2314             : #endif
    2315             : {
    2316             : #ifdef HAVE_SYSCALL_INT
    2317             :         int rc;
    2318             : #else
    2319             :         long int rc;
    2320             : #endif
    2321             :         va_list va;
    2322             : 
    2323    39121853 :         va_start(va, sysno);
    2324             : 
    2325    39121853 :         if (!uid_wrapper_enabled()) {
    2326        6922 :                 rc = libc_vsyscall(sysno, va);
    2327        6922 :                 va_end(va);
    2328        6922 :                 return rc;
    2329             :         }
    2330             : 
    2331    39114931 :         uwrap_init();
    2332    39114931 :         rc = uwrap_syscall(sysno, va);
    2333    39114931 :         va_end(va);
    2334             : 
    2335    39114931 :         return rc;
    2336             : }
    2337             : #endif /* HAVE_SYSCALL */
    2338             : #endif /* HAVE_SYS_SYSCALL_H || HAVE_SYSCALL_H */
    2339             : 
    2340             : /****************************
    2341             :  * CONSTRUCTOR
    2342             :  ***************************/
    2343             : 
    2344      126389 : void uwrap_constructor(void)
    2345             : {
    2346             :         char *glibc_malloc_lock_bug;
    2347             : 
    2348             :         /*
    2349             :          * This is a workaround for a bug in glibc < 2.24:
    2350             :          *
    2351             :          * The child handler for the malloc() function is called and locks the
    2352             :          * mutex. Then our child handler is called and we try to call setenv().
    2353             :          * setenv() wants to malloc and tries to aquire the lock for malloc and
    2354             :          * we end up in a deadlock.
    2355             :          *
    2356             :          * So as a workaround we need to call malloc once before we setup the
    2357             :          * handlers.
    2358             :          *
    2359             :          * See https://sourceware.org/bugzilla/show_bug.cgi?id=16742
    2360             :          */
    2361      126389 :         glibc_malloc_lock_bug = malloc(1);
    2362      126389 :         if (glibc_malloc_lock_bug == NULL) {
    2363           0 :                 exit(-1);
    2364             :         }
    2365      122092 :         glibc_malloc_lock_bug[0] = '\0';
    2366             : 
    2367             :         /*
    2368             :         * If we hold a lock and the application forks, then the child
    2369             :         * is not able to unlock the mutex and we are in a deadlock.
    2370             :         * This should prevent such deadlocks.
    2371             :         */
    2372      126389 :         pthread_atfork(&uwrap_thread_prepare,
    2373             :                        &uwrap_thread_parent,
    2374             :                        &uwrap_thread_child);
    2375             : 
    2376      126389 :         free(glibc_malloc_lock_bug);
    2377             : 
    2378             :         /* Here is safe place to call uwrap_init() and initialize data
    2379             :          * for main process.
    2380             :          */
    2381      126389 :         uwrap_init();
    2382      126389 : }
    2383             : 
    2384             : /****************************
    2385             :  * DESTRUCTOR
    2386             :  ***************************/
    2387             : 
    2388             : /*
    2389             :  * This function is called when the library is unloaded and makes sure that
    2390             :  * resources are freed.
    2391             :  */
    2392      166948 : void uwrap_destructor(void)
    2393             : {
    2394      166948 :         struct uwrap_thread *u = uwrap.ids;
    2395             : 
    2396      166948 :         UWRAP_LOCK_ALL;
    2397             : 
    2398      505234 :         while (u != NULL) {
    2399      171338 :                 UWRAP_DLIST_REMOVE(uwrap.ids, u);
    2400             : 
    2401      171338 :                 SAFE_FREE(u->groups);
    2402      171338 :                 SAFE_FREE(u);
    2403             : 
    2404      171338 :                 u = uwrap.ids;
    2405             :         }
    2406             : 
    2407             : 
    2408      166948 :         if (uwrap.libc.handle != NULL) {
    2409      166948 :                 dlclose(uwrap.libc.handle);
    2410             :         }
    2411             : 
    2412      166948 :         if (uwrap.libpthread.handle != NULL) {
    2413           0 :                 dlclose(uwrap.libpthread.handle);
    2414             :         }
    2415             : 
    2416      166948 :         UWRAP_UNLOCK_ALL;
    2417      166948 : }

Generated by: LCOV version 1.13