uwrap: Reflect changes of uid/gid in threads to main process.
authorRobin Hack <hack.robin@gmail.com>
Mon, 29 Sep 2014 07:53:21 +0000 (09:53 +0200)
committerAndreas Schneider <asn@samba.org>
Mon, 6 Oct 2014 14:16:21 +0000 (16:16 +0200)
When thread changes uid/gid this change must be reflected to main
process.

Syscalls changes only uid/gid of thread. Call of libc functions changes
also uid/gid of main process.

TESTS: Fix test_sync_setgid_syscall in test_glibc_thread_support.c

When changes of gid (and uid of course) is reflected to main process
test must check if call of setgid syscall changes gid of thread ONLY.

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

index 187cc113862900587c88bf45ec828ceb26aa6d51..8e3a7d312051d0537821abbc354f3f362bd8d01d 100644 (file)
@@ -236,8 +236,17 @@ struct uwrap {
        bool initialised;
        bool enabled;
 
+       uid_t ruid;
+       uid_t euid;
+       uid_t suid;
+
+       gid_t rgid;
+       gid_t egid;
+       gid_t sgid;
+
+       /* Real uid and gid of user who run uid wrapper */
        uid_t myuid;
-       uid_t mygid;
+       gid_t mygid;
 
        struct uwrap_thread *ids;
 };
@@ -533,8 +542,13 @@ static int uwrap_new_id(pthread_t tid, bool do_alloc)
        id->tid = tid;
        id->dead = false;
 
-       id->ruid = id->euid = id->suid = uwrap.myuid;
-       id->rgid = id->egid = id->sgid = uwrap.mygid;
+       id->ruid = uwrap.ruid;
+       id->euid = uwrap.euid;
+       id->suid = uwrap.suid;
+
+       id->rgid = uwrap.rgid;
+       id->egid = uwrap.egid;
+       id->sgid = uwrap.sgid;
 
        id->ngroups = 1;
        id->groups[0] = uwrap.mygid;
@@ -612,13 +626,15 @@ static void uwrap_init(void)
                const char *root = getenv("UID_WRAPPER_ROOT");
                int rc;
 
+               uwrap.myuid = libc_geteuid();
+               uwrap.mygid = libc_getegid();
                /* put us in one group */
                if (root != NULL && root[0] == '1') {
-                       uwrap.myuid = 0;
-                       uwrap.mygid = 0;
+                       uwrap.ruid = uwrap.euid = uwrap.suid = 0;
+                       uwrap.rgid = uwrap.egid = uwrap.sgid = 0;
                } else {
-                       uwrap.myuid = libc_geteuid();
-                       uwrap.mygid = libc_getegid();
+                       uwrap.ruid = uwrap.euid = uwrap.suid = libc_geteuid();
+                       uwrap.rgid = uwrap.egid = uwrap.sgid = libc_getegid();
                }
 
                rc = uwrap_new_id(tid, true);
@@ -704,6 +720,20 @@ static int uwrap_setresuid(uid_t ruid, uid_t euid, uid_t suid)
                        id->suid = suid;
                }
        }
+
+       /* Reflect changes in thread to main process. */
+       if (ruid != (uid_t)-1) {
+               uwrap.ruid = ruid;
+       }
+
+       if (euid != (uid_t)-1) {
+               uwrap.euid = euid;
+       }
+
+       if (suid != (uid_t)-1) {
+               uwrap.suid = suid;
+       }
+
        UWRAP_UNLOCK(uwrap_id);
 
        return 0;
@@ -877,6 +907,19 @@ static int uwrap_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
                        id->sgid = sgid;
                }
        }
+
+       /* Reflect changes in thread to main process. */
+       if (rgid != (gid_t)-1) {
+               uwrap.rgid = rgid;
+       }
+
+       if (egid != (gid_t)-1) {
+               uwrap.egid = egid;
+       }
+
+       if (sgid != (gid_t)-1) {
+               uwrap.sgid = sgid;
+       }
        UWRAP_UNLOCK(uwrap_id);
 
        return 0;
index 540338dedc10f27df29357ee5e4df0348cdae6b6..f9054cd4981cf2cd7eaa938356169b97f4e6ce6b 100644 (file)
@@ -141,13 +141,13 @@ static void *uwrap_setgid_syscall(void *arg)
 {
        int rc;
        gid_t g;
-       gid_t *gmp = (gid_t *) arg;
+       (void) arg; /* unused */
 
        rc = syscall(SYS_setgid, 999);
        assert_int_equal(rc, 0);
 
        g = getgid();
-       assert_int_equal(g, *gmp);
+       assert_int_equal(g, 999);
 
        return NULL;
 }
@@ -157,24 +157,19 @@ static void test_sync_setgid_syscall(void **state)
        pthread_attr_t pthread_custom_attr;
        pthread_t threads[NUM_THREADS];
        gid_t go, gn;
-       gid_t *gtp;
        int i;
 
-       gtp = malloc(sizeof(gid_t));
-       assert_non_null(gtp);
-
        (void) state; /* unused */
 
        pthread_attr_init(&pthread_custom_attr);
 
        go = getgid();
-       *gtp = go;
 
        for (i = 0; i < NUM_THREADS; i++) {
                pthread_create(&threads[i],
                               &pthread_custom_attr,
                               uwrap_setgid_syscall,
-                              gtp);
+                              NULL);
        }
 
        /* wait for threaads */
@@ -185,7 +180,6 @@ static void test_sync_setgid_syscall(void **state)
        gn = getgid();
        assert_int_equal(gn, go);
 
-       free(gtp);
        pthread_attr_destroy(&pthread_custom_attr);
 }