2 * Copyright (c) 2009 Andrew Tridgell
3 * Copyright (c) 2011-2013 Andreas Schneider <asn@samba.org>
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include <sys/types.h>
30 #ifdef HAVE_SYS_SYSCALL_H
31 #include <sys/syscall.h>
41 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
42 # define UWRAP_THREAD __thread
47 # define UWRAP_LOCK(m) do { \
48 pthread_mutex_lock(&( m ## _mutex)); \
51 # define UWRAP_UNLOCK(m) do { \
52 pthread_mutex_unlock(&( m ## _mutex)); \
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)
61 # define UWRAP_UNLOCK_ALL \
62 UWRAP_UNLOCK(libpthread_symbol_binding); \
63 UWRAP_UNLOCK(libc_symbol_binding); \
64 UWRAP_UNLOCK(uwrap_id)
66 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
67 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
69 #define CONSTRUCTOR_ATTRIBUTE
70 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
72 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
73 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
75 #define DESTRUCTOR_ATTRIBUTE
76 #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
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 */
84 /* GCC have printf type attribute check. */
85 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
86 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
88 #define PRINTF_ATTRIBUTE(a,b)
89 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
92 # ifdef HAVE_FALLTHROUGH_ATTRIBUTE
93 # define FALL_THROUGH __attribute__ ((fallthrough))
94 # else /* HAVE_FALLTHROUGH_ATTRIBUTE */
96 # endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
97 #endif /* FALL_THROUGH */
99 #define UWRAP_DLIST_ADD(list,item) do { \
101 (item)->prev = NULL; \
102 (item)->next = NULL; \
105 (item)->prev = NULL; \
106 (item)->next = (list); \
107 (list)->prev = (item); \
112 #define UWRAP_DLIST_REMOVE(list,item) do { \
113 if ((list) == (item)) { \
114 (list) = (item)->next; \
116 (list)->prev = NULL; \
119 if ((item)->prev) { \
120 (item)->prev->next = (item)->next; \
122 if ((item)->next) { \
123 (item)->next->prev = (item)->prev; \
126 (item)->prev = NULL; \
127 (item)->next = NULL; \
131 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
138 enum uwrap_dbglvl_e
{
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__)
148 static void uwrap_log(enum uwrap_dbglvl_e dbglvl
, const char *function
, const char *format
, ...)
153 unsigned int lvl
= 0;
154 const char *prefix
= "UWRAP";
156 d
= getenv("UID_WRAPPER_DEBUGLEVEL");
165 va_start(va
, format
);
166 vsnprintf(buffer
, sizeof(buffer
), format
, va
);
170 case UWRAP_LOG_ERROR
:
171 prefix
= "UWRAP_ERROR";
174 prefix
= "UWRAP_WARN";
176 case UWRAP_LOG_DEBUG
:
177 prefix
= "UWRAP_DEBUG";
179 case UWRAP_LOG_TRACE
:
180 prefix
= "UWRAP_TRACE";
196 #define LIBC_NAME "libc.so"
198 typedef int (*__libc_setuid
)(uid_t uid
);
200 typedef uid_t (*__libc_getuid
)(void);
203 typedef int (*__libc_seteuid
)(uid_t euid
);
207 typedef int (*__libc_setreuid
)(uid_t ruid
, uid_t euid
);
210 #ifdef HAVE_SETRESUID
211 typedef int (*__libc_setresuid
)(uid_t ruid
, uid_t euid
, uid_t suid
);
214 #ifdef HAVE_GETRESUID
215 typedef int (*__libc_getresuid
)(uid_t
*ruid
, uid_t
*euid
, uid_t
*suid
);
218 typedef uid_t (*__libc_geteuid
)(void);
220 typedef int (*__libc_setgid
)(gid_t gid
);
222 typedef gid_t (*__libc_getgid
)(void);
225 typedef int (*__libc_setegid
)(uid_t egid
);
229 typedef int (*__libc_setregid
)(uid_t rgid
, uid_t egid
);
232 #ifdef HAVE_SETRESGID
233 typedef int (*__libc_setresgid
)(uid_t rgid
, uid_t egid
, uid_t sgid
);
236 #ifdef HAVE_GETRESGID
237 typedef int (*__libc_getresgid
)(gid_t
*rgid
, gid_t
*egid
, gid_t
*sgid
);
240 typedef gid_t (*__libc_getegid
)(void);
242 typedef int (*__libc_getgroups
)(int size
, gid_t list
[]);
244 typedef int (*__libc_setgroups
)(size_t size
, const gid_t
*list
);
247 typedef long int (*__libc_syscall
)(long int sysno
, ...);
250 #define UWRAP_SYMBOL_ENTRY(i) \
256 struct uwrap_libc_symbols
{
257 UWRAP_SYMBOL_ENTRY(setuid
);
258 UWRAP_SYMBOL_ENTRY(getuid
);
260 UWRAP_SYMBOL_ENTRY(seteuid
);
263 UWRAP_SYMBOL_ENTRY(setreuid
);
265 #ifdef HAVE_SETRESUID
266 UWRAP_SYMBOL_ENTRY(setresuid
);
268 #ifdef HAVE_GETRESUID
269 UWRAP_SYMBOL_ENTRY(getresuid
);
271 UWRAP_SYMBOL_ENTRY(geteuid
);
272 UWRAP_SYMBOL_ENTRY(setgid
);
273 UWRAP_SYMBOL_ENTRY(getgid
);
275 UWRAP_SYMBOL_ENTRY(setegid
);
278 UWRAP_SYMBOL_ENTRY(setregid
);
280 #ifdef HAVE_SETRESGID
281 UWRAP_SYMBOL_ENTRY(setresgid
);
283 #ifdef HAVE_GETRESGID
284 UWRAP_SYMBOL_ENTRY(getresgid
);
286 UWRAP_SYMBOL_ENTRY(getegid
);
287 UWRAP_SYMBOL_ENTRY(getgroups
);
288 UWRAP_SYMBOL_ENTRY(setgroups
);
290 UWRAP_SYMBOL_ENTRY(syscall
);
293 #undef UWRAP_SYMBOL_ENTRY
298 /* Yeah... I'm pig. I overloading macro here... So what? */
299 #define UWRAP_SYMBOL_ENTRY(i) \
301 __libpthread_##i f; \
305 typedef int (*__libpthread_pthread_create
)(pthread_t
*thread
,
306 const pthread_attr_t
*attr
,
307 void *(*start_routine
) (void *),
309 typedef void (*__libpthread_pthread_exit
)(void *retval
);
311 struct uwrap_libpthread_symbols
{
312 UWRAP_SYMBOL_ENTRY(pthread_create
);
313 UWRAP_SYMBOL_ENTRY(pthread_exit
);
315 #undef UWRAP_SYMBOL_ENTRY
318 * We keep the virtualised euid/egid/groups information here
320 struct uwrap_thread
{
334 struct uwrap_thread
*next
;
335 struct uwrap_thread
*prev
;
341 struct uwrap_libc_symbols symbols
;
346 struct uwrap_libpthread_symbols symbols
;
351 /* Real uid and gid of user who run uid wrapper */
355 struct uwrap_thread
*ids
;
358 static struct uwrap uwrap
;
360 /* Shortcut to the list item */
361 static UWRAP_THREAD
struct uwrap_thread
*uwrap_tls_id
;
363 /* The mutex or accessing the id */
364 static pthread_mutex_t uwrap_id_mutex
= PTHREAD_MUTEX_INITIALIZER
;
366 /* The mutex for accessing the global libc.symbols */
367 static pthread_mutex_t libc_symbol_binding_mutex
= PTHREAD_MUTEX_INITIALIZER
;
369 /* The mutex for accessing the global libpthread.symbols */
370 static pthread_mutex_t libpthread_symbol_binding_mutex
= PTHREAD_MUTEX_INITIALIZER
;
372 /*********************************************************
374 *********************************************************/
376 bool uid_wrapper_enabled(void);
377 void uwrap_constructor(void) CONSTRUCTOR_ATTRIBUTE
;
378 void uwrap_destructor(void) DESTRUCTOR_ATTRIBUTE
;
380 /*********************************************************
381 * UWRAP LIBC LOADER FUNCTIONS
382 *********************************************************/
391 static void *uwrap_load_lib_handle(enum uwrap_lib lib
)
393 int flags
= RTLD_LAZY
;
398 const char *env_preload
= getenv("LD_PRELOAD");
399 const char *env_deepbind
= getenv("UID_WRAPPER_DISABLE_DEEPBIND");
400 bool enable_deepbind
= true;
402 /* Don't do a deepbind if we run with libasan */
403 if (env_preload
!= NULL
&& strlen(env_preload
) < 1024) {
404 const char *p
= strstr(env_preload
, "libasan.so");
406 enable_deepbind
= false;
410 if (env_deepbind
!= NULL
&& strlen(env_deepbind
) >= 1) {
411 enable_deepbind
= false;
414 if (enable_deepbind
) {
415 flags
|= RTLD_DEEPBIND
;
421 case UWRAP_LIBSOCKET
:
423 handle
= uwrap
.libc
.handle
;
424 if (handle
== NULL
) {
425 for (i
= 10; i
>= 0; i
--) {
426 char soname
[256] = {0};
428 snprintf(soname
, sizeof(soname
), "libc.so.%d", i
);
429 handle
= dlopen(soname
, flags
);
430 if (handle
!= NULL
) {
434 /* glibc on Alpha and IA64 is libc.so.6.1 */
435 snprintf(soname
, sizeof(soname
), "libc.so.%d.1", i
);
436 handle
= dlopen(soname
, flags
);
437 if (handle
!= NULL
) {
442 uwrap
.libc
.handle
= handle
;
445 case UWRAP_LIBPTHREAD
:
446 handle
= uwrap
.libpthread
.handle
;
447 if (handle
== NULL
) {
448 handle
= dlopen("libpthread.so.0", flags
);
449 if (handle
!= NULL
) {
456 if (handle
== NULL
) {
458 handle
= uwrap
.libc
.handle
= RTLD_NEXT
;
461 "Failed to dlopen library: %s\n",
470 static void *_uwrap_bind_symbol(enum uwrap_lib lib
, const char *fn_name
)
475 handle
= uwrap_load_lib_handle(lib
);
477 func
= dlsym(handle
, fn_name
);
480 "Failed to find %s: %s\n",
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); \
494 UWRAP_UNLOCK(libc_symbol_binding)
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); \
502 UWRAP_UNLOCK(libpthread_symbol_binding)
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.
512 static int libc_setuid(uid_t uid
)
514 uwrap_bind_symbol_libc(setuid
);
516 return uwrap
.libc
.symbols
._libc_setuid
.f(uid
);
519 static uid_t
libc_getuid(void)
521 uwrap_bind_symbol_libc(getuid
);
523 return uwrap
.libc
.symbols
._libc_getuid
.f();
527 static int libc_seteuid(uid_t euid
)
529 uwrap_bind_symbol_libc(seteuid
);
531 return uwrap
.libc
.symbols
._libc_seteuid
.f(euid
);
536 static int libc_setreuid(uid_t ruid
, uid_t euid
)
538 uwrap_bind_symbol_libc(setreuid
);
540 return uwrap
.libc
.symbols
._libc_setreuid
.f(ruid
, euid
);
544 #ifdef HAVE_SETRESUID
545 static int libc_setresuid(uid_t ruid
, uid_t euid
, uid_t suid
)
547 uwrap_bind_symbol_libc(setresuid
);
549 return uwrap
.libc
.symbols
._libc_setresuid
.f(ruid
, euid
, suid
);
553 #ifdef HAVE_GETRESUID
554 static int libc_getresuid(uid_t
*ruid
, uid_t
*euid
, uid_t
*suid
)
556 uwrap_bind_symbol_libc(getresuid
);
558 return uwrap
.libc
.symbols
._libc_getresuid
.f(ruid
, euid
, suid
);
562 static uid_t
libc_geteuid(void)
564 uwrap_bind_symbol_libc(geteuid
);
566 return uwrap
.libc
.symbols
._libc_geteuid
.f();
569 static int libc_setgid(gid_t gid
)
571 uwrap_bind_symbol_libc(setgid
);
573 return uwrap
.libc
.symbols
._libc_setgid
.f(gid
);
576 static gid_t
libc_getgid(void)
578 uwrap_bind_symbol_libc(getgid
);
580 return uwrap
.libc
.symbols
._libc_getgid
.f();
584 static int libc_setegid(gid_t egid
)
586 uwrap_bind_symbol_libc(setegid
);
588 return uwrap
.libc
.symbols
._libc_setegid
.f(egid
);
593 static int libc_setregid(gid_t rgid
, gid_t egid
)
595 uwrap_bind_symbol_libc(setregid
);
597 return uwrap
.libc
.symbols
._libc_setregid
.f(rgid
, egid
);
601 #ifdef HAVE_SETRESGID
602 static int libc_setresgid(gid_t rgid
, gid_t egid
, gid_t sgid
)
604 uwrap_bind_symbol_libc(setresgid
);
606 return uwrap
.libc
.symbols
._libc_setresgid
.f(rgid
, egid
, sgid
);
610 #ifdef HAVE_GETRESGID
611 static int libc_getresgid(gid_t
*rgid
, gid_t
*egid
, gid_t
*sgid
)
613 uwrap_bind_symbol_libc(setresgid
);
615 return uwrap
.libc
.symbols
._libc_getresgid
.f(rgid
, egid
, sgid
);
619 static gid_t
libc_getegid(void)
621 uwrap_bind_symbol_libc(getegid
);
623 return uwrap
.libc
.symbols
._libc_getegid
.f();
626 static int libc_getgroups(int size
, gid_t list
[])
628 uwrap_bind_symbol_libc(getgroups
);
630 return uwrap
.libc
.symbols
._libc_getgroups
.f(size
, list
);
633 static int libc_setgroups(size_t size
, const gid_t
*list
)
635 uwrap_bind_symbol_libc(setgroups
);
637 return uwrap
.libc
.symbols
._libc_setgroups
.f(size
, list
);
641 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
642 static long int libc_vsyscall(long int sysno
, va_list va
)
648 uwrap_bind_symbol_libc(syscall
);
650 for (i
= 0; i
< 8; i
++) {
651 args
[i
] = va_arg(va
, long int);
654 rc
= uwrap
.libc
.symbols
._libc_syscall
.f(sysno
,
669 * This part is "optimistic".
670 * Thread can ends without pthread_exit call.
672 static void libpthread_pthread_exit(void *retval
)
674 uwrap_bind_symbol_libpthread(pthread_exit
);
676 uwrap
.libpthread
.symbols
._libpthread_pthread_exit
.f(retval
);
679 static void uwrap_pthread_exit(void *retval
)
681 struct uwrap_thread
*id
= uwrap_tls_id
;
683 UWRAP_LOG(UWRAP_LOG_DEBUG
, "Cleanup thread");
685 UWRAP_LOCK(uwrap_id
);
687 UWRAP_UNLOCK(uwrap_id
);
688 libpthread_pthread_exit(retval
);
692 UWRAP_DLIST_REMOVE(uwrap
.ids
, id
);
693 SAFE_FREE(id
->groups
);
697 UWRAP_UNLOCK(uwrap_id
);
699 libpthread_pthread_exit(retval
);
702 void pthread_exit(void *retval
)
704 if (!uid_wrapper_enabled()) {
705 libpthread_pthread_exit(retval
);
708 uwrap_pthread_exit(retval
);
710 /* Calm down gcc warning. */
714 static int libpthread_pthread_create(pthread_t
*thread
,
715 const pthread_attr_t
*attr
,
716 void *(*start_routine
) (void *),
719 uwrap_bind_symbol_libpthread(pthread_create
);
720 return uwrap
.libpthread
.symbols
._libpthread_pthread_create
.f(thread
,
726 struct uwrap_pthread_create_args
{
727 struct uwrap_thread
*id
;
728 void *(*start_routine
) (void *);
732 static void *uwrap_pthread_create_start(void *_a
)
734 struct uwrap_pthread_create_args
*a
=
735 (struct uwrap_pthread_create_args
*)_a
;
736 void *(*start_routine
) (void *) = a
->start_routine
;
738 struct uwrap_thread
*id
= a
->id
;
744 return start_routine(arg
);
747 static int uwrap_pthread_create(pthread_t
*thread
,
748 const pthread_attr_t
*attr
,
749 void *(*start_routine
) (void *),
752 struct uwrap_pthread_create_args
*args
;
753 struct uwrap_thread
*src_id
= uwrap_tls_id
;
756 args
= malloc(sizeof(struct uwrap_pthread_create_args
));
758 UWRAP_LOG(UWRAP_LOG_ERROR
,
759 "uwrap_pthread_create: Unable to allocate memory");
763 args
->start_routine
= start_routine
;
766 args
->id
= calloc(1, sizeof(struct uwrap_thread
));
767 if (args
->id
== NULL
) {
769 UWRAP_LOG(UWRAP_LOG_ERROR
,
770 "uwrap_pthread_create: Unable to allocate memory");
775 UWRAP_LOCK(uwrap_id
);
777 args
->id
->groups
= calloc(src_id
->ngroups
, sizeof(gid_t
));
778 if (args
->id
->groups
== NULL
) {
779 UWRAP_UNLOCK(uwrap_id
);
782 UWRAP_LOG(UWRAP_LOG_ERROR
,
783 "uwrap_pthread_create: Unable to allocate memory again");
788 args
->id
->ruid
= src_id
->ruid
;
789 args
->id
->euid
= src_id
->euid
;
790 args
->id
->suid
= src_id
->suid
;
792 args
->id
->rgid
= src_id
->rgid
;
793 args
->id
->egid
= src_id
->egid
;
794 args
->id
->sgid
= src_id
->sgid
;
796 args
->id
->enabled
= src_id
->enabled
;
798 args
->id
->ngroups
= src_id
->ngroups
;
799 if (src_id
->groups
!= NULL
) {
800 memcpy(args
->id
->groups
, src_id
->groups
,
801 sizeof(gid_t
) * src_id
->ngroups
);
803 SAFE_FREE(args
->id
->groups
);
806 UWRAP_DLIST_ADD(uwrap
.ids
, args
->id
);
807 UWRAP_UNLOCK(uwrap_id
);
809 ret
= libpthread_pthread_create(thread
, attr
,
810 uwrap_pthread_create_start
,
819 int pthread_create(pthread_t
*thread
,
820 const pthread_attr_t
*attr
,
821 void *(*start_routine
) (void *),
824 if (!uid_wrapper_enabled()) {
825 return libpthread_pthread_create(thread
,
831 return uwrap_pthread_create(thread
,
837 /*********************************************************
839 *********************************************************/
841 #define GROUP_STRING_SIZE 16384
842 #define GROUP_MAX_COUNT (GROUP_STRING_SIZE / (10 + 1))
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
849 static void uwrap_export_ids(struct uwrap_thread
*id
)
851 char groups_str
[GROUP_STRING_SIZE
] = {0};
852 size_t groups_str_size
= sizeof(groups_str
);
853 char unsigned_str
[16] = {0}; /* We need 10 + 1 (+ 1) */
857 snprintf(unsigned_str
, sizeof(unsigned_str
), "%u", id
->ruid
);
858 setenv("UID_WRAPPER_INITIAL_RUID", unsigned_str
, 1);
860 snprintf(unsigned_str
, sizeof(unsigned_str
), "%u", id
->euid
);
861 setenv("UID_WRAPPER_INITIAL_EUID", unsigned_str
, 1);
863 snprintf(unsigned_str
, sizeof(unsigned_str
), "%u", id
->suid
);
864 setenv("UID_WRAPPER_INITIAL_SUID", unsigned_str
, 1);
867 snprintf(unsigned_str
, sizeof(unsigned_str
), "%u", id
->rgid
);
868 setenv("UID_WRAPPER_INITIAL_RGID", unsigned_str
, 1);
870 snprintf(unsigned_str
, sizeof(unsigned_str
), "%u", id
->egid
);
871 setenv("UID_WRAPPER_INITIAL_EGID", unsigned_str
, 1);
873 snprintf(unsigned_str
, sizeof(unsigned_str
), "%u", id
->sgid
);
874 setenv("UID_WRAPPER_INITIAL_SGID", unsigned_str
, 1);
876 if (id
->ngroups
> GROUP_MAX_COUNT
) {
877 UWRAP_LOG(UWRAP_LOG_ERROR
,
878 "ERROR: Number of groups (%u) exceeds maximum value "
879 "uid_wrapper can handle (%u).",
886 for (i
= 0; i
< id
->ngroups
; i
++) {
887 size_t groups_str_len
= strlen(groups_str
);
888 size_t groups_str_avail
= groups_str_size
- groups_str_len
- 1;
891 len
= snprintf(unsigned_str
, sizeof(unsigned_str
), ",%u", id
->groups
[i
]);
893 UWRAP_LOG(UWRAP_LOG_ERROR
,
894 "snprintf failed for groups[%d]=%u",
899 if (((size_t)len
) >= groups_str_avail
) {
900 UWRAP_LOG(UWRAP_LOG_ERROR
,
901 "groups env string is to small for %d groups",
906 len
= snprintf(groups_str
+ groups_str_len
,
907 groups_str_size
- groups_str_len
,
909 i
== 0 ? unsigned_str
+ 1 : unsigned_str
);
911 UWRAP_LOG(UWRAP_LOG_ERROR
,
912 "snprintf failed to create groups string at groups[%d]=%u",
919 if (id
->ngroups
== i
) {
920 setenv("UID_WRAPPER_INITIAL_GROUPS", groups_str
, 1);
922 snprintf(unsigned_str
, sizeof(unsigned_str
), "%u", id
->ngroups
);
923 setenv("UID_WRAPPER_INITIAL_GROUPS_COUNT", unsigned_str
, 1);
927 static void uwrap_thread_prepare(void)
929 struct uwrap_thread
*id
= uwrap_tls_id
;
933 /* uid_wrapper is loaded but not enabled */
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.
947 static void uwrap_thread_parent(void)
949 struct uwrap_thread
*id
= uwrap_tls_id
;
951 /* uid_wrapper is loaded but not enabled */
962 static void uwrap_thread_child(void)
964 struct uwrap_thread
*id
= uwrap_tls_id
;
965 struct uwrap_thread
*u
= uwrap
.ids
;
967 /* uid_wrapper is loaded but not enabled */
974 * "Garbage collector" - Inspired by DESTRUCTOR.
975 * All threads (except one which called fork()) are dead now.. Dave
976 * That's what posix said...
980 /* Skip this item. */
985 UWRAP_DLIST_REMOVE(uwrap
.ids
, u
);
987 SAFE_FREE(u
->groups
);
993 uwrap_export_ids(id
);
1000 static unsigned long uwrap_get_xid_from_env(const char *envname
)
1003 const char *env
= NULL
;
1006 env
= getenv(envname
);
1011 if (env
[0] == '\0') {
1016 xid
= strtoul(env
, &endp
, 10);
1026 * This initializes uid_wrapper with the IDs exported to the environment. Those
1027 * are normally set after we forked and executed.
1029 static void uwrap_init_env(struct uwrap_thread
*id
)
1036 xid
= uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_RUID");
1037 if (xid
!= ULONG_MAX
) {
1038 id
->ruid
= (uid_t
)xid
;
1041 xid
= uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_EUID");
1042 if (xid
!= ULONG_MAX
) {
1043 id
->euid
= (uid_t
)xid
;
1046 xid
= uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_SUID");
1047 if (xid
!= ULONG_MAX
) {
1048 id
->suid
= (uid_t
)xid
;
1052 xid
= uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_RGID");
1053 if (xid
!= ULONG_MAX
) {
1054 id
->rgid
= (gid_t
)xid
;
1057 xid
= uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_EGID");
1058 if (xid
!= ULONG_MAX
) {
1059 id
->egid
= (gid_t
)xid
;
1062 xid
= uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_SGID");
1063 if (xid
!= ULONG_MAX
) {
1064 id
->sgid
= (gid_t
)xid
;
1067 env
= getenv("UID_WRAPPER_INITIAL_GROUPS_COUNT");
1068 if (env
!= NULL
&& env
[0] != '\0') {
1072 n
= strtol(env
, &endp
, 10);
1075 } else if (n
> 0 && n
< GROUP_MAX_COUNT
) {
1078 unsetenv("UID_WRAPPER_INITIAL_GROUPS_COUNT");
1087 id
->groups
= calloc(ngroups
, sizeof(gid_t
));
1088 if (id
->groups
== NULL
) {
1089 UWRAP_LOG(UWRAP_LOG_ERROR
,
1090 "Unable to allocate memory");
1094 env
= getenv("UID_WRAPPER_INITIAL_GROUPS");
1095 if (env
!= NULL
&& env
[0] != '\0') {
1096 char *groups_str
= NULL
;
1097 char *saveptr
= NULL
;
1098 const char *p
= NULL
;
1100 groups_str
= strdup(env
);
1101 if (groups_str
== NULL
) {
1105 p
= strtok_r(groups_str
, ",", &saveptr
);
1107 id
->groups
[i
] = strtol(p
, (char **)NULL
, 10);
1110 p
= strtok_r(NULL
, ",", &saveptr
);
1112 SAFE_FREE(groups_str
);
1116 UWRAP_LOG(UWRAP_LOG_ERROR
,
1117 "ERROR: The number of groups (%u) passed, "
1118 "does not match the number of groups (%u) "
1125 UWRAP_LOG(UWRAP_LOG_DEBUG
, "Initalize groups with %s", env
);
1126 id
->ngroups
= ngroups
;
1130 static void uwrap_init(void)
1134 UWRAP_LOCK(uwrap_id
);
1136 if (uwrap
.initialised
) {
1137 struct uwrap_thread
*id
= uwrap_tls_id
;
1139 if (uwrap
.ids
== NULL
) {
1140 UWRAP_UNLOCK(uwrap_id
);
1145 UWRAP_LOG(UWRAP_LOG_ERROR
,
1146 "Invalid id for thread");
1150 UWRAP_UNLOCK(uwrap_id
);
1154 UWRAP_LOG(UWRAP_LOG_DEBUG
, "Initialize uid_wrapper");
1156 uwrap
.initialised
= true;
1158 env
= getenv("UID_WRAPPER");
1159 if (env
!= NULL
&& env
[0] == '1') {
1160 const char *root
= getenv("UID_WRAPPER_ROOT");
1161 struct uwrap_thread
*id
;
1163 id
= calloc(1, sizeof(struct uwrap_thread
));
1165 UWRAP_LOG(UWRAP_LOG_ERROR
,
1166 "Unable to allocate memory for main id");
1170 UWRAP_DLIST_ADD(uwrap
.ids
, id
);
1173 uwrap
.myuid
= libc_geteuid();
1174 uwrap
.mygid
= libc_getegid();
1176 /* put us in one group */
1177 if (root
!= NULL
&& root
[0] == '1') {
1178 id
->ruid
= id
->euid
= id
->suid
= 0;
1179 id
->rgid
= id
->egid
= id
->sgid
= 0;
1181 id
->groups
= malloc(sizeof(gid_t
) * 1);
1182 if (id
->groups
== NULL
) {
1183 UWRAP_LOG(UWRAP_LOG_ERROR
,
1184 "Unable to allocate memory");
1192 id
->ruid
= id
->euid
= id
->suid
= uwrap
.myuid
;
1193 id
->rgid
= id
->egid
= id
->sgid
= uwrap
.mygid
;
1195 id
->ngroups
= libc_getgroups(0, NULL
);
1196 if (id
->ngroups
== -1) {
1197 UWRAP_LOG(UWRAP_LOG_ERROR
,
1198 "Unable to call libc_getgroups in uwrap_init.");
1201 id
->groups
= malloc(sizeof(gid_t
) * id
->ngroups
);
1202 if (id
->groups
== NULL
) {
1203 UWRAP_LOG(UWRAP_LOG_ERROR
, "Unable to allocate memory");
1206 if (libc_getgroups(id
->ngroups
, id
->groups
) == -1) {
1207 UWRAP_LOG(UWRAP_LOG_ERROR
,
1208 "Unable to call libc_getgroups again in uwrap_init.");
1211 * Deallocation of uwrap.groups is handled by
1212 * library destructor.
1222 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
);
1228 UWRAP_UNLOCK(uwrap_id
);
1230 UWRAP_LOG(UWRAP_LOG_DEBUG
, "Successfully initialized uid_wrapper");
1233 bool uid_wrapper_enabled(void)
1235 struct uwrap_thread
*id
= uwrap_tls_id
;
1242 UWRAP_LOCK(uwrap_id
);
1243 enabled
= id
->enabled
;
1244 UWRAP_UNLOCK(uwrap_id
);
1250 * UWRAP_SETxUID FUNCTIONS
1253 static int uwrap_setresuid_args(uid_t ruid
, uid_t euid
, uid_t suid
)
1255 struct uwrap_thread
*id
= uwrap_tls_id
;
1257 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
);
1261 if (id
->euid
!= 0) {
1262 if (ruid
!= (uid_t
)-1 &&
1269 if (euid
!= (uid_t
)-1 &&
1276 if (suid
!= (uid_t
)-1 &&
1288 static int uwrap_setresuid_thread(uid_t ruid
, uid_t euid
, uid_t suid
)
1290 struct uwrap_thread
*id
= uwrap_tls_id
;
1293 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
);
1297 rc
= uwrap_setresuid_args(ruid
, euid
, suid
);
1302 UWRAP_LOCK(uwrap_id
);
1304 if (ruid
!= (uid_t
)-1) {
1308 if (euid
!= (uid_t
)-1) {
1312 if (suid
!= (uid_t
)-1) {
1316 UWRAP_UNLOCK(uwrap_id
);
1321 static int uwrap_setresuid(uid_t ruid
, uid_t euid
, uid_t suid
)
1323 struct uwrap_thread
*id
= uwrap_tls_id
;
1326 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
);
1330 rc
= uwrap_setresuid_args(ruid
, euid
, suid
);
1335 UWRAP_LOCK(uwrap_id
);
1337 for (id
= uwrap
.ids
; id
; id
= id
->next
) {
1338 if (ruid
!= (uid_t
)-1) {
1342 if (euid
!= (uid_t
)-1) {
1346 if (suid
!= (uid_t
)-1) {
1351 UWRAP_UNLOCK(uwrap_id
);
1356 static int uwrap_setreuid_args(uid_t ruid
, uid_t euid
,
1361 struct uwrap_thread
*id
= uwrap_tls_id
;
1362 uid_t new_ruid
= -1, new_euid
= -1, new_suid
= -1;
1364 UWRAP_LOG(UWRAP_LOG_TRACE
,
1365 "ruid %d -> %d, euid %d -> %d",
1366 id
->ruid
, ruid
, id
->euid
, euid
);
1368 if (ruid
!= (uid_t
)-1) {
1370 if (ruid
!= id
->ruid
&&
1378 if (euid
!= (uid_t
)-1) {
1380 if (euid
!= id
->ruid
&&
1389 if (ruid
!= (uid_t
) -1 ||
1390 (euid
!= (uid_t
)-1 && id
->ruid
!= euid
)) {
1391 new_suid
= new_euid
;
1394 *_new_ruid
= new_ruid
;
1395 *_new_euid
= new_euid
;
1396 *_new_suid
= new_suid
;
1401 static int uwrap_setreuid_thread(uid_t ruid
, uid_t euid
)
1403 struct uwrap_thread
*id
= uwrap_tls_id
;
1404 uid_t new_ruid
= -1, new_euid
= -1, new_suid
= -1;
1407 UWRAP_LOG(UWRAP_LOG_TRACE
,
1408 "ruid %d -> %d, euid %d -> %d",
1409 id
->ruid
, ruid
, id
->euid
, euid
);
1411 rc
= uwrap_setreuid_args(ruid
, euid
, &new_ruid
, &new_euid
, &new_suid
);
1416 return uwrap_setresuid_thread(new_ruid
, new_euid
, new_suid
);
1419 #ifdef HAVE_SETREUID
1420 static int uwrap_setreuid(uid_t ruid
, uid_t euid
)
1422 struct uwrap_thread
*id
= uwrap_tls_id
;
1423 uid_t new_ruid
= -1, new_euid
= -1, new_suid
= -1;
1426 UWRAP_LOG(UWRAP_LOG_TRACE
,
1427 "ruid %d -> %d, euid %d -> %d",
1428 id
->ruid
, ruid
, id
->euid
, euid
);
1430 rc
= uwrap_setreuid_args(ruid
, euid
, &new_ruid
, &new_euid
, &new_suid
);
1435 return uwrap_setresuid(new_ruid
, new_euid
, new_suid
);
1439 static int uwrap_setuid_args(uid_t uid
,
1444 struct uwrap_thread
*id
= uwrap_tls_id
;
1446 UWRAP_LOG(UWRAP_LOG_TRACE
,
1450 if (uid
== (uid_t
)-1) {
1455 if (id
->euid
== 0) {
1456 *new_suid
= *new_ruid
= uid
;
1457 } else if (uid
!= id
->ruid
&&
1468 static int uwrap_setuid_thread(uid_t uid
)
1470 uid_t new_ruid
= -1, new_euid
= -1, new_suid
= -1;
1473 rc
= uwrap_setuid_args(uid
, &new_ruid
, &new_euid
, &new_suid
);
1478 return uwrap_setresuid_thread(new_ruid
, new_euid
, new_suid
);
1481 static int uwrap_setuid(uid_t uid
)
1483 uid_t new_ruid
= -1, new_euid
= -1, new_suid
= -1;
1486 rc
= uwrap_setuid_args(uid
, &new_ruid
, &new_euid
, &new_suid
);
1491 return uwrap_setresuid(new_ruid
, new_euid
, new_suid
);
1495 * UWRAP_GETxUID FUNCTIONS
1498 #ifdef HAVE_GETRESUID
1499 static int uwrap_getresuid(uid_t
*ruid
, uid_t
*euid
, uid_t
*suid
)
1501 struct uwrap_thread
*id
= uwrap_tls_id
;
1503 UWRAP_LOCK(uwrap_id
);
1509 UWRAP_UNLOCK(uwrap_id
);
1515 #ifdef HAVE_GETRESGID
1516 static int uwrap_getresgid(gid_t
*rgid
, gid_t
*egid
, gid_t
*sgid
)
1518 struct uwrap_thread
*id
= uwrap_tls_id
;
1520 UWRAP_LOCK(uwrap_id
);
1526 UWRAP_UNLOCK(uwrap_id
);
1533 * UWRAP_SETxGID FUNCTIONS
1536 static int uwrap_setresgid_args(gid_t rgid
, gid_t egid
, gid_t sgid
)
1538 struct uwrap_thread
*id
= uwrap_tls_id
;
1540 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
);
1544 if (id
->euid
!= 0) {
1545 if (rgid
!= (gid_t
)-1 &&
1552 if (egid
!= (gid_t
)-1 &&
1559 if (sgid
!= (gid_t
)-1 &&
1571 static int uwrap_setresgid_thread(gid_t rgid
, gid_t egid
, gid_t sgid
)
1573 struct uwrap_thread
*id
= uwrap_tls_id
;
1576 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
);
1580 rc
= uwrap_setresgid_args(rgid
, egid
, sgid
);
1585 UWRAP_LOCK(uwrap_id
);
1587 if (rgid
!= (gid_t
)-1) {
1591 if (egid
!= (gid_t
)-1) {
1595 if (sgid
!= (gid_t
)-1) {
1599 UWRAP_UNLOCK(uwrap_id
);
1604 static int uwrap_setresgid(gid_t rgid
, gid_t egid
, gid_t sgid
)
1606 struct uwrap_thread
*id
= uwrap_tls_id
;
1609 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
);
1613 rc
= uwrap_setresgid_args(rgid
, egid
, sgid
);
1618 UWRAP_LOCK(uwrap_id
);
1620 for (id
= uwrap
.ids
; id
; id
= id
->next
) {
1621 if (rgid
!= (gid_t
)-1) {
1625 if (egid
!= (gid_t
)-1) {
1629 if (sgid
!= (gid_t
)-1) {
1634 UWRAP_UNLOCK(uwrap_id
);
1639 static int uwrap_setregid_args(gid_t rgid
, gid_t egid
,
1644 struct uwrap_thread
*id
= uwrap_tls_id
;
1645 gid_t new_rgid
= -1, new_egid
= -1, new_sgid
= -1;
1647 UWRAP_LOG(UWRAP_LOG_TRACE
,
1648 "rgid %d -> %d, egid %d -> %d",
1649 id
->rgid
, rgid
, id
->egid
, egid
);
1651 if (rgid
!= (gid_t
)-1) {
1653 if (rgid
!= id
->rgid
&&
1661 if (egid
!= (gid_t
)-1) {
1663 if (egid
!= id
->rgid
&&
1672 if (rgid
!= (gid_t
) -1 ||
1673 (egid
!= (gid_t
)-1 && id
->rgid
!= egid
)) {
1674 new_sgid
= new_egid
;
1677 *_new_rgid
= new_rgid
;
1678 *_new_egid
= new_egid
;
1679 *_new_sgid
= new_sgid
;
1684 static int uwrap_setregid_thread(gid_t rgid
, gid_t egid
)
1686 struct uwrap_thread
*id
= uwrap_tls_id
;
1687 gid_t new_rgid
= -1, new_egid
= -1, new_sgid
= -1;
1690 UWRAP_LOG(UWRAP_LOG_TRACE
,
1691 "rgid %d -> %d, egid %d -> %d",
1692 id
->rgid
, rgid
, id
->egid
, egid
);
1694 rc
= uwrap_setregid_args(rgid
, egid
, &new_rgid
, &new_egid
, &new_sgid
);
1699 return uwrap_setresgid_thread(new_rgid
, new_egid
, new_sgid
);
1702 #ifdef HAVE_SETREGID
1703 static int uwrap_setregid(gid_t rgid
, gid_t egid
)
1705 struct uwrap_thread
*id
= uwrap_tls_id
;
1706 gid_t new_rgid
= -1, new_egid
= -1, new_sgid
= -1;
1709 UWRAP_LOG(UWRAP_LOG_TRACE
,
1710 "rgid %d -> %d, egid %d -> %d",
1711 id
->rgid
, rgid
, id
->egid
, egid
);
1713 rc
= uwrap_setregid_args(rgid
, egid
, &new_rgid
, &new_egid
, &new_sgid
);
1718 return uwrap_setresgid(new_rgid
, new_egid
, new_sgid
);
1722 static int uwrap_setgid_args(gid_t gid
,
1727 struct uwrap_thread
*id
= uwrap_tls_id
;
1729 UWRAP_LOG(UWRAP_LOG_TRACE
,
1733 if (gid
== (gid_t
)-1) {
1738 if (id
->euid
== 0) {
1739 *new_sgid
= *new_rgid
= gid
;
1740 } else if (gid
!= id
->rgid
&&
1751 static int uwrap_setgid_thread(gid_t gid
)
1753 gid_t new_rgid
= -1, new_egid
= -1, new_sgid
= -1;
1756 rc
= uwrap_setgid_args(gid
, &new_rgid
, &new_egid
, &new_sgid
);
1761 return uwrap_setresgid_thread(new_rgid
, new_egid
, new_sgid
);
1764 static int uwrap_setgid(gid_t gid
)
1766 gid_t new_rgid
= -1, new_egid
= -1, new_sgid
= -1;
1769 rc
= uwrap_setgid_args(gid
, &new_rgid
, &new_egid
, &new_sgid
);
1774 return uwrap_setresgid(new_rgid
, new_egid
, new_sgid
);
1780 int setuid(uid_t uid
)
1782 if (!uid_wrapper_enabled()) {
1783 return libc_setuid(uid
);
1787 return uwrap_setuid(uid
);
1791 int seteuid(uid_t euid
)
1793 if (!uid_wrapper_enabled()) {
1794 return libc_seteuid(euid
);
1797 /* On FreeBSD the uid_t -1 is set and doesn't produce and error */
1798 if (euid
== (uid_t
)-1) {
1804 return uwrap_setresuid(-1, euid
, -1);
1808 #ifdef HAVE_SETREUID
1809 int setreuid(uid_t ruid
, uid_t euid
)
1811 if (!uid_wrapper_enabled()) {
1812 return libc_setreuid(ruid
, euid
);
1816 return uwrap_setreuid(ruid
, euid
);
1820 #ifdef HAVE_SETRESUID
1821 int setresuid(uid_t ruid
, uid_t euid
, uid_t suid
)
1823 if (!uid_wrapper_enabled()) {
1824 return libc_setresuid(ruid
, euid
, suid
);
1828 return uwrap_setresuid(ruid
, euid
, suid
);
1832 #ifdef HAVE_GETRESUID
1833 int getresuid(uid_t
*ruid
, uid_t
*euid
, uid_t
*suid
)
1835 if (!uid_wrapper_enabled()) {
1836 return libc_getresuid(ruid
, euid
, suid
);
1840 return uwrap_getresuid(ruid
, euid
, suid
);
1847 static uid_t
uwrap_getuid(void)
1849 struct uwrap_thread
*id
= uwrap_tls_id
;
1852 UWRAP_LOCK(uwrap_id
);
1854 UWRAP_UNLOCK(uwrap_id
);
1861 if (!uid_wrapper_enabled()) {
1862 return libc_getuid();
1866 return uwrap_getuid();
1872 static uid_t
uwrap_geteuid(void)
1874 const char *env
= getenv("UID_WRAPPER_MYUID");
1875 struct uwrap_thread
*id
= uwrap_tls_id
;
1878 UWRAP_LOCK(uwrap_id
);
1880 UWRAP_UNLOCK(uwrap_id
);
1882 /* Disable root and return myuid */
1883 if (env
!= NULL
&& env
[0] == '1') {
1892 if (!uid_wrapper_enabled()) {
1893 return libc_geteuid();
1897 return uwrap_geteuid();
1903 int setgid(gid_t gid
)
1905 if (!uid_wrapper_enabled()) {
1906 return libc_setgid(gid
);
1910 return uwrap_setgid(gid
);
1914 int setegid(gid_t egid
)
1916 if (!uid_wrapper_enabled()) {
1917 return libc_setegid(egid
);
1920 /* On FreeBSD the uid_t -1 is set and doesn't produce and error */
1921 if (egid
== (gid_t
)-1) {
1927 return uwrap_setresgid(-1, egid
, -1);
1931 #ifdef HAVE_SETREGID
1932 int setregid(gid_t rgid
, gid_t egid
)
1934 if (!uid_wrapper_enabled()) {
1935 return libc_setregid(rgid
, egid
);
1939 return uwrap_setregid(rgid
, egid
);
1943 #ifdef HAVE_SETRESGID
1944 int setresgid(gid_t rgid
, gid_t egid
, gid_t sgid
)
1946 if (!uid_wrapper_enabled()) {
1947 return libc_setresgid(rgid
, egid
, sgid
);
1951 return uwrap_setresgid(rgid
, egid
, sgid
);
1955 #ifdef HAVE_GETRESGID
1956 int getresgid(gid_t
*rgid
, gid_t
*egid
, gid_t
*sgid
)
1958 if (!uid_wrapper_enabled()) {
1959 return libc_getresgid(rgid
, egid
, sgid
);
1963 return uwrap_getresgid(rgid
, egid
, sgid
);
1970 static gid_t
uwrap_getgid(void)
1972 struct uwrap_thread
*id
= uwrap_tls_id
;
1975 UWRAP_LOCK(uwrap_id
);
1977 UWRAP_UNLOCK(uwrap_id
);
1984 if (!uid_wrapper_enabled()) {
1985 return libc_getgid();
1989 return uwrap_getgid();
1995 static uid_t
uwrap_getegid(void)
1997 struct uwrap_thread
*id
= uwrap_tls_id
;
2000 UWRAP_LOCK(uwrap_id
);
2002 UWRAP_UNLOCK(uwrap_id
);
2009 if (!uid_wrapper_enabled()) {
2010 return libc_getegid();
2014 return uwrap_getegid();
2017 static int uwrap_setgroups_thread(size_t size
, const gid_t
*list
)
2019 struct uwrap_thread
*id
= uwrap_tls_id
;
2022 UWRAP_LOCK(uwrap_id
);
2025 SAFE_FREE(id
->groups
);
2027 } else if (size
> 0) {
2030 tmp
= realloc(id
->groups
, sizeof(gid_t
) * size
);
2037 memcpy(id
->groups
, list
, size
* sizeof(gid_t
));
2042 UWRAP_UNLOCK(uwrap_id
);
2047 static int uwrap_setgroups(size_t size
, const gid_t
*list
)
2049 struct uwrap_thread
*id
;
2052 UWRAP_LOCK(uwrap_id
);
2055 for (id
= uwrap
.ids
; id
; id
= id
->next
) {
2056 SAFE_FREE(id
->groups
);
2060 } else if (size
> 0) {
2063 for (id
= uwrap
.ids
; id
; id
= id
->next
) {
2064 tmp
= realloc(id
->groups
, sizeof(gid_t
) * size
);
2072 memcpy(id
->groups
, list
, size
* sizeof(gid_t
));
2078 UWRAP_UNLOCK(uwrap_id
);
2083 #ifdef HAVE_SETGROUPS_INT
2084 int setgroups(int size
, const gid_t
*list
)
2086 int setgroups(size_t size
, const gid_t
*list
)
2089 if (!uid_wrapper_enabled()) {
2090 return libc_setgroups(size
, list
);
2094 return uwrap_setgroups(size
, list
);
2097 static int uwrap_getgroups(int size
, gid_t
*list
)
2099 struct uwrap_thread
*id
= uwrap_tls_id
;
2102 UWRAP_LOCK(uwrap_id
);
2103 ngroups
= id
->ngroups
;
2105 if (size
> ngroups
) {
2111 if (size
< ngroups
) {
2115 memcpy(list
, id
->groups
, size
* sizeof(gid_t
));
2118 UWRAP_UNLOCK(uwrap_id
);
2123 int getgroups(int size
, gid_t
*list
)
2125 if (!uid_wrapper_enabled()) {
2126 return libc_getgroups(size
, list
);
2130 return uwrap_getgroups(size
, list
);
2133 #if (defined(HAVE_SYS_SYSCALL_H) || defined(HAVE_SYSCALL_H)) \
2134 && (defined(SYS_setreuid) || defined(SYS_setreuid32))
2135 static long int uwrap_syscall (long int sysno
, va_list vp
)
2146 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2150 rc
= uwrap_getgid();
2155 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2159 rc
= uwrap_getegid();
2162 #endif /* SYS_getegid */
2164 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2168 gid_t gid
= (gid_t
) va_arg(vp
, gid_t
);
2170 rc
= uwrap_setgid_thread(gid
);
2174 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2175 case SYS_setregid32
:
2178 gid_t rgid
= (gid_t
) va_arg(vp
, gid_t
);
2179 gid_t egid
= (gid_t
) va_arg(vp
, gid_t
);
2181 rc
= uwrap_setregid_thread(rgid
, egid
);
2184 #ifdef SYS_setresgid
2186 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2187 case SYS_setresgid32
:
2190 gid_t rgid
= (gid_t
) va_arg(vp
, gid_t
);
2191 gid_t egid
= (gid_t
) va_arg(vp
, gid_t
);
2192 gid_t sgid
= (gid_t
) va_arg(vp
, gid_t
);
2194 rc
= uwrap_setresgid_thread(rgid
, egid
, sgid
);
2197 #endif /* SYS_setresgid */
2198 #if defined(SYS_getresgid) && defined(HAVE_GETRESGID)
2200 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2201 case SYS_getresgid32
:
2204 gid_t
*rgid
= (gid_t
*) va_arg(vp
, gid_t
*);
2205 gid_t
*egid
= (gid_t
*) va_arg(vp
, gid_t
*);
2206 gid_t
*sgid
= (gid_t
*) va_arg(vp
, gid_t
*);
2208 rc
= uwrap_getresgid(rgid
, egid
, sgid
);
2211 #endif /* SYS_getresgid && HAVE_GETRESGID */
2219 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2223 rc
= uwrap_getuid();
2228 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2232 rc
= uwrap_geteuid();
2235 #endif /* SYS_geteuid */
2237 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2241 uid_t uid
= (uid_t
) va_arg(vp
, uid_t
);
2243 rc
= uwrap_setuid_thread(uid
);
2247 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2248 case SYS_setreuid32
:
2251 uid_t ruid
= (uid_t
) va_arg(vp
, uid_t
);
2252 uid_t euid
= (uid_t
) va_arg(vp
, uid_t
);
2254 rc
= uwrap_setreuid_thread(ruid
, euid
);
2257 #ifdef SYS_setresuid
2259 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2260 case SYS_setresuid32
:
2263 uid_t ruid
= (uid_t
) va_arg(vp
, uid_t
);
2264 uid_t euid
= (uid_t
) va_arg(vp
, uid_t
);
2265 uid_t suid
= (uid_t
) va_arg(vp
, uid_t
);
2267 rc
= uwrap_setresuid_thread(ruid
, euid
, suid
);
2270 #endif /* SYS_setresuid */
2271 #if defined(SYS_getresuid) && defined(HAVE_GETRESUID)
2273 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2274 case SYS_getresuid32
:
2277 uid_t
*ruid
= (uid_t
*) va_arg(vp
, uid_t
*);
2278 uid_t
*euid
= (uid_t
*) va_arg(vp
, uid_t
*);
2279 uid_t
*suid
= (uid_t
*) va_arg(vp
, uid_t
*);
2281 rc
= uwrap_getresuid(ruid
, euid
, suid
);
2284 #endif /* SYS_getresuid && HAVE_GETRESUID*/
2287 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2288 case SYS_setgroups32
:
2291 size_t size
= (size_t) va_arg(vp
, size_t);
2292 gid_t
*list
= (gid_t
*) va_arg(vp
, int *);
2294 rc
= uwrap_setgroups_thread(size
, list
);
2298 UWRAP_LOG(UWRAP_LOG_DEBUG
,
2299 "UID_WRAPPER calling non-wrapped syscall %lu",
2302 rc
= libc_vsyscall(sysno
, vp
);
2310 #ifdef HAVE_SYSCALL_INT
2311 int syscall (int sysno
, ...)
2313 long int syscall (long int sysno
, ...)
2316 #ifdef HAVE_SYSCALL_INT
2323 va_start(va
, sysno
);
2325 if (!uid_wrapper_enabled()) {
2326 rc
= libc_vsyscall(sysno
, va
);
2332 rc
= uwrap_syscall(sysno
, va
);
2337 #endif /* HAVE_SYSCALL */
2338 #endif /* HAVE_SYS_SYSCALL_H || HAVE_SYSCALL_H */
2340 /****************************
2342 ***************************/
2344 void uwrap_constructor(void)
2346 char *glibc_malloc_lock_bug
;
2349 * This is a workaround for a bug in glibc < 2.24:
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.
2356 * So as a workaround we need to call malloc once before we setup the
2359 * See https://sourceware.org/bugzilla/show_bug.cgi?id=16742
2361 glibc_malloc_lock_bug
= malloc(1);
2362 if (glibc_malloc_lock_bug
== NULL
) {
2365 glibc_malloc_lock_bug
[0] = '\0';
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.
2372 pthread_atfork(&uwrap_thread_prepare
,
2373 &uwrap_thread_parent
,
2374 &uwrap_thread_child
);
2376 free(glibc_malloc_lock_bug
);
2378 /* Here is safe place to call uwrap_init() and initialize data
2384 /****************************
2386 ***************************/
2389 * This function is called when the library is unloaded and makes sure that
2390 * resources are freed.
2392 void uwrap_destructor(void)
2394 struct uwrap_thread
*u
= uwrap
.ids
;
2399 UWRAP_DLIST_REMOVE(uwrap
.ids
, u
);
2401 SAFE_FREE(u
->groups
);
2408 if (uwrap
.libc
.handle
!= NULL
) {
2409 dlclose(uwrap
.libc
.handle
);
2412 if (uwrap
.libpthread
.handle
!= NULL
) {
2413 dlclose(uwrap
.libpthread
.handle
);