The branch, master has been updated
       via  27e9f76 Bump version to 1.2.2
       via  6d69fef tests: Add a fork and exec test
       via  b5168be uwrap: Add support to initialize groups while forking
      from  0580449 tests: fix a comment typo

https://git.samba.org/?p=uid_wrapper.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 27e9f76f1ddc72987f0323f19341b2b6afefa5cd
Author: Andreas Schneider <[email protected]>
Date:   Wed Jul 12 13:03:35 2017 +0200

    Bump version to 1.2.2
    
    Signed-off-by: Andreas Schneider <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit 6d69fefcc5b39cf2007ad9b43fe4972c3b835d80
Author: Andreas Schneider <[email protected]>
Date:   Wed Jul 12 09:16:30 2017 +0200

    tests: Add a fork and exec test
    
    Signed-off-by: Andreas Schneider <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit b5168be4128d7585c30ba98da31926cd3d0066e5
Author: Andreas Schneider <[email protected]>
Date:   Tue Jul 11 11:59:33 2017 +0200

    uwrap: Add support to initialize groups while forking
    
    Signed-off-by: Andreas Schneider <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

-----------------------------------------------------------------------

Summary of changes:
 CMakeLists.txt         |   2 +-
 ChangeLog              |   4 ++
 src/uid_wrapper.c      | 163 +++++++++++++++++++++++++++++++++++++++++++++++++
 tests/CMakeLists.txt   |   4 +-
 tests/mock_exec_uid.c  | 157 +++++++++++++++++++++++++++++++++++++++++++++++
 tests/test_fork_exec.c |  88 ++++++++++++++++++++++++++
 6 files changed, 416 insertions(+), 2 deletions(-)
 create mode 100644 tests/mock_exec_uid.c
 create mode 100644 tests/test_fork_exec.c


Changeset truncated at 500 lines:

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 898440e..4dc42f2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,7 +8,7 @@ set(APPLICATION_NAME ${PROJECT_NAME})
 
 set(APPLICATION_VERSION_MAJOR "1")
 set(APPLICATION_VERSION_MINOR "2")
-set(APPLICATION_VERSION_PATCH "1")
+set(APPLICATION_VERSION_PATCH "2")
 
 set(APPLICATION_VERSION 
"${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
 
diff --git a/ChangeLog b/ChangeLog
index 6f776de..cc02554 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,10 @@
 ChangeLog
 ==========
 
+version 1.2.2 (released 2107-07-13)
+  * Added support for fork'ed and then exec'ed processes
+  * Added support for Alpha
+
 version 1.2.1 (released 2016-03-16)
   * Documented missing options.
   * Fixed a comipilation issue with -O3.
diff --git a/src/uid_wrapper.c b/src/uid_wrapper.c
index ded857a..6e39eb6 100644
--- a/src/uid_wrapper.c
+++ b/src/uid_wrapper.c
@@ -815,6 +815,66 @@ int pthread_create(pthread_t *thread,
  * UWRAP ID HANDLING
  *********************************************************/
 
+#define GROUP_STRING_SIZE 16384
+
+/**
+ * This function exports all the IDs of the current user so if
+ * we fork and then exec we can setup uid_wrapper in the new process
+ * with those IDs.
+ */
+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};
+       int i;
+
+       /* UIDS */
+       snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->ruid);
+       setenv("UID_WRAPPER_INITIAL_RUID", unsigned_str, 1);
+
+       snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->euid);
+       setenv("UID_WRAPPER_INITIAL_EUID", unsigned_str, 1);
+
+       snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->suid);
+       setenv("UID_WRAPPER_INITIAL_SUID", unsigned_str, 1);
+
+       /* GIDS */
+       snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->rgid);
+       setenv("UID_WRAPPER_INITIAL_RGID", unsigned_str, 1);
+
+       snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->egid);
+       setenv("UID_WRAPPER_INITIAL_EGID", unsigned_str, 1);
+
+       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);
+
+       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;
+
+               len = snprintf(unsigned_str, sizeof(unsigned_str), ",%u", 
id->groups[i]);
+               if (len <= 1) {
+                       continue;
+               }
+               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 (id->ngroups > 0) {
+               setenv("UID_WRAPPER_INITIAL_GROUPS", groups_str, 1);
+       }
+}
+
 static void uwrap_thread_prepare(void)
 {
        struct uwrap_thread *id = uwrap_tls_id;
@@ -859,6 +919,8 @@ static void uwrap_thread_child(void)
                return;
        }
 
+       uwrap_export_ids(id);
+
        /*
         * "Garbage collector" - Inspired by DESTRUCTOR.
         * All threads (except one which called fork()) are dead now.. Dave
@@ -884,6 +946,105 @@ static void uwrap_thread_child(void)
        UWRAP_UNLOCK_ALL;
 }
 
+/*
+ * This initializes uid_wrapper with the IDs exported to the environment. Those
+ * are normally set after we forked and executed.
+ */
+static void uwrap_init_env(struct uwrap_thread *id)
+{
+       const char *env;
+       int ngroups = 0;
+
+       env = getenv("UID_WRAPPER_INITIAL_RUID");
+       if (env != NULL && env[0] != '\0') {
+               UWRAP_LOG(UWRAP_LOG_DEBUG, "Initialize ruid with %s", env);
+               id->ruid = strtoul(env, (char **)NULL, 10);
+               unsetenv("UID_WRAPPER_INITIAL_RUID");
+       }
+
+       env = getenv("UID_WRAPPER_INITIAL_EUID");
+       if (env != NULL && env[0] != '\0') {
+               UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize euid with %s", env);
+               id->euid = strtoul(env, (char **)NULL, 10);
+               unsetenv("UID_WRAPPER_INITIAL_EUID");
+       }
+
+       env = getenv("UID_WRAPPER_INITIAL_SUID");
+       if (env != NULL && env[0] != '\0') {
+               UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize suid with %s", env);
+               id->suid = strtoul(env, (char **)NULL, 10);
+               unsetenv("UID_WRAPPER_INITIAL_SUID");
+       }
+
+       env = getenv("UID_WRAPPER_INITIAL_RGID");
+       if (env != NULL && env[0] != '\0') {
+               UWRAP_LOG(UWRAP_LOG_DEBUG, "Initialize ruid with %s", env);
+               id->rgid = strtoul(env, (char **)NULL, 10);
+               unsetenv("UID_WRAPPER_INITIAL_RGID");
+       }
+
+       env = getenv("UID_WRAPPER_INITIAL_EGID");
+       if (env != NULL && env[0] != '\0') {
+               UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize egid with %s", env);
+               id->egid = strtoul(env, (char **)NULL, 10);
+               unsetenv("UID_WRAPPER_INITIAL_EGID");
+       }
+
+       env = getenv("UID_WRAPPER_INITIAL_SGID");
+       if (env != NULL && env[0] != '\0') {
+               UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize sgid with %s", env);
+               id->sgid = strtoul(env, (char **)NULL, 10);
+               unsetenv("UID_WRAPPER_INITIAL_SGID");
+       }
+
+       env = getenv("UID_WRAPPER_INITIAL_GROUPS_COUNT");
+       if (env != NULL && env[0] != '\0') {
+               ngroups = strtol(env, (char **)NULL, 10);
+               unsetenv("UID_WRAPPER_INITIAL_GROUPS_COUNT");
+       }
+
+       if (ngroups > 0) {
+               int i = 0;
+
+               id->ngroups = 0;
+
+               free(id->groups);
+               id->groups = malloc(sizeof(gid_t) * ngroups);
+               if (id->groups == NULL) {
+                       UWRAP_LOG(UWRAP_LOG_ERROR,
+                                 "Unable to allocate memory");
+                       exit(-1);
+               }
+
+               env = getenv("UID_WRAPPER_INITIAL_GROUPS");
+               if (env != NULL && env[0] != '\0') {
+                       char *groups_str = NULL;
+                       char *saveptr = NULL;
+                       const char *p = NULL;
+
+                       groups_str = strdup(env);
+                       if (groups_str == NULL) {
+                               exit(-1);
+                       }
+
+                       p = strtok_r(groups_str, ",", &saveptr);
+                       while (p != NULL) {
+                               id->groups[i] = strtol(p, (char **)NULL, 10);
+                               i++;
+
+                               p = strtok_r(NULL, ",", &saveptr);
+                       }
+               }
+
+               if (i != ngroups) {
+                       exit(-1);
+               }
+
+               UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize groups with %s", env);
+               id->ngroups = ngroups;
+       }
+}
+
 static void uwrap_init(void)
 {
        const char *env;
@@ -972,6 +1133,8 @@ static void uwrap_init(void)
                        }
                }
 
+               uwrap_init_env(id);
+
                id->enabled = true;
 
                UWRAP_LOG(UWRAP_LOG_DEBUG,
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 8201d94..6a6188f 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -21,6 +21,8 @@ if (BSD)
     add_definitions(-DBSD)
 endif (BSD)
 
+add_executable(mock_exec_uid mock_exec_uid.c)
+
 set(UWRAP_UID_TESTS
      test_setuid
      test_seteuid)
@@ -32,7 +34,7 @@ endif (HAVE_SETREUID)
 if (HAVE_SETRESUID)
     list(APPEND UWRAP_UID_TESTS test_setresuid test_setuid_euid1 
test_setuid_euid2)
     if (HAVE_GETRESUID)
-        list(APPEND UWRAP_UID_TESTS test_getresuid)
+        list(APPEND UWRAP_UID_TESTS test_getresuid test_fork_exec)
     endif (HAVE_GETRESUID)
 endif (HAVE_SETRESUID)
 
diff --git a/tests/mock_exec_uid.c b/tests/mock_exec_uid.c
new file mode 100644
index 0000000..0e3737b
--- /dev/null
+++ b/tests/mock_exec_uid.c
@@ -0,0 +1,157 @@
+#include "config.h"
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#ifndef discard_const
+#define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
+#endif
+
+#ifndef discard_const_p
+#define discard_const_p(type, ptr) ((type *)discard_const(ptr))
+#endif
+
+struct user_ids {
+       uid_t ruid;
+       uid_t euid;
+       uid_t suid;
+       gid_t gid;
+};
+
+static void print_usage(const char *prog_name)
+{
+       fprintf(stderr,
+               "Usage: %s [-r ruid] [-e euid] [-s suid] [-g gid]\n"
+               "\n"
+               "    -r The ruid to validate\n"
+               "    -e The euid to validate\n"
+               "    -s The suid to validate\n"
+               "    -g The gid to validate\n"
+               "\n",
+               prog_name);
+}
+
+int main(int argc, char *argv[])
+{
+       const struct option long_options[] = {
+               { discard_const_p(char, "ruid"),  required_argument,  0, 'r' },
+               { discard_const_p(char, "euid"),  required_argument,  0, 'e' },
+               { discard_const_p(char, "suid"),  required_argument,  0, 's' },
+               { discard_const_p(char, "gid"),   required_argument,  0, 'g' },
+               { 0,                              0,                  0, 0 }
+       };
+       int opt_idx;
+       int opt;
+       struct user_ids expected_ids = {
+               .ruid = (uid_t)-1,
+               .euid = (uid_t)-1,
+               .suid = (uid_t)-1,
+               .gid  = (gid_t)-1,
+       };
+       struct user_ids real_ids = {
+               .ruid = (uid_t)-1,
+               .euid = (uid_t)-1,
+               .suid = (uid_t)-1,
+               .gid  = (gid_t)-1,
+       };
+       int rc;
+
+       for (opt = getopt_long(argc, argv, "r:e:s:g:", long_options, &opt_idx);
+            opt != -1;
+            opt = getopt_long(argc, argv, "r:e:s:g:", long_options, &opt_idx)) 
{
+               errno = 0;
+
+               switch (opt) {
+                       case 0:
+                               break;
+                       case 'r':
+                               expected_ids.ruid = strtol(optarg,
+                                                          (char **)NULL,
+                                                          10);
+                               break;
+                       case 'e':
+                               expected_ids.euid = strtol(optarg,
+                                                          (char **)NULL,
+                                                          10);
+                               break;
+                       case 's':
+                               expected_ids.suid = strtol(optarg,
+                                                          (char **)NULL,
+                                                          10);
+                               break;
+                       case 'g':
+                               expected_ids.gid = strtol(optarg,
+                                                         (char **)NULL,
+                                                         10);
+                               break;
+                       default:
+                               print_usage(argv[0]);
+                               return 1;
+               }
+
+               if (errno == EINVAL || errno == ERANGE) {
+                       return 1;
+               }
+       }
+
+       if (expected_ids.ruid == (uid_t)-1 &&
+           expected_ids.euid == (uid_t)-1 &&
+           expected_ids.suid == (uid_t)-1) {
+               print_usage(argv[0]);
+               return 1;
+       }
+
+       rc = getresuid(&real_ids.ruid, &real_ids.euid, &real_ids.suid);
+       if (rc != 0) {
+               fprintf(stderr, "getresuid() failed - %s\n", strerror(errno));
+               return 1;
+       }
+
+       if (expected_ids.ruid != (uid_t)-1) {
+               if (expected_ids.ruid != real_ids.ruid) {
+                       printf("MOCK_TEST ruid mismatch - ruid=%u, expected 
ruid=%u\n",
+                              real_ids.ruid,
+                              expected_ids.ruid);
+                       return 1;
+               }
+               printf("MOCK_TEST ruid=%d\n", real_ids.ruid);
+       }
+
+       if (expected_ids.euid != (uid_t)-1) {
+               if (expected_ids.euid != real_ids.euid) {
+                       printf("MOCK_TEST euid mismatch - euid=%u, expected 
euid=%u\n",
+                              real_ids.euid,
+                              expected_ids.euid);
+                       return 1;
+               }
+               printf("MOCK_TEST euid=%d\n", real_ids.euid);
+       }
+
+       if (expected_ids.suid != (uid_t)-1) {
+               if (expected_ids.suid != real_ids.suid) {
+                       printf("MOCK_TEST suid mismatch - suid=%u, expected 
suid=%u\n",
+                              real_ids.suid,
+                              expected_ids.suid);
+                       return 1;
+               }
+               printf("MOCK_TEST suid=%d\n", real_ids.suid);
+       }
+
+       real_ids.gid = getgid();
+       if (real_ids.gid != (gid_t)-1) {
+               if (expected_ids.gid != real_ids.gid) {
+                       printf("MOCK_TEST gid mismatch - gid=%u, expected 
gid=%u\n",
+                              real_ids.gid,
+                              expected_ids.gid);
+                       return 1;
+               }
+               printf("MOCK_TEST gid=%d\n", real_ids.gid);
+       }
+
+       return 0;
+}
diff --git a/tests/test_fork_exec.c b/tests/test_fork_exec.c
new file mode 100644
index 0000000..36077c4
--- /dev/null
+++ b/tests/test_fork_exec.c
@@ -0,0 +1,88 @@
+#include "config.h"
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#define TEST_MOCK_EXECUTABLE "mock_exec_uid"
+
+static void test_uwrap_fork_exec(void **state)
+{
+       pid_t pid;
+       int rc;
+       uid_t cp_ruid, cp_euid, cp_suid;
+
+       (void)state; /* unused */
+
+       rc = getresuid(&cp_ruid, &cp_euid, &cp_suid);
+       assert_return_code(rc, errno);
+       assert_int_equal(cp_ruid, 0);
+       assert_int_equal(cp_euid, 0);
+       assert_int_equal(cp_suid, 0);
+
+       rc = setresuid(2000, -1, 4000);
+       assert_return_code(rc, errno);
+
+       rc = setgid(5000);
+       assert_return_code(rc, errno);
+
+       pid = fork();
+       assert_return_code(pid, errno);
+
+       /* child */
+       if (pid == 0) {
+               char const *argv[] = {
+                       TEST_MOCK_EXECUTABLE,
+                       "-r 2000",
+                       "-e 0",
+                       "-s 4000",
+                       "-g 5000",
+                       NULL
+               };
+               char cmd[1024] = {0};
+
+               snprintf(cmd, sizeof(cmd),
+                        "%s/tests/%s",
+                        BINARYDIR,
+                        TEST_MOCK_EXECUTABLE);
+
+               rc = execvp(cmd, (char *const *)argv);
+               exit(rc);
+       }
+
+       /* parent */
+       if (pid > 0) {
+               pid_t child_pid;
+               int wstatus = -1;
+
+               rc = setresuid(cp_ruid, cp_euid, cp_suid);
+               assert_return_code(rc, errno);
+
+               child_pid = waitpid(-1, &wstatus, 0);
+               assert_return_code(child_pid, errno);
+
+               assert_true(WIFEXITED(wstatus));
+
+               assert_int_equal(WEXITSTATUS(wstatus), 0);
+       }
+}
+
+int main(void) {
+       int rc;
+
+       const struct CMUnitTest uwrap_tests[] = {
+               cmocka_unit_test(test_uwrap_fork_exec),
+       };
+
+       rc = cmocka_run_group_tests(uwrap_tests, NULL, NULL);
+


-- 
UID Wrapper Repository

Reply via email to