]> granicus.if.org Git - sudo/commitdiff
Fix a user after free crash as well as a memory leak when filtering
authorTodd C. Miller <Todd.Miller@sudo.ws>
Fri, 13 Apr 2018 16:49:05 +0000 (10:49 -0600)
committerTodd C. Miller <Todd.Miller@sudo.ws>
Fri, 13 Apr 2018 16:49:05 +0000 (10:49 -0600)
Defaults.

plugins/sudoers/cvtsudoers.c
plugins/sudoers/gram.c
plugins/sudoers/gram.y

index 0fac62c3b9da799721e9c23cce53b23098d28a37..27dd59e4887cdd15cebdeffd543e26c921e9dcb7 100644 (file)
@@ -1048,16 +1048,15 @@ filter_defaults(struct cvtsudoers_config *conf)
     struct member_list host_aliases = TAILQ_HEAD_INITIALIZER(host_aliases);
     struct member_list cmnd_aliases = TAILQ_HEAD_INITIALIZER(cmnd_aliases);
     struct member_list *prev_binding = NULL;
-    struct defaults *def;
-    struct member *m;
-    void *next;
+    struct defaults *def, *def_next;
+    struct member *m, *m_next;
     int alias_type;
     debug_decl(filter_defaults, SUDOERS_DEBUG_DEFAULTS)
 
     if (filters == NULL && conf->defaults == CVT_DEFAULTS_ALL)
        debug_return;
 
-    TAILQ_FOREACH_SAFE(def, &defaults, entries, next) {
+    TAILQ_FOREACH_SAFE(def, &defaults, entries, def_next) {
        bool keep = true;
 
        switch (def->type) {
@@ -1097,7 +1096,7 @@ filter_defaults(struct cvtsudoers_config *conf)
            /* Look for aliases used by the binding. */
            /* XXX - move to function */
            if (alias_type != UNSPEC && def->binding != prev_binding) {
-               TAILQ_FOREACH_SAFE(m, def->binding, entries, next) {
+               TAILQ_FOREACH_SAFE(m, def->binding, entries, m_next) {
                    if (m->type == ALIAS) {
                        TAILQ_REMOVE(def->binding, m, entries);
                        switch (alias_type) {
@@ -1122,6 +1121,15 @@ filter_defaults(struct cvtsudoers_config *conf)
            }
            TAILQ_REMOVE(&defaults, def, entries);
            free_default(def, &prev_binding);
+           if (prev_binding != NULL) {
+               /* Remove and free Defaults that share the same binding. */
+               while (def_next != NULL && def_next->binding == prev_binding) {
+                   def = def_next;
+                   def_next = TAILQ_NEXT(def, entries);
+                   TAILQ_REMOVE(&defaults, def, entries);
+                   free_default(def, &prev_binding);
+               }
+           }
        } else {
            prev_binding = def->binding;
        }
@@ -1130,21 +1138,25 @@ filter_defaults(struct cvtsudoers_config *conf)
     /* Remove now-unreferenced aliases. */
     alias_used_by_userspecs(&user_aliases, &runas_aliases, &host_aliases,
        &cmnd_aliases);
-    TAILQ_FOREACH_SAFE(m, &user_aliases, entries, next) {
+    TAILQ_FOREACH_SAFE(m, &user_aliases, entries, m_next) {
        struct alias *a = alias_remove(m->name, USERALIAS);
        alias_free(a);
+       free_member(m);
     }
-    TAILQ_FOREACH_SAFE(m, &runas_aliases, entries, next) {
+    TAILQ_FOREACH_SAFE(m, &runas_aliases, entries, m_next) {
        struct alias *a = alias_remove(m->name, RUNASALIAS);
        alias_free(a);
+       free_member(m);
     }
-    TAILQ_FOREACH_SAFE(m, &host_aliases, entries, next) {
+    TAILQ_FOREACH_SAFE(m, &host_aliases, entries, m_next) {
        struct alias *a = alias_remove(m->name, HOSTALIAS);
        alias_free(a);
+       free_member(m);
     }
-    TAILQ_FOREACH_SAFE(m, &cmnd_aliases, entries, next) {
+    TAILQ_FOREACH_SAFE(m, &cmnd_aliases, entries, m_next) {
        struct alias *a = alias_remove(m->name, CMNDALIAS);
        alias_free(a);
+       free_member(m);
     }
 
     debug_return;
index a88dea3a687cbc355ce4f5a0c87cec5c6c3ab3ce..c0ef367c188c6c72b00ba25132186c23db33027f 100644 (file)
@@ -878,8 +878,10 @@ free_default(struct defaults *def, struct member_list **binding)
 
     if (def->binding != *binding) {
        *binding = def->binding;
-       free_members(def->binding);
-       free(def->binding);
+       if (def->binding != NULL) {
+           free_members(def->binding);
+           free(def->binding);
+       }
     }
     rcstr_delref(def->file);
     free(def->var);
@@ -1044,7 +1046,7 @@ init_options(struct command_options *opts)
     opts->limitprivs = NULL;
 #endif
 }
-#line 995 "gram.c"
+#line 997 "gram.c"
 /* allocate initial stack or double stack size, up to YYMAXDEPTH */
 #if defined(__cplusplus) || defined(__STDC__)
 static int yygrowstack(void)
@@ -2169,7 +2171,7 @@ case 116:
                            }
                        }
 break;
-#line 2120 "gram.c"
+#line 2122 "gram.c"
     }
     yyssp -= yym;
     yystate = *yyssp;
index a6556ec473111a2e3c7864bf26a623b5da32bcda..489c98f0f7810fe61b5d04104dc28c6c6515d92c 100644 (file)
@@ -1106,8 +1106,10 @@ free_default(struct defaults *def, struct member_list **binding)
 
     if (def->binding != *binding) {
        *binding = def->binding;
-       free_members(def->binding);
-       free(def->binding);
+       if (def->binding != NULL) {
+           free_members(def->binding);
+           free(def->binding);
+       }
     }
     rcstr_delref(def->file);
     free(def->var);