service: initialize supplementary group ids
authorYousong Zhou <yszhou4tech@gmail.com>
Sun, 11 Feb 2018 09:19:11 +0000 (17:19 +0800)
committerYousong Zhou <yszhou4tech@gmail.com>
Wed, 28 Mar 2018 09:29:49 +0000 (17:29 +0800)
We currently only call setgid() with user's primary group id for service
instance processes.  In the case of a user belong to multiple groups,
it's natural to also explicitly initialize their supplementary group ids

Fixes FS#988

Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
service/instance.c
service/instance.h

index 74c47fac36cabc4b1e762c6f2c099a112920eb8c..917b003b3907c5e06014129db9e9ca95bdf17100 100644 (file)
@@ -17,6 +17,7 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
+#include <grp.h>
 #include <net/if.h>
 #include <unistd.h>
 #include <stdint.h>
@@ -347,6 +348,10 @@ instance_run(struct service_instance *in, int _stdout, int _stderr)
                closefd(_stderr);
        }
 
+       if (in->user && in->gid && initgroups(in->user, in->gid)) {
+               ERROR("failed to initgroups() for user %s: %m\n", in->user);
+               exit(127);
+       }
        if (in->gid && setgid(in->gid)) {
                ERROR("failed to set group id %d: %m\n", in->gid);
                exit(127);
@@ -613,6 +618,9 @@ instance_config_changed(struct service_instance *in, struct service_instance *in
        if (in->nice != in_new->nice)
                return true;
 
+       if (string_changed(in->user, in_new->user))
+               return true;
+
        if (in->uid != in_new->uid)
                return true;
 
@@ -862,8 +870,10 @@ instance_config_parse(struct service_instance *in)
        }
 
        if (tb[INSTANCE_ATTR_USER]) {
-               struct passwd *p = getpwnam(blobmsg_get_string(tb[INSTANCE_ATTR_USER]));
+               const char *user = blobmsg_get_string(tb[INSTANCE_ATTR_USER]);
+               struct passwd *p = getpwnam(user);
                if (p) {
+                       in->user = strdup(user);
                        in->uid = p->pw_uid;
                        in->gid = p->pw_gid;
                }
@@ -982,6 +992,7 @@ instance_free(struct service_instance *in)
        watch_del(in);
        instance_config_cleanup(in);
        free(in->config);
+       free(in->user);
        free(in);
 }
 
index bdd14de737a50f53e53a1417f2c1a350b13b88d1..771406c8f64d0e61b2cddc9b64f91fd152a62d07 100644 (file)
@@ -42,6 +42,7 @@ struct service_instance {
        int8_t nice;
        bool valid;
 
+       char *user;
        uid_t uid;
        gid_t gid;