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);
