Hello community,

here is the log from the commit of package uid_wrapper for openSUSE:Factory 
checked in at 2017-07-28 09:40:05
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/uid_wrapper (Old)
 and      /work/SRC/openSUSE:Factory/.uid_wrapper.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "uid_wrapper"

Fri Jul 28 09:40:05 2017 rev:7 rq:512450 version:1.2.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/uid_wrapper/uid_wrapper.changes  2017-07-17 
09:02:33.920547577 +0200
+++ /work/SRC/openSUSE:Factory/.uid_wrapper.new/uid_wrapper.changes     
2017-07-28 09:40:09.467517080 +0200
@@ -1,0 +2,15 @@
+Tue Jul 25 09:17:48 UTC 2017 - [email protected]
+
+- Update to version 1.2.4
+  * Added deadlock workaround for glibc < 2.24
+  * Fixed a possible deadlock bug if uid_wrapper is turned off
+
+-------------------------------------------------------------------
+Fri Jul 14 13:24:08 UTC 2017 - [email protected]
+
+- Update to version 1.2.3
+  * Logging is always turned on now
+  * Fixed a memory leak
+  * Limited number of groups during fork+exec
+
+-------------------------------------------------------------------

Old:
----
  uid_wrapper-1.2.2.tar.gz

New:
----
  uid_wrapper-1.2.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ uid_wrapper.spec ++++++
--- /var/tmp/diff_new_pack.O4qSXM/_old  2017-07-28 09:40:10.099428086 +0200
+++ /var/tmp/diff_new_pack.O4qSXM/_new  2017-07-28 09:40:10.103427523 +0200
@@ -24,7 +24,7 @@
 ############################# NOTE ##################################
 
 Name:           uid_wrapper
-Version:        1.2.2
+Version:        1.2.4
 Release:        0
 
 Summary:        A wrapper for privilege seperation

++++++ uid_wrapper-1.2.2.tar.gz -> uid_wrapper-1.2.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/uid_wrapper-1.2.2/CMakeLists.txt 
new/uid_wrapper-1.2.4/CMakeLists.txt
--- old/uid_wrapper-1.2.2/CMakeLists.txt        2017-07-13 08:41:33.000000000 
+0200
+++ new/uid_wrapper-1.2.4/CMakeLists.txt        2017-07-24 09:12:05.000000000 
+0200
@@ -8,7 +8,7 @@
 
 set(APPLICATION_VERSION_MAJOR "1")
 set(APPLICATION_VERSION_MINOR "2")
-set(APPLICATION_VERSION_PATCH "2")
+set(APPLICATION_VERSION_PATCH "4")
 
 set(APPLICATION_VERSION 
"${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/uid_wrapper-1.2.2/ChangeLog 
new/uid_wrapper-1.2.4/ChangeLog
--- old/uid_wrapper-1.2.2/ChangeLog     2017-07-13 08:41:33.000000000 +0200
+++ new/uid_wrapper-1.2.4/ChangeLog     2017-07-24 09:12:17.000000000 +0200
@@ -1,7 +1,16 @@
 ChangeLog
 ==========
 
-version 1.2.2 (released 2107-07-13)
+version 1.2.4 (released 2017-07-24)
+  * Added deadlock workaround for glibc < 2.24
+  * Fixed a possible deadlock bug if uid_wrapper is turned off
+
+version 1.2.3 (released 2017-07-14)
+  * Logging is always turned on now
+  * Fixed a memory leak
+  * Limited number of groups during fork+exec
+
+version 1.2.2 (released 2017-07-13)
   * Added support for fork'ed and then exec'ed processes
   * Added support for Alpha
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/uid_wrapper-1.2.2/src/uid_wrapper.c 
new/uid_wrapper-1.2.4/src/uid_wrapper.c
--- old/uid_wrapper-1.2.2/src/uid_wrapper.c     2017-07-13 08:41:33.000000000 
+0200
+++ new/uid_wrapper-1.2.4/src/uid_wrapper.c     2017-07-21 17:20:14.000000000 
+0200
@@ -133,9 +133,6 @@
        UWRAP_LOG_TRACE
 };
 
-#ifdef NDEBUG
-# define UWRAP_LOG(...)
-#else /* NDEBUG */
 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__)
 
@@ -145,42 +142,43 @@
        va_list va;
        const char *d;
        unsigned int lvl = 0;
+       const char *prefix = "UWRAP";
 
        d = getenv("UID_WRAPPER_DEBUGLEVEL");
        if (d != NULL) {
                lvl = atoi(d);
        }
 
+       if (lvl < dbglvl) {
+               return;
+       }
+
        va_start(va, format);
        vsnprintf(buffer, sizeof(buffer), format, va);
        va_end(va);
 
-       if (lvl >= dbglvl) {
-               const char *prefix = "UWRAP";
-               switch (dbglvl) {
-                       case UWRAP_LOG_ERROR:
-                               prefix = "UWRAP_ERROR";
-                               break;
-                       case UWRAP_LOG_WARN:
-                               prefix = "UWRAP_WARN";
-                               break;
-                       case UWRAP_LOG_DEBUG:
-                               prefix = "UWRAP_DEBUG";
-                               break;
-                       case UWRAP_LOG_TRACE:
-                               prefix = "UWRAP_TRACE";
-                               break;
-               }
-
-               fprintf(stderr,
-                       "%s(%d) - %s: %s\n",
-                       prefix,
-                       (int)getpid(),
-                       function,
-                       buffer);
+       switch (dbglvl) {
+               case UWRAP_LOG_ERROR:
+                       prefix = "UWRAP_ERROR";
+                       break;
+               case UWRAP_LOG_WARN:
+                       prefix = "UWRAP_WARN";
+                       break;
+               case UWRAP_LOG_DEBUG:
+                       prefix = "UWRAP_DEBUG";
+                       break;
+               case UWRAP_LOG_TRACE:
+                       prefix = "UWRAP_TRACE";
+                       break;
        }
+
+       fprintf(stderr,
+               "%s(%d) - %s: %s\n",
+               prefix,
+               (int)getpid(),
+               function,
+               buffer);
 }
-#endif /* NDEBUG */
 
 /*****************
  * LIBC
@@ -816,6 +814,7 @@
  *********************************************************/
 
 #define GROUP_STRING_SIZE 16384
+#define GROUP_MAX_COUNT (GROUP_STRING_SIZE / (10 + 1))
 
 /**
  * This function exports all the IDs of the current user so if
@@ -826,7 +825,7 @@
 {
        char groups_str[GROUP_STRING_SIZE] = {0};
        size_t groups_str_size = sizeof(groups_str);
-       char unsigned_str[32] = {0};
+       char unsigned_str[16] = {0}; /* We need 10 + 1 (+ 1) */
        int i;
 
        /* UIDS */
@@ -849,29 +848,54 @@
        snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->sgid);
        setenv("UID_WRAPPER_INITIAL_SGID", unsigned_str, 1);
 
-       /* GROUPS */
-       snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->ngroups);
-       setenv("UID_WRAPPER_INITIAL_GROUPS_COUNT", unsigned_str, 1);
+       if (id->ngroups > GROUP_MAX_COUNT) {
+               UWRAP_LOG(UWRAP_LOG_ERROR,
+                         "ERROR: Number of groups (%u) exceeds maximum value "
+                         "uid_wrapper can handle (%u).",
+                         id->ngroups,
+                         GROUP_MAX_COUNT);
+               exit(-1);
+       }
 
+       /* GROUPS */
        for (i = 0; i < id->ngroups; i++) {
                size_t groups_str_len = strlen(groups_str);
-               size_t groups_str_avail = groups_str_size - groups_str_len;
-               size_t len;
+               size_t groups_str_avail = groups_str_size - groups_str_len - 1;
+               int len;
 
                len = snprintf(unsigned_str, sizeof(unsigned_str), ",%u", 
id->groups[i]);
                if (len <= 1) {
-                       continue;
+                       UWRAP_LOG(UWRAP_LOG_ERROR,
+                                 "snprintf failed for groups[%d]=%u",
+                                 i,
+                                 id->groups[i]);
+                       break;
                }
-               if (len < groups_str_avail) {
-                       snprintf(groups_str + groups_str_len,
-                                groups_str_size - groups_str_len,
-                                "%s",
-                                i == 0 ? unsigned_str + 1 : unsigned_str);
+               if (((size_t)len) >= groups_str_avail) {
+                       UWRAP_LOG(UWRAP_LOG_ERROR,
+                                 "groups env string is to small for %d groups",
+                                 i);
+                       break;
+               }
+
+               len = snprintf(groups_str + groups_str_len,
+                              groups_str_size - groups_str_len,
+                              "%s",
+                              i == 0 ? unsigned_str + 1 : unsigned_str);
+               if (len < 1) {
+                       UWRAP_LOG(UWRAP_LOG_ERROR,
+                                 "snprintf failed to create groups string at 
groups[%d]=%u",
+                                 i,
+                                 id->groups[i]);
+                       break;
                }
        }
 
-       if (id->ngroups > 0) {
+       if (id->ngroups == i) {
                setenv("UID_WRAPPER_INITIAL_GROUPS", groups_str, 1);
+
+               snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->ngroups);
+               setenv("UID_WRAPPER_INITIAL_GROUPS_COUNT", unsigned_str, 1);
        }
 }
 
@@ -879,13 +903,13 @@
 {
        struct uwrap_thread *id = uwrap_tls_id;
 
+       UWRAP_LOCK_ALL;
+
        /* uid_wrapper is loaded but not enabled */
        if (id == NULL) {
                return;
        }
 
-       UWRAP_LOCK_ALL;
-
        /*
         * What happens if another atfork prepare functions calls a uwrap
         * function? So disable it in case another atfork prepare function
@@ -901,6 +925,7 @@
 
        /* uid_wrapper is loaded but not enabled */
        if (id == NULL) {
+               UWRAP_UNLOCK_ALL;
                return;
        }
 
@@ -916,11 +941,10 @@
 
        /* uid_wrapper is loaded but not enabled */
        if (id == NULL) {
+               UWRAP_UNLOCK_ALL;
                return;
        }
 
-       uwrap_export_ids(id);
-
        /*
         * "Garbage collector" - Inspired by DESTRUCTOR.
         * All threads (except one which called fork()) are dead now.. Dave
@@ -941,6 +965,8 @@
                u = uwrap.ids;
        }
 
+       uwrap_export_ids(id);
+
        id->enabled = true;
 
        UWRAP_UNLOCK_ALL;
@@ -1003,7 +1029,7 @@
                unsetenv("UID_WRAPPER_INITIAL_GROUPS_COUNT");
        }
 
-       if (ngroups > 0) {
+       if (ngroups > 0 && ngroups < GROUP_MAX_COUNT) {
                int i = 0;
 
                id->ngroups = 0;
@@ -1034,9 +1060,16 @@
 
                                p = strtok_r(NULL, ",", &saveptr);
                        }
+                       SAFE_FREE(groups_str);
                }
 
                if (i != ngroups) {
+                       UWRAP_LOG(UWRAP_LOG_ERROR,
+                                 "ERROR: The number of groups (%u) passed, "
+                                 "does not match the number of groups (%u) "
+                                 "we parsed.",
+                                 ngroups,
+                                 i);
                        exit(-1);
                }
 
@@ -1145,7 +1178,7 @@
 
        UWRAP_UNLOCK(uwrap_id);
 
-       UWRAP_LOG(UWRAP_LOG_DEBUG, "Succeccfully initialized uid_wrapper");
+       UWRAP_LOG(UWRAP_LOG_DEBUG, "Successfully initialized uid_wrapper");
 }
 
 bool uid_wrapper_enabled(void)
@@ -1318,9 +1351,7 @@
 
 static int uwrap_setreuid_thread(uid_t ruid, uid_t euid)
 {
-#ifndef NDEBUG
        struct uwrap_thread *id = uwrap_tls_id;
-#endif
        uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
        int rc;
 
@@ -1339,9 +1370,7 @@
 #ifdef HAVE_SETREUID
 static int uwrap_setreuid(uid_t ruid, uid_t euid)
 {
-#ifndef NDEBUG
        struct uwrap_thread *id = uwrap_tls_id;
-#endif
        uid_t new_ruid = -1, new_euid = -1, new_suid = -1;
        int rc;
 
@@ -1605,9 +1634,7 @@
 
 static int uwrap_setregid_thread(gid_t rgid, gid_t egid)
 {
-#ifndef NDEBUG
        struct uwrap_thread *id = uwrap_tls_id;
-#endif
        gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
        int rc;
 
@@ -1626,9 +1653,7 @@
 #ifdef HAVE_SETREGID
 static int uwrap_setregid(gid_t rgid, gid_t egid)
 {
-#ifndef NDEBUG
        struct uwrap_thread *id = uwrap_tls_id;
-#endif
        gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
        int rc;
 
@@ -2266,8 +2291,30 @@
 /****************************
  * CONSTRUCTOR
  ***************************/
+
 void uwrap_constructor(void)
 {
+       char *glibc_malloc_lock_bug;
+
+       /*
+        * This is a workaround for a bug in glibc < 2.24:
+        *
+        * The child handler for the malloc() function is called and locks the
+        * mutex. Then our child handler is called and we try to call setenv().
+        * setenv() wants to malloc and tries to aquire the lock for malloc and
+        * we end up in a deadlock.
+        *
+        * So as a workaround we need to call malloc once before we setup the
+        * handlers.
+        *
+        * See https://sourceware.org/bugzilla/show_bug.cgi?id=16742
+        */
+       glibc_malloc_lock_bug = malloc(1);
+       if (glibc_malloc_lock_bug == NULL) {
+               exit(-1);
+       }
+       glibc_malloc_lock_bug[0] = '\0';
+
        /*
        * 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.
@@ -2277,6 +2324,8 @@
                       &uwrap_thread_parent,
                       &uwrap_thread_child);
 
+       free(glibc_malloc_lock_bug);
+
        /* Here is safe place to call uwrap_init() and initialize data
         * for main process.
         */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/uid_wrapper-1.2.2/tests/test_fork_exec.c 
new/uid_wrapper-1.2.4/tests/test_fork_exec.c
--- old/uid_wrapper-1.2.2/tests/test_fork_exec.c        2017-07-13 
08:41:33.000000000 +0200
+++ new/uid_wrapper-1.2.4/tests/test_fork_exec.c        2017-07-21 
17:20:14.000000000 +0200
@@ -6,12 +6,15 @@
 #include <cmocka.h>
 
 #include <errno.h>
+#include <grp.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
 
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
+
 #define TEST_MOCK_EXECUTABLE "mock_exec_uid"
 
 static void test_uwrap_fork_exec(void **state)
@@ -19,6 +22,7 @@
        pid_t pid;
        int rc;
        uid_t cp_ruid, cp_euid, cp_suid;
+       gid_t glist[] = {0, 10000, 20000, 40000, 100000};
 
        (void)state; /* unused */
 
@@ -34,6 +38,9 @@
        rc = setgid(5000);
        assert_return_code(rc, errno);
 
+       rc = setgroups(ARRAY_SIZE(glist), glist);
+       assert_return_code(rc, errno);
+
        pid = fork();
        assert_return_code(pid, errno);
 


Reply via email to