uwrap: Prepare for overload of libpthread functions.
authorRobin Hack <hack.robin@gmail.com>
Fri, 23 Jan 2015 14:30:03 +0000 (15:30 +0100)
committerAndreas Schneider <asn@cryptomilk.org>
Wed, 28 Jan 2015 16:17:08 +0000 (17:17 +0100)
uwrap_bind_symbol are now renamed to uwrap_bind_symbol_libc
and simlilar uwrap_bind_symbol_libpthread are introduced.

Signed-off-by: Robin Hack <hack.robin@gmail.com>
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
lib/uid_wrapper/uid_wrapper.c

index b04e334cac51851c6c03de42913e9683673256aa..84ed83cec3ae5d8870c1bc6f777b643424581968 100644 (file)
 # 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)
 
@@ -281,6 +283,29 @@ struct uwrap_libc_symbols {
        UWRAP_SYMBOL_ENTRY(syscall);
 #endif
 };
+#undef UWRAP_SYMBOL_ENTRY
+
+/*****************
+ * LIBPTHREAD
+ *****************/
+/* Yeah... I'm pig. I overloading macro here... So what? */
+#define UWRAP_SYMBOL_ENTRY(i) \
+       union { \
+               __libpthread_##i f; \
+               void *obj; \
+       } _libpthread_##i
+
+typedef int (*__libpthread_pthread_create)(pthread_t *thread,
+                                   const pthread_attr_t *attr,
+                                   void *(*start_routine) (void *),
+                                   void *arg);
+typedef void (*__libpthread_pthread_exit)(void *retval);
+
+struct uwrap_libpthread_symbols {
+       UWRAP_SYMBOL_ENTRY(pthread_create);
+       UWRAP_SYMBOL_ENTRY(pthread_exit);
+};
+#undef UWRAP_SYMBOL_ENTRY
 
 /*
  * We keep the virtualised euid/egid/groups information here
@@ -312,6 +337,11 @@ struct uwrap {
                struct uwrap_libc_symbols symbols;
        } libc;
 
+       struct {
+               void *handle;
+               struct uwrap_libpthread_symbols symbols;
+       } libpthread;
+
        bool initialised;
        bool enabled;
 
@@ -344,6 +374,9 @@ 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;
 
+/* The mutex for accessing the global libpthread.symbols */
+static pthread_mutex_t libpthread_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
+
 /*********************************************************
  * UWRAP PROTOTYPES
  *********************************************************/
@@ -360,6 +393,7 @@ enum uwrap_lib {
     UWRAP_LIBC,
     UWRAP_LIBNSL,
     UWRAP_LIBSOCKET,
+    UWRAP_LIBPTHREAD,
 };
 
 static void *uwrap_load_lib_handle(enum uwrap_lib lib)
@@ -393,6 +427,15 @@ static void *uwrap_load_lib_handle(enum uwrap_lib lib)
                        uwrap.libc.handle = handle;
                }
                break;
+       case UWRAP_LIBPTHREAD:
+               handle = uwrap.libpthread.handle;
+               if (handle == NULL) {
+                       handle = dlopen("libpthread.so.0", flags);
+                       if (handle != NULL) {
+                               break;
+                       }
+               }
+               break;
        }
 
        if (handle == NULL) {
@@ -427,14 +470,22 @@ static void *_uwrap_bind_symbol(enum uwrap_lib lib, const char *fn_name)
        return func;
 }
 
-#define uwrap_bind_symbol(lib, sym_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(lib, #sym_name); \
+                       _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)
+
 /*
  * IMPORTANT
  *
@@ -445,14 +496,14 @@ static void *_uwrap_bind_symbol(enum uwrap_lib lib, const char *fn_name)
  */
 static int libc_setuid(uid_t uid)
 {
-       uwrap_bind_symbol(UWRAP_LIBC, setuid);
+       uwrap_bind_symbol_libc(setuid);
 
        return uwrap.libc.symbols._libc_setuid.f(uid);
 }
 
 static uid_t libc_getuid(void)
 {
-       uwrap_bind_symbol(UWRAP_LIBC, getuid);
+       uwrap_bind_symbol_libc(getuid);
 
        return uwrap.libc.symbols._libc_getuid.f();
 }
@@ -460,7 +511,7 @@ static uid_t libc_getuid(void)
 #ifdef HAVE_SETEUID
 static int libc_seteuid(uid_t euid)
 {
-       uwrap_bind_symbol(UWRAP_LIBC, seteuid);
+       uwrap_bind_symbol_libc(seteuid);
 
        return uwrap.libc.symbols._libc_seteuid.f(euid);
 }
@@ -469,7 +520,7 @@ static int libc_seteuid(uid_t euid)
 #ifdef HAVE_SETREUID
 static int libc_setreuid(uid_t ruid, uid_t euid)
 {
-       uwrap_bind_symbol(UWRAP_LIBC, setreuid);
+       uwrap_bind_symbol_libc(setreuid);
 
        return uwrap.libc.symbols._libc_setreuid.f(ruid, euid);
 }
@@ -478,7 +529,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(UWRAP_LIBC, setresuid);
+       uwrap_bind_symbol_libc(setresuid);
 
        return uwrap.libc.symbols._libc_setresuid.f(ruid, euid, suid);
 }
@@ -487,7 +538,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(UWRAP_LIBC, getresuid);
+       uwrap_bind_symbol_libc(getresuid);
 
        return uwrap.libc.symbols._libc_getresuid.f(ruid, euid, suid);
 }
@@ -495,21 +546,21 @@ static int libc_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
 
 static uid_t libc_geteuid(void)
 {
-       uwrap_bind_symbol(UWRAP_LIBC, geteuid);
+       uwrap_bind_symbol_libc(geteuid);
 
        return uwrap.libc.symbols._libc_geteuid.f();
 }
 
 static int libc_setgid(gid_t gid)
 {
-       uwrap_bind_symbol(UWRAP_LIBC, setgid);
+       uwrap_bind_symbol_libc(setgid);
 
        return uwrap.libc.symbols._libc_setgid.f(gid);
 }
 
 static gid_t libc_getgid(void)
 {
-       uwrap_bind_symbol(UWRAP_LIBC, getgid);
+       uwrap_bind_symbol_libc(getgid);
 
        return uwrap.libc.symbols._libc_getgid.f();
 }
@@ -517,7 +568,7 @@ static gid_t libc_getgid(void)
 #ifdef HAVE_SETEGID
 static int libc_setegid(gid_t egid)
 {
-       uwrap_bind_symbol(UWRAP_LIBC, setegid);
+       uwrap_bind_symbol_libc(setegid);
 
        return uwrap.libc.symbols._libc_setegid.f(egid);
 }
@@ -526,7 +577,7 @@ static int libc_setegid(gid_t egid)
 #ifdef HAVE_SETREGID
 static int libc_setregid(gid_t rgid, gid_t egid)
 {
-       uwrap_bind_symbol(UWRAP_LIBC, setregid);
+       uwrap_bind_symbol_libc(setregid);
 
        return uwrap.libc.symbols._libc_setregid.f(rgid, egid);
 }
@@ -535,7 +586,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(UWRAP_LIBC, setresgid);
+       uwrap_bind_symbol_libc(setresgid);
 
        return uwrap.libc.symbols._libc_setresgid.f(rgid, egid, sgid);
 }
@@ -544,7 +595,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(UWRAP_LIBC, setresgid);
+       uwrap_bind_symbol_libc(setresgid);
 
        return uwrap.libc.symbols._libc_getresgid.f(rgid, egid, sgid);
 }
@@ -552,21 +603,21 @@ static int libc_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
 
 static gid_t libc_getegid(void)
 {
-       uwrap_bind_symbol(UWRAP_LIBC, getegid);
+       uwrap_bind_symbol_libc(getegid);
 
        return uwrap.libc.symbols._libc_getegid.f();
 }
 
 static int libc_getgroups(int size, gid_t list[])
 {
-       uwrap_bind_symbol(UWRAP_LIBC, getgroups);
+       uwrap_bind_symbol_libc(getgroups);
 
        return uwrap.libc.symbols._libc_getgroups.f(size, list);
 }
 
 static int libc_setgroups(size_t size, const gid_t *list)
 {
-       uwrap_bind_symbol(UWRAP_LIBC, setgroups);
+       uwrap_bind_symbol_libc(setgroups);
 
        return uwrap.libc.symbols._libc_setgroups.f(size, list);
 }
@@ -579,7 +630,7 @@ static long int libc_vsyscall(long int sysno, va_list va)
        long int rc;
        int i;
 
-       uwrap_bind_symbol(UWRAP_LIBC, syscall);
+       uwrap_bind_symbol_libc(syscall);
 
        for (i = 0; i < 8; i++) {
                args[i] = va_arg(va, long int);
@@ -599,6 +650,72 @@ static long int libc_vsyscall(long int sysno, va_list va)
 }
 #endif
 
+/*
+ * 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.libpthread.symbols._libpthread_pthread_exit.f(retval);
+}
+
+static void uwrap_pthread_exit(void *retval)
+{
+       libpthread_pthread_exit(retval);
+}
+
+void pthread_exit(void *retval)
+{
+       if (!uid_wrapper_enabled()) {
+               libpthread_pthread_exit(retval);
+       };
+
+       uwrap_pthread_exit(retval);
+
+       /* Calm down gcc warning. */
+       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);
+}
+
+static int uwrap_pthread_create(pthread_t *thread,
+                                const pthread_attr_t *attr,
+                                void *(*start_routine) (void *),
+                                void *arg)
+{
+       return libpthread_pthread_create(thread, attr, start_routine, arg);
+}
+
+int pthread_create(pthread_t *thread,
+                   const pthread_attr_t *attr,
+                   void *(*start_routine) (void *),
+                   void *arg)
+{
+       if (!uid_wrapper_enabled()) {
+               return libpthread_pthread_create(thread,
+                                          attr,
+                                          start_routine,
+                                          arg);
+       };
+
+       return uwrap_pthread_create(thread,
+                                   attr,
+                                   start_routine,
+                                   arg);
+}
+
 /*********************************************************
  * UWRAP ID HANDLING
  *********************************************************/
@@ -1649,5 +1766,9 @@ void uwrap_destructor(void)
                dlclose(uwrap.libc.handle);
        }
 
+       if (uwrap.libpthread.handle != NULL) {
+               dlclose(uwrap.libpthread.handle);
+       }
+
        UWRAP_UNLOCK_ALL;
 }