exec plugin: Use `setgroups' to set the list of supplementary group IDs.
[collectd.git] / src / exec.c
index e899a1c..b8b538b 100644 (file)
@@ -118,6 +118,7 @@ static void exec_child (program_list_t *pl)
   int status;
   int uid;
   int gid;
+  int egid;
   char *arg0;
 
   struct passwd *sp_ptr;
@@ -140,12 +141,16 @@ static void exec_child (program_list_t *pl)
   }
 
   uid = sp.pw_uid;
+  gid = sp.pw_gid;
   if (uid == 0)
   {
     ERROR ("exec plugin: Cowardly refusing to exec program as root.");
     exit (-1);
   }
 
+  /* The group configured in the configfile is set as effective group, because
+   * this way the forked process can (re-)gain the user's primary group. */
+  egid = -1;
   if (NULL != pl->group)
   {
     if ('\0' != *pl->group) {
@@ -165,27 +170,57 @@ static void exec_child (program_list_t *pl)
        exit (-1);
       }
 
-      gid = gr.gr_gid;
+      egid = gr.gr_gid;
     }
     else
     {
-      gid = sp.pw_gid;
+      egid = gid;
     }
+  } /* if (pl->group == NULL) */
+
+#if HAVE_SETGROUPS
+  if (getuid () == 0)
+  {
+    gid_t  glist[2];
+    size_t glist_len;
+
+    glist[0] = gid;
+    glist_len = 1;
+
+    if (gid != egid)
+    {
+      glist[1] = egid;
+      glist_len = 2;
+    }
+
+    setgroups (glist_len, glist);
+  }
+#endif /* HAVE_SETGROUPS */
 
-    status = setgid (gid);
-    if (0 != status)
+  status = setgid (gid);
+  if (status != 0)
+  {
+    ERROR ("exec plugin: setgid (%i) failed: %s",
+       gid, sstrerror (errno, errbuf, sizeof (errbuf)));
+    exit (-1);
+  }
+
+  if (egid != -1)
+  {
+    status = setegid (egid);
+    if (status != 0)
     {
-      ERROR ("exec plugin: setgid failed: %s",
-         sstrerror (errno, errbuf, sizeof (errbuf)));
+      ERROR ("exec plugin: setegid (%i) failed: %s",
+         egid, sstrerror (errno, errbuf, sizeof (errbuf)));
       exit (-1);
     }
-  } /* if (pl->group == NULL) */
+  }
 
   status = setuid (uid);
   if (status != 0)
   {
-    ERROR ("exec plugin: setuid failed: %s",
-       sstrerror (errno, errbuf, sizeof (errbuf)));
+    ERROR ("exec plugin: setuid (%i) failed: %s",
+       uid, sstrerror (errno, errbuf, sizeof (errbuf)));
     exit (-1);
   }
 
@@ -279,6 +314,7 @@ static void *exec_read_one (void *arg)
     ERROR ("exec plugin: fdopen (%i) failed: %s", fd,
        sstrerror (errno, errbuf, sizeof (errbuf)));
     kill (pl->pid, SIGTERM);
+    pl->pid = 0;
     close (fd);
     pthread_exit ((void *) 1);
   }