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.
This commit is contained in:
Todd C. Miller
2018-03-21 12:11:19 -06:00
parent b6c53ac846
commit bc5e2d06a7
4 changed files with 80 additions and 37 deletions

View File

@@ -457,7 +457,7 @@ run_early_defaults(void)
} }
static 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) { switch (type & T_MASK) {
case T_STR: case T_STR:
@@ -484,7 +484,7 @@ init_defaults(void)
/* Clear any old settings. */ /* Clear any old settings. */
if (!firsttime) { if (!firsttime) {
for (def = sudo_defs_table; def->name != NULL; def++) 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. */ /* First initialize the flags. */
@@ -800,7 +800,7 @@ check_defaults(bool quiet)
memset(&sd_un, 0, sizeof(sd_un)); memset(&sd_un, 0, sizeof(sd_un));
if (parse_default_entry(def, d->val, d->op, &sd_un, d->file, if (parse_default_entry(def, d->val, d->op, &sd_un, d->file,
d->lineno, quiet)) { d->lineno, quiet)) {
free_default(def->type, &sd_un); free_defs_val(def->type, &sd_un);
continue; continue;
} }
} }

View File

@@ -837,6 +837,8 @@ add_userspec(struct member *members, struct privilege *privs)
void void
free_member(struct member *m) free_member(struct member *m)
{ {
debug_decl(free_member, SUDOERS_DEBUG_PARSER)
if (m->type == COMMAND) { if (m->type == COMMAND) {
struct sudo_command *c = (struct sudo_command *)m->name; struct sudo_command *c = (struct sudo_command *)m->name;
free(c->cmnd); free(c->cmnd);
@@ -848,6 +850,8 @@ free_member(struct member *m)
} }
free(m->name); free(m->name);
free(m); free(m);
debug_return;
} }
/* /*
@@ -857,17 +861,39 @@ void
free_members(struct member_list *members) free_members(struct member_list *members)
{ {
struct member *m; struct member *m;
debug_decl(free_members, SUDOERS_DEBUG_PARSER)
while ((m = TAILQ_FIRST(members)) != NULL) { while ((m = TAILQ_FIRST(members)) != NULL) {
TAILQ_REMOVE(members, m, entries); TAILQ_REMOVE(members, m, entries);
free_member(m); 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 void
free_privilege(struct privilege *priv) free_privilege(struct privilege *priv)
{ {
struct member_list *runasuserlist = NULL, *runasgrouplist = NULL; struct member_list *runasuserlist = NULL, *runasgrouplist = NULL;
struct member_list *binding = NULL;
struct cmndspec *cs; struct cmndspec *cs;
struct defaults *def; struct defaults *def;
#ifdef HAVE_SELINUX #ifdef HAVE_SELINUX
@@ -876,6 +902,7 @@ free_privilege(struct privilege *priv)
#ifdef HAVE_PRIV_SET #ifdef HAVE_PRIV_SET
char *privs = NULL, *limitprivs = NULL; char *privs = NULL, *limitprivs = NULL;
#endif /* HAVE_PRIV_SET */ #endif /* HAVE_PRIV_SET */
debug_decl(free_privilege, SUDOERS_DEBUG_PARSER)
free(priv->ldap_role); free(priv->ldap_role);
free_members(&priv->hostlist); free_members(&priv->hostlist);
@@ -919,11 +946,11 @@ free_privilege(struct privilege *priv)
} }
while ((def = TAILQ_FIRST(&priv->defaults)) != NULL) { while ((def = TAILQ_FIRST(&priv->defaults)) != NULL) {
TAILQ_REMOVE(&priv->defaults, def, entries); TAILQ_REMOVE(&priv->defaults, def, entries);
free(def->var); binding = free_default(def, binding);
free(def->val);
free(def);
} }
free(priv); free(priv);
debug_return;
} }
void void
@@ -931,6 +958,7 @@ free_userspec(struct userspec *us)
{ {
struct privilege *priv; struct privilege *priv;
struct sudoers_comment *comment; struct sudoers_comment *comment;
debug_decl(free_userspec, SUDOERS_DEBUG_PARSER)
free_members(&us->users); free_members(&us->users);
while ((priv = TAILQ_FIRST(&us->privileges)) != NULL) { while ((priv = TAILQ_FIRST(&us->privileges)) != NULL) {
@@ -944,6 +972,8 @@ free_userspec(struct userspec *us)
} }
rcstr_delref(us->file); rcstr_delref(us->file);
free(us); free(us);
debug_return;
} }
/* /*
@@ -953,8 +983,8 @@ free_userspec(struct userspec *us)
bool bool
init_parser(const char *path, bool quiet) init_parser(const char *path, bool quiet)
{ {
struct member_list *binding; struct member_list *binding = NULL;
struct defaults *d; struct defaults *def;
struct userspec *us; struct userspec *us;
bool ret = true; bool ret = true;
void *next; void *next;
@@ -965,17 +995,8 @@ init_parser(const char *path, bool quiet)
} }
TAILQ_INIT(&userspecs); TAILQ_INIT(&userspecs);
binding = NULL; TAILQ_FOREACH_SAFE(def, &defaults, entries, next) {
TAILQ_FOREACH_SAFE(d, &defaults, entries, next) { binding = free_default(def, binding);
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_INIT(&defaults); TAILQ_INIT(&defaults);
@@ -1023,7 +1044,7 @@ init_options(struct command_options *opts)
opts->limitprivs = NULL; opts->limitprivs = NULL;
#endif #endif
} }
#line 974 "gram.c" #line 995 "gram.c"
/* allocate initial stack or double stack size, up to YYMAXDEPTH */ /* allocate initial stack or double stack size, up to YYMAXDEPTH */
#if defined(__cplusplus) || defined(__STDC__) #if defined(__cplusplus) || defined(__STDC__)
static int yygrowstack(void) static int yygrowstack(void)
@@ -2148,7 +2169,7 @@ case 116:
} }
} }
break; break;
#line 2099 "gram.c" #line 2120 "gram.c"
} }
yyssp -= yym; yyssp -= yym;
yystate = *yyssp; yystate = *yyssp;

View File

@@ -1065,6 +1065,8 @@ add_userspec(struct member *members, struct privilege *privs)
void void
free_member(struct member *m) free_member(struct member *m)
{ {
debug_decl(free_member, SUDOERS_DEBUG_PARSER)
if (m->type == COMMAND) { if (m->type == COMMAND) {
struct sudo_command *c = (struct sudo_command *)m->name; struct sudo_command *c = (struct sudo_command *)m->name;
free(c->cmnd); free(c->cmnd);
@@ -1076,6 +1078,8 @@ free_member(struct member *m)
} }
free(m->name); free(m->name);
free(m); free(m);
debug_return;
} }
/* /*
@@ -1085,17 +1089,39 @@ void
free_members(struct member_list *members) free_members(struct member_list *members)
{ {
struct member *m; struct member *m;
debug_decl(free_members, SUDOERS_DEBUG_PARSER)
while ((m = TAILQ_FIRST(members)) != NULL) { while ((m = TAILQ_FIRST(members)) != NULL) {
TAILQ_REMOVE(members, m, entries); TAILQ_REMOVE(members, m, entries);
free_member(m); 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 void
free_privilege(struct privilege *priv) free_privilege(struct privilege *priv)
{ {
struct member_list *runasuserlist = NULL, *runasgrouplist = NULL; struct member_list *runasuserlist = NULL, *runasgrouplist = NULL;
struct member_list *binding = NULL;
struct cmndspec *cs; struct cmndspec *cs;
struct defaults *def; struct defaults *def;
#ifdef HAVE_SELINUX #ifdef HAVE_SELINUX
@@ -1104,6 +1130,7 @@ free_privilege(struct privilege *priv)
#ifdef HAVE_PRIV_SET #ifdef HAVE_PRIV_SET
char *privs = NULL, *limitprivs = NULL; char *privs = NULL, *limitprivs = NULL;
#endif /* HAVE_PRIV_SET */ #endif /* HAVE_PRIV_SET */
debug_decl(free_privilege, SUDOERS_DEBUG_PARSER)
free(priv->ldap_role); free(priv->ldap_role);
free_members(&priv->hostlist); free_members(&priv->hostlist);
@@ -1147,11 +1174,11 @@ free_privilege(struct privilege *priv)
} }
while ((def = TAILQ_FIRST(&priv->defaults)) != NULL) { while ((def = TAILQ_FIRST(&priv->defaults)) != NULL) {
TAILQ_REMOVE(&priv->defaults, def, entries); TAILQ_REMOVE(&priv->defaults, def, entries);
free(def->var); binding = free_default(def, binding);
free(def->val);
free(def);
} }
free(priv); free(priv);
debug_return;
} }
void void
@@ -1159,6 +1186,7 @@ free_userspec(struct userspec *us)
{ {
struct privilege *priv; struct privilege *priv;
struct sudoers_comment *comment; struct sudoers_comment *comment;
debug_decl(free_userspec, SUDOERS_DEBUG_PARSER)
free_members(&us->users); free_members(&us->users);
while ((priv = TAILQ_FIRST(&us->privileges)) != NULL) { while ((priv = TAILQ_FIRST(&us->privileges)) != NULL) {
@@ -1172,6 +1200,8 @@ free_userspec(struct userspec *us)
} }
rcstr_delref(us->file); rcstr_delref(us->file);
free(us); free(us);
debug_return;
} }
/* /*
@@ -1181,8 +1211,8 @@ free_userspec(struct userspec *us)
bool bool
init_parser(const char *path, bool quiet) init_parser(const char *path, bool quiet)
{ {
struct member_list *binding; struct member_list *binding = NULL;
struct defaults *d; struct defaults *def;
struct userspec *us; struct userspec *us;
bool ret = true; bool ret = true;
void *next; void *next;
@@ -1193,17 +1223,8 @@ init_parser(const char *path, bool quiet)
} }
TAILQ_INIT(&userspecs); TAILQ_INIT(&userspecs);
binding = NULL; TAILQ_FOREACH_SAFE(def, &defaults, entries, next) {
TAILQ_FOREACH_SAFE(d, &defaults, entries, next) { binding = free_default(def, binding);
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_INIT(&defaults); TAILQ_INIT(&defaults);

View File

@@ -268,6 +268,7 @@ void free_member(struct member *m);
void free_members(struct member_list *members); void free_members(struct member_list *members);
void free_privilege(struct privilege *priv); void free_privilege(struct privilege *priv);
void free_userspec(struct userspec *us); void free_userspec(struct userspec *us);
struct member_list *free_default(struct defaults *def, struct member_list *binding);
/* match_addr.c */ /* match_addr.c */
bool addr_matches(char *n); bool addr_matches(char *n);