From bc5e2d06a7a39e8bed61b57285a8e2af35d25448 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Wed, 21 Mar 2018 12:11:19 -0600 Subject: [PATCH] Add free_default() to free a struct defaults pointer so we have a single place where we free the defaults. A pointer to the previous Default's binding may be passed in to avoid freeing an already free binding. --- plugins/sudoers/defaults.c | 6 ++-- plugins/sudoers/gram.c | 57 ++++++++++++++++++++++++++------------ plugins/sudoers/gram.y | 53 ++++++++++++++++++++++++----------- plugins/sudoers/parse.h | 1 + 4 files changed, 80 insertions(+), 37 deletions(-) diff --git a/plugins/sudoers/defaults.c b/plugins/sudoers/defaults.c index 69766a81d..b6ba7fad5 100644 --- a/plugins/sudoers/defaults.c +++ b/plugins/sudoers/defaults.c @@ -457,7 +457,7 @@ run_early_defaults(void) } static void -free_default(int type, union sudo_defs_val *sd_un) +free_defs_val(int type, union sudo_defs_val *sd_un) { switch (type & T_MASK) { case T_STR: @@ -484,7 +484,7 @@ init_defaults(void) /* Clear any old settings. */ if (!firsttime) { for (def = sudo_defs_table; def->name != NULL; def++) - free_default(def->type, &def->sd_un); + free_defs_val(def->type, &def->sd_un); } /* First initialize the flags. */ @@ -800,7 +800,7 @@ check_defaults(bool quiet) memset(&sd_un, 0, sizeof(sd_un)); if (parse_default_entry(def, d->val, d->op, &sd_un, d->file, d->lineno, quiet)) { - free_default(def->type, &sd_un); + free_defs_val(def->type, &sd_un); continue; } } diff --git a/plugins/sudoers/gram.c b/plugins/sudoers/gram.c index 2a7ddf234..ba5803745 100644 --- a/plugins/sudoers/gram.c +++ b/plugins/sudoers/gram.c @@ -837,6 +837,8 @@ add_userspec(struct member *members, struct privilege *privs) void free_member(struct member *m) { + debug_decl(free_member, SUDOERS_DEBUG_PARSER) + if (m->type == COMMAND) { struct sudo_command *c = (struct sudo_command *)m->name; free(c->cmnd); @@ -848,6 +850,8 @@ free_member(struct member *m) } free(m->name); free(m); + + debug_return; } /* @@ -857,17 +861,39 @@ void free_members(struct member_list *members) { struct member *m; + debug_decl(free_members, SUDOERS_DEBUG_PARSER) while ((m = TAILQ_FIRST(members)) != NULL) { TAILQ_REMOVE(members, m, entries); free_member(m); } + + debug_return; +} + +struct member_list * +free_default(struct defaults *def, struct member_list *binding) +{ + debug_decl(free_default, SUDOERS_DEBUG_PARSER) + + if (def->binding != binding) { + binding = def->binding; + free_members(def->binding); + free(def->binding); + } + rcstr_delref(def->file); + free(def->var); + free(def->val); + free(def); + + debug_return_ptr(binding); } void free_privilege(struct privilege *priv) { struct member_list *runasuserlist = NULL, *runasgrouplist = NULL; + struct member_list *binding = NULL; struct cmndspec *cs; struct defaults *def; #ifdef HAVE_SELINUX @@ -876,6 +902,7 @@ free_privilege(struct privilege *priv) #ifdef HAVE_PRIV_SET char *privs = NULL, *limitprivs = NULL; #endif /* HAVE_PRIV_SET */ + debug_decl(free_privilege, SUDOERS_DEBUG_PARSER) free(priv->ldap_role); free_members(&priv->hostlist); @@ -919,11 +946,11 @@ free_privilege(struct privilege *priv) } while ((def = TAILQ_FIRST(&priv->defaults)) != NULL) { TAILQ_REMOVE(&priv->defaults, def, entries); - free(def->var); - free(def->val); - free(def); + binding = free_default(def, binding); } free(priv); + + debug_return; } void @@ -931,6 +958,7 @@ free_userspec(struct userspec *us) { struct privilege *priv; struct sudoers_comment *comment; + debug_decl(free_userspec, SUDOERS_DEBUG_PARSER) free_members(&us->users); while ((priv = TAILQ_FIRST(&us->privileges)) != NULL) { @@ -944,6 +972,8 @@ free_userspec(struct userspec *us) } rcstr_delref(us->file); free(us); + + debug_return; } /* @@ -953,8 +983,8 @@ free_userspec(struct userspec *us) bool init_parser(const char *path, bool quiet) { - struct member_list *binding; - struct defaults *d; + struct member_list *binding = NULL; + struct defaults *def; struct userspec *us; bool ret = true; void *next; @@ -965,17 +995,8 @@ init_parser(const char *path, bool quiet) } TAILQ_INIT(&userspecs); - binding = NULL; - TAILQ_FOREACH_SAFE(d, &defaults, entries, next) { - if (d->binding != binding) { - binding = d->binding; - free_members(d->binding); - free(d->binding); - } - rcstr_delref(d->file); - free(d->var); - free(d->val); - free(d); + TAILQ_FOREACH_SAFE(def, &defaults, entries, next) { + binding = free_default(def, binding); } TAILQ_INIT(&defaults); @@ -1023,7 +1044,7 @@ init_options(struct command_options *opts) opts->limitprivs = NULL; #endif } -#line 974 "gram.c" +#line 995 "gram.c" /* allocate initial stack or double stack size, up to YYMAXDEPTH */ #if defined(__cplusplus) || defined(__STDC__) static int yygrowstack(void) @@ -2148,7 +2169,7 @@ case 116: } } break; -#line 2099 "gram.c" +#line 2120 "gram.c" } yyssp -= yym; yystate = *yyssp; diff --git a/plugins/sudoers/gram.y b/plugins/sudoers/gram.y index 1f36c5057..59f40b25e 100644 --- a/plugins/sudoers/gram.y +++ b/plugins/sudoers/gram.y @@ -1065,6 +1065,8 @@ add_userspec(struct member *members, struct privilege *privs) void free_member(struct member *m) { + debug_decl(free_member, SUDOERS_DEBUG_PARSER) + if (m->type == COMMAND) { struct sudo_command *c = (struct sudo_command *)m->name; free(c->cmnd); @@ -1076,6 +1078,8 @@ free_member(struct member *m) } free(m->name); free(m); + + debug_return; } /* @@ -1085,17 +1089,39 @@ void free_members(struct member_list *members) { struct member *m; + debug_decl(free_members, SUDOERS_DEBUG_PARSER) while ((m = TAILQ_FIRST(members)) != NULL) { TAILQ_REMOVE(members, m, entries); free_member(m); } + + debug_return; +} + +struct member_list * +free_default(struct defaults *def, struct member_list *binding) +{ + debug_decl(free_default, SUDOERS_DEBUG_PARSER) + + if (def->binding != binding) { + binding = def->binding; + free_members(def->binding); + free(def->binding); + } + rcstr_delref(def->file); + free(def->var); + free(def->val); + free(def); + + debug_return_ptr(binding); } void free_privilege(struct privilege *priv) { struct member_list *runasuserlist = NULL, *runasgrouplist = NULL; + struct member_list *binding = NULL; struct cmndspec *cs; struct defaults *def; #ifdef HAVE_SELINUX @@ -1104,6 +1130,7 @@ free_privilege(struct privilege *priv) #ifdef HAVE_PRIV_SET char *privs = NULL, *limitprivs = NULL; #endif /* HAVE_PRIV_SET */ + debug_decl(free_privilege, SUDOERS_DEBUG_PARSER) free(priv->ldap_role); free_members(&priv->hostlist); @@ -1147,11 +1174,11 @@ free_privilege(struct privilege *priv) } while ((def = TAILQ_FIRST(&priv->defaults)) != NULL) { TAILQ_REMOVE(&priv->defaults, def, entries); - free(def->var); - free(def->val); - free(def); + binding = free_default(def, binding); } free(priv); + + debug_return; } void @@ -1159,6 +1186,7 @@ free_userspec(struct userspec *us) { struct privilege *priv; struct sudoers_comment *comment; + debug_decl(free_userspec, SUDOERS_DEBUG_PARSER) free_members(&us->users); while ((priv = TAILQ_FIRST(&us->privileges)) != NULL) { @@ -1172,6 +1200,8 @@ free_userspec(struct userspec *us) } rcstr_delref(us->file); free(us); + + debug_return; } /* @@ -1181,8 +1211,8 @@ free_userspec(struct userspec *us) bool init_parser(const char *path, bool quiet) { - struct member_list *binding; - struct defaults *d; + struct member_list *binding = NULL; + struct defaults *def; struct userspec *us; bool ret = true; void *next; @@ -1193,17 +1223,8 @@ init_parser(const char *path, bool quiet) } TAILQ_INIT(&userspecs); - binding = NULL; - TAILQ_FOREACH_SAFE(d, &defaults, entries, next) { - if (d->binding != binding) { - binding = d->binding; - free_members(d->binding); - free(d->binding); - } - rcstr_delref(d->file); - free(d->var); - free(d->val); - free(d); + TAILQ_FOREACH_SAFE(def, &defaults, entries, next) { + binding = free_default(def, binding); } TAILQ_INIT(&defaults); diff --git a/plugins/sudoers/parse.h b/plugins/sudoers/parse.h index 85c9e750b..347baa77c 100644 --- a/plugins/sudoers/parse.h +++ b/plugins/sudoers/parse.h @@ -268,6 +268,7 @@ void free_member(struct member *m); void free_members(struct member_list *members); void free_privilege(struct privilege *priv); void free_userspec(struct userspec *us); +struct member_list *free_default(struct defaults *def, struct member_list *binding); /* match_addr.c */ bool addr_matches(char *n); -- 2.50.1