]> err.no Git - dpkg/commitdiff
s-s-d: Check uid and gid before calling setuid, setgid and initgroups
authorGuillem Jover <guillem@debian.org>
Thu, 17 Jan 2008 02:17:27 +0000 (04:17 +0200)
committerGuillem Jover <guillem@debian.org>
Thu, 17 Jan 2008 03:53:16 +0000 (05:53 +0200)
Based on a patch by Samuel Thibault. Closes: #222524

ChangeLog
debian/changelog
utils/start-stop-daemon.c

index 44bd23f868cda25355daf08ac734246655a28efd..74c226a97d38454d54cd6601be813c590d2d820a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2008-01-17  Samuel Thibault  <samuel.thibault@ens-lyon.org>,
+            Guillem Jover  <guillem@debian.org>
+
+       * utils/start-stop-daemon.c (gid_in_current_groups): New function.
+       (main): Call setuid only if requested to run as a different user
+       than the current one. Call setgid only if requested to run as a group
+       different than the current one, and initgroups only if the groups is
+       not part of the supplementary groups.
+
 2008-01-16  Guillem Jover  <guillem@debian.org>
 
        * utils/start-stop-daemon.c (do_stop): Do not print messages when
index b88b4c72bfa8af0dd235ca34c274a6bd8a920198..271d0db613fe3cc458d4ac807df8b272f2f58cca 100644 (file)
@@ -11,6 +11,9 @@ dpkg (1.14.16) UNRELEASED; urgency=low
     --retry even if the daemon removed the pidfile. Closes: #460903
     Thanks to Justin Pryzby for the analysis.
   * Make --quiet silence --test in start-stop-daemon. Closes: #367998
+  * Check current uid and gid in start-stop-daemon before calling setuid,
+    setgid and initgroups. Closes: #222524
+    Based on a patch by Samuel Thibault.
 
   [ Frank Lichtenheld ]
   * Make the -L option of dpkg-parsechangelog actually work (it's
index a74f7c740cfea660751aae459e6d353d13dc2f0a..c384031e39dd534d990e44994d5d5a2e7fc4ebc7 100644 (file)
@@ -313,6 +313,27 @@ clear(struct pid_list **list)
        *list = NULL;
 }
 
+static int
+gid_in_current_groups(gid_t gid)
+{
+       gid_t *gids;
+       int i, ngroups;
+
+       ngroups = getgroups(0, NULL);
+       gids = xmalloc(ngroups * sizeof(gid_t));
+       getgroups(ngroups, gids);
+
+       for (i = 0; i < ngroups; i++) {
+               if (gid == gids[i]) {
+                       free(gids);
+                       return 1;
+               }
+       }
+
+       free(gids);
+       return 0;
+}
+
 static void
 do_help(void)
 {
@@ -1376,14 +1397,20 @@ main(int argc, char **argv)
        }
        if (chdir(changedir) < 0)
                fatal("Unable to chdir() to %s", changedir);
-       if (changeuser != NULL) {
-               if (setgid(runas_gid))
-                       fatal("Unable to set gid to %d", runas_gid);
-               if (initgroups(changeuser, runas_gid))
-                       fatal("Unable to set initgroups() with gid %d", runas_gid);
+
+       if (changeuser != NULL && getuid() != runas_uid) {
                if (setuid(runas_uid))
                        fatal("Unable to set uid to %s", changeuser);
        }
+       if (changegroup != NULL && *changegroup != '\0' && getgid() != runas_gid) {
+               if (!gid_in_current_groups(runas_gid))
+                       if (initgroups(changeuser, runas_gid))
+                               fatal("Unable to set initgroups() with gid %d",
+                                     runas_gid);
+               if (setgid(runas_gid))
+                       fatal("Unable to set gid to %d", runas_gid);
+       }
+
        if (background) {
                /* Continue background setup */
                int i;