aboutsummaryrefslogtreecommitdiff
path: root/modutils
diff options
context:
space:
mode:
Diffstat (limited to 'modutils')
-rw-r--r--modutils/depmod.c39
-rw-r--r--modutils/modinfo.c14
-rw-r--r--modutils/modprobe-small.c182
-rw-r--r--modutils/modprobe.c48
-rw-r--r--modutils/modutils-24.c2
-rw-r--r--modutils/modutils.c14
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 {
33static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARAM, 33static 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
117static char* find_keyword(char *ptr, size_t len, const char *word) 117static 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)
149static char *filename2modname(const char *filename, char *modname) 149static 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
166static 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 */
163static char* str_2_list(const char *str) 176static 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
294static 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
306static FAST_FUNC int fileAction(const char *pathname, 307static 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()
536static int already_loaded(const char *name) 537static 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
588static 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}
232static 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 */
240static 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
237static void add_probe(const char *name) 245static 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
48char* FAST_FUNC filename2modname(const char *filename, char *modname) 48char* 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