summaryrefslogtreecommitdiff
path: root/third_party
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2023-01-16 22:14:03 +0100
committerStefan Metzmacher <metze@samba.org>2023-01-18 12:47:48 +0000
commit25aa870fed548805a8cf64037a01ce0c87c6a01f (patch)
treed8319d10a5cbca15485ec10e487a2e57cd90a432 /third_party
parent77110bc9e8a09ebefaa42eb4fd3a7449373fec9a (diff)
downloadsamba-25aa870fed548805a8cf64037a01ce0c87c6a01f.tar.gz
third_party: Update uid_wrapper to version 1.3.0
This is mainly needed in order to have some interaction with socket_wrapper 1.4.0 regarding the implementation of syscall(). Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org> Autobuild-User(master): Stefan Metzmacher <metze@samba.org> Autobuild-Date(master): Wed Jan 18 12:47:48 UTC 2023 on sn-devel-184
Diffstat (limited to 'third_party')
-rw-r--r--third_party/uid_wrapper/uid_wrapper.c600
1 files changed, 525 insertions, 75 deletions
diff --git a/third_party/uid_wrapper/uid_wrapper.c b/third_party/uid_wrapper/uid_wrapper.c
index 6e4a6da2f0d..5b6a82b8fef 100644
--- a/third_party/uid_wrapper/uid_wrapper.c
+++ b/third_party/uid_wrapper/uid_wrapper.c
@@ -44,25 +44,6 @@
# define UWRAP_THREAD
#endif
-# define UWRAP_LOCK(m) do { \
- pthread_mutex_lock(&( m ## _mutex)); \
-} while(0)
-
-# define UWRAP_UNLOCK(m) do { \
- pthread_mutex_unlock(&( m ## _mutex)); \
-} while(0)
-
-/* Add new global locks here please */
-# define UWRAP_LOCK_ALL \
- UWRAP_LOCK(uwrap_id); \
- UWRAP_LOCK(libc_symbol_binding); \
- UWRAP_LOCK(libpthread_symbol_binding)
-
-# define UWRAP_UNLOCK_ALL \
- UWRAP_UNLOCK(libpthread_symbol_binding); \
- UWRAP_UNLOCK(libc_symbol_binding); \
- UWRAP_UNLOCK(uwrap_id)
-
#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
#define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
#else
@@ -142,6 +123,19 @@ enum uwrap_dbglvl_e {
UWRAP_LOG_TRACE
};
+#ifndef HAVE_GETPROGNAME
+static const char *getprogname(void)
+{
+#if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
+ return program_invocation_short_name;
+#elif defined(HAVE_GETEXECNAME)
+ return getexecname();
+#else
+ return NULL;
+#endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
+}
+#endif /* HAVE_GETPROGNAME */
+
static void uwrap_log(enum uwrap_dbglvl_e dbglvl, const char *function, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
# define UWRAP_LOG(dbglvl, ...) uwrap_log((dbglvl), __func__, __VA_ARGS__)
@@ -152,6 +146,7 @@ static void uwrap_log(enum uwrap_dbglvl_e dbglvl, const char *function, const ch
const char *d;
unsigned int lvl = 0;
const char *prefix = "UWRAP";
+ const char *progname = getprogname();
d = getenv("UID_WRAPPER_DEBUGLEVEL");
if (d != NULL) {
@@ -181,9 +176,14 @@ static void uwrap_log(enum uwrap_dbglvl_e dbglvl, const char *function, const ch
break;
}
+ if (progname == NULL) {
+ progname = "<unknown>";
+ }
+
fprintf(stderr,
- "%s(%d) - %s: %s\n",
+ "%s[%s (%u)] - %s: %s\n",
prefix,
+ progname,
(int)getpid(),
function,
buffer);
@@ -240,6 +240,9 @@ typedef int (*__libc_getresgid)(gid_t *rgid, gid_t *egid, gid_t *sgid);
typedef gid_t (*__libc_getegid)(void);
typedef int (*__libc_getgroups)(int size, gid_t list[]);
+#ifdef HAVE___GETGROUPS_CHK
+typedef int (*__libc___getgroups_chk)(int size, gid_t list[], size_t listlen);
+#endif
typedef int (*__libc_setgroups)(size_t size, const gid_t *list);
@@ -285,6 +288,9 @@ struct uwrap_libc_symbols {
#endif
UWRAP_SYMBOL_ENTRY(getegid);
UWRAP_SYMBOL_ENTRY(getgroups);
+#ifdef HAVE___GETGROUPS_CHK
+ UWRAP_SYMBOL_ENTRY(__getgroups_chk);
+#endif
UWRAP_SYMBOL_ENTRY(setgroups);
#ifdef HAVE_SYSCALL
UWRAP_SYMBOL_ENTRY(syscall);
@@ -292,6 +298,28 @@ struct uwrap_libc_symbols {
};
#undef UWRAP_SYMBOL_ENTRY
+#define UWRAP_SYMBOL_ENTRY(i) \
+ union { \
+ __rtld_default_##i f; \
+ void *obj; \
+ } _rtld_default_##i
+
+#ifdef HAVE_SYSCALL
+typedef bool (*__rtld_default_socket_wrapper_syscall_valid)(long int sysno);
+typedef long int (*__rtld_default_socket_wrapper_syscall_va)(long int sysno,
+ va_list va);
+#endif
+
+struct uwrap_rtld_default_symbols {
+#ifdef HAVE_SYSCALL
+ UWRAP_SYMBOL_ENTRY(socket_wrapper_syscall_valid);
+ UWRAP_SYMBOL_ENTRY(socket_wrapper_syscall_va);
+#else
+ uint8_t dummy;
+#endif
+};
+#undef UWRAP_SYMBOL_ENTRY
+
/*****************
* LIBPTHREAD
*****************/
@@ -342,6 +370,10 @@ struct uwrap {
} libc;
struct {
+ struct uwrap_rtld_default_symbols symbols;
+ } rtld_default;
+
+ struct {
void *handle;
struct uwrap_libpthread_symbols symbols;
} libpthread;
@@ -363,18 +395,127 @@ static UWRAP_THREAD struct uwrap_thread *uwrap_tls_id;
/* The mutex or accessing the id */
static pthread_mutex_t uwrap_id_mutex = PTHREAD_MUTEX_INITIALIZER;
-/* The mutex for accessing the global libc.symbols */
-static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
+#define uwrap_init_mutex(m) _uwrap_init_mutex(m, #m)
+static int _uwrap_init_mutex(pthread_mutex_t *m, const char *name)
+{
+ pthread_mutexattr_t ma;
+ bool need_destroy = false;
+ int ret = 0;
+
+#define __CHECK(cmd) \
+ do { \
+ ret = cmd; \
+ if (ret != 0) { \
+ UWRAP_LOG(UWRAP_LOG_ERROR, \
+ "%s: %s - failed %d", \
+ name, \
+ #cmd, \
+ ret); \
+ goto done; \
+ } \
+ } while (0)
+
+ *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
+ __CHECK(pthread_mutexattr_init(&ma));
+ need_destroy = true;
+ __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK));
+ __CHECK(pthread_mutex_init(m, &ma));
+done:
+ if (need_destroy) {
+ pthread_mutexattr_destroy(&ma);
+ }
+ return ret;
+}
+
+#define uwrap_mutex_lock(m) _uwrap_mutex_lock(m, #m, __func__, __LINE__)
+static void _uwrap_mutex_lock(pthread_mutex_t *mutex,
+ const char *name,
+ const char *caller,
+ unsigned line)
+{
+ int ret;
-/* The mutex for accessing the global libpthread.symbols */
-static pthread_mutex_t libpthread_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
+ ret = pthread_mutex_lock(mutex);
+ if (ret != 0) {
+ UWRAP_LOG(UWRAP_LOG_ERROR,
+ "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread "
+ "mutex(%s) - %s",
+ getpid(),
+ getppid(),
+ caller,
+ line,
+ name,
+ strerror(ret));
+ abort();
+ }
+}
+
+#define uwrap_mutex_unlock(m) _uwrap_mutex_unlock(m, #m, __func__, __LINE__)
+static void _uwrap_mutex_unlock(pthread_mutex_t *mutex,
+ const char *name,
+ const char *caller,
+ unsigned line)
+{
+ int ret;
+
+ ret = pthread_mutex_unlock(mutex);
+ if (ret != 0) {
+ UWRAP_LOG(UWRAP_LOG_ERROR,
+ "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread "
+ "mutex(%s) - %s",
+ getpid(),
+ getppid(),
+ caller,
+ line,
+ name,
+ strerror(ret));
+ abort();
+ }
+}
+
+#define UWRAP_LOCK(m) \
+ do { \
+ uwrap_mutex_lock(&(m##_mutex)); \
+ } while (0)
+
+#define UWRAP_UNLOCK(m) \
+ do { \
+ uwrap_mutex_unlock(&(m##_mutex)); \
+ } while (0)
+
+/* Add new global locks here please */
+#define UWRAP_REINIT_ALL \
+ do { \
+ int ret; \
+ ret = uwrap_init_mutex(&uwrap_id_mutex); \
+ if (ret != 0) \
+ exit(-1); \
+ } while (0)
+
+/* Add new global locks here please */
+#define UWRAP_LOCK_ALL \
+ do { \
+ UWRAP_LOCK(uwrap_id); \
+ } while (0)
+
+#define UWRAP_UNLOCK_ALL \
+ do { \
+ UWRAP_UNLOCK(uwrap_id); \
+ } while (0)
/*********************************************************
* UWRAP PROTOTYPES
*********************************************************/
bool uid_wrapper_enabled(void);
+#if ! defined(HAVE_CONSTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_INIT)
+/* xlC and other oldschool compilers support (only) this */
+#pragma init (uwrap_constructor)
+#endif
void uwrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
+#if ! defined(HAVE_DESTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_FINI)
+#pragma fini (uwrap_destructor)
+#endif
void uwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
/*********************************************************
@@ -383,8 +524,6 @@ void uwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
enum uwrap_lib {
UWRAP_LIBC,
- UWRAP_LIBNSL,
- UWRAP_LIBSOCKET,
UWRAP_LIBPTHREAD,
};
@@ -417,8 +556,6 @@ static void *uwrap_load_lib_handle(enum uwrap_lib lib)
#endif
switch (lib) {
- case UWRAP_LIBNSL:
- case UWRAP_LIBSOCKET:
case UWRAP_LIBC:
handle = uwrap.libc.handle;
if (handle == NULL) {
@@ -445,7 +582,16 @@ static void *uwrap_load_lib_handle(enum uwrap_lib lib)
case UWRAP_LIBPTHREAD:
handle = uwrap.libpthread.handle;
if (handle == NULL) {
+#ifdef RTLD_NEXT
+ /*
+ * Because thread sanatizer also overloads
+ * pthread_create() and pthread_exit() we need use
+ * RTLD_NEXT instead of libpthread.so.0
+ */
+ handle = uwrap.libpthread.handle = RTLD_NEXT;
+#else
handle = dlopen("libpthread.so.0", flags);
+#endif
if (handle != NULL) {
break;
}
@@ -455,7 +601,14 @@ static void *uwrap_load_lib_handle(enum uwrap_lib lib)
if (handle == NULL) {
#ifdef RTLD_NEXT
- handle = uwrap.libc.handle = RTLD_NEXT;
+ switch (lib) {
+ case UWRAP_LIBC:
+ handle = uwrap.libc.handle = RTLD_NEXT;
+ break;
+ case UWRAP_LIBPTHREAD:
+ handle = uwrap.libpthread.handle = RTLD_NEXT;
+ break;
+ }
#else
fprintf(stderr,
"Failed to dlopen library: %s\n",
@@ -486,20 +639,74 @@ static void *_uwrap_bind_symbol(enum uwrap_lib lib, const char *fn_name)
}
#define uwrap_bind_symbol_libc(sym_name) \
- UWRAP_LOCK(libc_symbol_binding); \
if (uwrap.libc.symbols._libc_##sym_name.obj == NULL) { \
uwrap.libc.symbols._libc_##sym_name.obj = \
_uwrap_bind_symbol(UWRAP_LIBC, #sym_name); \
- } \
- UWRAP_UNLOCK(libc_symbol_binding)
+ }
#define uwrap_bind_symbol_libpthread(sym_name) \
- UWRAP_LOCK(libpthread_symbol_binding); \
if (uwrap.libpthread.symbols._libpthread_##sym_name.obj == NULL) { \
uwrap.libpthread.symbols._libpthread_##sym_name.obj = \
_uwrap_bind_symbol(UWRAP_LIBPTHREAD, #sym_name); \
- } \
- UWRAP_UNLOCK(libpthread_symbol_binding)
+ }
+
+#define uwrap_bind_symbol_rtld_default_optional(sym_name) \
+ if (uwrap.rtld_default.symbols._rtld_default_##sym_name.obj == NULL) { \
+ uwrap.rtld_default.symbols._rtld_default_##sym_name.obj = \
+ dlsym(RTLD_DEFAULT, #sym_name); \
+ }
+
+/* DO NOT call this function during library initialization! */
+static void __uwrap_bind_symbol_all_once(void)
+{
+ uwrap_bind_symbol_libc(setuid);
+ uwrap_bind_symbol_libc(getuid);
+#ifdef HAVE_SETEUID
+ uwrap_bind_symbol_libc(seteuid);
+#endif
+#ifdef HAVE_SETREUID
+ uwrap_bind_symbol_libc(setreuid);
+#endif
+#ifdef HAVE_SETRESUID
+ uwrap_bind_symbol_libc(setresuid);
+#endif
+#ifdef HAVE_GETRESUID
+ uwrap_bind_symbol_libc(getresuid);
+#endif
+ uwrap_bind_symbol_libc(geteuid);
+ uwrap_bind_symbol_libc(setgid);
+ uwrap_bind_symbol_libc(getgid);
+#ifdef HAVE_SETEGID
+ uwrap_bind_symbol_libc(setegid);
+#endif
+#ifdef HAVE_SETREGID
+ uwrap_bind_symbol_libc(setregid);
+#endif
+
+#ifdef HAVE_SETRESGID
+ uwrap_bind_symbol_libc(setresgid);
+#endif
+#ifdef HAVE_GETRESGID
+ uwrap_bind_symbol_libc(setresgid);
+#endif
+ uwrap_bind_symbol_libc(getegid);
+ uwrap_bind_symbol_libc(getgroups);
+ uwrap_bind_symbol_libc(setgroups);
+#ifdef HAVE_SYSCALL
+ uwrap_bind_symbol_libc(syscall);
+ uwrap_bind_symbol_rtld_default_optional(socket_wrapper_syscall_valid);
+ uwrap_bind_symbol_rtld_default_optional(socket_wrapper_syscall_va);
+#endif
+ uwrap_bind_symbol_libpthread(pthread_create);
+ uwrap_bind_symbol_libpthread(pthread_exit);
+}
+
+static void uwrap_bind_symbol_all(void)
+{
+ static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT;
+
+ pthread_once(&all_symbol_binding_once, __uwrap_bind_symbol_all_once);
+}
/*
* IMPORTANT
@@ -511,14 +718,14 @@ static void *_uwrap_bind_symbol(enum uwrap_lib lib, const char *fn_name)
*/
static int libc_setuid(uid_t uid)
{
- uwrap_bind_symbol_libc(setuid);
+ uwrap_bind_symbol_all();
return uwrap.libc.symbols._libc_setuid.f(uid);
}
static uid_t libc_getuid(void)
{
- uwrap_bind_symbol_libc(getuid);
+ uwrap_bind_symbol_all();
return uwrap.libc.symbols._libc_getuid.f();
}
@@ -526,7 +733,7 @@ static uid_t libc_getuid(void)
#ifdef HAVE_SETEUID
static int libc_seteuid(uid_t euid)
{
- uwrap_bind_symbol_libc(seteuid);
+ uwrap_bind_symbol_all();
return uwrap.libc.symbols._libc_seteuid.f(euid);
}
@@ -535,7 +742,7 @@ static int libc_seteuid(uid_t euid)
#ifdef HAVE_SETREUID
static int libc_setreuid(uid_t ruid, uid_t euid)
{
- uwrap_bind_symbol_libc(setreuid);
+ uwrap_bind_symbol_all();
return uwrap.libc.symbols._libc_setreuid.f(ruid, euid);
}
@@ -544,7 +751,7 @@ static int libc_setreuid(uid_t ruid, uid_t euid)
#ifdef HAVE_SETRESUID
static int libc_setresuid(uid_t ruid, uid_t euid, uid_t suid)
{
- uwrap_bind_symbol_libc(setresuid);
+ uwrap_bind_symbol_all();
return uwrap.libc.symbols._libc_setresuid.f(ruid, euid, suid);
}
@@ -553,7 +760,7 @@ static int libc_setresuid(uid_t ruid, uid_t euid, uid_t suid)
#ifdef HAVE_GETRESUID
static int libc_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
{
- uwrap_bind_symbol_libc(getresuid);
+ uwrap_bind_symbol_all();
return uwrap.libc.symbols._libc_getresuid.f(ruid, euid, suid);
}
@@ -561,21 +768,21 @@ static int libc_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
static uid_t libc_geteuid(void)
{
- uwrap_bind_symbol_libc(geteuid);
+ uwrap_bind_symbol_all();
return uwrap.libc.symbols._libc_geteuid.f();
}
static int libc_setgid(gid_t gid)
{
- uwrap_bind_symbol_libc(setgid);
+ uwrap_bind_symbol_all();
return uwrap.libc.symbols._libc_setgid.f(gid);
}
static gid_t libc_getgid(void)
{
- uwrap_bind_symbol_libc(getgid);
+ uwrap_bind_symbol_all();
return uwrap.libc.symbols._libc_getgid.f();
}
@@ -583,7 +790,7 @@ static gid_t libc_getgid(void)
#ifdef HAVE_SETEGID
static int libc_setegid(gid_t egid)
{
- uwrap_bind_symbol_libc(setegid);
+ uwrap_bind_symbol_all();
return uwrap.libc.symbols._libc_setegid.f(egid);
}
@@ -592,7 +799,7 @@ static int libc_setegid(gid_t egid)
#ifdef HAVE_SETREGID
static int libc_setregid(gid_t rgid, gid_t egid)
{
- uwrap_bind_symbol_libc(setregid);
+ uwrap_bind_symbol_all();
return uwrap.libc.symbols._libc_setregid.f(rgid, egid);
}
@@ -601,7 +808,7 @@ static int libc_setregid(gid_t rgid, gid_t egid)
#ifdef HAVE_SETRESGID
static int libc_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
{
- uwrap_bind_symbol_libc(setresgid);
+ uwrap_bind_symbol_all();
return uwrap.libc.symbols._libc_setresgid.f(rgid, egid, sgid);
}
@@ -610,7 +817,7 @@ static int libc_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
#ifdef HAVE_GETRESGID
static int libc_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
{
- uwrap_bind_symbol_libc(setresgid);
+ uwrap_bind_symbol_all();
return uwrap.libc.symbols._libc_getresgid.f(rgid, egid, sgid);
}
@@ -618,21 +825,32 @@ static int libc_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
static gid_t libc_getegid(void)
{
- uwrap_bind_symbol_libc(getegid);
+ uwrap_bind_symbol_all();
return uwrap.libc.symbols._libc_getegid.f();
}
static int libc_getgroups(int size, gid_t list[])
{
- uwrap_bind_symbol_libc(getgroups);
+ uwrap_bind_symbol_all();
return uwrap.libc.symbols._libc_getgroups.f(size, list);
}
+#ifdef HAVE___GETGROUPS_CHK
+static int libc___getgroups_chk(int size, gid_t list[], size_t listlen)
+{
+ uwrap_bind_symbol_libc(__getgroups_chk);
+
+ return uwrap.libc.symbols._libc___getgroups_chk.f(size,
+ list,
+ listlen);
+}
+#endif /* HAVE___GETGROUPS_CHK */
+
static int libc_setgroups(size_t size, const gid_t *list)
{
- uwrap_bind_symbol_libc(setgroups);
+ uwrap_bind_symbol_all();
return uwrap.libc.symbols._libc_setgroups.f(size, list);
}
@@ -645,7 +863,7 @@ static long int libc_vsyscall(long int sysno, va_list va)
long int rc;
int i;
- uwrap_bind_symbol_libc(syscall);
+ uwrap_bind_symbol_all();
for (i = 0; i < 8; i++) {
args[i] = va_arg(va, long int);
@@ -663,15 +881,57 @@ static long int libc_vsyscall(long int sysno, va_list va)
return rc;
}
+
+static bool uwrap_swrap_syscall_valid(long int sysno)
+{
+ uwrap_bind_symbol_all();
+
+ if (uwrap.rtld_default.symbols._rtld_default_socket_wrapper_syscall_valid.f == NULL) {
+ return false;
+ }
+
+ return uwrap.rtld_default.symbols._rtld_default_socket_wrapper_syscall_valid.f(
+ sysno);
+}
+
+DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
+static long int uwrap_swrap_syscall_va(long int sysno, va_list va)
+{
+ uwrap_bind_symbol_all();
+
+ if (uwrap.rtld_default.symbols._rtld_default_socket_wrapper_syscall_va.f == NULL) {
+ /*
+ * Fallback to libc, if socket_wrapper_vsyscall is not
+ * available.
+ */
+ return libc_vsyscall(sysno, va);
+ }
+
+ return uwrap.rtld_default.symbols._rtld_default_socket_wrapper_syscall_va.f(
+ sysno,
+ va);
+}
#endif
+static int libpthread_pthread_create(pthread_t *thread,
+ const pthread_attr_t *attr,
+ void *(*start_routine) (void *),
+ void *arg)
+{
+ uwrap_bind_symbol_all();
+ return uwrap.libpthread.symbols._libpthread_pthread_create.f(thread,
+ attr,
+ start_routine,
+ arg);
+}
+
/*
* This part is "optimistic".
* Thread can ends without pthread_exit call.
*/
static void libpthread_pthread_exit(void *retval)
{
- uwrap_bind_symbol_libpthread(pthread_exit);
+ uwrap_bind_symbol_all();
uwrap.libpthread.symbols._libpthread_pthread_exit.f(retval);
}
@@ -711,18 +971,6 @@ void pthread_exit(void *retval)
exit(666);
}
-static int libpthread_pthread_create(pthread_t *thread,
- const pthread_attr_t *attr,
- void *(*start_routine) (void *),
- void *arg)
-{
- uwrap_bind_symbol_libpthread(pthread_create);
- return uwrap.libpthread.symbols._libpthread_pthread_create.f(thread,
- attr,
- start_routine,
- arg);
-}
-
struct uwrap_pthread_create_args {
struct uwrap_thread *id;
void *(*start_routine) (void *);
@@ -928,6 +1176,12 @@ static void uwrap_thread_prepare(void)
{
struct uwrap_thread *id = uwrap_tls_id;
+ /*
+ * We bind all symbols to avoid deadlocks of the fork is interrupted by
+ * a signal handler using a symbol of this library.
+ */
+ uwrap_bind_symbol_all();
+
UWRAP_LOCK_ALL;
/* uid_wrapper is loaded but not enabled */
@@ -964,9 +1218,10 @@ static void uwrap_thread_child(void)
struct uwrap_thread *id = uwrap_tls_id;
struct uwrap_thread *u = uwrap.ids;
+ UWRAP_REINIT_ALL;
+
/* uid_wrapper is loaded but not enabled */
if (id == NULL) {
- UWRAP_UNLOCK_ALL;
return;
}
@@ -993,8 +1248,6 @@ static void uwrap_thread_child(void)
uwrap_export_ids(id);
id->enabled = true;
-
- UWRAP_UNLOCK_ALL;
}
static unsigned long uwrap_get_xid_from_env(const char *envname)
@@ -2130,8 +2383,144 @@ int getgroups(int size, gid_t *list)
return uwrap_getgroups(size, list);
}
+#ifdef HAVE___GETGROUPS_CHK
+static int uwrap___getgroups_chk(int size, gid_t *list, size_t listlen)
+{
+ if (size * sizeof(gid_t) > listlen) {
+ UWRAP_LOG(UWRAP_LOG_DEBUG, "Buffer overflow detected");
+ abort();
+ }
+
+ return uwrap_getgroups(size, list);
+}
+
+int __getgroups_chk(int size, gid_t *list, size_t listlen);
+
+int __getgroups_chk(int size, gid_t *list, size_t listlen)
+{
+ if (!uid_wrapper_enabled()) {
+ return libc___getgroups_chk(size, list, listlen);
+ }
+
+ uwrap_init();
+ return uwrap___getgroups_chk(size, list, listlen);
+}
+#endif /* HAVE___GETGROUPS_CHK */
+
#if (defined(HAVE_SYS_SYSCALL_H) || defined(HAVE_SYSCALL_H)) \
&& (defined(SYS_setreuid) || defined(SYS_setreuid32))
+static bool uwrap_is_uwrap_related_syscall(long int sysno)
+{
+ switch (sysno) {
+ /* gid */
+#ifdef __alpha__
+ case SYS_getxgid:
+ return true;
+#else
+ case SYS_getgid:
+ return true;
+#endif
+#ifdef HAVE_LINUX_32BIT_SYSCALLS
+ case SYS_getgid32:
+ return true;
+#endif
+#ifdef SYS_getegid
+ case SYS_getegid:
+ return true;
+#ifdef HAVE_LINUX_32BIT_SYSCALLS
+ case SYS_getegid32:
+ return true;
+#endif
+#endif /* SYS_getegid */
+ case SYS_setgid:
+ return true;
+#ifdef HAVE_LINUX_32BIT_SYSCALLS
+ case SYS_setgid32:
+ return true;
+#endif
+ case SYS_setregid:
+ return true;
+#ifdef HAVE_LINUX_32BIT_SYSCALLS
+ case SYS_setregid32:
+ return true;
+#endif
+#ifdef SYS_setresgid
+ case SYS_setresgid:
+ return true;
+#ifdef HAVE_LINUX_32BIT_SYSCALLS
+ case SYS_setresgid32:
+ return true;
+#endif
+#endif /* SYS_setresgid */
+#if defined(SYS_getresgid) && defined(HAVE_GETRESGID)
+ case SYS_getresgid:
+ return true;
+#ifdef HAVE_LINUX_32BIT_SYSCALLS
+ case SYS_getresgid32:
+ return true;
+#endif
+#endif /* SYS_getresgid && HAVE_GETRESGID */
+
+ /* uid */
+#ifdef __alpha__
+ case SYS_getxuid:
+ return true;
+#else
+ case SYS_getuid:
+ return true;
+#endif
+#ifdef HAVE_LINUX_32BIT_SYSCALLS
+ case SYS_getuid32:
+ return true;
+#endif
+#ifdef SYS_geteuid
+ case SYS_geteuid:
+ return true;
+#ifdef HAVE_LINUX_32BIT_SYSCALLS
+ case SYS_geteuid32:
+ return true;
+#endif
+#endif /* SYS_geteuid */
+ case SYS_setuid:
+ return true;
+#ifdef HAVE_LINUX_32BIT_SYSCALLS
+ case SYS_setuid32:
+ return true;
+#endif
+ case SYS_setreuid:
+ return true;
+#ifdef HAVE_LINUX_32BIT_SYSCALLS
+ case SYS_setreuid32:
+ return true;
+#endif
+#ifdef SYS_setresuid
+ case SYS_setresuid:
+ return true;
+#ifdef HAVE_LINUX_32BIT_SYSCALLS
+ case SYS_setresuid32:
+ return true;
+#endif
+#endif /* SYS_setresuid */
+#if defined(SYS_getresuid) && defined(HAVE_GETRESUID)
+ case SYS_getresuid:
+ return true;
+#ifdef HAVE_LINUX_32BIT_SYSCALLS
+ case SYS_getresuid32:
+ return true;
+#endif
+#endif /* SYS_getresuid && HAVE_GETRESUID*/
+ /* groups */
+ case SYS_setgroups:
+ return true;
+#ifdef HAVE_LINUX_32BIT_SYSCALLS
+ case SYS_setgroups32:
+ return true;
+#endif
+ default:
+ return false;
+ }
+}
+
static long int uwrap_syscall (long int sysno, va_list vp)
{
long int rc;
@@ -2295,11 +2684,8 @@ static long int uwrap_syscall (long int sysno, va_list vp)
}
break;
default:
- UWRAP_LOG(UWRAP_LOG_DEBUG,
- "UID_WRAPPER calling non-wrapped syscall %lu",
- sysno);
-
- rc = libc_vsyscall(sysno, vp);
+ rc = -1;
+ errno = ENOSYS;
break;
}
@@ -2322,6 +2708,27 @@ long int syscall (long int sysno, ...)
va_start(va, sysno);
+ /*
+ * We need to check for uwrap related syscall numbers before calling
+ * uid_wrapper_enabled() otherwise we'd deadlock during the freebsd libc
+ * fork() which calls syscall() after invoking uwrap_thread_prepare().
+ */
+ if (!uwrap_is_uwrap_related_syscall(sysno)) {
+ /*
+ * We need to give socket_wrapper a
+ * chance to take over...
+ */
+ if (uwrap_swrap_syscall_valid(sysno)) {
+ rc = uwrap_swrap_syscall_va(sysno, va);
+ va_end(va);
+ return rc;
+ }
+
+ rc = libc_vsyscall(sysno, va);
+ va_end(va);
+ return rc;
+ }
+
if (!uid_wrapper_enabled()) {
rc = libc_vsyscall(sysno, va);
va_end(va);
@@ -2334,6 +2741,39 @@ long int syscall (long int sysno, ...)
return rc;
}
+
+/* used by socket_wrapper */
+bool uid_wrapper_syscall_valid(long int sysno);
+bool uid_wrapper_syscall_valid(long int sysno)
+{
+ if (!uwrap_is_uwrap_related_syscall(sysno)) {
+ return false;
+ }
+
+ if (!uid_wrapper_enabled()) {
+ return false;
+ }
+
+ return true;
+}
+
+/* used by socket_wrapper */
+long int uid_wrapper_syscall_va(long int sysno, va_list va);
+long int uid_wrapper_syscall_va(long int sysno, va_list va)
+{
+ if (!uwrap_is_uwrap_related_syscall(sysno)) {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ if (!uid_wrapper_enabled()) {
+ return libc_vsyscall(sysno, va);
+ }
+
+ uwrap_init();
+
+ return uwrap_syscall(sysno, va);
+}
#endif /* HAVE_SYSCALL */
#endif /* HAVE_SYS_SYSCALL_H || HAVE_SYSCALL_H */
@@ -2364,6 +2804,8 @@ void uwrap_constructor(void)
}
glibc_malloc_lock_bug[0] = '\0';
+ UWRAP_REINIT_ALL;
+
/*
* If we hold a lock and the application forks, then the child
* is not able to unlock the mutex and we are in a deadlock.
@@ -2405,11 +2847,19 @@ void uwrap_destructor(void)
}
- if (uwrap.libc.handle != NULL) {
+ if (uwrap.libc.handle != NULL
+#ifdef RTLD_NEXT
+ && uwrap.libc.handle != RTLD_NEXT
+#endif
+ ) {
dlclose(uwrap.libc.handle);
}
- if (uwrap.libpthread.handle != NULL) {
+ if (uwrap.libpthread.handle != NULL
+#ifdef RTLD_NEXT
+ && uwrap.libpthread.handle != RTLD_NEXT
+#endif
+ ) {
dlclose(uwrap.libpthread.handle);
}