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_GNU_LIB_NAMES_H
42 #include <gnu/lib-names.h>
45 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
46 # define UWRAP_THREAD __thread
51 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
52 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
54 #define CONSTRUCTOR_ATTRIBUTE
55 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
57 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
58 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
60 #define DESTRUCTOR_ATTRIBUTE
61 #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
63 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
64 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
65 #else /* DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE */
66 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
67 #endif /* DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE */
69 /* GCC have printf type attribute check. */
70 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
71 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
73 #define PRINTF_ATTRIBUTE(a,b)
74 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
77 # ifdef HAVE_FALLTHROUGH_ATTRIBUTE
78 # define FALL_THROUGH __attribute__ ((fallthrough))
79 # else /* HAVE_FALLTHROUGH_ATTRIBUTE */
81 # endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
82 #endif /* FALL_THROUGH */
84 #define UWRAP_DLIST_ADD(list,item) do { \
86 (item)->prev = NULL; \
87 (item)->next = NULL; \
90 (item)->prev = NULL; \
91 (item)->next = (list); \
92 (list)->prev = (item); \
97 #define UWRAP_DLIST_REMOVE(list,item) do { \
98 if ((list) == (item)) { \
99 (list) = (item)->next; \
101 (list)->prev = NULL; \
104 if ((item)->prev) { \
105 (item)->prev->next = (item)->next; \
107 if ((item)->next) { \
108 (item)->next->prev = (item)->prev; \
111 (item)->prev = NULL; \
112 (item)->next = NULL; \
116 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
123 enum uwrap_dbglvl_e
{
130 #ifndef HAVE_GETPROGNAME
131 static const char *getprogname(void)
133 #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
134 return program_invocation_short_name
;
135 #elif defined(HAVE_GETEXECNAME)
136 return getexecname();
139 #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
141 #endif /* HAVE_GETPROGNAME */
143 static void uwrap_log(enum uwrap_dbglvl_e dbglvl
, const char *function
, const char *format
, ...) PRINTF_ATTRIBUTE(3, 4);
144 # define UWRAP_LOG(dbglvl, ...) uwrap_log((dbglvl), __func__, __VA_ARGS__)
146 static void uwrap_log(enum uwrap_dbglvl_e dbglvl
, const char *function
, const char *format
, ...)
151 unsigned int lvl
= 0;
152 const char *prefix
= "UWRAP";
153 const char *progname
= getprogname();
155 d
= getenv("UID_WRAPPER_DEBUGLEVEL");
164 va_start(va
, format
);
165 vsnprintf(buffer
, sizeof(buffer
), format
, va
);
169 case UWRAP_LOG_ERROR
:
170 prefix
= "UWRAP_ERROR";
173 prefix
= "UWRAP_WARN";
175 case UWRAP_LOG_DEBUG
:
176 prefix
= "UWRAP_DEBUG";
178 case UWRAP_LOG_TRACE
:
179 prefix
= "UWRAP_TRACE";
183 if (progname
== NULL
) {
184 progname
= "<unknown>";
188 "%s[%s (%u)] - %s: %s\n",
200 #define LIBC_NAME "libc.so"
202 typedef int (*__libc_setuid
)(uid_t uid
);
204 typedef uid_t (*__libc_getuid
)(void);
207 typedef int (*__libc_seteuid
)(uid_t euid
);
211 typedef int (*__libc_setreuid
)(uid_t ruid
, uid_t euid
);
214 #ifdef HAVE_SETRESUID
215 typedef int (*__libc_setresuid
)(uid_t ruid
, uid_t euid
, uid_t suid
);
218 #ifdef HAVE_GETRESUID
219 typedef int (*__libc_getresuid
)(uid_t
*ruid
, uid_t
*euid
, uid_t
*suid
);
222 typedef uid_t (*__libc_geteuid
)(void);
224 typedef int (*__libc_setgid
)(gid_t gid
);
226 typedef gid_t (*__libc_getgid
)(void);
229 typedef int (*__libc_setegid
)(uid_t egid
);
233 typedef int (*__libc_setregid
)(uid_t rgid
, uid_t egid
);
236 #ifdef HAVE_SETRESGID
237 typedef int (*__libc_setresgid
)(uid_t rgid
, uid_t egid
, uid_t sgid
);
240 #ifdef HAVE_GETRESGID
241 typedef int (*__libc_getresgid
)(gid_t
*rgid
, gid_t
*egid
, gid_t
*sgid
);
244 typedef gid_t (*__libc_getegid
)(void);
246 typedef int (*__libc_getgroups
)(int size
, gid_t list
[]);
247 #ifdef HAVE___GETGROUPS_CHK
248 typedef int (*__libc___getgroups_chk
)(int size
, gid_t list
[], size_t listlen
);
251 typedef int (*__libc_setgroups
)(size_t size
, const gid_t
*list
);
254 typedef long int (*__libc_syscall
)(long int sysno
, ...);
257 #define UWRAP_SYMBOL_ENTRY(i) \
263 struct uwrap_libc_symbols
{
264 UWRAP_SYMBOL_ENTRY(setuid
);
265 UWRAP_SYMBOL_ENTRY(getuid
);
267 UWRAP_SYMBOL_ENTRY(seteuid
);
270 UWRAP_SYMBOL_ENTRY(setreuid
);
272 #ifdef HAVE_SETRESUID
273 UWRAP_SYMBOL_ENTRY(setresuid
);
275 #ifdef HAVE_GETRESUID
276 UWRAP_SYMBOL_ENTRY(getresuid
);
278 UWRAP_SYMBOL_ENTRY(geteuid
);
279 UWRAP_SYMBOL_ENTRY(setgid
);
280 UWRAP_SYMBOL_ENTRY(getgid
);
282 UWRAP_SYMBOL_ENTRY(setegid
);
285 UWRAP_SYMBOL_ENTRY(setregid
);
287 #ifdef HAVE_SETRESGID
288 UWRAP_SYMBOL_ENTRY(setresgid
);
290 #ifdef HAVE_GETRESGID
291 UWRAP_SYMBOL_ENTRY(getresgid
);
293 UWRAP_SYMBOL_ENTRY(getegid
);
294 UWRAP_SYMBOL_ENTRY(getgroups
);
295 #ifdef HAVE___GETGROUPS_CHK
296 UWRAP_SYMBOL_ENTRY(__getgroups_chk
);
298 UWRAP_SYMBOL_ENTRY(setgroups
);
300 UWRAP_SYMBOL_ENTRY(syscall
);
303 #undef UWRAP_SYMBOL_ENTRY
305 #define UWRAP_SYMBOL_ENTRY(i) \
307 __rtld_default_##i f; \
312 typedef bool (*__rtld_default_socket_wrapper_syscall_valid
)(long int sysno
);
313 typedef long int (*__rtld_default_socket_wrapper_syscall_va
)(long int sysno
,
317 struct uwrap_rtld_default_symbols
{
319 UWRAP_SYMBOL_ENTRY(socket_wrapper_syscall_valid
);
320 UWRAP_SYMBOL_ENTRY(socket_wrapper_syscall_va
);
325 #undef UWRAP_SYMBOL_ENTRY
330 /* Yeah... I'm pig. I overloading macro here... So what? */
331 #define UWRAP_SYMBOL_ENTRY(i) \
333 __libpthread_##i f; \
337 typedef int (*__libpthread_pthread_create
)(pthread_t
*thread
,
338 const pthread_attr_t
*attr
,
339 void *(*start_routine
) (void *),
341 typedef void (*__libpthread_pthread_exit
)(void *retval
);
343 struct uwrap_libpthread_symbols
{
344 UWRAP_SYMBOL_ENTRY(pthread_create
);
345 UWRAP_SYMBOL_ENTRY(pthread_exit
);
347 #undef UWRAP_SYMBOL_ENTRY
350 * We keep the virtualised euid/egid/groups information here
352 struct uwrap_thread
{
366 struct uwrap_thread
*next
;
367 struct uwrap_thread
*prev
;
373 struct uwrap_libc_symbols symbols
;
377 struct uwrap_rtld_default_symbols symbols
;
382 struct uwrap_libpthread_symbols symbols
;
387 /* Real uid and gid of user who run uid wrapper */
391 struct uwrap_thread
*ids
;
394 static struct uwrap uwrap
;
396 /* Shortcut to the list item */
397 static UWRAP_THREAD
struct uwrap_thread
*uwrap_tls_id
;
399 /* The mutex or accessing the id */
400 static pthread_mutex_t uwrap_id_mutex
= PTHREAD_MUTEX_INITIALIZER
;
402 #define uwrap_init_mutex(m) _uwrap_init_mutex(m, #m)
403 static int _uwrap_init_mutex(pthread_mutex_t
*m
, const char *name
)
405 pthread_mutexattr_t ma
;
406 bool need_destroy
= false;
409 #define __CHECK(cmd) \
413 UWRAP_LOG(UWRAP_LOG_ERROR, \
414 "%s: %s - failed %d", \
422 *m
= (pthread_mutex_t
)PTHREAD_MUTEX_INITIALIZER
;
423 __CHECK(pthread_mutexattr_init(&ma
));
425 __CHECK(pthread_mutexattr_settype(&ma
, PTHREAD_MUTEX_ERRORCHECK
));
426 __CHECK(pthread_mutex_init(m
, &ma
));
429 pthread_mutexattr_destroy(&ma
);
434 #define uwrap_mutex_lock(m) _uwrap_mutex_lock(m, #m, __func__, __LINE__)
435 static void _uwrap_mutex_lock(pthread_mutex_t
*mutex
,
442 ret
= pthread_mutex_lock(mutex
);
444 UWRAP_LOG(UWRAP_LOG_ERROR
,
445 "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread "
457 #define uwrap_mutex_unlock(m) _uwrap_mutex_unlock(m, #m, __func__, __LINE__)
458 static void _uwrap_mutex_unlock(pthread_mutex_t
*mutex
,
465 ret
= pthread_mutex_unlock(mutex
);
467 UWRAP_LOG(UWRAP_LOG_ERROR
,
468 "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread "
480 #define UWRAP_LOCK(m) \
482 uwrap_mutex_lock(&(m##_mutex)); \
485 #define UWRAP_UNLOCK(m) \
487 uwrap_mutex_unlock(&(m##_mutex)); \
490 /* Add new global locks here please */
491 #define UWRAP_REINIT_ALL \
494 ret = uwrap_init_mutex(&uwrap_id_mutex); \
499 /* Add new global locks here please */
500 #define UWRAP_LOCK_ALL \
502 UWRAP_LOCK(uwrap_id); \
505 #define UWRAP_UNLOCK_ALL \
507 UWRAP_UNLOCK(uwrap_id); \
510 /*********************************************************
512 *********************************************************/
514 bool uid_wrapper_enabled(void);
515 #if ! defined(HAVE_CONSTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_INIT)
516 /* xlC and other oldschool compilers support (only) this */
517 #pragma init (uwrap_constructor)
519 void uwrap_constructor(void) CONSTRUCTOR_ATTRIBUTE
;
520 #if ! defined(HAVE_DESTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_FINI)
521 #pragma fini (uwrap_destructor)
523 void uwrap_destructor(void) DESTRUCTOR_ATTRIBUTE
;
525 /*********************************************************
526 * UWRAP LIBC LOADER FUNCTIONS
527 *********************************************************/
534 static void *uwrap_load_lib_handle(enum uwrap_lib lib
)
536 int flags
= RTLD_LAZY
;
541 const char *env_preload
= getenv("LD_PRELOAD");
542 const char *env_deepbind
= getenv("UID_WRAPPER_DISABLE_DEEPBIND");
543 bool enable_deepbind
= true;
545 /* Don't do a deepbind if we run with libasan */
546 if (env_preload
!= NULL
&& strlen(env_preload
) < 1024) {
547 const char *p
= strstr(env_preload
, "libasan.so");
549 enable_deepbind
= false;
553 if (env_deepbind
!= NULL
&& strlen(env_deepbind
) >= 1) {
554 enable_deepbind
= false;
557 if (enable_deepbind
) {
558 flags
|= RTLD_DEEPBIND
;
564 handle
= uwrap
.libc
.handle
;
566 if (handle
== NULL
) {
567 handle
= dlopen(LIBC_SO
, flags
);
569 uwrap
.libc
.handle
= handle
;
572 if (handle
== NULL
) {
573 for (i
= 10; i
>= 0; i
--) {
574 char soname
[256] = {0};
576 snprintf(soname
, sizeof(soname
), "libc.so.%d", i
);
577 handle
= dlopen(soname
, flags
);
578 if (handle
!= NULL
) {
582 /* glibc on Alpha and IA64 is libc.so.6.1 */
583 snprintf(soname
, sizeof(soname
), "libc.so.%d.1", i
);
584 handle
= dlopen(soname
, flags
);
585 if (handle
!= NULL
) {
590 uwrap
.libc
.handle
= handle
;
593 case UWRAP_LIBPTHREAD
:
594 handle
= uwrap
.libpthread
.handle
;
595 if (handle
== NULL
) {
598 * Because thread sanatizer also overloads
599 * pthread_create() and pthread_exit() we need use
600 * RTLD_NEXT instead of libpthread.so.0
602 handle
= uwrap
.libpthread
.handle
= RTLD_NEXT
;
604 handle
= dlopen("libpthread.so.0", flags
);
606 if (handle
!= NULL
) {
613 if (handle
== NULL
) {
617 handle
= uwrap
.libc
.handle
= RTLD_NEXT
;
619 case UWRAP_LIBPTHREAD
:
620 handle
= uwrap
.libpthread
.handle
= RTLD_NEXT
;
625 "Failed to dlopen library: %s\n",
634 static void *_uwrap_bind_symbol(enum uwrap_lib lib
, const char *fn_name
)
639 handle
= uwrap_load_lib_handle(lib
);
641 func
= dlsym(handle
, fn_name
);
644 "Failed to find %s: %s\n",
652 #define uwrap_bind_symbol_libc(sym_name) \
653 if (uwrap.libc.symbols._libc_##sym_name.obj == NULL) { \
654 uwrap.libc.symbols._libc_##sym_name.obj = \
655 _uwrap_bind_symbol(UWRAP_LIBC, #sym_name); \
658 #define uwrap_bind_symbol_libpthread(sym_name) \
659 if (uwrap.libpthread.symbols._libpthread_##sym_name.obj == NULL) { \
660 uwrap.libpthread.symbols._libpthread_##sym_name.obj = \
661 _uwrap_bind_symbol(UWRAP_LIBPTHREAD, #sym_name); \
664 #define uwrap_bind_symbol_rtld_default_optional(sym_name) \
665 if (uwrap.rtld_default.symbols._rtld_default_##sym_name.obj == NULL) { \
666 uwrap.rtld_default.symbols._rtld_default_##sym_name.obj = \
667 dlsym(RTLD_DEFAULT, #sym_name); \
670 /* JEMALLOC: This tells uid_wrapper if it should handle syscall() */
671 static bool uwrap_handle_syscall
;
673 /* DO NOT call this function during library initialization! */
674 static void __uwrap_bind_symbol_all_once(void)
676 uwrap_bind_symbol_libc(setuid
);
677 uwrap_bind_symbol_libc(getuid
);
679 uwrap_bind_symbol_libc(seteuid
);
682 uwrap_bind_symbol_libc(setreuid
);
684 #ifdef HAVE_SETRESUID
685 uwrap_bind_symbol_libc(setresuid
);
687 #ifdef HAVE_GETRESUID
688 uwrap_bind_symbol_libc(getresuid
);
690 uwrap_bind_symbol_libc(geteuid
);
691 uwrap_bind_symbol_libc(setgid
);
692 uwrap_bind_symbol_libc(getgid
);
694 uwrap_bind_symbol_libc(setegid
);
697 uwrap_bind_symbol_libc(setregid
);
700 #ifdef HAVE_SETRESGID
701 uwrap_bind_symbol_libc(setresgid
);
703 #ifdef HAVE_GETRESGID
704 uwrap_bind_symbol_libc(setresgid
);
706 uwrap_bind_symbol_libc(getegid
);
707 uwrap_bind_symbol_libc(getgroups
);
708 uwrap_bind_symbol_libc(setgroups
);
710 uwrap_bind_symbol_libc(syscall
);
711 uwrap_bind_symbol_rtld_default_optional(socket_wrapper_syscall_valid
);
712 uwrap_bind_symbol_rtld_default_optional(socket_wrapper_syscall_va
);
714 uwrap_bind_symbol_libpthread(pthread_create
);
715 uwrap_bind_symbol_libpthread(pthread_exit
);
717 uwrap_handle_syscall
= true;
720 static void uwrap_bind_symbol_all(void)
722 static pthread_once_t all_symbol_binding_once
= PTHREAD_ONCE_INIT
;
724 pthread_once(&all_symbol_binding_once
, __uwrap_bind_symbol_all_once
);
730 * Functions expeciall from libc need to be loaded individually, you can't load
731 * all at once or gdb will segfault at startup. The same applies to valgrind and
732 * has probably something todo with with the linker.
733 * So we need load each function at the point it is called the first time.
735 static int libc_setuid(uid_t uid
)
737 uwrap_bind_symbol_all();
739 return uwrap
.libc
.symbols
._libc_setuid
.f(uid
);
742 static uid_t
libc_getuid(void)
744 uwrap_bind_symbol_all();
746 return uwrap
.libc
.symbols
._libc_getuid
.f();
750 static int libc_seteuid(uid_t euid
)
752 uwrap_bind_symbol_all();
754 return uwrap
.libc
.symbols
._libc_seteuid
.f(euid
);
759 static int libc_setreuid(uid_t ruid
, uid_t euid
)
761 uwrap_bind_symbol_all();
763 return uwrap
.libc
.symbols
._libc_setreuid
.f(ruid
, euid
);
767 #ifdef HAVE_SETRESUID
768 static int libc_setresuid(uid_t ruid
, uid_t euid
, uid_t suid
)
770 uwrap_bind_symbol_all();
772 return uwrap
.libc
.symbols
._libc_setresuid
.f(ruid
, euid
, suid
);
776 #ifdef HAVE_GETRESUID
777 static int libc_getresuid(uid_t
*ruid
, uid_t
*euid
, uid_t
*suid
)
779 uwrap_bind_symbol_all();
781 return uwrap
.libc
.symbols
._libc_getresuid
.f(ruid
, euid
, suid
);
785 static uid_t
libc_geteuid(void)
787 uwrap_bind_symbol_all();
789 return uwrap
.libc
.symbols
._libc_geteuid
.f();
792 static int libc_setgid(gid_t gid
)
794 uwrap_bind_symbol_all();
796 return uwrap
.libc
.symbols
._libc_setgid
.f(gid
);
799 static gid_t
libc_getgid(void)
801 uwrap_bind_symbol_all();
803 return uwrap
.libc
.symbols
._libc_getgid
.f();
807 static int libc_setegid(gid_t egid
)
809 uwrap_bind_symbol_all();
811 return uwrap
.libc
.symbols
._libc_setegid
.f(egid
);
816 static int libc_setregid(gid_t rgid
, gid_t egid
)
818 uwrap_bind_symbol_all();
820 return uwrap
.libc
.symbols
._libc_setregid
.f(rgid
, egid
);
824 #ifdef HAVE_SETRESGID
825 static int libc_setresgid(gid_t rgid
, gid_t egid
, gid_t sgid
)
827 uwrap_bind_symbol_all();
829 return uwrap
.libc
.symbols
._libc_setresgid
.f(rgid
, egid
, sgid
);
833 #ifdef HAVE_GETRESGID
834 static int libc_getresgid(gid_t
*rgid
, gid_t
*egid
, gid_t
*sgid
)
836 uwrap_bind_symbol_all();
838 return uwrap
.libc
.symbols
._libc_getresgid
.f(rgid
, egid
, sgid
);
842 static gid_t
libc_getegid(void)
844 uwrap_bind_symbol_all();
846 return uwrap
.libc
.symbols
._libc_getegid
.f();
849 static int libc_getgroups(int size
, gid_t list
[])
851 uwrap_bind_symbol_all();
853 return uwrap
.libc
.symbols
._libc_getgroups
.f(size
, list
);
856 #ifdef HAVE___GETGROUPS_CHK
857 static int libc___getgroups_chk(int size
, gid_t list
[], size_t listlen
)
859 uwrap_bind_symbol_libc(__getgroups_chk
);
861 return uwrap
.libc
.symbols
._libc___getgroups_chk
.f(size
,
865 #endif /* HAVE___GETGROUPS_CHK */
867 static int libc_setgroups(size_t size
, const gid_t
*list
)
869 uwrap_bind_symbol_all();
871 return uwrap
.libc
.symbols
._libc_setgroups
.f(size
, list
);
875 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
876 static long int libc_vsyscall(long int sysno
, va_list va
)
885 * This is a workaround to prevent a deadlock in jemalloc calling
886 * malloc_init() twice. The first allocation call will trigger a
887 * malloc_init() of jemalloc. The functions calls syscall(SYS_open, ...)
888 * so it goes to socket or uid wrapper. In this code path we need to
889 * avoid any allocation calls. This will prevent the deadlock.
891 * We also need to avoid dlopen() as that would trigger the recursion
892 * into malloc_init(), so we use dlsym(RTLD_NEXT), until we reached
893 * swrap_constructor() or any real socket call at that time
894 * swrap_bind_symbol_all() will replace the function pointer again after
897 if (uwrap_handle_syscall
) {
898 uwrap_bind_symbol_all();
899 } else if (uwrap
.libc
.symbols
._libc_syscall
.obj
== NULL
) {
900 uwrap
.libc
.symbols
._libc_syscall
.obj
= dlsym(RTLD_NEXT
,
904 for (i
= 0; i
< 8; i
++) {
905 args
[i
] = va_arg(va
, long int);
908 rc
= uwrap
.libc
.symbols
._libc_syscall
.f(sysno
,
921 static bool uwrap_swrap_syscall_valid(long int sysno
)
923 uwrap_bind_symbol_all();
925 if (uwrap
.rtld_default
.symbols
._rtld_default_socket_wrapper_syscall_valid
.f
== NULL
) {
929 return uwrap
.rtld_default
.symbols
._rtld_default_socket_wrapper_syscall_valid
.f(
933 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
934 static long int uwrap_swrap_syscall_va(long int sysno
, va_list va
)
936 uwrap_bind_symbol_all();
938 if (uwrap
.rtld_default
.symbols
._rtld_default_socket_wrapper_syscall_va
.f
== NULL
) {
940 * Fallback to libc, if socket_wrapper_vsyscall is not
943 return libc_vsyscall(sysno
, va
);
946 return uwrap
.rtld_default
.symbols
._rtld_default_socket_wrapper_syscall_va
.f(
952 static int libpthread_pthread_create(pthread_t
*thread
,
953 const pthread_attr_t
*attr
,
954 void *(*start_routine
) (void *),
957 uwrap_bind_symbol_all();
958 return uwrap
.libpthread
.symbols
._libpthread_pthread_create
.f(thread
,
965 * This part is "optimistic".
966 * Thread can ends without pthread_exit call.
968 static void libpthread_pthread_exit(void *retval
)
970 uwrap_bind_symbol_all();
972 uwrap
.libpthread
.symbols
._libpthread_pthread_exit
.f(retval
);
975 static void uwrap_pthread_exit(void *retval
)
977 struct uwrap_thread
*id
= uwrap_tls_id
;
979 UWRAP_LOG(UWRAP_LOG_DEBUG
, "Cleanup thread");
981 UWRAP_LOCK(uwrap_id
);
983 UWRAP_UNLOCK(uwrap_id
);
984 libpthread_pthread_exit(retval
);
988 UWRAP_DLIST_REMOVE(uwrap
.ids
, id
);
989 SAFE_FREE(id
->groups
);
993 UWRAP_UNLOCK(uwrap_id
);
995 libpthread_pthread_exit(retval
);
998 void pthread_exit(void *retval
)
1000 if (!uid_wrapper_enabled()) {
1001 libpthread_pthread_exit(retval
);
1004 uwrap_pthread_exit(retval
);
1006 /* Calm down gcc warning. */
1010 struct uwrap_pthread_create_args
{
1011 struct uwrap_thread
*id
;
1012 void *(*start_routine
) (void *);
1016 static void *uwrap_pthread_create_start(void *_a
)
1018 struct uwrap_pthread_create_args
*a
=
1019 (struct uwrap_pthread_create_args
*)_a
;
1020 void *(*start_routine
) (void *) = a
->start_routine
;
1022 struct uwrap_thread
*id
= a
->id
;
1028 return start_routine(arg
);
1031 static int uwrap_pthread_create(pthread_t
*thread
,
1032 const pthread_attr_t
*attr
,
1033 void *(*start_routine
) (void *),
1036 struct uwrap_pthread_create_args
*args
;
1037 struct uwrap_thread
*src_id
= uwrap_tls_id
;
1040 args
= malloc(sizeof(struct uwrap_pthread_create_args
));
1042 UWRAP_LOG(UWRAP_LOG_ERROR
,
1043 "uwrap_pthread_create: Unable to allocate memory");
1047 args
->start_routine
= start_routine
;
1050 args
->id
= calloc(1, sizeof(struct uwrap_thread
));
1051 if (args
->id
== NULL
) {
1053 UWRAP_LOG(UWRAP_LOG_ERROR
,
1054 "uwrap_pthread_create: Unable to allocate memory");
1059 UWRAP_LOCK(uwrap_id
);
1061 args
->id
->groups
= calloc(src_id
->ngroups
, sizeof(gid_t
));
1062 if (args
->id
->groups
== NULL
) {
1063 UWRAP_UNLOCK(uwrap_id
);
1064 SAFE_FREE(args
->id
);
1066 UWRAP_LOG(UWRAP_LOG_ERROR
,
1067 "uwrap_pthread_create: Unable to allocate memory again");
1072 args
->id
->ruid
= src_id
->ruid
;
1073 args
->id
->euid
= src_id
->euid
;
1074 args
->id
->suid
= src_id
->suid
;
1076 args
->id
->rgid
= src_id
->rgid
;
1077 args
->id
->egid
= src_id
->egid
;
1078 args
->id
->sgid
= src_id
->sgid
;
1080 args
->id
->enabled
= src_id
->enabled
;
1082 args
->id
->ngroups
= src_id
->ngroups
;
1083 if (src_id
->groups
!= NULL
) {
1084 memcpy(args
->id
->groups
, src_id
->groups
,
1085 sizeof(gid_t
) * src_id
->ngroups
);
1087 SAFE_FREE(args
->id
->groups
);
1090 UWRAP_DLIST_ADD(uwrap
.ids
, args
->id
);
1091 UWRAP_UNLOCK(uwrap_id
);
1093 ret
= libpthread_pthread_create(thread
, attr
,
1094 uwrap_pthread_create_start
,
1103 int pthread_create(pthread_t
*thread
,
1104 const pthread_attr_t
*attr
,
1105 void *(*start_routine
) (void *),
1108 if (!uid_wrapper_enabled()) {
1109 return libpthread_pthread_create(thread
,
1115 return uwrap_pthread_create(thread
,
1121 /*********************************************************
1123 *********************************************************/
1125 #define GROUP_STRING_SIZE 16384
1126 #define GROUP_MAX_COUNT (GROUP_STRING_SIZE / (10 + 1))
1129 * This function exports all the IDs of the current user so if
1130 * we fork and then exec we can setup uid_wrapper in the new process
1133 static void uwrap_export_ids(struct uwrap_thread
*id
)
1135 char groups_str
[GROUP_STRING_SIZE
] = {0};
1136 size_t groups_str_size
= sizeof(groups_str
);
1137 char unsigned_str
[16] = {0}; /* We need 10 + 1 (+ 1) */
1141 snprintf(unsigned_str
, sizeof(unsigned_str
), "%u", id
->ruid
);
1142 setenv("UID_WRAPPER_INITIAL_RUID", unsigned_str
, 1);
1144 snprintf(unsigned_str
, sizeof(unsigned_str
), "%u", id
->euid
);
1145 setenv("UID_WRAPPER_INITIAL_EUID", unsigned_str
, 1);
1147 snprintf(unsigned_str
, sizeof(unsigned_str
), "%u", id
->suid
);
1148 setenv("UID_WRAPPER_INITIAL_SUID", unsigned_str
, 1);
1151 snprintf(unsigned_str
, sizeof(unsigned_str
), "%u", id
->rgid
);
1152 setenv("UID_WRAPPER_INITIAL_RGID", unsigned_str
, 1);
1154 snprintf(unsigned_str
, sizeof(unsigned_str
), "%u", id
->egid
);
1155 setenv("UID_WRAPPER_INITIAL_EGID", unsigned_str
, 1);
1157 snprintf(unsigned_str
, sizeof(unsigned_str
), "%u", id
->sgid
);
1158 setenv("UID_WRAPPER_INITIAL_SGID", unsigned_str
, 1);
1160 if (id
->ngroups
> GROUP_MAX_COUNT
) {
1161 UWRAP_LOG(UWRAP_LOG_ERROR
,
1162 "ERROR: Number of groups (%u) exceeds maximum value "
1163 "uid_wrapper can handle (%u).",
1170 for (i
= 0; i
< id
->ngroups
; i
++) {
1171 size_t groups_str_len
= strlen(groups_str
);
1172 size_t groups_str_avail
= groups_str_size
- groups_str_len
- 1;
1175 len
= snprintf(unsigned_str
, sizeof(unsigned_str
), ",%u", id
->groups
[i
]);
1177 UWRAP_LOG(UWRAP_LOG_ERROR
,
1178 "snprintf failed for groups[%d]=%u",
1183 if (((size_t)len
) >= groups_str_avail
) {
1184 UWRAP_LOG(UWRAP_LOG_ERROR
,
1185 "groups env string is to small for %d groups",
1190 len
= snprintf(groups_str
+ groups_str_len
,
1191 groups_str_size
- groups_str_len
,
1193 i
== 0 ? unsigned_str
+ 1 : unsigned_str
);
1195 UWRAP_LOG(UWRAP_LOG_ERROR
,
1196 "snprintf failed to create groups string at groups[%d]=%u",
1203 if (id
->ngroups
== i
) {
1204 setenv("UID_WRAPPER_INITIAL_GROUPS", groups_str
, 1);
1206 snprintf(unsigned_str
, sizeof(unsigned_str
), "%u", id
->ngroups
);
1207 setenv("UID_WRAPPER_INITIAL_GROUPS_COUNT", unsigned_str
, 1);
1211 static void uwrap_thread_prepare(void)
1213 struct uwrap_thread
*id
= uwrap_tls_id
;
1216 * We bind all symbols to avoid deadlocks of the fork is interrupted by
1217 * a signal handler using a symbol of this library.
1219 uwrap_bind_symbol_all();
1223 /* uid_wrapper is loaded but not enabled */
1229 * What happens if another atfork prepare functions calls a uwrap
1230 * function? So disable it in case another atfork prepare function
1231 * calls a (s)uid function. We disable uid_wrapper only for thread
1232 * (process) which called fork.
1234 id
->enabled
= false;
1237 static void uwrap_thread_parent(void)
1239 struct uwrap_thread
*id
= uwrap_tls_id
;
1241 /* uid_wrapper is loaded but not enabled */
1252 static void uwrap_thread_child(void)
1254 struct uwrap_thread
*id
= uwrap_tls_id
;
1255 struct uwrap_thread
*u
= uwrap
.ids
;
1259 /* uid_wrapper is loaded but not enabled */
1265 * "Garbage collector" - Inspired by DESTRUCTOR.
1266 * All threads (except one which called fork()) are dead now.. Dave
1267 * That's what posix said...
1271 /* Skip this item. */
1272 u
= uwrap
.ids
->next
;
1276 UWRAP_DLIST_REMOVE(uwrap
.ids
, u
);
1278 SAFE_FREE(u
->groups
);
1284 uwrap_export_ids(id
);
1289 static unsigned long uwrap_get_xid_from_env(const char *envname
)
1292 const char *env
= NULL
;
1295 env
= getenv(envname
);
1300 if (env
[0] == '\0') {
1305 xid
= strtoul(env
, &endp
, 10);
1315 * This initializes uid_wrapper with the IDs exported to the environment. Those
1316 * are normally set after we forked and executed.
1318 static void uwrap_init_env(struct uwrap_thread
*id
)
1325 xid
= uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_RUID");
1326 if (xid
!= ULONG_MAX
) {
1327 id
->ruid
= (uid_t
)xid
;
1330 xid
= uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_EUID");
1331 if (xid
!= ULONG_MAX
) {
1332 id
->euid
= (uid_t
)xid
;
1335 xid
= uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_SUID");
1336 if (xid
!= ULONG_MAX
) {
1337 id
->suid
= (uid_t
)xid
;
1341 xid
= uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_RGID");
1342 if (xid
!= ULONG_MAX
) {
1343 id
->rgid
= (gid_t
)xid
;
1346 xid
= uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_EGID");
1347 if (xid
!= ULONG_MAX
) {
1348 id
->egid
= (gid_t
)xid
;
1351 xid
= uwrap_get_xid_from_env("UID_WRAPPER_INITIAL_SGID");
1352 if (xid
!= ULONG_MAX
) {
1353 id
->sgid
= (gid_t
)xid
;
1356 env
= getenv("UID_WRAPPER_INITIAL_GROUPS_COUNT");
1357 if (env
!= NULL
&& env
[0] != '\0') {
1361 n
= strtol(env
, &endp
, 10);
1364 } else if (n
> 0 && n
< GROUP_MAX_COUNT
) {
1367 unsetenv("UID_WRAPPER_INITIAL_GROUPS_COUNT");
1376 id
->groups
= calloc(ngroups
, sizeof(gid_t
));
1377 if (id
->groups
== NULL
) {
1378 UWRAP_LOG(UWRAP_LOG_ERROR
,
1379 "Unable to allocate memory");
1383 env
= getenv("UID_WRAPPER_INITIAL_GROUPS");
1384 if (env
!= NULL
&& env
[0] != '\0') {
1385 char *groups_str
= NULL
;
1386 char *saveptr
= NULL
;
1387 const char *p
= NULL
;
1389 groups_str
= strdup(env
);
1390 if (groups_str
== NULL
) {
1394 p
= strtok_r(groups_str
, ",", &saveptr
);
1396 id
->groups
[i
] = strtol(p
, (char **)NULL
, 10);
1399 p
= strtok_r(NULL
, ",", &saveptr
);
1401 SAFE_FREE(groups_str
);
1405 UWRAP_LOG(UWRAP_LOG_ERROR
,
1406 "ERROR: The number of groups (%u) passed, "
1407 "does not match the number of groups (%u) "
1414 UWRAP_LOG(UWRAP_LOG_DEBUG
, "Initialize groups with %s", env
);
1415 id
->ngroups
= ngroups
;
1419 static void uwrap_init(void)
1423 UWRAP_LOCK(uwrap_id
);
1425 if (uwrap
.initialised
) {
1426 struct uwrap_thread
*id
= uwrap_tls_id
;
1428 if (uwrap
.ids
== NULL
) {
1429 UWRAP_UNLOCK(uwrap_id
);
1434 UWRAP_LOG(UWRAP_LOG_ERROR
,
1435 "Invalid id for thread");
1439 UWRAP_UNLOCK(uwrap_id
);
1443 UWRAP_LOG(UWRAP_LOG_DEBUG
, "Initialize uid_wrapper");
1445 uwrap
.initialised
= true;
1447 env
= getenv("UID_WRAPPER");
1448 if (env
!= NULL
&& env
[0] == '1') {
1449 const char *root
= getenv("UID_WRAPPER_ROOT");
1450 struct uwrap_thread
*id
;
1452 id
= calloc(1, sizeof(struct uwrap_thread
));
1454 UWRAP_LOG(UWRAP_LOG_ERROR
,
1455 "Unable to allocate memory for main id");
1459 UWRAP_DLIST_ADD(uwrap
.ids
, id
);
1462 uwrap
.myuid
= libc_geteuid();
1463 uwrap
.mygid
= libc_getegid();
1465 /* put us in one group */
1466 if (root
!= NULL
&& root
[0] == '1') {
1467 id
->ruid
= id
->euid
= id
->suid
= 0;
1468 id
->rgid
= id
->egid
= id
->sgid
= 0;
1470 id
->groups
= malloc(sizeof(gid_t
) * 1);
1471 if (id
->groups
== NULL
) {
1472 UWRAP_LOG(UWRAP_LOG_ERROR
,
1473 "Unable to allocate memory");
1481 id
->ruid
= id
->euid
= id
->suid
= uwrap
.myuid
;
1482 id
->rgid
= id
->egid
= id
->sgid
= uwrap
.mygid
;
1484 id
->ngroups
= libc_getgroups(0, NULL
);
1485 if (id
->ngroups
== -1) {
1486 UWRAP_LOG(UWRAP_LOG_ERROR
,
1487 "Unable to call libc_getgroups in uwrap_init.");
1490 id
->groups
= malloc(sizeof(gid_t
) * id
->ngroups
);
1491 if (id
->groups
== NULL
) {
1492 UWRAP_LOG(UWRAP_LOG_ERROR
, "Unable to allocate memory");
1495 if (libc_getgroups(id
->ngroups
, id
->groups
) == -1) {
1496 UWRAP_LOG(UWRAP_LOG_ERROR
,
1497 "Unable to call libc_getgroups again in uwrap_init.");
1500 * Deallocation of uwrap.groups is handled by
1501 * library destructor.
1511 UWRAP_LOG(UWRAP_LOG_DEBUG
,
1512 "Enabled uid_wrapper as %s (real uid=%u)",
1513 id
->ruid
== 0 ? "root" : "user",
1514 (unsigned int)uwrap
.myuid
);
1517 UWRAP_UNLOCK(uwrap_id
);
1519 UWRAP_LOG(UWRAP_LOG_DEBUG
, "Successfully initialized uid_wrapper");
1522 bool uid_wrapper_enabled(void)
1524 struct uwrap_thread
*id
= uwrap_tls_id
;
1531 UWRAP_LOCK(uwrap_id
);
1532 enabled
= id
->enabled
;
1533 UWRAP_UNLOCK(uwrap_id
);
1539 * UWRAP_SETxUID FUNCTIONS
1542 static int uwrap_setresuid_args(uid_t ruid
, uid_t euid
, uid_t suid
)
1544 struct uwrap_thread
*id
= uwrap_tls_id
;
1546 UWRAP_LOG(UWRAP_LOG_TRACE
,
1547 "ruid %d -> %d, euid %d -> %d, suid %d -> %d",
1548 id
->ruid
, ruid
, id
->euid
, euid
, id
->suid
, suid
);
1550 if (id
->euid
!= 0) {
1551 if (ruid
!= (uid_t
)-1 &&
1558 if (euid
!= (uid_t
)-1 &&
1565 if (suid
!= (uid_t
)-1 &&
1577 static int uwrap_setresuid_thread(uid_t ruid
, uid_t euid
, uid_t suid
)
1579 struct uwrap_thread
*id
= uwrap_tls_id
;
1582 UWRAP_LOG(UWRAP_LOG_TRACE
,
1583 "ruid %d -> %d, euid %d -> %d, suid %d -> %d",
1584 id
->ruid
, ruid
, id
->euid
, euid
, id
->suid
, suid
);
1586 rc
= uwrap_setresuid_args(ruid
, euid
, suid
);
1591 UWRAP_LOCK(uwrap_id
);
1593 if (ruid
!= (uid_t
)-1) {
1597 if (euid
!= (uid_t
)-1) {
1601 if (suid
!= (uid_t
)-1) {
1605 UWRAP_UNLOCK(uwrap_id
);
1610 static int uwrap_setresuid(uid_t ruid
, uid_t euid
, uid_t suid
)
1612 struct uwrap_thread
*id
= uwrap_tls_id
;
1615 UWRAP_LOG(UWRAP_LOG_TRACE
,
1616 "ruid %d -> %d, euid %d -> %d, suid %d -> %d",
1617 id
->ruid
, ruid
, id
->euid
, euid
, id
->suid
, suid
);
1619 rc
= uwrap_setresuid_args(ruid
, euid
, suid
);
1624 UWRAP_LOCK(uwrap_id
);
1626 for (id
= uwrap
.ids
; id
; id
= id
->next
) {
1627 if (ruid
!= (uid_t
)-1) {
1631 if (euid
!= (uid_t
)-1) {
1635 if (suid
!= (uid_t
)-1) {
1640 UWRAP_UNLOCK(uwrap_id
);
1645 static int uwrap_setreuid_args(uid_t ruid
, uid_t euid
,
1650 struct uwrap_thread
*id
= uwrap_tls_id
;
1651 uid_t new_ruid
= -1, new_euid
= -1, new_suid
= -1;
1653 UWRAP_LOG(UWRAP_LOG_TRACE
,
1654 "ruid %d -> %d, euid %d -> %d",
1655 id
->ruid
, ruid
, id
->euid
, euid
);
1657 if (ruid
!= (uid_t
)-1) {
1659 if (ruid
!= id
->ruid
&&
1667 if (euid
!= (uid_t
)-1) {
1669 if (euid
!= id
->ruid
&&
1678 if (ruid
!= (uid_t
) -1 ||
1679 (euid
!= (uid_t
)-1 && id
->ruid
!= euid
)) {
1680 new_suid
= new_euid
;
1683 *_new_ruid
= new_ruid
;
1684 *_new_euid
= new_euid
;
1685 *_new_suid
= new_suid
;
1690 static int uwrap_setreuid_thread(uid_t ruid
, uid_t euid
)
1692 struct uwrap_thread
*id
= uwrap_tls_id
;
1693 uid_t new_ruid
= -1, new_euid
= -1, new_suid
= -1;
1696 UWRAP_LOG(UWRAP_LOG_TRACE
,
1697 "ruid %d -> %d, euid %d -> %d",
1698 id
->ruid
, ruid
, id
->euid
, euid
);
1700 rc
= uwrap_setreuid_args(ruid
, euid
, &new_ruid
, &new_euid
, &new_suid
);
1705 return uwrap_setresuid_thread(new_ruid
, new_euid
, new_suid
);
1708 #ifdef HAVE_SETREUID
1709 static int uwrap_setreuid(uid_t ruid
, uid_t euid
)
1711 struct uwrap_thread
*id
= uwrap_tls_id
;
1712 uid_t new_ruid
= -1, new_euid
= -1, new_suid
= -1;
1715 UWRAP_LOG(UWRAP_LOG_TRACE
,
1716 "ruid %d -> %d, euid %d -> %d",
1717 id
->ruid
, ruid
, id
->euid
, euid
);
1719 rc
= uwrap_setreuid_args(ruid
, euid
, &new_ruid
, &new_euid
, &new_suid
);
1724 return uwrap_setresuid(new_ruid
, new_euid
, new_suid
);
1728 static int uwrap_setuid_args(uid_t uid
,
1733 struct uwrap_thread
*id
= uwrap_tls_id
;
1735 UWRAP_LOG(UWRAP_LOG_TRACE
,
1739 if (uid
== (uid_t
)-1) {
1744 if (id
->euid
== 0) {
1745 *new_suid
= *new_ruid
= uid
;
1746 } else if (uid
!= id
->ruid
&&
1757 static int uwrap_setuid_thread(uid_t uid
)
1759 uid_t new_ruid
= -1, new_euid
= -1, new_suid
= -1;
1762 rc
= uwrap_setuid_args(uid
, &new_ruid
, &new_euid
, &new_suid
);
1767 return uwrap_setresuid_thread(new_ruid
, new_euid
, new_suid
);
1770 static int uwrap_setuid(uid_t uid
)
1772 uid_t new_ruid
= -1, new_euid
= -1, new_suid
= -1;
1775 rc
= uwrap_setuid_args(uid
, &new_ruid
, &new_euid
, &new_suid
);
1780 return uwrap_setresuid(new_ruid
, new_euid
, new_suid
);
1784 * UWRAP_GETxUID FUNCTIONS
1787 #ifdef HAVE_GETRESUID
1788 static int uwrap_getresuid(uid_t
*ruid
, uid_t
*euid
, uid_t
*suid
)
1790 struct uwrap_thread
*id
= uwrap_tls_id
;
1792 UWRAP_LOCK(uwrap_id
);
1798 UWRAP_UNLOCK(uwrap_id
);
1804 #ifdef HAVE_GETRESGID
1805 static int uwrap_getresgid(gid_t
*rgid
, gid_t
*egid
, gid_t
*sgid
)
1807 struct uwrap_thread
*id
= uwrap_tls_id
;
1809 UWRAP_LOCK(uwrap_id
);
1815 UWRAP_UNLOCK(uwrap_id
);
1822 * UWRAP_SETxGID FUNCTIONS
1825 static int uwrap_setresgid_args(gid_t rgid
, gid_t egid
, gid_t sgid
)
1827 struct uwrap_thread
*id
= uwrap_tls_id
;
1829 UWRAP_LOG(UWRAP_LOG_TRACE
,
1830 "rgid %d -> %d, egid %d -> %d, sgid %d -> %d",
1831 id
->rgid
, rgid
, id
->egid
, egid
, id
->sgid
, sgid
);
1833 if (id
->euid
!= 0) {
1834 if (rgid
!= (gid_t
)-1 &&
1841 if (egid
!= (gid_t
)-1 &&
1848 if (sgid
!= (gid_t
)-1 &&
1860 static int uwrap_setresgid_thread(gid_t rgid
, gid_t egid
, gid_t sgid
)
1862 struct uwrap_thread
*id
= uwrap_tls_id
;
1865 UWRAP_LOG(UWRAP_LOG_TRACE
,
1866 "rgid %d -> %d, egid %d -> %d, sgid %d -> %d",
1867 id
->rgid
, rgid
, id
->egid
, egid
, id
->sgid
, sgid
);
1869 rc
= uwrap_setresgid_args(rgid
, egid
, sgid
);
1874 UWRAP_LOCK(uwrap_id
);
1876 if (rgid
!= (gid_t
)-1) {
1880 if (egid
!= (gid_t
)-1) {
1884 if (sgid
!= (gid_t
)-1) {
1888 UWRAP_UNLOCK(uwrap_id
);
1893 static int uwrap_setresgid(gid_t rgid
, gid_t egid
, gid_t sgid
)
1895 struct uwrap_thread
*id
= uwrap_tls_id
;
1898 UWRAP_LOG(UWRAP_LOG_TRACE
,
1899 "rgid %d -> %d, egid %d -> %d, sgid %d -> %d",
1900 id
->rgid
, rgid
, id
->egid
, egid
, id
->sgid
, sgid
);
1902 rc
= uwrap_setresgid_args(rgid
, egid
, sgid
);
1907 UWRAP_LOCK(uwrap_id
);
1909 for (id
= uwrap
.ids
; id
; id
= id
->next
) {
1910 if (rgid
!= (gid_t
)-1) {
1914 if (egid
!= (gid_t
)-1) {
1918 if (sgid
!= (gid_t
)-1) {
1923 UWRAP_UNLOCK(uwrap_id
);
1928 static int uwrap_setregid_args(gid_t rgid
, gid_t egid
,
1933 struct uwrap_thread
*id
= uwrap_tls_id
;
1934 gid_t new_rgid
= -1, new_egid
= -1, new_sgid
= -1;
1936 UWRAP_LOG(UWRAP_LOG_TRACE
,
1937 "rgid %d -> %d, egid %d -> %d",
1938 id
->rgid
, rgid
, id
->egid
, egid
);
1940 if (rgid
!= (gid_t
)-1) {
1942 if (rgid
!= id
->rgid
&&
1950 if (egid
!= (gid_t
)-1) {
1952 if (egid
!= id
->rgid
&&
1961 if (rgid
!= (gid_t
) -1 ||
1962 (egid
!= (gid_t
)-1 && id
->rgid
!= egid
)) {
1963 new_sgid
= new_egid
;
1966 *_new_rgid
= new_rgid
;
1967 *_new_egid
= new_egid
;
1968 *_new_sgid
= new_sgid
;
1973 static int uwrap_setregid_thread(gid_t rgid
, gid_t egid
)
1975 struct uwrap_thread
*id
= uwrap_tls_id
;
1976 gid_t new_rgid
= -1, new_egid
= -1, new_sgid
= -1;
1979 UWRAP_LOG(UWRAP_LOG_TRACE
,
1980 "rgid %d -> %d, egid %d -> %d",
1981 id
->rgid
, rgid
, id
->egid
, egid
);
1983 rc
= uwrap_setregid_args(rgid
, egid
, &new_rgid
, &new_egid
, &new_sgid
);
1988 return uwrap_setresgid_thread(new_rgid
, new_egid
, new_sgid
);
1991 #ifdef HAVE_SETREGID
1992 static int uwrap_setregid(gid_t rgid
, gid_t egid
)
1994 struct uwrap_thread
*id
= uwrap_tls_id
;
1995 gid_t new_rgid
= -1, new_egid
= -1, new_sgid
= -1;
1998 UWRAP_LOG(UWRAP_LOG_TRACE
,
1999 "rgid %d -> %d, egid %d -> %d",
2000 id
->rgid
, rgid
, id
->egid
, egid
);
2002 rc
= uwrap_setregid_args(rgid
, egid
, &new_rgid
, &new_egid
, &new_sgid
);
2007 return uwrap_setresgid(new_rgid
, new_egid
, new_sgid
);
2011 static int uwrap_setgid_args(gid_t gid
,
2016 struct uwrap_thread
*id
= uwrap_tls_id
;
2018 UWRAP_LOG(UWRAP_LOG_TRACE
,
2022 if (gid
== (gid_t
)-1) {
2027 if (id
->euid
== 0) {
2028 *new_sgid
= *new_rgid
= gid
;
2029 } else if (gid
!= id
->rgid
&&
2040 static int uwrap_setgid_thread(gid_t gid
)
2042 gid_t new_rgid
= -1, new_egid
= -1, new_sgid
= -1;
2045 rc
= uwrap_setgid_args(gid
, &new_rgid
, &new_egid
, &new_sgid
);
2050 return uwrap_setresgid_thread(new_rgid
, new_egid
, new_sgid
);
2053 static int uwrap_setgid(gid_t gid
)
2055 gid_t new_rgid
= -1, new_egid
= -1, new_sgid
= -1;
2058 rc
= uwrap_setgid_args(gid
, &new_rgid
, &new_egid
, &new_sgid
);
2063 return uwrap_setresgid(new_rgid
, new_egid
, new_sgid
);
2069 int setuid(uid_t uid
)
2071 if (!uid_wrapper_enabled()) {
2072 return libc_setuid(uid
);
2076 return uwrap_setuid(uid
);
2080 int seteuid(uid_t euid
)
2082 if (!uid_wrapper_enabled()) {
2083 return libc_seteuid(euid
);
2086 /* On FreeBSD the uid_t -1 is set and doesn't produce and error */
2087 if (euid
== (uid_t
)-1) {
2093 return uwrap_setresuid(-1, euid
, -1);
2097 #ifdef HAVE_SETREUID
2098 int setreuid(uid_t ruid
, uid_t euid
)
2100 if (!uid_wrapper_enabled()) {
2101 return libc_setreuid(ruid
, euid
);
2105 return uwrap_setreuid(ruid
, euid
);
2109 #ifdef HAVE_SETRESUID
2110 int setresuid(uid_t ruid
, uid_t euid
, uid_t suid
)
2112 if (!uid_wrapper_enabled()) {
2113 return libc_setresuid(ruid
, euid
, suid
);
2117 return uwrap_setresuid(ruid
, euid
, suid
);
2121 #ifdef HAVE_GETRESUID
2122 int getresuid(uid_t
*ruid
, uid_t
*euid
, uid_t
*suid
)
2124 if (!uid_wrapper_enabled()) {
2125 return libc_getresuid(ruid
, euid
, suid
);
2129 return uwrap_getresuid(ruid
, euid
, suid
);
2136 static uid_t
uwrap_getuid(void)
2138 struct uwrap_thread
*id
= uwrap_tls_id
;
2141 UWRAP_LOCK(uwrap_id
);
2143 UWRAP_UNLOCK(uwrap_id
);
2150 if (!uid_wrapper_enabled()) {
2151 return libc_getuid();
2155 return uwrap_getuid();
2161 static uid_t
uwrap_geteuid(void)
2163 const char *env
= getenv("UID_WRAPPER_MYUID");
2164 struct uwrap_thread
*id
= uwrap_tls_id
;
2167 UWRAP_LOCK(uwrap_id
);
2169 UWRAP_UNLOCK(uwrap_id
);
2171 /* Disable root and return myuid */
2172 if (env
!= NULL
&& env
[0] == '1') {
2181 if (!uid_wrapper_enabled()) {
2182 return libc_geteuid();
2186 return uwrap_geteuid();
2192 int setgid(gid_t gid
)
2194 if (!uid_wrapper_enabled()) {
2195 return libc_setgid(gid
);
2199 return uwrap_setgid(gid
);
2203 int setegid(gid_t egid
)
2205 if (!uid_wrapper_enabled()) {
2206 return libc_setegid(egid
);
2209 /* On FreeBSD the uid_t -1 is set and doesn't produce and error */
2210 if (egid
== (gid_t
)-1) {
2216 return uwrap_setresgid(-1, egid
, -1);
2220 #ifdef HAVE_SETREGID
2221 int setregid(gid_t rgid
, gid_t egid
)
2223 if (!uid_wrapper_enabled()) {
2224 return libc_setregid(rgid
, egid
);
2228 return uwrap_setregid(rgid
, egid
);
2232 #ifdef HAVE_SETRESGID
2233 int setresgid(gid_t rgid
, gid_t egid
, gid_t sgid
)
2235 if (!uid_wrapper_enabled()) {
2236 return libc_setresgid(rgid
, egid
, sgid
);
2240 return uwrap_setresgid(rgid
, egid
, sgid
);
2244 #ifdef HAVE_GETRESGID
2245 int getresgid(gid_t
*rgid
, gid_t
*egid
, gid_t
*sgid
)
2247 if (!uid_wrapper_enabled()) {
2248 return libc_getresgid(rgid
, egid
, sgid
);
2252 return uwrap_getresgid(rgid
, egid
, sgid
);
2259 static gid_t
uwrap_getgid(void)
2261 struct uwrap_thread
*id
= uwrap_tls_id
;
2264 UWRAP_LOCK(uwrap_id
);
2266 UWRAP_UNLOCK(uwrap_id
);
2273 if (!uid_wrapper_enabled()) {
2274 return libc_getgid();
2278 return uwrap_getgid();
2284 static uid_t
uwrap_getegid(void)
2286 struct uwrap_thread
*id
= uwrap_tls_id
;
2289 UWRAP_LOCK(uwrap_id
);
2291 UWRAP_UNLOCK(uwrap_id
);
2298 if (!uid_wrapper_enabled()) {
2299 return libc_getegid();
2303 return uwrap_getegid();
2306 static int uwrap_setgroups_thread(size_t size
, const gid_t
*list
)
2308 struct uwrap_thread
*id
= uwrap_tls_id
;
2311 UWRAP_LOCK(uwrap_id
);
2314 SAFE_FREE(id
->groups
);
2316 } else if (size
> 0) {
2319 tmp
= realloc(id
->groups
, sizeof(gid_t
) * size
);
2326 memcpy(id
->groups
, list
, size
* sizeof(gid_t
));
2331 UWRAP_UNLOCK(uwrap_id
);
2336 static int uwrap_setgroups(size_t size
, const gid_t
*list
)
2338 struct uwrap_thread
*id
;
2341 UWRAP_LOCK(uwrap_id
);
2344 for (id
= uwrap
.ids
; id
; id
= id
->next
) {
2345 SAFE_FREE(id
->groups
);
2349 } else if (size
> 0) {
2352 for (id
= uwrap
.ids
; id
; id
= id
->next
) {
2353 tmp
= realloc(id
->groups
, sizeof(gid_t
) * size
);
2361 memcpy(id
->groups
, list
, size
* sizeof(gid_t
));
2367 UWRAP_UNLOCK(uwrap_id
);
2372 #ifdef HAVE_SETGROUPS_INT
2373 int setgroups(int size
, const gid_t
*list
)
2375 int setgroups(size_t size
, const gid_t
*list
)
2378 if (!uid_wrapper_enabled()) {
2379 return libc_setgroups(size
, list
);
2383 return uwrap_setgroups(size
, list
);
2386 static int uwrap_getgroups(int size
, gid_t
*list
)
2388 struct uwrap_thread
*id
= uwrap_tls_id
;
2391 UWRAP_LOCK(uwrap_id
);
2392 ngroups
= id
->ngroups
;
2394 if (size
> ngroups
) {
2400 if (size
< ngroups
) {
2404 memcpy(list
, id
->groups
, size
* sizeof(gid_t
));
2407 UWRAP_UNLOCK(uwrap_id
);
2412 int getgroups(int size
, gid_t
*list
)
2414 if (!uid_wrapper_enabled()) {
2415 return libc_getgroups(size
, list
);
2419 return uwrap_getgroups(size
, list
);
2422 #ifdef HAVE___GETGROUPS_CHK
2423 static int uwrap___getgroups_chk(int size
, gid_t
*list
, size_t listlen
)
2425 if (size
* sizeof(gid_t
) > listlen
) {
2426 UWRAP_LOG(UWRAP_LOG_DEBUG
, "Buffer overflow detected");
2430 return uwrap_getgroups(size
, list
);
2433 int __getgroups_chk(int size
, gid_t
*list
, size_t listlen
);
2435 int __getgroups_chk(int size
, gid_t
*list
, size_t listlen
)
2437 if (!uid_wrapper_enabled()) {
2438 return libc___getgroups_chk(size
, list
, listlen
);
2442 return uwrap___getgroups_chk(size
, list
, listlen
);
2444 #endif /* HAVE___GETGROUPS_CHK */
2446 #if (defined(HAVE_SYS_SYSCALL_H) || defined(HAVE_SYSCALL_H)) \
2447 && (defined(SYS_setreuid) || defined(SYS_setreuid32))
2448 static bool uwrap_is_uwrap_related_syscall(long int sysno
)
2459 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2466 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2470 #endif /* SYS_getegid */
2473 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2479 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2480 case SYS_setregid32
:
2483 #ifdef SYS_setresgid
2486 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2487 case SYS_setresgid32
:
2490 #endif /* SYS_setresgid */
2491 #if defined(SYS_getresgid) && defined(HAVE_GETRESGID)
2494 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2495 case SYS_getresgid32
:
2498 #endif /* SYS_getresgid && HAVE_GETRESGID */
2508 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2515 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2519 #endif /* SYS_geteuid */
2522 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2528 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2529 case SYS_setreuid32
:
2532 #ifdef SYS_setresuid
2535 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2536 case SYS_setresuid32
:
2539 #endif /* SYS_setresuid */
2540 #if defined(SYS_getresuid) && defined(HAVE_GETRESUID)
2543 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2544 case SYS_getresuid32
:
2547 #endif /* SYS_getresuid && HAVE_GETRESUID*/
2551 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2552 case SYS_setgroups32
:
2560 static long int uwrap_syscall (long int sysno
, va_list vp
)
2571 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2575 rc
= uwrap_getgid();
2580 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2584 rc
= uwrap_getegid();
2587 #endif /* SYS_getegid */
2589 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2593 gid_t gid
= (gid_t
) va_arg(vp
, gid_t
);
2595 rc
= uwrap_setgid_thread(gid
);
2599 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2600 case SYS_setregid32
:
2603 gid_t rgid
= (gid_t
) va_arg(vp
, gid_t
);
2604 gid_t egid
= (gid_t
) va_arg(vp
, gid_t
);
2606 rc
= uwrap_setregid_thread(rgid
, egid
);
2609 #ifdef SYS_setresgid
2611 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2612 case SYS_setresgid32
:
2615 gid_t rgid
= (gid_t
) va_arg(vp
, gid_t
);
2616 gid_t egid
= (gid_t
) va_arg(vp
, gid_t
);
2617 gid_t sgid
= (gid_t
) va_arg(vp
, gid_t
);
2619 rc
= uwrap_setresgid_thread(rgid
, egid
, sgid
);
2622 #endif /* SYS_setresgid */
2623 #if defined(SYS_getresgid) && defined(HAVE_GETRESGID)
2625 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2626 case SYS_getresgid32
:
2629 gid_t
*rgid
= (gid_t
*) va_arg(vp
, gid_t
*);
2630 gid_t
*egid
= (gid_t
*) va_arg(vp
, gid_t
*);
2631 gid_t
*sgid
= (gid_t
*) va_arg(vp
, gid_t
*);
2633 rc
= uwrap_getresgid(rgid
, egid
, sgid
);
2636 #endif /* SYS_getresgid && HAVE_GETRESGID */
2644 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2648 rc
= uwrap_getuid();
2653 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2657 rc
= uwrap_geteuid();
2660 #endif /* SYS_geteuid */
2662 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2666 uid_t uid
= (uid_t
) va_arg(vp
, uid_t
);
2668 rc
= uwrap_setuid_thread(uid
);
2672 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2673 case SYS_setreuid32
:
2676 uid_t ruid
= (uid_t
) va_arg(vp
, uid_t
);
2677 uid_t euid
= (uid_t
) va_arg(vp
, uid_t
);
2679 rc
= uwrap_setreuid_thread(ruid
, euid
);
2682 #ifdef SYS_setresuid
2684 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2685 case SYS_setresuid32
:
2688 uid_t ruid
= (uid_t
) va_arg(vp
, uid_t
);
2689 uid_t euid
= (uid_t
) va_arg(vp
, uid_t
);
2690 uid_t suid
= (uid_t
) va_arg(vp
, uid_t
);
2692 rc
= uwrap_setresuid_thread(ruid
, euid
, suid
);
2695 #endif /* SYS_setresuid */
2696 #if defined(SYS_getresuid) && defined(HAVE_GETRESUID)
2698 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2699 case SYS_getresuid32
:
2702 uid_t
*ruid
= (uid_t
*) va_arg(vp
, uid_t
*);
2703 uid_t
*euid
= (uid_t
*) va_arg(vp
, uid_t
*);
2704 uid_t
*suid
= (uid_t
*) va_arg(vp
, uid_t
*);
2706 rc
= uwrap_getresuid(ruid
, euid
, suid
);
2709 #endif /* SYS_getresuid && HAVE_GETRESUID*/
2712 #ifdef HAVE_LINUX_32BIT_SYSCALLS
2713 case SYS_setgroups32
:
2716 size_t size
= (size_t) va_arg(vp
, size_t);
2717 gid_t
*list
= (gid_t
*) va_arg(vp
, int *);
2719 rc
= uwrap_setgroups_thread(size
, list
);
2732 #ifdef HAVE_SYSCALL_INT
2733 int syscall (int sysno
, ...)
2735 long int syscall (long int sysno
, ...)
2738 #ifdef HAVE_SYSCALL_INT
2745 va_start(va
, sysno
);
2750 * This is a workaround to prevent a deadlock in jemalloc calling
2751 * malloc_init() twice. The first allocation call will trigger a
2752 * malloc_init() of jemalloc. The functions calls syscall(SYS_open, ...)
2753 * so it goes to socket or uid wrapper. In this code path we need to
2754 * avoid any allocation calls. This will prevent the deadlock.
2756 if (!uwrap_handle_syscall
) {
2757 rc
= libc_vsyscall(sysno
, va
);
2763 * We need to check for uwrap related syscall numbers before calling
2764 * uid_wrapper_enabled() otherwise we'd deadlock during the freebsd libc
2765 * fork() which calls syscall() after invoking uwrap_thread_prepare().
2767 if (!uwrap_is_uwrap_related_syscall(sysno
)) {
2769 * We need to give socket_wrapper a
2770 * chance to take over...
2772 if (uwrap_swrap_syscall_valid(sysno
)) {
2773 rc
= uwrap_swrap_syscall_va(sysno
, va
);
2778 rc
= libc_vsyscall(sysno
, va
);
2783 if (!uid_wrapper_enabled()) {
2784 rc
= libc_vsyscall(sysno
, va
);
2790 rc
= uwrap_syscall(sysno
, va
);
2796 /* used by socket_wrapper */
2797 bool uid_wrapper_syscall_valid(long int sysno
);
2798 bool uid_wrapper_syscall_valid(long int sysno
)
2800 if (!uwrap_is_uwrap_related_syscall(sysno
)) {
2804 if (!uid_wrapper_enabled()) {
2811 /* used by socket_wrapper */
2812 long int uid_wrapper_syscall_va(long int sysno
, va_list va
);
2813 long int uid_wrapper_syscall_va(long int sysno
, va_list va
)
2815 if (!uwrap_is_uwrap_related_syscall(sysno
)) {
2820 if (!uid_wrapper_enabled()) {
2821 return libc_vsyscall(sysno
, va
);
2826 return uwrap_syscall(sysno
, va
);
2828 #endif /* HAVE_SYSCALL */
2829 #endif /* HAVE_SYS_SYSCALL_H || HAVE_SYSCALL_H */
2831 /****************************
2833 ***************************/
2835 void uwrap_constructor(void)
2837 char *glibc_malloc_lock_bug
;
2840 * This is a workaround for a bug in glibc < 2.24:
2842 * The child handler for the malloc() function is called and locks the
2843 * mutex. Then our child handler is called and we try to call setenv().
2844 * setenv() wants to malloc and tries to aquire the lock for malloc and
2845 * we end up in a deadlock.
2847 * So as a workaround we need to call malloc once before we setup the
2850 * See https://sourceware.org/bugzilla/show_bug.cgi?id=16742
2852 glibc_malloc_lock_bug
= malloc(1);
2853 if (glibc_malloc_lock_bug
== NULL
) {
2856 glibc_malloc_lock_bug
[0] = '\0';
2861 * If we hold a lock and the application forks, then the child
2862 * is not able to unlock the mutex and we are in a deadlock.
2863 * This should prevent such deadlocks.
2865 pthread_atfork(&uwrap_thread_prepare
,
2866 &uwrap_thread_parent
,
2867 &uwrap_thread_child
);
2869 free(glibc_malloc_lock_bug
);
2871 /* Here is safe place to call uwrap_init() and initialize data
2876 /* Let socket_wrapper handle syscall() */
2877 uwrap_handle_syscall
= true;
2880 /****************************
2882 ***************************/
2885 * This function is called when the library is unloaded and makes sure that
2886 * resources are freed.
2888 void uwrap_destructor(void)
2890 struct uwrap_thread
*u
= uwrap
.ids
;
2895 UWRAP_DLIST_REMOVE(uwrap
.ids
, u
);
2897 SAFE_FREE(u
->groups
);
2904 if (uwrap
.libc
.handle
!= NULL
2906 && uwrap
.libc
.handle
!= RTLD_NEXT
2909 dlclose(uwrap
.libc
.handle
);
2912 if (uwrap
.libpthread
.handle
!= NULL
2914 && uwrap
.libpthread
.handle
!= RTLD_NEXT
2917 dlclose(uwrap
.libpthread
.handle
);