uwrap: First do garbage collection before exporting ids
[uid_wrapper.git] / src / uid_wrapper.c
index a2ddd8b350c2379fb28375ae540938f7e39d3ebb..a48cc3bda275597cec8126c14446ef5e747e0f0d 100644 (file)
@@ -142,40 +142,42 @@ static void uwrap_log(enum uwrap_dbglvl_e dbglvl, const char *function, const ch
        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);
 }
 
 /*****************
@@ -823,7 +825,7 @@ static void uwrap_export_ids(struct uwrap_thread *id)
 {
        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,35 +851,51 @@ static void uwrap_export_ids(struct uwrap_thread *id)
        if (id->ngroups > GROUP_MAX_COUNT) {
                UWRAP_LOG(UWRAP_LOG_ERROR,
                          "ERROR: Number of groups (%u) exceeds maximum value "
-                         "uid_wrapper will handle (%u).",
+                         "uid_wrapper can handle (%u).",
                          id->ngroups,
                          GROUP_MAX_COUNT);
                exit(-1);
        }
 
        /* GROUPS */
-       snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->ngroups);
-       setenv("UID_WRAPPER_INITIAL_GROUPS_COUNT", unsigned_str, 1);
-
        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);
        }
 }
 
@@ -885,13 +903,13 @@ static void uwrap_thread_prepare(void)
 {
        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
@@ -907,6 +925,7 @@ static void uwrap_thread_parent(void)
 
        /* uid_wrapper is loaded but not enabled */
        if (id == NULL) {
+               UWRAP_UNLOCK_ALL;
                return;
        }
 
@@ -922,11 +941,10 @@ static void uwrap_thread_child(void)
 
        /* 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
@@ -947,6 +965,8 @@ static void uwrap_thread_child(void)
                u = uwrap.ids;
        }
 
+       uwrap_export_ids(id);
+
        id->enabled = true;
 
        UWRAP_UNLOCK_ALL;
@@ -1046,8 +1066,8 @@ static void uwrap_init_env(struct uwrap_thread *id)
                if (i != ngroups) {
                        UWRAP_LOG(UWRAP_LOG_ERROR,
                                  "ERROR: The number of groups (%u) passed, "
-                                 "does not the number of groups (%u) we "
-                                 "parsed",
+                                 "does not match the number of groups (%u) "
+                                 "we parsed.",
                                  ngroups,
                                  i);
                        exit(-1);
@@ -1158,7 +1178,7 @@ static void uwrap_init(void)
 
        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)
@@ -1331,9 +1351,7 @@ static int uwrap_setreuid_args(uid_t ruid, uid_t euid,
 
 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;
 
@@ -1352,9 +1370,7 @@ static int uwrap_setreuid_thread(uid_t ruid, uid_t euid)
 #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;
 
@@ -1618,9 +1634,7 @@ static int uwrap_setregid_args(gid_t rgid, gid_t egid,
 
 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;
 
@@ -1639,9 +1653,7 @@ static int uwrap_setregid_thread(gid_t rgid, gid_t egid)
 #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;