diff options
Diffstat (limited to 'modutils')
-rw-r--r-- | modutils/depmod.c | 39 | ||||
-rw-r--r-- | modutils/modinfo.c | 14 | ||||
-rw-r--r-- | modutils/modprobe-small.c | 182 | ||||
-rw-r--r-- | modutils/modprobe.c | 48 | ||||
-rw-r--r-- | modutils/modutils-24.c | 2 | ||||
-rw-r--r-- | modutils/modutils.c | 14 |
6 files changed, 178 insertions, 121 deletions
diff --git a/modutils/depmod.c b/modutils/depmod.c index aa228ec85..9713aef92 100644 --- a/modutils/depmod.c +++ b/modutils/depmod.c | |||
@@ -33,7 +33,6 @@ typedef struct module_info { | |||
33 | static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARAM, | 33 | static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARAM, |
34 | void *data, int depth UNUSED_PARAM) | 34 | void *data, int depth UNUSED_PARAM) |
35 | { | 35 | { |
36 | char modname[MODULE_NAME_LEN]; | ||
37 | module_info **first = (module_info **) data; | 36 | module_info **first = (module_info **) data; |
38 | char *image, *ptr; | 37 | char *image, *ptr; |
39 | module_info *info; | 38 | module_info *info; |
@@ -51,9 +50,12 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA | |||
51 | 50 | ||
52 | info->dnext = info->dprev = info; | 51 | info->dnext = info->dprev = info; |
53 | info->name = xstrdup(fname + 2); /* skip "./" */ | 52 | info->name = xstrdup(fname + 2); /* skip "./" */ |
54 | info->modname = xstrdup(filename2modname(fname, modname)); | 53 | info->modname = filename2modname( |
54 | bb_get_last_path_component_nostrip(fname), | ||
55 | NULL | ||
56 | ); | ||
55 | for (ptr = image; ptr < image + len - 10; ptr++) { | 57 | for (ptr = image; ptr < image + len - 10; ptr++) { |
56 | if (strncmp(ptr, "depends=", 8) == 0) { | 58 | if (is_prefixed_with(ptr, "depends=")) { |
57 | char *u; | 59 | char *u; |
58 | 60 | ||
59 | ptr += 8; | 61 | ptr += 8; |
@@ -62,15 +64,15 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA | |||
62 | *u = '_'; | 64 | *u = '_'; |
63 | ptr += string_to_llist(ptr, &info->dependencies, ","); | 65 | ptr += string_to_llist(ptr, &info->dependencies, ","); |
64 | } else if (ENABLE_FEATURE_MODUTILS_ALIAS | 66 | } else if (ENABLE_FEATURE_MODUTILS_ALIAS |
65 | && strncmp(ptr, "alias=", 6) == 0 | 67 | && is_prefixed_with(ptr, "alias=") |
66 | ) { | 68 | ) { |
67 | llist_add_to(&info->aliases, xstrdup(ptr + 6)); | 69 | llist_add_to(&info->aliases, xstrdup(ptr + 6)); |
68 | ptr += strlen(ptr); | 70 | ptr += strlen(ptr); |
69 | } else if (ENABLE_FEATURE_MODUTILS_SYMBOLS | 71 | } else if (ENABLE_FEATURE_MODUTILS_SYMBOLS |
70 | && strncmp(ptr, "__ksymtab_", 10) == 0 | 72 | && is_prefixed_with(ptr, "__ksymtab_") |
71 | ) { | 73 | ) { |
72 | ptr += 10; | 74 | ptr += 10; |
73 | if (strncmp(ptr, "gpl", 3) == 0 | 75 | if (is_prefixed_with(ptr, "gpl") |
74 | || strcmp(ptr, "strings") == 0 | 76 | || strcmp(ptr, "strings") == 0 |
75 | ) { | 77 | ) { |
76 | continue; | 78 | continue; |
@@ -242,17 +244,19 @@ int depmod_main(int argc UNUSED_PARAM, char **argv) | |||
242 | if (!(option_mask32 & OPT_n)) | 244 | if (!(option_mask32 & OPT_n)) |
243 | xfreopen_write("modules.alias", stdout); | 245 | xfreopen_write("modules.alias", stdout); |
244 | for (m = modules; m != NULL; m = m->next) { | 246 | for (m = modules; m != NULL; m = m->next) { |
247 | char modname[MODULE_NAME_LEN]; | ||
245 | const char *fname = bb_basename(m->name); | 248 | const char *fname = bb_basename(m->name); |
246 | int fnlen = strchrnul(fname, '.') - fname; | 249 | filename2modname(fname, modname); |
247 | while (m->aliases) { | 250 | while (m->aliases) { |
248 | /* Last word can well be m->modname instead, | 251 | /* |
249 | * but depmod from module-init-tools 3.4 | 252 | * Last word used to be a basename |
250 | * uses module basename, i.e., no s/-/_/g. | 253 | * (filename with path and .ko.* stripped) |
251 | * (pathname and .ko.* are still stripped) | 254 | * at the time of module-init-tools 3.4. |
252 | * Mimicking that... */ | 255 | * kmod v.12 uses module name, i.e., s/-/_/g. |
253 | printf("alias %s %.*s\n", | 256 | */ |
257 | printf("alias %s %s\n", | ||
254 | (char*)llist_pop(&m->aliases), | 258 | (char*)llist_pop(&m->aliases), |
255 | fnlen, fname); | 259 | modname); |
256 | } | 260 | } |
257 | } | 261 | } |
258 | #endif | 262 | #endif |
@@ -260,12 +264,13 @@ int depmod_main(int argc UNUSED_PARAM, char **argv) | |||
260 | if (!(option_mask32 & OPT_n)) | 264 | if (!(option_mask32 & OPT_n)) |
261 | xfreopen_write("modules.symbols", stdout); | 265 | xfreopen_write("modules.symbols", stdout); |
262 | for (m = modules; m != NULL; m = m->next) { | 266 | for (m = modules; m != NULL; m = m->next) { |
267 | char modname[MODULE_NAME_LEN]; | ||
263 | const char *fname = bb_basename(m->name); | 268 | const char *fname = bb_basename(m->name); |
264 | int fnlen = strchrnul(fname, '.') - fname; | 269 | filename2modname(fname, modname); |
265 | while (m->symbols) { | 270 | while (m->symbols) { |
266 | printf("alias symbol:%s %.*s\n", | 271 | printf("alias symbol:%s %s\n", |
267 | (char*)llist_pop(&m->symbols), | 272 | (char*)llist_pop(&m->symbols), |
268 | fnlen, fname); | 273 | modname); |
269 | } | 274 | } |
270 | } | 275 | } |
271 | #endif | 276 | #endif |
diff --git a/modutils/modinfo.c b/modutils/modinfo.c index 0ab942890..8e74b6438 100644 --- a/modutils/modinfo.c +++ b/modutils/modinfo.c | |||
@@ -62,7 +62,7 @@ static void modinfo(const char *path, const char *version, | |||
62 | "firmware", | 62 | "firmware", |
63 | }; | 63 | }; |
64 | size_t len; | 64 | size_t len; |
65 | int j, length; | 65 | int j; |
66 | char *ptr, *the_module; | 66 | char *ptr, *the_module; |
67 | const char *field = env->field; | 67 | const char *field = env->field; |
68 | int tags = env->tags; | 68 | int tags = env->tags; |
@@ -94,16 +94,18 @@ static void modinfo(const char *path, const char *version, | |||
94 | pattern = field; | 94 | pattern = field; |
95 | if ((1<<j) & OPT_TAGS) | 95 | if ((1<<j) & OPT_TAGS) |
96 | pattern = shortcuts[j]; | 96 | pattern = shortcuts[j]; |
97 | length = strlen(pattern); | ||
98 | ptr = the_module; | 97 | ptr = the_module; |
99 | while (1) { | 98 | while (1) { |
99 | char *after_pattern; | ||
100 | |||
100 | ptr = memchr(ptr, *pattern, len - (ptr - (char*)the_module)); | 101 | ptr = memchr(ptr, *pattern, len - (ptr - (char*)the_module)); |
101 | if (ptr == NULL) /* no occurance left, done */ | 102 | if (ptr == NULL) /* no occurance left, done */ |
102 | break; | 103 | break; |
103 | if (strncmp(ptr, pattern, length) == 0 && ptr[length] == '=') { | 104 | after_pattern = is_prefixed_with(ptr, pattern); |
105 | if (after_pattern && *after_pattern == '=') { | ||
104 | /* field prefixes are 0x80 or 0x00 */ | 106 | /* field prefixes are 0x80 or 0x00 */ |
105 | if ((ptr[-1] & 0x7F) == '\0') { | 107 | if ((ptr[-1] & 0x7F) == 0x00) { |
106 | ptr += length + 1; | 108 | ptr = after_pattern + 1; |
107 | display(ptr, pattern, (1<<j) != tags); | 109 | display(ptr, pattern, (1<<j) != tags); |
108 | ptr += strlen(ptr); | 110 | ptr += strlen(ptr); |
109 | } | 111 | } |
@@ -154,7 +156,7 @@ int modinfo_main(int argc UNUSED_PARAM, char **argv) | |||
154 | if (colon == NULL) | 156 | if (colon == NULL) |
155 | continue; | 157 | continue; |
156 | *colon = '\0'; | 158 | *colon = '\0'; |
157 | filename2modname(tokens[0], name); | 159 | filename2modname(bb_basename(tokens[0]), name); |
158 | for (i = 0; argv[i]; i++) { | 160 | for (i = 0; argv[i]; i++) { |
159 | if (fnmatch(argv[i], name, 0) == 0) { | 161 | if (fnmatch(argv[i], name, 0) == 0) { |
160 | modinfo(tokens[0], uts.release, &env); | 162 | modinfo(tokens[0], uts.release, &env); |
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index b7990bff1..9c941064b 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c | |||
@@ -116,21 +116,21 @@ static char* copy_stringbuf(void) | |||
116 | 116 | ||
117 | static char* find_keyword(char *ptr, size_t len, const char *word) | 117 | static char* find_keyword(char *ptr, size_t len, const char *word) |
118 | { | 118 | { |
119 | int wlen; | ||
120 | |||
121 | if (!ptr) /* happens if xmalloc_open_zipped_read_close cannot read it */ | 119 | if (!ptr) /* happens if xmalloc_open_zipped_read_close cannot read it */ |
122 | return NULL; | 120 | return NULL; |
123 | 121 | ||
124 | wlen = strlen(word); | 122 | len -= strlen(word) - 1; |
125 | len -= wlen - 1; | ||
126 | while ((ssize_t)len > 0) { | 123 | while ((ssize_t)len > 0) { |
127 | char *old = ptr; | 124 | char *old = ptr; |
125 | char *after_word; | ||
126 | |||
128 | /* search for the first char in word */ | 127 | /* search for the first char in word */ |
129 | ptr = memchr(ptr, *word, len); | 128 | ptr = memchr(ptr, word[0], len); |
130 | if (ptr == NULL) /* no occurance left, done */ | 129 | if (ptr == NULL) /* no occurance left, done */ |
131 | break; | 130 | break; |
132 | if (strncmp(ptr, word, wlen) == 0) | 131 | after_word = is_prefixed_with(ptr, word); |
133 | return ptr + wlen; /* found, return ptr past it */ | 132 | if (after_word) |
133 | return after_word; /* found, return ptr past it */ | ||
134 | ++ptr; | 134 | ++ptr; |
135 | len -= (ptr - old); | 135 | len -= (ptr - old); |
136 | } | 136 | } |
@@ -149,9 +149,13 @@ static void replace(char *s, char what, char with) | |||
149 | static char *filename2modname(const char *filename, char *modname) | 149 | static char *filename2modname(const char *filename, char *modname) |
150 | { | 150 | { |
151 | int i; | 151 | int i; |
152 | char *from; | 152 | const char *from; |
153 | 153 | ||
154 | from = bb_get_last_path_component_nostrip(filename); | 154 | // Disabled since otherwise "modprobe dir/name" would work |
155 | // as if it is "modprobe name". It is unclear why | ||
156 | // 'basenamization' was here in the first place. | ||
157 | //from = bb_get_last_path_component_nostrip(filename); | ||
158 | from = filename; | ||
155 | for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++) | 159 | for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++) |
156 | modname[i] = (from[i] == '-') ? '_' : from[i]; | 160 | modname[i] = (from[i] == '-') ? '_' : from[i]; |
157 | modname[i] = '\0'; | 161 | modname[i] = '\0'; |
@@ -159,6 +163,15 @@ static char *filename2modname(const char *filename, char *modname) | |||
159 | return modname; | 163 | return modname; |
160 | } | 164 | } |
161 | 165 | ||
166 | static int pathname_matches_modname(const char *pathname, const char *modname) | ||
167 | { | ||
168 | int r; | ||
169 | char name[MODULE_NAME_LEN]; | ||
170 | filename2modname(bb_get_last_path_component_nostrip(pathname), name); | ||
171 | r = (strcmp(name, modname) == 0); | ||
172 | return r; | ||
173 | } | ||
174 | |||
162 | /* Take "word word", return malloced "word",NUL,"word",NUL,NUL */ | 175 | /* Take "word word", return malloced "word",NUL,"word",NUL,NUL */ |
163 | static char* str_2_list(const char *str) | 176 | static char* str_2_list(const char *str) |
164 | { | 177 | { |
@@ -291,18 +304,6 @@ static void parse_module(module_info *info, const char *pathname) | |||
291 | free(module_image); | 304 | free(module_image); |
292 | } | 305 | } |
293 | 306 | ||
294 | static int pathname_matches_modname(const char *pathname, const char *modname) | ||
295 | { | ||
296 | int r; | ||
297 | char name[MODULE_NAME_LEN]; | ||
298 | const char *fname = bb_get_last_path_component_nostrip(pathname); | ||
299 | const char *suffix = strrstr(fname, ".ko"); | ||
300 | safe_strncpy(name, fname, suffix - fname + 1); | ||
301 | replace(name, '-', '_'); | ||
302 | r = (strcmp(name, modname) == 0); | ||
303 | return r; | ||
304 | } | ||
305 | |||
306 | static FAST_FUNC int fileAction(const char *pathname, | 307 | static FAST_FUNC int fileAction(const char *pathname, |
307 | struct stat *sb UNUSED_PARAM, | 308 | struct stat *sb UNUSED_PARAM, |
308 | void *modname_to_match, | 309 | void *modname_to_match, |
@@ -535,22 +536,69 @@ static module_info** find_alias(const char *alias) | |||
535 | // TODO: open only once, invent config_rewind() | 536 | // TODO: open only once, invent config_rewind() |
536 | static int already_loaded(const char *name) | 537 | static int already_loaded(const char *name) |
537 | { | 538 | { |
538 | int ret = 0; | 539 | int ret; |
539 | char *s; | 540 | char *line; |
540 | parser_t *parser = config_open2("/proc/modules", xfopen_for_read); | 541 | FILE *fp; |
541 | while (config_read(parser, &s, 1, 1, "# \t", PARSE_NORMAL & ~PARSE_GREEDY)) { | 542 | |
542 | if (strcmp(s, name) == 0) { | 543 | ret = 5 * 2; |
543 | ret = 1; | 544 | again: |
544 | break; | 545 | fp = fopen_for_read("/proc/modules"); |
546 | if (!fp) | ||
547 | return 0; | ||
548 | while ((line = xmalloc_fgetline(fp)) != NULL) { | ||
549 | char *live; | ||
550 | char *after_name; | ||
551 | |||
552 | // Examples from kernel 3.14.6: | ||
553 | //pcspkr 12718 0 - Live 0xffffffffa017e000 | ||
554 | //snd_timer 28690 2 snd_seq,snd_pcm, Live 0xffffffffa025e000 | ||
555 | //i915 801405 2 - Live 0xffffffffa0096000 | ||
556 | after_name = is_prefixed_with(line, name); | ||
557 | if (!after_name || *after_name != ' ') { | ||
558 | free(line); | ||
559 | continue; | ||
545 | } | 560 | } |
561 | live = strstr(line, " Live"); | ||
562 | free(line); | ||
563 | if (!live) { | ||
564 | /* State can be Unloading, Loading, or Live. | ||
565 | * modprobe must not return prematurely if we see "Loading": | ||
566 | * it can cause further programs to assume load completed, | ||
567 | * but it did not (yet)! | ||
568 | * Wait up to 5*20 ms for it to resolve. | ||
569 | */ | ||
570 | ret -= 2; | ||
571 | if (ret == 0) | ||
572 | break; /* huh? report as "not loaded" */ | ||
573 | fclose(fp); | ||
574 | usleep(20*1000); | ||
575 | goto again; | ||
576 | } | ||
577 | ret = 1; | ||
578 | break; | ||
546 | } | 579 | } |
547 | config_close(parser); | 580 | fclose(fp); |
548 | return ret; | 581 | |
582 | return ret & 1; | ||
549 | } | 583 | } |
550 | #else | 584 | #else |
551 | #define already_loaded(name) is_rmmod | 585 | #define already_loaded(name) 0 |
552 | #endif | 586 | #endif |
553 | 587 | ||
588 | static int rmmod(const char *filename) | ||
589 | { | ||
590 | int r; | ||
591 | char modname[MODULE_NAME_LEN]; | ||
592 | |||
593 | filename2modname(filename, modname); | ||
594 | r = delete_module(modname, O_NONBLOCK | O_EXCL); | ||
595 | dbg1_error_msg("delete_module('%s', O_NONBLOCK | O_EXCL):%d", modname, r); | ||
596 | if (r != 0 && !(option_mask32 & OPT_q)) { | ||
597 | bb_perror_msg("remove '%s'", modname); | ||
598 | } | ||
599 | return r; | ||
600 | } | ||
601 | |||
554 | /* | 602 | /* |
555 | * Given modules definition and module name (or alias, or symbol) | 603 | * Given modules definition and module name (or alias, or symbol) |
556 | * load/remove the module respecting dependencies. | 604 | * load/remove the module respecting dependencies. |
@@ -567,26 +615,36 @@ static void process_module(char *name, const char *cmdline_options) | |||
567 | module_info **infovec; | 615 | module_info **infovec; |
568 | module_info *info; | 616 | module_info *info; |
569 | int infoidx; | 617 | int infoidx; |
570 | int is_rmmod = (option_mask32 & OPT_r) != 0; | 618 | int is_remove = (option_mask32 & OPT_r) != 0; |
571 | 619 | ||
572 | dbg1_error_msg("process_module('%s','%s')", name, cmdline_options); | 620 | dbg1_error_msg("process_module('%s','%s')", name, cmdline_options); |
573 | 621 | ||
574 | replace(name, '-', '_'); | 622 | replace(name, '-', '_'); |
575 | 623 | ||
576 | dbg1_error_msg("already_loaded:%d is_rmmod:%d", already_loaded(name), is_rmmod); | 624 | dbg1_error_msg("already_loaded:%d is_remove:%d", already_loaded(name), is_remove); |
625 | |||
626 | if (applet_name[0] == 'r') { | ||
627 | /* rmmod. | ||
628 | * Does not remove dependencies, no need to scan, just remove. | ||
629 | * (compat note: this allows and strips .ko suffix) | ||
630 | */ | ||
631 | rmmod(name); | ||
632 | return; | ||
633 | } | ||
634 | |||
577 | /* | 635 | /* |
578 | * We used to have "is_rmmod != already_loaded(name)" check here, but | 636 | * We used to have "is_remove != already_loaded(name)" check here, but |
579 | * modprobe -r pci:v00008086d00007010sv00000000sd00000000bc01sc01i80 | 637 | * modprobe -r pci:v00008086d00007010sv00000000sd00000000bc01sc01i80 |
580 | * won't unload modules (there are more than one) | 638 | * won't unload modules (there are more than one) |
581 | * which have this alias. | 639 | * which have this alias. |
582 | */ | 640 | */ |
583 | if (!is_rmmod && already_loaded(name)) { | 641 | if (!is_remove && already_loaded(name)) { |
584 | dbg1_error_msg("nothing to do for '%s'", name); | 642 | dbg1_error_msg("nothing to do for '%s'", name); |
585 | return; | 643 | return; |
586 | } | 644 | } |
587 | 645 | ||
588 | options = NULL; | 646 | options = NULL; |
589 | if (!is_rmmod) { | 647 | if (!is_remove) { |
590 | char *opt_filename = xasprintf("/etc/modules/%s", name); | 648 | char *opt_filename = xasprintf("/etc/modules/%s", name); |
591 | options = xmalloc_open_read_close(opt_filename, NULL); | 649 | options = xmalloc_open_read_close(opt_filename, NULL); |
592 | if (options) | 650 | if (options) |
@@ -620,7 +678,7 @@ static void process_module(char *name, const char *cmdline_options) | |||
620 | 0 /* depth */ | 678 | 0 /* depth */ |
621 | ); | 679 | ); |
622 | dbg1_error_msg("dirscan complete"); | 680 | dbg1_error_msg("dirscan complete"); |
623 | /* Module was not found, or load failed, or is_rmmod */ | 681 | /* Module was not found, or load failed, or is_remove */ |
624 | if (module_found_idx >= 0) { /* module was found */ | 682 | if (module_found_idx >= 0) { /* module was found */ |
625 | infovec = xzalloc(2 * sizeof(infovec[0])); | 683 | infovec = xzalloc(2 * sizeof(infovec[0])); |
626 | infovec[0] = &modinfo[module_found_idx]; | 684 | infovec[0] = &modinfo[module_found_idx]; |
@@ -631,6 +689,14 @@ static void process_module(char *name, const char *cmdline_options) | |||
631 | infovec = find_alias(name); | 689 | infovec = find_alias(name); |
632 | } | 690 | } |
633 | 691 | ||
692 | if (!infovec) { | ||
693 | /* both dirscan and find_alias found nothing */ | ||
694 | if (!is_remove && applet_name[0] != 'd') /* it wasn't rmmod or depmod */ | ||
695 | bb_error_msg("module '%s' not found", name); | ||
696 | //TODO: _and_die()? or should we continue (un)loading modules listed on cmdline? | ||
697 | goto ret; | ||
698 | } | ||
699 | |||
634 | /* There can be more than one module for the given alias. For example, | 700 | /* There can be more than one module for the given alias. For example, |
635 | * "pci:v00008086d00007010sv00000000sd00000000bc01sc01i80" matches | 701 | * "pci:v00008086d00007010sv00000000sd00000000bc01sc01i80" matches |
636 | * ata_piix because it has alias "pci:v00008086d00007010sv*sd*bc*sc*i*" | 702 | * ata_piix because it has alias "pci:v00008086d00007010sv*sd*bc*sc*i*" |
@@ -639,28 +705,15 @@ static void process_module(char *name, const char *cmdline_options) | |||
639 | * a *list* of modinfo pointers from find_alias(). | 705 | * a *list* of modinfo pointers from find_alias(). |
640 | */ | 706 | */ |
641 | 707 | ||
642 | /* rmmod or modprobe -r? unload module(s) */ | 708 | /* modprobe -r? unload module(s) */ |
643 | if (is_rmmod) { | 709 | if (is_remove) { |
644 | infoidx = 0; | 710 | infoidx = 0; |
645 | while ((info = infovec[infoidx++]) != NULL) { | 711 | while ((info = infovec[infoidx++]) != NULL) { |
646 | int r; | 712 | int r = rmmod(bb_get_last_path_component_nostrip(info->pathname)); |
647 | char modname[MODULE_NAME_LEN]; | ||
648 | |||
649 | filename2modname(info->pathname, modname); | ||
650 | r = delete_module(modname, O_NONBLOCK | O_EXCL); | ||
651 | dbg1_error_msg("delete_module('%s', O_NONBLOCK | O_EXCL):%d", modname, r); | ||
652 | if (r != 0) { | 713 | if (r != 0) { |
653 | if (!(option_mask32 & OPT_q)) | 714 | goto ret; /* error */ |
654 | bb_perror_msg("remove '%s'", modname); | ||
655 | goto ret; | ||
656 | } | 715 | } |
657 | } | 716 | } |
658 | |||
659 | if (applet_name[0] == 'r') { | ||
660 | /* rmmod: do not remove dependencies, exit */ | ||
661 | goto ret; | ||
662 | } | ||
663 | |||
664 | /* modprobe -r: we do not stop here - | 717 | /* modprobe -r: we do not stop here - |
665 | * continue to unload modules on which the module depends: | 718 | * continue to unload modules on which the module depends: |
666 | * "-r --remove: option causes modprobe to remove a module. | 719 | * "-r --remove: option causes modprobe to remove a module. |
@@ -669,14 +722,6 @@ static void process_module(char *name, const char *cmdline_options) | |||
669 | */ | 722 | */ |
670 | } | 723 | } |
671 | 724 | ||
672 | if (!infovec) { | ||
673 | /* both dirscan and find_alias found nothing */ | ||
674 | if (!is_rmmod && applet_name[0] != 'd') /* it wasn't rmmod or depmod */ | ||
675 | bb_error_msg("module '%s' not found", name); | ||
676 | //TODO: _and_die()? or should we continue (un)loading modules listed on cmdline? | ||
677 | goto ret; | ||
678 | } | ||
679 | |||
680 | infoidx = 0; | 725 | infoidx = 0; |
681 | while ((info = infovec[infoidx++]) != NULL) { | 726 | while ((info = infovec[infoidx++]) != NULL) { |
682 | /* Iterate thru dependencies, trying to (un)load them */ | 727 | /* Iterate thru dependencies, trying to (un)load them */ |
@@ -689,7 +734,7 @@ static void process_module(char *name, const char *cmdline_options) | |||
689 | } | 734 | } |
690 | free(deps); | 735 | free(deps); |
691 | 736 | ||
692 | if (is_rmmod) | 737 | if (is_remove) |
693 | continue; | 738 | continue; |
694 | 739 | ||
695 | /* We are modprobe: load it */ | 740 | /* We are modprobe: load it */ |
@@ -892,10 +937,10 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
892 | } | 937 | } |
893 | 938 | ||
894 | #if ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE | 939 | #if ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE |
895 | /* If not rmmod, parse possible module options given on command line. | 940 | /* If not rmmod/-r, parse possible module options given on command line. |
896 | * insmod/modprobe takes one module name, the rest are parameters. */ | 941 | * insmod/modprobe takes one module name, the rest are parameters. */ |
897 | options = NULL; | 942 | options = NULL; |
898 | if ('r' != applet0) { | 943 | if (!(option_mask32 & OPT_r)) { |
899 | char **arg = argv; | 944 | char **arg = argv; |
900 | while (*++arg) { | 945 | while (*++arg) { |
901 | /* Enclose options in quotes */ | 946 | /* Enclose options in quotes */ |
@@ -906,7 +951,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
906 | } | 951 | } |
907 | } | 952 | } |
908 | #else | 953 | #else |
909 | if ('r' != applet0) | 954 | if (!(option_mask32 & OPT_r)) |
910 | argv[1] = NULL; | 955 | argv[1] = NULL; |
911 | #endif | 956 | #endif |
912 | 957 | ||
@@ -930,10 +975,11 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
930 | } | 975 | } |
931 | 976 | ||
932 | /* Try to load modprobe.dep.bb */ | 977 | /* Try to load modprobe.dep.bb */ |
933 | load_dep_bb(); | 978 | if ('r' != applet0) /* not rmmod */ |
979 | load_dep_bb(); | ||
934 | 980 | ||
935 | /* Load/remove modules. | 981 | /* Load/remove modules. |
936 | * Only rmmod loops here, modprobe has only argv[0] */ | 982 | * Only rmmod/modprobe -r loops here, insmod/modprobe has only argv[0] */ |
937 | do { | 983 | do { |
938 | process_module(*argv, options); | 984 | process_module(*argv, options); |
939 | } while (*++argv); | 985 | } while (*++argv); |
diff --git a/modutils/modprobe.c b/modutils/modprobe.c index f0904285b..996de4074 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c | |||
@@ -15,8 +15,11 @@ | |||
15 | #include <sys/utsname.h> | 15 | #include <sys/utsname.h> |
16 | #include <fnmatch.h> | 16 | #include <fnmatch.h> |
17 | 17 | ||
18 | //#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__) | 18 | #if 1 |
19 | #define DBG(...) ((void)0) | 19 | #define DBG(...) ((void)0) |
20 | #else | ||
21 | #define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__) | ||
22 | #endif | ||
20 | 23 | ||
21 | /* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t), | 24 | /* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t), |
22 | * we expect the full dependency list to be specified in modules.dep. | 25 | * we expect the full dependency list to be specified in modules.dep. |
@@ -229,26 +232,20 @@ static ALWAYS_INLINE struct module_entry *get_or_add_modentry(const char *module | |||
229 | { | 232 | { |
230 | return helper_get_module(module, 1); | 233 | return helper_get_module(module, 1); |
231 | } | 234 | } |
232 | static ALWAYS_INLINE struct module_entry *get_modentry(const char *module) | 235 | /* So far this function always gets a module pathname, never an alias name. |
236 | * The crucial difference is that pathname needs dirname stripping, | ||
237 | * while alias name must NOT do it! | ||
238 | * Testcase where dirname stripping is likely to go wrong: "modprobe devname:snd/timer" | ||
239 | */ | ||
240 | static ALWAYS_INLINE struct module_entry *get_modentry(const char *pathname) | ||
233 | { | 241 | { |
234 | return helper_get_module(module, 0); | 242 | return helper_get_module(bb_get_last_path_component_nostrip(pathname), 0); |
235 | } | 243 | } |
236 | 244 | ||
237 | static void add_probe(const char *name) | 245 | static void add_probe(const char *name) |
238 | { | 246 | { |
239 | struct module_entry *m; | 247 | struct module_entry *m; |
240 | 248 | ||
241 | /* | ||
242 | * get_or_add_modentry() strips path from name and works | ||
243 | * on remaining basename. | ||
244 | * This would make "rmmod dir/name" and "modprobe dir/name" | ||
245 | * to work like "rmmod name" and "modprobe name", | ||
246 | * which is wrong, and can be abused via implicit modprobing: | ||
247 | * "ifconfig /usbserial up" tries to modprobe netdev-/usbserial. | ||
248 | */ | ||
249 | if (strchr(name, '/')) | ||
250 | bb_error_msg_and_die("malformed module name '%s'", name); | ||
251 | |||
252 | m = get_or_add_modentry(name); | 249 | m = get_or_add_modentry(name); |
253 | if (!(option_mask32 & (OPT_REMOVE | OPT_SHOW_DEPS)) | 250 | if (!(option_mask32 & (OPT_REMOVE | OPT_SHOW_DEPS)) |
254 | && (m->flags & MODULE_FLAG_LOADED) | 251 | && (m->flags & MODULE_FLAG_LOADED) |
@@ -263,7 +260,7 @@ static void add_probe(const char *name) | |||
263 | llist_add_to_end(&G.probes, m); | 260 | llist_add_to_end(&G.probes, m); |
264 | G.num_unresolved_deps++; | 261 | G.num_unresolved_deps++; |
265 | if (ENABLE_FEATURE_MODUTILS_SYMBOLS | 262 | if (ENABLE_FEATURE_MODUTILS_SYMBOLS |
266 | && strncmp(m->modname, "symbol:", 7) == 0 | 263 | && is_prefixed_with(m->modname, "symbol:") |
267 | ) { | 264 | ) { |
268 | G.need_symbols = 1; | 265 | G.need_symbols = 1; |
269 | } | 266 | } |
@@ -356,22 +353,18 @@ static char *parse_and_add_kcmdline_module_options(char *options, const char *mo | |||
356 | char *kcmdline_buf; | 353 | char *kcmdline_buf; |
357 | char *kcmdline; | 354 | char *kcmdline; |
358 | char *kptr; | 355 | char *kptr; |
359 | int len; | ||
360 | 356 | ||
361 | kcmdline_buf = xmalloc_open_read_close("/proc/cmdline", NULL); | 357 | kcmdline_buf = xmalloc_open_read_close("/proc/cmdline", NULL); |
362 | if (!kcmdline_buf) | 358 | if (!kcmdline_buf) |
363 | return options; | 359 | return options; |
364 | 360 | ||
365 | kcmdline = kcmdline_buf; | 361 | kcmdline = kcmdline_buf; |
366 | len = strlen(modulename); | ||
367 | while ((kptr = strsep(&kcmdline, "\n\t ")) != NULL) { | 362 | while ((kptr = strsep(&kcmdline, "\n\t ")) != NULL) { |
368 | if (strncmp(modulename, kptr, len) != 0) | 363 | char *after_modulename = is_prefixed_with(kptr, modulename); |
369 | continue; | 364 | if (!after_modulename || *after_modulename != '.') |
370 | kptr += len; | ||
371 | if (*kptr != '.') | ||
372 | continue; | 365 | continue; |
373 | /* It is "modulename.xxxx" */ | 366 | /* It is "modulename.xxxx" */ |
374 | kptr++; | 367 | kptr = after_modulename + 1; |
375 | if (strchr(kptr, '=') != NULL) { | 368 | if (strchr(kptr, '=') != NULL) { |
376 | /* It is "modulename.opt=[val]" */ | 369 | /* It is "modulename.opt=[val]" */ |
377 | options = gather_options_str(options, kptr); | 370 | options = gather_options_str(options, kptr); |
@@ -428,7 +421,7 @@ static int do_modprobe(struct module_entry *m) | |||
428 | 421 | ||
429 | rc = 0; | 422 | rc = 0; |
430 | fn = llist_pop(&m->deps); /* we leak it */ | 423 | fn = llist_pop(&m->deps); /* we leak it */ |
431 | m2 = get_or_add_modentry(fn); | 424 | m2 = get_or_add_modentry(bb_get_last_path_component_nostrip(fn)); |
432 | 425 | ||
433 | if (option_mask32 & OPT_REMOVE) { | 426 | if (option_mask32 & OPT_REMOVE) { |
434 | /* modprobe -r */ | 427 | /* modprobe -r */ |
@@ -510,7 +503,7 @@ static void load_modules_dep(void) | |||
510 | colon = last_char_is(tokens[0], ':'); | 503 | colon = last_char_is(tokens[0], ':'); |
511 | if (colon == NULL) | 504 | if (colon == NULL) |
512 | continue; | 505 | continue; |
513 | *colon = 0; | 506 | *colon = '\0'; |
514 | 507 | ||
515 | m = get_modentry(tokens[0]); | 508 | m = get_modentry(tokens[0]); |
516 | if (m == NULL) | 509 | if (m == NULL) |
@@ -557,7 +550,6 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
557 | 550 | ||
558 | if (opt & OPT_LIST_ONLY) { | 551 | if (opt & OPT_LIST_ONLY) { |
559 | int i; | 552 | int i; |
560 | char name[MODULE_NAME_LEN]; | ||
561 | char *colon, *tokens[2]; | 553 | char *colon, *tokens[2]; |
562 | parser_t *p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read); | 554 | parser_t *p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read); |
563 | 555 | ||
@@ -569,10 +561,14 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
569 | if (!colon) | 561 | if (!colon) |
570 | continue; | 562 | continue; |
571 | *colon = '\0'; | 563 | *colon = '\0'; |
572 | filename2modname(tokens[0], name); | ||
573 | if (!argv[0]) | 564 | if (!argv[0]) |
574 | puts(tokens[0]); | 565 | puts(tokens[0]); |
575 | else { | 566 | else { |
567 | char name[MODULE_NAME_LEN]; | ||
568 | filename2modname( | ||
569 | bb_get_last_path_component_nostrip(tokens[0]), | ||
570 | name | ||
571 | ); | ||
576 | for (i = 0; argv[i]; i++) { | 572 | for (i = 0; argv[i]; i++) { |
577 | if (fnmatch(argv[i], name, 0) == 0) { | 573 | if (fnmatch(argv[i], name, 0) == 0) { |
578 | puts(tokens[0]); | 574 | puts(tokens[0]); |
diff --git a/modutils/modutils-24.c b/modutils/modutils-24.c index 12cb75c54..fe46fc3fd 100644 --- a/modutils/modutils-24.c +++ b/modutils/modutils-24.c | |||
@@ -2255,7 +2255,7 @@ static int add_symbols_from(struct obj_file *f, | |||
2255 | * symbols so they cannot fudge it by adding the prefix on | 2255 | * symbols so they cannot fudge it by adding the prefix on |
2256 | * their references. | 2256 | * their references. |
2257 | */ | 2257 | */ |
2258 | if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) { | 2258 | if (is_prefixed_with((char *)s->name, "GPLONLY_")) { |
2259 | #if ENABLE_FEATURE_CHECK_TAINTED_MODULE | 2259 | #if ENABLE_FEATURE_CHECK_TAINTED_MODULE |
2260 | if (gpl) | 2260 | if (gpl) |
2261 | s->name += 8; | 2261 | s->name += 8; |
diff --git a/modutils/modutils.c b/modutils/modutils.c index 6187ca72f..84300d931 100644 --- a/modutils/modutils.c +++ b/modutils/modutils.c | |||
@@ -47,18 +47,26 @@ int FAST_FUNC string_to_llist(char *string, llist_t **llist, const char *delim) | |||
47 | 47 | ||
48 | char* FAST_FUNC filename2modname(const char *filename, char *modname) | 48 | char* FAST_FUNC filename2modname(const char *filename, char *modname) |
49 | { | 49 | { |
50 | char local_modname[MODULE_NAME_LEN]; | ||
50 | int i; | 51 | int i; |
51 | char *from; | 52 | const char *from; |
52 | 53 | ||
53 | if (filename == NULL) | 54 | if (filename == NULL) |
54 | return NULL; | 55 | return NULL; |
55 | if (modname == NULL) | 56 | if (modname == NULL) |
56 | modname = xmalloc(MODULE_NAME_LEN); | 57 | modname = local_modname; |
57 | from = bb_get_last_path_component_nostrip(filename); | 58 | // Disabled since otherwise "modprobe dir/name" would work |
59 | // as if it is "modprobe name". It is unclear why | ||
60 | // 'basenamization' was here in the first place. | ||
61 | //from = bb_get_last_path_component_nostrip(filename); | ||
62 | from = filename; | ||
58 | for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++) | 63 | for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++) |
59 | modname[i] = (from[i] == '-') ? '_' : from[i]; | 64 | modname[i] = (from[i] == '-') ? '_' : from[i]; |
60 | modname[i] = '\0'; | 65 | modname[i] = '\0'; |
61 | 66 | ||
67 | if (modname == local_modname) | ||
68 | return xstrdup(modname); | ||
69 | |||
62 | return modname; | 70 | return modname; |
63 | } | 71 | } |
64 | 72 | ||