The while loop for -a or -r was forgetting that argv is a char**. Also:
* sort the options in the help. * remove DBASE_SIZE and the comment about keeping it up to date, since we can just use ARRAY_LEN instead (though I wonder whether anyone has enough modules to benefit from a hash table rather than just a list?). * fix the comment explaining why read_line() exists. * fix a typo 'aliase' for 'alias'. * fix bad intentation in depmode_read_entry(). * simplify rm_mod() since no-one was relying on the return value being errno, the O_EXCL flag is irrelevant (but ignored by the kernel), and all callers want the same flags. * simplify ins_mod() because even CentOS 7.2 has finit_module(2), and unlike insmod(1) -- which I've touched in a separate patch -- modprobe doesn't need to handle loading a module from stdin. --- toys/pending/modprobe.c | 75 ++++++++++++----------------------------- 1 file changed, 22 insertions(+), 53 deletions(-)
From df632c6991ea088afc1ff7630c75421993c384c2 Mon Sep 17 00:00:00 2001 From: Elliott Hughes <e...@google.com> Date: Sat, 11 Sep 2021 11:23:21 -0700 Subject: [PATCH 2/2] modprobe: handle module lists correctly. The while loop for -a or -r was forgetting that argv is a char**. Also: * sort the options in the help. * remove DBASE_SIZE and the comment about keeping it up to date, since we can just use ARRAY_LEN instead (though I wonder whether anyone has enough modules to benefit from a hash table rather than just a list?). * fix the comment explaining why read_line() exists. * fix a typo 'aliase' for 'alias'. * fix bad intentation in depmode_read_entry(). * simplify rm_mod() since no-one was relying on the return value being errno, the O_EXCL flag is irrelevant (but ignored by the kernel), and all callers want the same flags. * simplify ins_mod() because even CentOS 7.2 has finit_module(2), and unlike insmod(1) -- which I've touched in a separate patch -- modprobe doesn't need to handle loading a module from stdin. --- toys/pending/modprobe.c | 75 ++++++++++++----------------------------- 1 file changed, 22 insertions(+), 53 deletions(-) diff --git a/toys/pending/modprobe.c b/toys/pending/modprobe.c index a3f5bb9e..fcd1cc3e 100644 --- a/toys/pending/modprobe.c +++ b/toys/pending/modprobe.c @@ -16,14 +16,14 @@ config MODPROBE modprobe utility - inserts modules and dependencies. -a Load multiple MODULEs + -b Apply blacklist to module names too + -D Show dependencies -d Load modules from DIR, option may be used multiple times -l List (MODULE is a pattern) - -r Remove MODULE (stacks) or do autoclean -q Quiet - -v Verbose + -r Remove MODULE (stacks) or do autoclean -s Log to syslog - -D Show dependencies - -b Apply blacklist to module names too + -v Verbose */ #define FOR_modprobe #include "toys.h" @@ -37,10 +37,6 @@ GLOBALS( int nudeps, symreq; ) -/* Note: if "#define DBASE_SIZE" modified, - * Please update GLOBALS dbase[256] accordingly. - */ -#define DBASE_SIZE 256 #define MODNAME_LEN 256 // Modules flag definations @@ -146,7 +142,7 @@ static struct module_s *get_mod(char *mod, uint8_t add) path2mod(mod, name); for (i = 0; name[i]; i++) hash = ((hash*31) + hash) + name[i]; - hash %= DBASE_SIZE; + hash %= ARRAY_LEN(TT.dbase); for (temp = TT.dbase[hash]; temp; temp = temp->next) { modentry = (struct module_s *) temp->arg; if (!strcmp(modentry->name, name)) return modentry; @@ -159,7 +155,7 @@ static struct module_s *get_mod(char *mod, uint8_t add) } /* - * Read a line from file with \ continuation and escape commented line. + * Read a line from file with \ continuation and skip commented lines. * Return the line in allocated string (*li) */ static int read_line(FILE *fl, char **li) @@ -243,13 +239,13 @@ static int config_action(struct dirtree *node) // process the tokens[0] contains first word of config line. if (!strcmp(tokens[0], "alias")) { struct arg_list *temp; - char aliase[MODNAME_LEN], *realname; + char alias[MODNAME_LEN], *realname; if (!tokens[2]) continue; - path2mod(tokens[1], aliase); + path2mod(tokens[1], alias); for (temp = TT.probes; temp; temp = temp->next) { modent = (struct module_s *) temp->arg; - if (fnmatch(aliase, modent->name, 0)) continue; + if (fnmatch(alias, modent->name, 0)) continue; realname = path2mod(tokens[2], NULL); llist_add(&modent->rnames, realname); if (modent->flags & MOD_NDDEPS) { @@ -283,7 +279,7 @@ static int config_action(struct dirtree *node) // Show matched modules else return -1 on failure. static int depmode_read_entry(char *cmdname) { - char *line; + char *line, *name; int ret = -1; FILE *fe = xfopen("modules.dep", "r"); @@ -292,8 +288,7 @@ static int depmode_read_entry(char *cmdname) if (tmp) { *tmp = '\0'; - char *name = basename(line); - + name = basename(line); tmp = strchr(name, '.'); if (tmp) *tmp = '\0'; if (!cmdname || !fnmatch(cmdname, name, 0)) { @@ -344,47 +339,22 @@ static void find_dep(void) } // Remove a module from the Linux Kernel. if !modules does auto remove. -static int rm_mod(char *modules, unsigned flags) +static int rm_mod(char *modules) { char *s; if (modules && (s = strend(modules, ".ko"))) *s = 0; - errno = 0; - syscall(__NR_delete_module, modules, flags ? : O_NONBLOCK|O_EXCL); - - return errno; + return syscall(__NR_delete_module, modules, O_NONBLOCK); } -// Insert module same as insmod implementation. +// Insert module; simpler than insmod(1) because we already flattened the array +// of flags, and don't need to support loading from stdin. static int ins_mod(char *modules, char *flags) { - char *buf = NULL; - int len, res; - int fd = xopenro(modules); - - while (flags && strlen(toybuf) + strlen(flags) + 2 < sizeof(toybuf)) { - strcat(toybuf, flags); - strcat(toybuf, " "); - } - -#ifdef __NR_finit_module - res = syscall(__NR_finit_module, fd, toybuf, 0); - if (!res || errno != ENOSYS) { - xclose(fd); - return res; - } -#endif + int fd = xopenro(modules), rc = syscall(__NR_finit_module, fd, flags, 0); - // TODO xreadfile() - - len = fdlength(fd); - buf = xmalloc(len); - xreadall(fd, buf, len); xclose(fd); - - res = syscall(__NR_init_module, buf, len, toybuf); - if (CFG_TOYBOX_FREE && buf != toybuf) free(buf); - return res; + return rc; } // Add module in probes list, if not loaded. @@ -425,13 +395,13 @@ static char *add_cmdopt(char **argv) } // Probes a single module and loads all its dependencies. -static int go_probe(struct module_s *m) +static void go_probe(struct module_s *m) { int rc = 0, first = 1; if (!(m->flags & MOD_FNDDEPMOD)) { if (!FLAG(q)) error_msg("module %s not found in modules.dep", m->name); - return -ENOENT; + return; } if (FLAG(v)) printf("go_prob'ing %s\n", m->name); if (!FLAG(r)) m->dep = llist_rev(m->dep); @@ -446,7 +416,7 @@ static int go_probe(struct module_s *m) // are we removing ? if (FLAG(r)) { if (m2->flags & MOD_ALOADED) { - if ((rc = rm_mod(m2->name, O_EXCL))) { + if (rm_mod(m2->name)) { if (first) { perror_msg("can't unload module %s", m2->name); break; @@ -486,7 +456,6 @@ static int go_probe(struct module_s *m) } m2->flags |= MOD_ALOADED; } - return rc; } void modprobe_main(void) @@ -499,7 +468,7 @@ void modprobe_main(void) if (toys.optc<1 && !FLAG(r) == !FLAG(l)) help_exit("bad syntax"); // Check for -r flag without arg if yes then do auto remove. if (FLAG(r) && !toys.optc) { - if (rm_mod(0, O_NONBLOCK|O_EXCL)) perror_exit("rmmod"); + if (rm_mod(0)) perror_exit("rmmod"); return; } @@ -530,7 +499,7 @@ void modprobe_main(void) procline = NULL; } fclose(fs); - if (FLAG(a) || FLAG(r)) while (argv) add_mod(*argv++); + if (FLAG(a) || FLAG(r)) for (; *argv; argv++) add_mod(*argv); else { add_mod(*argv); TT.cmdopts = add_cmdopt(argv); -- 2.33.0.309.g3052b89438-goog
_______________________________________________ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net