Ignore:
Timestamp:
Nov 24, 2016, 1:14:11 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to version 4.4.3

Location:
vendor/current/lib/uid_wrapper
Files:
3 deleted
2 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/lib/uid_wrapper/uid_wrapper.c

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

    r740 r988  
    22
    33import Options
     4import os, sys
    45
    5 def set_options(opt):
    6     gr = opt.option_group('developer options')
    7     gr.add_option('--enable-uid-wrapper',
    8                    help=("Turn on uid wrapper library (default=no)"),
    9                    action="store_true", dest='enable_uid_wrapper', default=False)
     6VERSION="1.2.0"
    107
    118def configure(conf):
    12     if (Options.options.enable_uid_wrapper or
    13     Options.options.developer or
    14     Options.options.enable_selftest):
    15         conf.DEFINE('UID_WRAPPER', 1)
    16         conf.ADD_GLOBAL_DEPENDENCY('uid_wrapper')
     9    if conf.CHECK_BUNDLED_SYSTEM('uid_wrapper', minversion=VERSION, set_target=False):
     10        conf.DEFINE('USING_SYSTEM_UID_WRAPPER', 1)
     11        libuid_wrapper_so_path = 'libuid_wrapper.so'
     12    else:
     13        # check HAVE_GCC_ATOMIC_BUILTINS
     14        conf.CHECK_CODE('''
     15            #include <stdbool.h>
     16            int main(void) {
     17                bool x;
     18                bool *p_x = &x;
     19                __atomic_load(p_x, &x, __ATOMIC_RELAXED);
     20                return 0;
     21            ''',
     22            'HAVE_GCC_ATOMIC_BUILTINS',
     23            addmain=False,
     24            msg='Checking for atomic builtins')
    1725
     26        # check HAVE_GCC_THREAD_LOCAL_STORAGE
     27        conf.CHECK_CODE('''
     28            __thread int tls;
     29
     30            int main(void) {
     31                return 0;
     32            }
     33            ''',
     34            'HAVE_GCC_THREAD_LOCAL_STORAGE',
     35            addmain=False,
     36            msg='Checking for thread local storage')
     37
     38        if Options.options.address_sanitizer:
     39            # check HAVE_ADDRESS_SANITIZER_ATTRIBUTE
     40            conf.CHECK_CODE('''
     41                void test_address_sanitizer_attribute(void) __attribute__((no_sanitize_address));
     42
     43                void test_address_sanitizer_attribute(void)
     44                {
     45                    return;
     46                }
     47
     48                int main(void) {
     49                    return 0;
     50                }
     51                ''',
     52                'HAVE_ADDRESS_SANITIZER_ATTRIBUTE',
     53                addmain=False,
     54                cflags='-Wall -Wextra -Werror',
     55                msg='Checking for address sanitizer attribute')
     56
     57        # check HAVE_FUNCTION_ATTRIBUTE_FORMAT
     58        conf.CHECK_CODE('''
     59            void log_fn(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
     60
     61            int main(void) {
     62                return 0;
     63            }
     64            ''',
     65            'HAVE_FUNCTION_ATTRIBUTE_FORMAT',
     66            addmain=False,
     67            msg='Checking for printf format validation support')
     68        # Prototype checks
     69        conf.CHECK_C_PROTOTYPE('setgroups',
     70                        'int setgroups(int ngroups, const gid_t *grouplist)',
     71                        define='HAVE_SETGROUPS_INT', headers='unistd.h sys/types.h')
     72        conf.CHECK_C_PROTOTYPE('syscall',
     73                        'int syscall(int number, ...)',
     74                        define='HAVE_SYSCALL_INT', headers='unistd.h sys/syscall.h')
     75
     76        if (sys.platform.rfind('linux') > -1):
     77            conf.CHECK_CODE('''
     78#if defined(HAVE_UNISTD_H)
     79#include <unistd.h>
     80#endif
     81#include <stdlib.h>
     82#include <stdio.h>
     83#include <sys/types.h>
     84#include <errno.h>
     85
     86#ifdef HAVE_SYS_PRIV_H
     87#include <sys/priv.h>
     88#endif
     89#ifdef HAVE_SYS_ID_H
     90#include <sys/id.h>
     91#endif
     92
     93#if defined(HAVE_SYSCALL_H)
     94#include <syscall.h>
     95#endif
     96
     97#if defined(HAVE_SYS_SYSCALL_H)
     98#include <sys/syscall.h>
     99#endif
     100
     101syscall(SYS_setresuid32, -1, -1, -1);
     102syscall(SYS_setresgid32, -1, -1, -1);
     103syscall(SYS_setreuid32, -1, -1);
     104syscall(SYS_setregid32, -1, -1);
     105syscall(SYS_setuid32, -1);
     106syscall(SYS_setgid32, -1);
     107syscall(SYS_setgroups32, 0, NULL);
     108''',
     109                'HAVE_LINUX_32BIT_SYSCALLS',
     110                msg="Checking whether Linux has 32-bit credential calls");
     111
     112        conf.CHECK_FUNCS('getresuid getresgid')
     113
     114        # Create full path to uid_wrapper
     115        srcdir = os.path.realpath(conf.srcdir)
     116        libuid_wrapper_so_path = srcdir + '/bin/default/lib/uid_wrapper/libuid-wrapper.so'
     117
     118    conf.DEFINE('LIBUID_WRAPPER_SO_PATH', libuid_wrapper_so_path)
     119    conf.DEFINE('UID_WRAPPER', 1)
     120
     121def build(bld):
     122    if not bld.CONFIG_SET("USING_SYSTEM_UID_WRAPPER"):
     123        # We need to do it this way or the library wont work.
     124        # Using private_library=True will add symbol version which
     125        # breaks preloading!
     126        bld.SAMBA_LIBRARY('uid_wrapper',
     127                          source='uid_wrapper.c',
     128                          deps='dl',
     129                          install=False,
     130                          realname='libuid-wrapper.so')
     131
Note: See TracChangeset for help on using the changeset viewer.