]> granicus.if.org Git - sudo/commitdiff
When matching paths with glob(3), check returned matches against
authorTodd C. Miller <Todd.Miller@courtesan.com>
Thu, 9 Jun 2016 17:41:09 +0000 (11:41 -0600)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Thu, 9 Jun 2016 17:41:09 +0000 (11:41 -0600)
user_cmnd first if it is fully-qualified.  This avoids a lot of
needless stat(2) calls and avoids a mismatch between safe_cmnd and
argv[0] if there are multiple matches with the same inode/dev due
to links.  Bug #746.

plugins/sudoers/match.c

index bc0b50906a29538b836deeffef8268d590bde099..fda2e33c30de12e19bb77e3ed6afd695642a5f38 100644 (file)
@@ -482,7 +482,28 @@ command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args)
        globfree(&gl);
        debug_return_bool(false);
     }
-    /* For each glob match, compare basename, st_dev and st_ino. */
+    /* If user_cmnd is fully-qualified, check for an exact match. */
+    if (user_cmnd[0] == '/') {
+       for (ap = gl.gl_pathv; (cp = *ap) != NULL; ap++) {
+           if (strcmp(cp, user_cmnd) != 0 || stat(cp, &sudoers_stat) == -1)
+               continue;
+           if (user_stat == NULL ||
+               (user_stat->st_dev == sudoers_stat.st_dev &&
+               user_stat->st_ino == sudoers_stat.st_ino)) {
+               free(safe_cmnd);
+               if ((safe_cmnd = strdup(cp)) == NULL) {
+                   sudo_warnx(U_("%s: %s"), __func__,
+                       U_("unable to allocate memory"));
+                   cp = NULL;          /* fail closed */
+               }
+           } else {
+               /* Paths match, but st_dev and st_ino are different. */
+               cp = NULL;              /* fail closed */
+           }
+           goto done;
+       }
+    }
+    /* No exact match, compare basename, st_dev and st_ino. */
     for (ap = gl.gl_pathv; (cp = *ap) != NULL; ap++) {
        /* If it ends in '/' it is a directory spec. */
        dlen = strlen(cp);
@@ -505,12 +526,14 @@ command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args)
            user_stat->st_ino == sudoers_stat.st_ino)) {
            free(safe_cmnd);
            if ((safe_cmnd = strdup(cp)) == NULL) {
-               sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+               sudo_warnx(U_("%s: %s"), __func__,
+                   U_("unable to allocate memory"));
                cp = NULL;              /* fail closed */
            }
-           break;
+           goto done;
        }
     }
+done:
     globfree(&gl);
     if (cp == NULL)
        debug_return_bool(false);
@@ -796,7 +819,8 @@ command_matches_dir(const char *sudoers_dir, size_t dlen)
            user_stat->st_ino == sudoers_stat.st_ino)) {
            free(safe_cmnd);
            if ((safe_cmnd = strdup(buf)) == NULL) {
-               sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+               sudo_warnx(U_("%s: %s"), __func__,
+                   U_("unable to allocate memory"));
                dent = NULL;
            }
            break;