diff options
author | Alan Jenkins <alan-jenkins@tuffmail.co.uk> | 2010-02-26 14:48:27 +0000 |
---|---|---|
committer | Alan Jenkins <alan-jenkins@tuffmail.co.uk> | 2010-03-02 09:10:14 +0000 |
commit | eb1e17254348d2c9b209439826306327663e1c14 (patch) | |
tree | 2656052f20e49b9f351737c146667169fb13fe53 | |
parent | 4ad092b0bf31c28ccd5c03a7d86e93eba688044b (diff) | |
download | module-init-tools-eb1e17254348d2c9b209439826306327663e1c14.tar.gz |
modprobe: clean up minor memory leaks
- "struct module"
- use of setenv()
- internal node leak in index_search() and index_searchwild()
- some of the more obscure modprobe options, which were bypassing the
cleanup code in main()
I can see only one more leak (which occurred during the softdep work):
- the contents of "struct modprobe_conf"
-rw-r--r-- | index.c | 15 | ||||
-rw-r--r-- | modprobe.c | 46 |
2 files changed, 47 insertions, 14 deletions
@@ -624,6 +624,7 @@ char *index_search(struct index_file *in, const char *key) static char *index_search__node(struct index_node_f *node, const char *key, int i) { + char *value; struct index_node_f *child; int ch; int j; @@ -640,10 +641,13 @@ static char *index_search__node(struct index_node_f *node, const char *key, int i += j; if (key[i] == '\0') { - if (node->values) - return strdup(node->values[0].value); - else + if (node->values) { + value = strdup(node->values[0].value); + index_close(node); + return value; + } else { return NULL; + } } child = index_readchild(node, key[i]); @@ -784,9 +788,10 @@ static void index_searchwild__all(struct index_node_f *node, int j, if (node->values) { if (fnmatch(buf_str(buf), subkey, 0) == 0) index_searchwild__allvalues(node, out); + } else { + index_close(node); } - index_close(node); buf_popchars(buf, pushed); } @@ -797,4 +802,6 @@ static void index_searchwild__allvalues(struct index_node_f *node, for (v = node->values; v != NULL; v = v->next) add_value(out, v->value, v->priority); + + index_close(node); } @@ -145,6 +145,12 @@ static void add_module(char *filename, int namelen, struct list_head *list) list_add_tail(&mod->list, list); } +static void free_module(struct module *mod) +{ + free(mod->modname); + free(mod); +} + /* Compare len chars of a to b, with _ and - equivalent. */ static int modname_equal(const char *a, const char *b, unsigned int len) { @@ -453,6 +459,19 @@ add_alias(const char *modname, struct module_alias *aliases) return new; } +static void free_aliases(struct module_alias *alias_list) +{ + while (alias_list) { + struct module_alias *alias; + + alias = alias_list; + alias_list = alias_list->next; + + free(alias->module); + free(alias); + } +} + /* Link in a new blacklist line from the config file. */ static struct module_blacklist * add_blacklist(const char *modname, struct module_blacklist *blacklist) @@ -1081,6 +1100,7 @@ static void add_to_env_var(const char *option) char *newenv; nofail_asprintf(&newenv, "%s %s", oldenv, option); setenv("MODPROBE_OPTIONS", newenv, 1); + free(newenv); } else setenv("MODPROBE_OPTIONS", option, 1); } @@ -1159,12 +1179,14 @@ static void do_command(const char *modname, info("%s %s\n", type, replaced_cmd); if (dry_run) - return; + goto out; setenv("MODPROBE_MODULE", modname, 1); ret = system(replaced_cmd); if (ret == -1 || WEXITSTATUS(ret)) error("Error running %s command for %s\n", type, modname); + +out: free(replaced_cmd); } @@ -1342,6 +1364,7 @@ static int insmod(struct list_head *list, close_file(fd); out_optstring: free(optstring); + free_module(mod); return rc; } @@ -1415,6 +1438,7 @@ static void rmmod(struct list_head *list, rmmod(list, NULL, softdeps, commands, "", configname, dirname, warn, flags); } + free_module(mod); return; nonexistent_module: @@ -1501,6 +1525,7 @@ int do_modprobe(const char *modulename, { char *modname; struct modprobe_conf conf = {}; + struct module_alias *filtered_aliases; LIST_HEAD(list); int failed = 0; @@ -1547,17 +1572,17 @@ int do_modprobe(const char *modulename, } } - conf.aliases = apply_blacklist(conf.aliases, conf.blacklist); + filtered_aliases = apply_blacklist(conf.aliases, conf.blacklist); if(flags & mit_resolve_alias) { - struct module_alias *aliases = conf.aliases; + struct module_alias *aliases = filtered_aliases; for(; aliases; aliases=aliases->next) printf("%s\n", aliases->module); goto out; } - if (conf.aliases) { + if (filtered_aliases) { errfn_t err = error; - struct module_alias *aliases = conf.aliases; + struct module_alias *aliases = filtered_aliases; /* More than one alias? Don't bail out on failure. */ if (aliases->next) @@ -1587,6 +1612,7 @@ int do_modprobe(const char *modulename, } out: free(modname); + free_aliases(filtered_aliases); return failed; } @@ -1745,7 +1771,8 @@ int main(int argc, char *argv[]) if (optind+1 < argc) fatal("Can't have multiple wildcards\n"); /* fprintf(stderr, "man find\n"); return 1; */ - return do_wildcard(dirname, type, argv[optind]?:"*"); + failed = do_wildcard(dirname, type, argv[optind]?:"*"); + goto out; } if (type) fatal("-t only supported with -l"); @@ -1763,9 +1790,7 @@ int main(int argc, char *argv[]) read_aliases(aliasfilename, "", 1, &conf.aliases); read_aliases(symfilename, "", 1, &conf.aliases); - free(dirname); - free(aliasfilename); - exit(0); + goto out; } if ((flags & mit_remove) || all) { @@ -1787,9 +1812,10 @@ int main(int argc, char *argv[]) configname, dirname, error, flags); } + +out: if (logging) closelog(); - free(dirname); free(cmdline_opts); |