LCOV - code coverage report
Current view: top level - third_party/uid_wrapper - uid_wrapper.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 496 914 54.3 %
Date: 2024-06-13 04:01:37 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     9719395 : 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     9719395 :         unsigned int lvl = 0;
     154     9719395 :         const char *prefix = "UWRAP";
     155             : 
     156     9719395 :         d = getenv("UID_WRAPPER_DEBUGLEVEL");
     157     9719395 :         if (d != NULL) {
     158           0 :                 lvl = atoi(d);
     159             :         }
     160             : 
     161     9719395 :         if (lvl < dbglvl) {
     162     9719395 :                 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      170796 : static void *uwrap_load_lib_handle(enum uwrap_lib lib)
     392             : {
     393      170796 :         int flags = RTLD_LAZY;
     394      170796 :         void *handle = NULL;
     395             :         int i;
     396             : 
     397             : #ifdef RTLD_DEEPBIND
     398      170796 :         const char *env_preload = getenv("LD_PRELOAD");
     399      170796 :         const char *env_deepbind = getenv("UID_WRAPPER_DISABLE_DEEPBIND");
     400      170796 :         bool enable_deepbind = true;
     401             : 
     402             :         /* Don't do a deepbind if we run with libasan */
     403      170796 :         if (env_preload != NULL && strlen(env_preload) < 1024) {
     404      170796 :                 const char *p = strstr(env_preload, "libasan.so");
     405      170796 :                 if (p != NULL) {
     406           0 :                         enable_deepbind = false;
     407             :                 }
     408             :         }
     409             : 
     410      170796 :         if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
     411           0 :                 enable_deepbind = false;
     412             :         }
     413             : 
     414      170796 :         if (enable_deepbind) {
     415      170796 :                 flags |= RTLD_DEEPBIND;
     416             :         }
     417             : #endif
     418             : 
     419      170796 :         switch (lib) {
     420      170248 :         case UWRAP_LIBNSL:
     421             :         case UWRAP_LIBSOCKET:
     422             :         case UWRAP_LIBC:
     423      170248 :                 handle = uwrap.libc.handle;
     424      170248 :                 if (handle == NULL) {
     425      495365 :                         for (i = 10; i >= 0; i--) {
     426      289010 :                                 char soname[256] = {0};
     427             : 
     428      289010 :                                 snprintf(soname, sizeof(soname), "libc.so.%d", i);
     429      289010 :                                 handle = dlopen(soname, flags);
     430      289010 :                                 if (handle != NULL) {
     431       99073 :                                         break;
     432             :                                 }
     433             : 
     434             :                                 /* glibc on Alpha and IA64 is libc.so.6.1 */
     435      231208 :                                 snprintf(soname, sizeof(soname), "libc.so.%d.1", i);
     436      231208 :                                 handle = dlopen(soname, flags);
     437      231208 :                                 if (handle != NULL) {
     438           0 :                                         break;
     439             :                                 }
     440             :                         }
     441             : 
     442       57802 :                         uwrap.libc.handle = handle;
     443             :                 }
     444      170248 :                 break;
     445         548 :         case UWRAP_LIBPTHREAD:
     446         548 :                 handle = uwrap.libpthread.handle;
     447         548 :                 if (handle == NULL) {
     448         548 :                         handle = dlopen("libpthread.so.0", flags);
     449         548 :                         if (handle != NULL) {
     450         548 :                                 break;
     451             :                         }
     452             :                 }
     453           0 :                 break;
     454             :         }
     455             : 
     456      170796 :         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      170796 :         return handle;
     468             : }
     469             : 
     470      170796 : static void *_uwrap_bind_symbol(enum uwrap_lib lib, const char *fn_name)
     471             : {
     472             :         void *handle;
     473             :         void *func;
     474             : 
     475      170796 :         handle = uwrap_load_lib_handle(lib);
     476             : 
     477      170796 :         func = dlsym(handle, fn_name);
     478      170796 :         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      170796 :         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       57802 : static uid_t libc_geteuid(void)
     563             : {
     564       57802 :         uwrap_bind_symbol_libc(geteuid);
     565             : 
     566       57802 :         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       57802 : static gid_t libc_getegid(void)
     620             : {
     621       57802 :         uwrap_bind_symbol_libc(getegid);
     622             : 
     623       57802 :         return uwrap.libc.symbols._libc_getegid.f();
     624             : }
     625             : 
     626       90506 : static int libc_getgroups(int size, gid_t list[])
     627             : {
     628       90506 :         uwrap_bind_symbol_libc(getgroups);
     629             : 
     630       90506 :         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      265038 : 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      265038 :         uwrap_bind_symbol_libc(syscall);
     649             : 
     650     2385342 :         for (i = 0; i < 8; i++) {
     651     2120304 :                 args[i] = va_arg(va, long int);
     652             :         }
     653             : 
     654      265038 :         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      265038 :         return rc;
     665             : }
     666             : #endif
     667             : 
     668             : /*
     669             :  * This part is "optimistic".
     670             :  * Thread can ends without pthread_exit call.
     671             :  */
     672          36 : static void libpthread_pthread_exit(void *retval)
     673             : {
     674          36 :         uwrap_bind_symbol_libpthread(pthread_exit);
     675             : 
     676          36 :         uwrap.libpthread.symbols._libpthread_pthread_exit.f(retval);
     677           0 : }
     678             : 
     679          36 : static void uwrap_pthread_exit(void *retval)
     680             : {
     681          36 :         struct uwrap_thread *id = uwrap_tls_id;
     682             : 
     683          36 :         UWRAP_LOG(UWRAP_LOG_DEBUG, "Cleanup thread");
     684             : 
     685          36 :         UWRAP_LOCK(uwrap_id);
     686          36 :         if (id == NULL) {
     687           0 :                 UWRAP_UNLOCK(uwrap_id);
     688           0 :                 libpthread_pthread_exit(retval);
     689           0 :                 return;
     690             :         }
     691             : 
     692          36 :         UWRAP_DLIST_REMOVE(uwrap.ids, id);
     693          36 :         SAFE_FREE(id->groups);
     694          36 :         SAFE_FREE(id);
     695          36 :         uwrap_tls_id = NULL;
     696             : 
     697          36 :         UWRAP_UNLOCK(uwrap_id);
     698             : 
     699          36 :         libpthread_pthread_exit(retval);
     700             : }
     701             : 
     702             : void pthread_exit(void *retval)
     703             : {
     704          36 :         if (!uid_wrapper_enabled()) {
     705           0 :                 libpthread_pthread_exit(retval);
     706             :         };
     707             : 
     708          36 :         uwrap_pthread_exit(retval);
     709             : 
     710             :         /* Calm down gcc warning. */
     711           0 :         exit(666);
     712             : }
     713             : 
     714         906 : static int libpthread_pthread_create(pthread_t *thread,
     715             :                                 const pthread_attr_t *attr,
     716             :                                 void *(*start_routine) (void *),
     717             :                                 void *arg)
     718             : {
     719         906 :         uwrap_bind_symbol_libpthread(pthread_create);
     720         906 :         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         906 : static void *uwrap_pthread_create_start(void *_a)
     733             : {
     734         906 :         struct uwrap_pthread_create_args *a =
     735             :                 (struct uwrap_pthread_create_args *)_a;
     736         906 :         void *(*start_routine) (void *) = a->start_routine;
     737         906 :         void *arg = a->arg;
     738         906 :         struct uwrap_thread *id = a->id;
     739             : 
     740         906 :         SAFE_FREE(a);
     741             : 
     742         906 :         uwrap_tls_id = id;
     743             : 
     744         906 :         return start_routine(arg);
     745             : }
     746             : 
     747         906 : 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         906 :         struct uwrap_thread *src_id = uwrap_tls_id;
     754             :         int ret;
     755             : 
     756         906 :         args = malloc(sizeof(struct uwrap_pthread_create_args));
     757         906 :         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         906 :         args->start_routine = start_routine;
     764         906 :         args->arg = arg;
     765             : 
     766         906 :         args->id = calloc(1, sizeof(struct uwrap_thread));
     767         906 :         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         906 :         UWRAP_LOCK(uwrap_id);
     776             : 
     777         906 :         args->id->groups = calloc(src_id->ngroups, sizeof(gid_t));
     778         906 :         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         906 :         args->id->ruid = src_id->ruid;
     789         906 :         args->id->euid = src_id->euid;
     790         906 :         args->id->suid = src_id->suid;
     791             : 
     792         906 :         args->id->rgid = src_id->rgid;
     793         906 :         args->id->egid = src_id->egid;
     794         906 :         args->id->sgid = src_id->sgid;
     795             : 
     796         906 :         args->id->enabled = src_id->enabled;
     797             : 
     798         906 :         args->id->ngroups = src_id->ngroups;
     799         906 :         if (src_id->groups != NULL) {
     800         906 :                 memcpy(args->id->groups, src_id->groups,
     801         906 :                        sizeof(gid_t) * src_id->ngroups);
     802             :         } else {
     803           0 :                 SAFE_FREE(args->id->groups);
     804             :         }
     805             : 
     806         906 :         UWRAP_DLIST_ADD(uwrap.ids, args->id);
     807         906 :         UWRAP_UNLOCK(uwrap_id);
     808             : 
     809         906 :         ret = libpthread_pthread_create(thread, attr,
     810             :                                         uwrap_pthread_create_start,
     811             :                                         args);
     812         906 :         if (ret != 0) {
     813           0 :                 return ret;
     814             :         }
     815             : 
     816         906 :         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         906 :         if (!uid_wrapper_enabled()) {
     825           0 :                 return libpthread_pthread_create(thread,
     826             :                                            attr,
     827             :                                            start_routine,
     828             :                                            arg);
     829             :         };
     830             : 
     831         906 :         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       17675 : static void uwrap_export_ids(struct uwrap_thread *id)
     850             : {
     851       17675 :         char groups_str[GROUP_STRING_SIZE] = {0};
     852       17675 :         size_t groups_str_size = sizeof(groups_str);
     853       17675 :         char unsigned_str[16] = {0}; /* We need 10 + 1 (+ 1) */
     854             :         int i;
     855             : 
     856             :         /* UIDS */
     857       17675 :         snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->ruid);
     858       17675 :         setenv("UID_WRAPPER_INITIAL_RUID", unsigned_str, 1);
     859             : 
     860       17675 :         snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->euid);
     861       17675 :         setenv("UID_WRAPPER_INITIAL_EUID", unsigned_str, 1);
     862             : 
     863       17675 :         snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->suid);
     864       17675 :         setenv("UID_WRAPPER_INITIAL_SUID", unsigned_str, 1);
     865             : 
     866             :         /* GIDS */
     867       17675 :         snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->rgid);
     868       17675 :         setenv("UID_WRAPPER_INITIAL_RGID", unsigned_str, 1);
     869             : 
     870       17675 :         snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->egid);
     871       17675 :         setenv("UID_WRAPPER_INITIAL_EGID", unsigned_str, 1);
     872             : 
     873       17675 :         snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->sgid);
     874       17675 :         setenv("UID_WRAPPER_INITIAL_SGID", unsigned_str, 1);
     875             : 
     876       17675 :         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       35349 :         for (i = 0; i < id->ngroups; i++) {
     887       17674 :                 size_t groups_str_len = strlen(groups_str);
     888       17674 :                 size_t groups_str_avail = groups_str_size - groups_str_len - 1;
     889             :                 int len;
     890             : 
     891       17674 :                 len = snprintf(unsigned_str, sizeof(unsigned_str), ",%u", id->groups[i]);
     892       17674 :                 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       17674 :                 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       17674 :                 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       17674 :                 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       17675 :         if (id->ngroups == i) {
     920       17675 :                 setenv("UID_WRAPPER_INITIAL_GROUPS", groups_str, 1);
     921             : 
     922       17675 :                 snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->ngroups);
     923       17675 :                 setenv("UID_WRAPPER_INITIAL_GROUPS_COUNT", unsigned_str, 1);
     924             :         }
     925       17675 : }
     926             : 
     927      419750 : static void uwrap_thread_prepare(void)
     928             : {
     929      419750 :         struct uwrap_thread *id = uwrap_tls_id;
     930             : 
     931      419750 :         UWRAP_LOCK_ALL;
     932             : 
     933             :         /* uid_wrapper is loaded but not enabled */
     934      419750 :         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      419750 :         id->enabled = false;
     945             : }
     946             : 
     947      402075 : static void uwrap_thread_parent(void)
     948             : {
     949      402075 :         struct uwrap_thread *id = uwrap_tls_id;
     950             : 
     951             :         /* uid_wrapper is loaded but not enabled */
     952      402075 :         if (id == NULL) {
     953           0 :                 UWRAP_UNLOCK_ALL;
     954           0 :                 return;
     955             :         }
     956             : 
     957      402075 :         id->enabled = true;
     958             : 
     959      402075 :         UWRAP_UNLOCK_ALL;
     960             : }
     961             : 
     962       17675 : static void uwrap_thread_child(void)
     963             : {
     964       17675 :         struct uwrap_thread *id = uwrap_tls_id;
     965       17675 :         struct uwrap_thread *u = uwrap.ids;
     966             : 
     967             :         /* uid_wrapper is loaded but not enabled */
     968       17675 :         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       49960 :         while (u != NULL) {
     979       17825 :                 if (u == id) {
     980             :                         /* Skip this item. */
     981       17675 :                         u = uwrap.ids->next;
     982       17675 :                         continue;
     983             :                 }
     984             : 
     985         150 :                 UWRAP_DLIST_REMOVE(uwrap.ids, u);
     986             : 
     987         150 :                 SAFE_FREE(u->groups);
     988         150 :                 SAFE_FREE(u);
     989             : 
     990         150 :                 u = uwrap.ids;
     991             :         }
     992             : 
     993       17675 :         uwrap_export_ids(id);
     994             : 
     995       17675 :         id->enabled = true;
     996             : 
     997       17675 :         UWRAP_UNLOCK_ALL;
     998             : }
     999             : 
    1000      346812 : static unsigned long uwrap_get_xid_from_env(const char *envname)
    1001             : {
    1002             :         unsigned long xid;
    1003      346812 :         const char *env = NULL;
    1004      346812 :         char *endp = NULL;
    1005             : 
    1006      346812 :         env = getenv(envname);
    1007      346812 :         if (env == NULL) {
    1008      158480 :                 return ULONG_MAX;
    1009             :         }
    1010             : 
    1011      188332 :         if (env[0] == '\0') {
    1012           0 :                 unsetenv(envname);
    1013           0 :                 return ULONG_MAX;
    1014             :         }
    1015             : 
    1016      188332 :         xid = strtoul(env, &endp, 10);
    1017      188332 :         unsetenv(envname);
    1018      188332 :         if (env == endp) {
    1019           0 :                 return ULONG_MAX;
    1020             :         }
    1021             : 
    1022      188332 :         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       57802 : static void uwrap_init_env(struct uwrap_thread *id)
    1030             : {
    1031             :         const char *env;
    1032       57802 :         int ngroups = 0;
    1033             :         unsigned long xid;
    1034             : 
    1035             :         /* UIDs */
    1036       57802 :         xid = uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_RUID");
    1037       57802 :         if (xid != ULONG_MAX) {
    1038       31392 :                 id->ruid = (uid_t)xid;
    1039             :         }
    1040             : 
    1041       57802 :         xid = uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_EUID");
    1042       57802 :         if (xid != ULONG_MAX) {
    1043       31392 :                 id->euid = (uid_t)xid;
    1044             :         }
    1045             : 
    1046       57802 :         xid = uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_SUID");
    1047       57802 :         if (xid != ULONG_MAX) {
    1048       31387 :                 id->suid = (uid_t)xid;
    1049             :         }
    1050             : 
    1051             :         /* GIDs */
    1052       57802 :         xid = uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_RGID");
    1053       57802 :         if (xid != ULONG_MAX) {
    1054       31387 :                 id->rgid = (gid_t)xid;
    1055             :         }
    1056             : 
    1057       57802 :         xid = uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_EGID");
    1058       57802 :         if (xid != ULONG_MAX) {
    1059       31387 :                 id->egid = (gid_t)xid;
    1060             :         }
    1061             : 
    1062       57802 :         xid = uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_SGID");
    1063       57802 :         if (xid != ULONG_MAX) {
    1064       31387 :                 id->sgid = (gid_t)xid;
    1065             :         }
    1066             : 
    1067       57802 :         env = getenv("UID_WRAPPER_INITIAL_GROUPS_COUNT");
    1068       57802 :         if (env != NULL && env[0] != '\0') {
    1069       31387 :                 char *endp = NULL;
    1070             :                 long n;
    1071             : 
    1072       31387 :                 n = strtol(env, &endp, 10);
    1073       31387 :                 if (env == endp) {
    1074           0 :                         ngroups = 0;
    1075       31387 :                 } else if (n > 0 && n < GROUP_MAX_COUNT) {
    1076       31385 :                         ngroups = (int)n;
    1077             :                 }
    1078       31387 :                 unsetenv("UID_WRAPPER_INITIAL_GROUPS_COUNT");
    1079             :         }
    1080             : 
    1081       57802 :         if (ngroups > 0) {
    1082       31385 :                 int i = 0;
    1083             : 
    1084       31385 :                 id->ngroups = 0;
    1085             : 
    1086       31385 :                 free(id->groups);
    1087       31385 :                 id->groups = calloc(ngroups, sizeof(gid_t));
    1088       31385 :                 if (id->groups == NULL) {
    1089           0 :                         UWRAP_LOG(UWRAP_LOG_ERROR,
    1090             :                                   "Unable to allocate memory");
    1091           0 :                         exit(-1);
    1092             :                 }
    1093             : 
    1094       31385 :                 env = getenv("UID_WRAPPER_INITIAL_GROUPS");
    1095       31385 :                 if (env != NULL && env[0] != '\0') {
    1096       31385 :                         char *groups_str = NULL;
    1097       31385 :                         char *saveptr = NULL;
    1098       31385 :                         const char *p = NULL;
    1099             : 
    1100       31385 :                         groups_str = strdup(env);
    1101       31385 :                         if (groups_str == NULL) {
    1102           0 :                                 exit(-1);
    1103             :                         }
    1104             : 
    1105       31385 :                         p = strtok_r(groups_str, ",", &saveptr);
    1106       79848 :                         while (p != NULL) {
    1107       31385 :                                 id->groups[i] = strtol(p, (char **)NULL, 10);
    1108       31385 :                                 i++;
    1109             : 
    1110       31385 :                                 p = strtok_r(NULL, ",", &saveptr);
    1111             :                         }
    1112       31385 :                         SAFE_FREE(groups_str);
    1113             :                 }
    1114             : 
    1115       31385 :                 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       31385 :                 UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize groups with %s", env);
    1126       31385 :                 id->ngroups = ngroups;
    1127             :         }
    1128       57802 : }
    1129             : 
    1130    10954196 : static void uwrap_init(void)
    1131             : {
    1132             :         const char *env;
    1133             : 
    1134    10954196 :         UWRAP_LOCK(uwrap_id);
    1135             : 
    1136    10954196 :         if (uwrap.initialised) {
    1137    10896394 :                 struct uwrap_thread *id = uwrap_tls_id;
    1138             : 
    1139    10896394 :                 if (uwrap.ids == NULL) {
    1140           0 :                         UWRAP_UNLOCK(uwrap_id);
    1141           0 :                         return;
    1142             :                 }
    1143             : 
    1144    10896394 :                 if (id == NULL) {
    1145           0 :                         UWRAP_LOG(UWRAP_LOG_ERROR,
    1146             :                                   "Invalid id for thread");
    1147           0 :                         exit(-1);
    1148             :                 }
    1149             : 
    1150    10896394 :                 UWRAP_UNLOCK(uwrap_id);
    1151    10896394 :                 return;
    1152             :         }
    1153             : 
    1154       57802 :         UWRAP_LOG(UWRAP_LOG_DEBUG, "Initialize uid_wrapper");
    1155             : 
    1156       57802 :         uwrap.initialised = true;
    1157             : 
    1158       57802 :         env = getenv("UID_WRAPPER");
    1159       57802 :         if (env != NULL && env[0] == '1') {
    1160       57802 :                 const char *root = getenv("UID_WRAPPER_ROOT");
    1161             :                 struct uwrap_thread *id;
    1162             : 
    1163       57802 :                 id = calloc(1, sizeof(struct uwrap_thread));
    1164       57802 :                 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       57802 :                 UWRAP_DLIST_ADD(uwrap.ids, id);
    1171       57802 :                 uwrap_tls_id = id;
    1172             : 
    1173       57802 :                 uwrap.myuid = libc_geteuid();
    1174       57802 :                 uwrap.mygid = libc_getegid();
    1175             : 
    1176             :                 /* put us in one group */
    1177       57802 :                 if (root != NULL && root[0] == '1') {
    1178       12549 :                         id->ruid = id->euid = id->suid = 0;
    1179       12549 :                         id->rgid = id->egid = id->sgid = 0;
    1180             : 
    1181       12549 :                         id->groups = malloc(sizeof(gid_t) * 1);
    1182       12549 :                         if (id->groups == NULL) {
    1183           0 :                                 UWRAP_LOG(UWRAP_LOG_ERROR,
    1184             :                                           "Unable to allocate memory");
    1185           0 :                                 exit(-1);
    1186             :                         }
    1187             : 
    1188       12549 :                         id->ngroups = 1;
    1189       12549 :                         id->groups[0] = 0;
    1190             : 
    1191             :                 } else {
    1192       45253 :                         id->ruid = id->euid = id->suid = uwrap.myuid;
    1193       45253 :                         id->rgid = id->egid = id->sgid = uwrap.mygid;
    1194             : 
    1195       45253 :                         id->ngroups = libc_getgroups(0, NULL);
    1196       45253 :                         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       45253 :                         id->groups = malloc(sizeof(gid_t) * id->ngroups);
    1202       45253 :                         if (id->groups == NULL) {
    1203           0 :                                 UWRAP_LOG(UWRAP_LOG_ERROR, "Unable to allocate memory");
    1204           0 :                                 exit(-1);
    1205             :                         }
    1206       45253 :                         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       57802 :                 uwrap_init_env(id);
    1219             : 
    1220       57802 :                 id->enabled = true;
    1221             : 
    1222       57802 :                 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       57802 :         UWRAP_UNLOCK(uwrap_id);
    1229             : 
    1230       57802 :         UWRAP_LOG(UWRAP_LOG_DEBUG, "Successfully initialized uid_wrapper");
    1231             : }
    1232             : 
    1233    12092552 : bool uid_wrapper_enabled(void)
    1234             : {
    1235    12092552 :         struct uwrap_thread *id = uwrap_tls_id;
    1236             :         bool enabled;
    1237             : 
    1238    12092552 :         if (id == NULL) {
    1239          46 :                 return false;
    1240             :         }
    1241             : 
    1242    12092506 :         UWRAP_LOCK(uwrap_id);
    1243    12092506 :         enabled = id->enabled;
    1244    12092506 :         UWRAP_UNLOCK(uwrap_id);
    1245             : 
    1246    12092506 :         return enabled;
    1247             : }
    1248             : 
    1249             : /*
    1250             :  * UWRAP_SETxUID FUNCTIONS
    1251             :  */
    1252             : 
    1253     3008713 : static int uwrap_setresuid_args(uid_t ruid, uid_t euid, uid_t suid)
    1254             : {
    1255     3008713 :         struct uwrap_thread *id = uwrap_tls_id;
    1256             : 
    1257     3008713 :         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     3008713 :         if (id->euid != 0) {
    1262      753225 :                 if (ruid != (uid_t)-1 &&
    1263       55723 :                     ruid != id->ruid &&
    1264       55057 :                     ruid != id->euid &&
    1265       33233 :                     ruid != id->suid) {
    1266           0 :                         errno = EPERM;
    1267           0 :                         return -1;
    1268             :                 }
    1269     1450027 :                 if (euid != (uid_t)-1 &&
    1270      752656 :                     euid != id->ruid &&
    1271       55057 :                     euid != id->euid &&
    1272       33233 :                     euid != id->suid) {
    1273           0 :                         errno = EPERM;
    1274           0 :                         return -1;
    1275             :                 }
    1276      730835 :                 if (suid != (uid_t)-1 &&
    1277           6 :                     suid != id->ruid &&
    1278           6 :                     suid != id->euid &&
    1279           3 :                     suid != id->suid) {
    1280           0 :                         errno = EPERM;
    1281           0 :                         return -1;
    1282             :                 }
    1283             :         }
    1284             : 
    1285     3008713 :         return 0;
    1286             : }
    1287             : 
    1288     3008713 : static int uwrap_setresuid_thread(uid_t ruid, uid_t euid, uid_t suid)
    1289             : {
    1290     3008713 :         struct uwrap_thread *id = uwrap_tls_id;
    1291             :         int rc;
    1292             : 
    1293     3008713 :         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     3008713 :         rc = uwrap_setresuid_args(ruid, euid, suid);
    1298     3008713 :         if (rc != 0) {
    1299           0 :                 return rc;
    1300             :         }
    1301             : 
    1302     3008713 :         UWRAP_LOCK(uwrap_id);
    1303             : 
    1304     3008713 :         if (ruid != (uid_t)-1) {
    1305      224160 :                 id->ruid = ruid;
    1306             :         }
    1307             : 
    1308     3008713 :         if (euid != (uid_t)-1) {
    1309     3008713 :                 id->euid = euid;
    1310             :         }
    1311             : 
    1312     3008713 :         if (suid != (uid_t)-1) {
    1313         133 :                 id->suid = suid;
    1314             :         }
    1315             : 
    1316     3008713 :         UWRAP_UNLOCK(uwrap_id);
    1317             : 
    1318     3008713 :         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          68 : 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          68 :         struct uwrap_thread *id = uwrap_tls_id;
    1445             : 
    1446          68 :         UWRAP_LOG(UWRAP_LOG_TRACE,
    1447             :                   "uid %d -> %d",
    1448             :                   id->ruid, uid);
    1449             : 
    1450          68 :         if (uid == (uid_t)-1) {
    1451           0 :                 errno = EINVAL;
    1452           0 :                 return -1;
    1453             :         }
    1454             : 
    1455          68 :         if (id->euid == 0) {
    1456          65 :                 *new_suid = *new_ruid = uid;
    1457           3 :         } else if (uid != id->ruid &&
    1458           0 :                    uid != id->suid) {
    1459           0 :                 errno = EPERM;
    1460           0 :                 return -1;
    1461             :         }
    1462             : 
    1463          68 :         *new_euid = uid;
    1464             : 
    1465          68 :         return 0;
    1466             : }
    1467             : 
    1468          68 : static int uwrap_setuid_thread(uid_t uid)
    1469             : {
    1470          68 :         uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
    1471             :         int rc;
    1472             : 
    1473          68 :         rc = uwrap_setuid_args(uid, &new_ruid, &new_euid, &new_suid);
    1474          68 :         if (rc != 0) {
    1475           0 :                 return rc;
    1476             :         }
    1477             : 
    1478          68 :         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     1615985 : static int uwrap_setresgid_args(gid_t rgid, gid_t egid, gid_t sgid)
    1537             : {
    1538     1615985 :         struct uwrap_thread *id = uwrap_tls_id;
    1539             : 
    1540     1615985 :         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     1615985 :         if (id->euid != 0) {
    1545       33896 :                 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       56286 :                 if (egid != (gid_t)-1 &&
    1553       34465 :                     egid != id->rgid &&
    1554         666 :                     egid != id->egid &&
    1555           0 :                     egid != id->sgid) {
    1556           0 :                         errno = EPERM;
    1557           0 :                         return -1;
    1558             :                 }
    1559       33896 :                 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     1615985 :         return 0;
    1569             : }
    1570             : 
    1571     1615985 : static int uwrap_setresgid_thread(gid_t rgid, gid_t egid, gid_t sgid)
    1572             : {
    1573     1615985 :         struct uwrap_thread *id = uwrap_tls_id;
    1574             :         int rc;
    1575             : 
    1576     1615985 :         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     1615985 :         rc = uwrap_setresgid_args(rgid, egid, sgid);
    1581     1615985 :         if (rc != 0) {
    1582           0 :                 return rc;
    1583             :         }
    1584             : 
    1585     1615985 :         UWRAP_LOCK(uwrap_id);
    1586             : 
    1587     1615985 :         if (rgid != (gid_t)-1) {
    1588         224 :                 id->rgid = rgid;
    1589             :         }
    1590             : 
    1591     1615985 :         if (egid != (gid_t)-1) {
    1592     1615985 :                 id->egid = egid;
    1593             :         }
    1594             : 
    1595     1615985 :         if (sgid != (gid_t)-1) {
    1596         180 :                 id->sgid = sgid;
    1597             :         }
    1598             : 
    1599     1615985 :         UWRAP_UNLOCK(uwrap_id);
    1600             : 
    1601     1615985 :         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         112 : 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         112 :         struct uwrap_thread *id = uwrap_tls_id;
    1728             : 
    1729         112 :         UWRAP_LOG(UWRAP_LOG_TRACE,
    1730             :                   "gid %d -> %d",
    1731             :                   id->rgid, gid);
    1732             : 
    1733         112 :         if (gid == (gid_t)-1) {
    1734           0 :                 errno = EINVAL;
    1735           0 :                 return -1;
    1736             :         }
    1737             : 
    1738         112 :         if (id->euid == 0) {
    1739         112 :                 *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         112 :         *new_egid = gid;
    1747             : 
    1748         112 :         return 0;
    1749             : }
    1750             : 
    1751         112 : static int uwrap_setgid_thread(gid_t gid)
    1752             : {
    1753         112 :         gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
    1754             :         int rc;
    1755             : 
    1756         112 :         rc = uwrap_setgid_args(gid, &new_rgid, &new_egid, &new_sgid);
    1757         112 :         if (rc != 0) {
    1758           0 :                 return rc;
    1759             :         }
    1760             : 
    1761         112 :         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       55996 : static uid_t uwrap_getuid(void)
    1848             : {
    1849       55996 :         struct uwrap_thread *id = uwrap_tls_id;
    1850             :         uid_t uid;
    1851             : 
    1852       55996 :         UWRAP_LOCK(uwrap_id);
    1853       55996 :         uid = id->ruid;
    1854       55996 :         UWRAP_UNLOCK(uwrap_id);
    1855             : 
    1856       55996 :         return uid;
    1857             : }
    1858             : 
    1859             : uid_t getuid(void)
    1860             : {
    1861       55996 :         if (!uid_wrapper_enabled()) {
    1862           0 :                 return libc_getuid();
    1863             :         }
    1864             : 
    1865       55996 :         uwrap_init();
    1866       55996 :         return uwrap_getuid();
    1867             : }
    1868             : 
    1869             : /*
    1870             :  * GETEUID
    1871             :  */
    1872     1830879 : static uid_t uwrap_geteuid(void)
    1873             : {
    1874     1830879 :         const char *env = getenv("UID_WRAPPER_MYUID");
    1875     1830879 :         struct uwrap_thread *id = uwrap_tls_id;
    1876             :         uid_t uid;
    1877             : 
    1878     1830879 :         UWRAP_LOCK(uwrap_id);
    1879     1830879 :         uid = id->euid;
    1880     1830879 :         UWRAP_UNLOCK(uwrap_id);
    1881             : 
    1882             :         /* Disable root and return myuid */
    1883     1830879 :         if (env != NULL && env[0] == '1') {
    1884      370479 :                 uid = uwrap.myuid;
    1885             :         }
    1886             : 
    1887     1830879 :         return uid;
    1888             : }
    1889             : 
    1890             : uid_t geteuid(void)
    1891             : {
    1892     1830879 :         if (!uid_wrapper_enabled()) {
    1893           0 :                 return libc_geteuid();
    1894             :         }
    1895             : 
    1896     1830879 :         uwrap_init();
    1897     1830879 :         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       13470 : static gid_t uwrap_getgid(void)
    1971             : {
    1972       13470 :         struct uwrap_thread *id = uwrap_tls_id;
    1973             :         gid_t gid;
    1974             : 
    1975       13470 :         UWRAP_LOCK(uwrap_id);
    1976       13470 :         gid = id->rgid;
    1977       13470 :         UWRAP_UNLOCK(uwrap_id);
    1978             : 
    1979       13470 :         return gid;
    1980             : }
    1981             : 
    1982             : gid_t getgid(void)
    1983             : {
    1984       13470 :         if (!uid_wrapper_enabled()) {
    1985           0 :                 return libc_getgid();
    1986             :         }
    1987             : 
    1988       13470 :         uwrap_init();
    1989       13470 :         return uwrap_getgid();
    1990             : }
    1991             : 
    1992             : /*
    1993             :  * GETEGID
    1994             :  */
    1995     1011412 : static uid_t uwrap_getegid(void)
    1996             : {
    1997     1011412 :         struct uwrap_thread *id = uwrap_tls_id;
    1998             :         gid_t gid;
    1999             : 
    2000     1011412 :         UWRAP_LOCK(uwrap_id);
    2001     1011412 :         gid = id->egid;
    2002     1011412 :         UWRAP_UNLOCK(uwrap_id);
    2003             : 
    2004     1011412 :         return gid;
    2005             : }
    2006             : 
    2007             : uid_t getegid(void)
    2008             : {
    2009     1011412 :         if (!uid_wrapper_enabled()) {
    2010           0 :                 return libc_getegid();
    2011             :         }
    2012             : 
    2013     1011412 :         uwrap_init();
    2014     1011412 :         return uwrap_getegid();
    2015             : }
    2016             : 
    2017     1615717 : static int uwrap_setgroups_thread(size_t size, const gid_t *list)
    2018             : {
    2019     1615717 :         struct uwrap_thread *id = uwrap_tls_id;
    2020     1615717 :         int rc = -1;
    2021             : 
    2022     1615717 :         UWRAP_LOCK(uwrap_id);
    2023             : 
    2024     1615717 :         if (size == 0) {
    2025      184450 :                 SAFE_FREE(id->groups);
    2026      184450 :                 id->ngroups = 0;
    2027     1431267 :         } else if (size > 0) {
    2028             :                 gid_t *tmp;
    2029             : 
    2030     1431267 :                 tmp = realloc(id->groups, sizeof(gid_t) * size);
    2031     1431267 :                 if (tmp == NULL) {
    2032           0 :                         errno = ENOMEM;
    2033           0 :                         goto out;
    2034             :                 }
    2035     1431267 :                 id->groups = tmp;
    2036     1431267 :                 id->ngroups = size;
    2037     1431267 :                 memcpy(id->groups, list, size * sizeof(gid_t));
    2038             :         }
    2039             : 
    2040     1615717 :         rc = 0;
    2041     1615717 : out:
    2042     1615717 :         UWRAP_UNLOCK(uwrap_id);
    2043             : 
    2044     1615717 :         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     1479230 : static int uwrap_getgroups(int size, gid_t *list)
    2098             : {
    2099     1479230 :         struct uwrap_thread *id = uwrap_tls_id;
    2100             :         int ngroups;
    2101             : 
    2102     1479230 :         UWRAP_LOCK(uwrap_id);
    2103     1479230 :         ngroups = id->ngroups;
    2104             : 
    2105     1479230 :         if (size > ngroups) {
    2106           0 :                 size = ngroups;
    2107             :         }
    2108     1479230 :         if (size == 0) {
    2109      766012 :                 goto out;
    2110             :         }
    2111      713218 :         if (size < ngroups) {
    2112           0 :                 errno = EINVAL;
    2113           0 :                 ngroups = -1;
    2114             :         }
    2115      713218 :         memcpy(list, id->groups, size * sizeof(gid_t));
    2116             : 
    2117     1479230 : out:
    2118     1479230 :         UWRAP_UNLOCK(uwrap_id);
    2119             : 
    2120     1479230 :         return ngroups;
    2121             : }
    2122             : 
    2123             : int getgroups(int size, gid_t *list)
    2124             : {
    2125     1479230 :         if (!uid_wrapper_enabled()) {
    2126           0 :                 return libc_getgroups(size, list);
    2127             :         }
    2128             : 
    2129     1479230 :         uwrap_init();
    2130     1479230 :         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     6505407 : static long int uwrap_syscall (long int sysno, va_list vp)
    2136             : {
    2137             :         long int rc;
    2138             : 
    2139     6505407 :         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         112 :                 case SYS_setgid:
    2164             : #ifdef HAVE_LINUX_32BIT_SYSCALLS
    2165             :                 case SYS_setgid32:
    2166             : #endif
    2167             :                         {
    2168         112 :                                 gid_t gid = (gid_t) va_arg(vp, gid_t);
    2169             : 
    2170         112 :                                 rc = uwrap_setgid_thread(gid);
    2171             :                         }
    2172         112 :                         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     1615873 :                 case SYS_setresgid:
    2186             : #ifdef HAVE_LINUX_32BIT_SYSCALLS
    2187             :                 case SYS_setresgid32:
    2188             : #endif
    2189             :                         {
    2190     1615873 :                                 gid_t rgid = (gid_t) va_arg(vp, gid_t);
    2191     1615873 :                                 gid_t egid = (gid_t) va_arg(vp, gid_t);
    2192     1615873 :                                 gid_t sgid = (gid_t) va_arg(vp, gid_t);
    2193             : 
    2194     1615873 :                                 rc = uwrap_setresgid_thread(rgid, egid, sgid);
    2195             :                         }
    2196     1615873 :                         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          68 :                 case SYS_setuid:
    2237             : #ifdef HAVE_LINUX_32BIT_SYSCALLS
    2238             :                 case SYS_setuid32:
    2239             : #endif
    2240             :                         {
    2241          68 :                                 uid_t uid = (uid_t) va_arg(vp, uid_t);
    2242             : 
    2243          68 :                                 rc = uwrap_setuid_thread(uid);
    2244             :                         }
    2245          68 :                         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     3008645 :                 case SYS_setresuid:
    2259             : #ifdef HAVE_LINUX_32BIT_SYSCALLS
    2260             :                 case SYS_setresuid32:
    2261             : #endif
    2262             :                         {
    2263     3008645 :                                 uid_t ruid = (uid_t) va_arg(vp, uid_t);
    2264     3008645 :                                 uid_t euid = (uid_t) va_arg(vp, uid_t);
    2265     3008645 :                                 uid_t suid = (uid_t) va_arg(vp, uid_t);
    2266             : 
    2267     3008645 :                                 rc = uwrap_setresuid_thread(ruid, euid, suid);
    2268             :                         }
    2269     3008645 :                         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     1615717 :                 case SYS_setgroups:
    2287             : #ifdef HAVE_LINUX_32BIT_SYSCALLS
    2288             :                 case SYS_setgroups32:
    2289             : #endif
    2290             :                         {
    2291     1615717 :                                 size_t size = (size_t) va_arg(vp, size_t);
    2292     1615717 :                                 gid_t *list = (gid_t *) va_arg(vp, int *);
    2293             : 
    2294     1615717 :                                 rc = uwrap_setgroups_thread(size, list);
    2295             :                         }
    2296     1615717 :                         break;
    2297      264992 :                 default:
    2298      264992 :                         UWRAP_LOG(UWRAP_LOG_DEBUG,
    2299             :                                   "UID_WRAPPER calling non-wrapped syscall %lu",
    2300             :                                   sysno);
    2301             : 
    2302      264992 :                         rc = libc_vsyscall(sysno, vp);
    2303      264992 :                         break;
    2304             :         }
    2305             : 
    2306     6505407 :         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     6505453 :         va_start(va, sysno);
    2324             : 
    2325     6505453 :         if (!uid_wrapper_enabled()) {
    2326          46 :                 rc = libc_vsyscall(sysno, va);
    2327          46 :                 va_end(va);
    2328          46 :                 return rc;
    2329             :         }
    2330             : 
    2331     6505407 :         uwrap_init();
    2332     6505407 :         rc = uwrap_syscall(sysno, va);
    2333     6505407 :         va_end(va);
    2334             : 
    2335     6505407 :         return rc;
    2336             : }
    2337             : #endif /* HAVE_SYSCALL */
    2338             : #endif /* HAVE_SYS_SYSCALL_H || HAVE_SYSCALL_H */
    2339             : 
    2340             : /****************************
    2341             :  * CONSTRUCTOR
    2342             :  ***************************/
    2343             : 
    2344       57802 : 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       57802 :         glibc_malloc_lock_bug = malloc(1);
    2362       57802 :         if (glibc_malloc_lock_bug == NULL) {
    2363           0 :                 exit(-1);
    2364             :         }
    2365       57802 :         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       57802 :         pthread_atfork(&uwrap_thread_prepare,
    2373             :                        &uwrap_thread_parent,
    2374             :                        &uwrap_thread_child);
    2375             : 
    2376       57802 :         free(glibc_malloc_lock_bug);
    2377             : 
    2378             :         /* Here is safe place to call uwrap_init() and initialize data
    2379             :          * for main process.
    2380             :          */
    2381       57802 :         uwrap_init();
    2382       57802 : }
    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       76848 : void uwrap_destructor(void)
    2393             : {
    2394       76848 :         struct uwrap_thread *u = uwrap.ids;
    2395             : 
    2396       76848 :         UWRAP_LOCK_ALL;
    2397             : 
    2398      208364 :         while (u != NULL) {
    2399       77718 :                 UWRAP_DLIST_REMOVE(uwrap.ids, u);
    2400             : 
    2401       77718 :                 SAFE_FREE(u->groups);
    2402       77718 :                 SAFE_FREE(u);
    2403             : 
    2404       77718 :                 u = uwrap.ids;
    2405             :         }
    2406             : 
    2407             : 
    2408       76848 :         if (uwrap.libc.handle != NULL) {
    2409       76848 :                 dlclose(uwrap.libc.handle);
    2410             :         }
    2411             : 
    2412       76848 :         if (uwrap.libpthread.handle != NULL) {
    2413           0 :                 dlclose(uwrap.libpthread.handle);
    2414             :         }
    2415             : 
    2416       76848 :         UWRAP_UNLOCK_ALL;
    2417       76848 : }

Generated by: LCOV version 1.13