diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2016-06-20 10:59:06 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2016-06-20 11:02:40 +0200 |
commit | 5c3e060604444b18303f55e631637c28d889704f (patch) | |
tree | 6afe8c3d5292b171149f79393a4b2ca293dafa84 | |
parent | 0ad872baf30b660ffb87265470d29f14cfc4b2d4 (diff) | |
download | busybox-w32-5c3e060604444b18303f55e631637c28d889704f.tar.gz busybox-w32-5c3e060604444b18303f55e631637c28d889704f.tar.bz2 busybox-w32-5c3e060604444b18303f55e631637c28d889704f.zip |
modprobe-small: fix bogus handling of unpack errors
"modprobe minix; echo $?"
Was:
modprobe: corrupted data
modprobe: read error from 'kernel/fs/minix/minix.ko.xz': No such file or directory
modprobe: corrupted data
modprobe: read error from 'kernel/fs/minix/minix.ko.xz': No such file or directory
modprobe: corrupted data
modprobe: read error from 'kernel/fs/minix/minix.ko.xz'
modprobe: 'kernel/fs/minix/minix.ko.xz': Success
0
Now:
modprobe: corrupted data
modprobe: read error from 'kernel/fs/minix/minix.ko.xz'
1
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | modutils/modprobe-small.c | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index ffb46e6be..5936e48cf 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c | |||
@@ -45,6 +45,7 @@ typedef struct module_info { | |||
45 | char *pathname; | 45 | char *pathname; |
46 | char *aliases; | 46 | char *aliases; |
47 | char *deps; | 47 | char *deps; |
48 | smallint open_read_failed; | ||
48 | } module_info; | 49 | } module_info; |
49 | 50 | ||
50 | /* | 51 | /* |
@@ -222,7 +223,8 @@ static int load_module(const char *fname, const char *options) | |||
222 | #endif | 223 | #endif |
223 | } | 224 | } |
224 | 225 | ||
225 | static void parse_module(module_info *info, const char *pathname) | 226 | /* Returns !0 if open/read was unsuccessful */ |
227 | static int parse_module(module_info *info, const char *pathname) | ||
226 | { | 228 | { |
227 | char *module_image; | 229 | char *module_image; |
228 | char *ptr; | 230 | char *ptr; |
@@ -231,6 +233,7 @@ static void parse_module(module_info *info, const char *pathname) | |||
231 | dbg1_error_msg("parse_module('%s')", pathname); | 233 | dbg1_error_msg("parse_module('%s')", pathname); |
232 | 234 | ||
233 | /* Read (possibly compressed) module */ | 235 | /* Read (possibly compressed) module */ |
236 | errno = 0; | ||
234 | len = 64 * 1024 * 1024; /* 64 Mb at most */ | 237 | len = 64 * 1024 * 1024; /* 64 Mb at most */ |
235 | module_image = xmalloc_open_zipped_read_close(pathname, &len); | 238 | module_image = xmalloc_open_zipped_read_close(pathname, &len); |
236 | /* module_image == NULL is ok here, find_keyword handles it */ | 239 | /* module_image == NULL is ok here, find_keyword handles it */ |
@@ -298,9 +301,11 @@ static void parse_module(module_info *info, const char *pathname) | |||
298 | dbg2_error_msg("dep:'%s'", ptr); | 301 | dbg2_error_msg("dep:'%s'", ptr); |
299 | append(ptr); | 302 | append(ptr); |
300 | } | 303 | } |
304 | free(module_image); | ||
301 | info->deps = copy_stringbuf(); | 305 | info->deps = copy_stringbuf(); |
302 | 306 | ||
303 | free(module_image); | 307 | info->open_read_failed = (module_image == NULL); |
308 | return info->open_read_failed; | ||
304 | } | 309 | } |
305 | 310 | ||
306 | static FAST_FUNC int fileAction(const char *pathname, | 311 | static FAST_FUNC int fileAction(const char *pathname, |
@@ -331,7 +336,8 @@ static FAST_FUNC int fileAction(const char *pathname, | |||
331 | 336 | ||
332 | dbg1_error_msg("'%s' module name matches", pathname); | 337 | dbg1_error_msg("'%s' module name matches", pathname); |
333 | module_found_idx = cur; | 338 | module_found_idx = cur; |
334 | parse_module(&modinfo[cur], pathname); | 339 | if (parse_module(&modinfo[cur], pathname) != 0) |
340 | return TRUE; /* failed to open/read it, no point in trying loading */ | ||
335 | 341 | ||
336 | if (!(option_mask32 & OPT_r)) { | 342 | if (!(option_mask32 & OPT_r)) { |
337 | if (load_module(pathname, module_load_options) == 0) { | 343 | if (load_module(pathname, module_load_options) == 0) { |
@@ -608,13 +614,14 @@ static int rmmod(const char *filename) | |||
608 | #define process_module(a,b) process_module(a) | 614 | #define process_module(a,b) process_module(a) |
609 | #define cmdline_options "" | 615 | #define cmdline_options "" |
610 | #endif | 616 | #endif |
611 | static void process_module(char *name, const char *cmdline_options) | 617 | static int process_module(char *name, const char *cmdline_options) |
612 | { | 618 | { |
613 | char *s, *deps, *options; | 619 | char *s, *deps, *options; |
614 | module_info **infovec; | 620 | module_info **infovec; |
615 | module_info *info; | 621 | module_info *info; |
616 | int infoidx; | 622 | int infoidx; |
617 | int is_remove = (option_mask32 & OPT_r) != 0; | 623 | int is_remove = (option_mask32 & OPT_r) != 0; |
624 | int exitcode = EXIT_SUCCESS; | ||
618 | 625 | ||
619 | dbg1_error_msg("process_module('%s','%s')", name, cmdline_options); | 626 | dbg1_error_msg("process_module('%s','%s')", name, cmdline_options); |
620 | 627 | ||
@@ -628,7 +635,7 @@ static void process_module(char *name, const char *cmdline_options) | |||
628 | * (compat note: this allows and strips .ko suffix) | 635 | * (compat note: this allows and strips .ko suffix) |
629 | */ | 636 | */ |
630 | rmmod(name); | 637 | rmmod(name); |
631 | return; | 638 | return EXIT_SUCCESS; |
632 | } | 639 | } |
633 | 640 | ||
634 | /* | 641 | /* |
@@ -639,7 +646,7 @@ static void process_module(char *name, const char *cmdline_options) | |||
639 | */ | 646 | */ |
640 | if (!is_remove && already_loaded(name)) { | 647 | if (!is_remove && already_loaded(name)) { |
641 | dbg1_error_msg("nothing to do for '%s'", name); | 648 | dbg1_error_msg("nothing to do for '%s'", name); |
642 | return; | 649 | return EXIT_SUCCESS; |
643 | } | 650 | } |
644 | 651 | ||
645 | options = NULL; | 652 | options = NULL; |
@@ -741,6 +748,11 @@ static void process_module(char *name, const char *cmdline_options) | |||
741 | dbg1_error_msg("'%s': blacklisted", info->pathname); | 748 | dbg1_error_msg("'%s': blacklisted", info->pathname); |
742 | continue; | 749 | continue; |
743 | } | 750 | } |
751 | if (info->open_read_failed) { | ||
752 | /* We already tried it, didn't work. Don't try load again */ | ||
753 | exitcode = EXIT_FAILURE; | ||
754 | continue; | ||
755 | } | ||
744 | errno = 0; | 756 | errno = 0; |
745 | if (load_module(info->pathname, options) != 0) { | 757 | if (load_module(info->pathname, options) != 0) { |
746 | if (EEXIST != errno) { | 758 | if (EEXIST != errno) { |
@@ -752,13 +764,14 @@ static void process_module(char *name, const char *cmdline_options) | |||
752 | info->pathname, | 764 | info->pathname, |
753 | moderror(errno)); | 765 | moderror(errno)); |
754 | } | 766 | } |
767 | exitcode = EXIT_FAILURE; | ||
755 | } | 768 | } |
756 | } | 769 | } |
757 | ret: | 770 | ret: |
758 | free(infovec); | 771 | free(infovec); |
759 | free(options); | 772 | free(options); |
760 | //TODO: return load attempt result from process_module. | 773 | |
761 | //If dep didn't load ok, continuing makes little sense. | 774 | return exitcode; |
762 | } | 775 | } |
763 | #undef cmdline_options | 776 | #undef cmdline_options |
764 | 777 | ||
@@ -865,6 +878,7 @@ The following options are useful for people managing distributions: | |||
865 | int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 878 | int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
866 | int modprobe_main(int argc UNUSED_PARAM, char **argv) | 879 | int modprobe_main(int argc UNUSED_PARAM, char **argv) |
867 | { | 880 | { |
881 | int exitcode; | ||
868 | struct utsname uts; | 882 | struct utsname uts; |
869 | char applet0 = applet_name[0]; | 883 | char applet0 = applet_name[0]; |
870 | IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(char *options;) | 884 | IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(char *options;) |
@@ -970,21 +984,23 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
970 | bb_error_msg_and_die("can't insert '%s': %s", | 984 | bb_error_msg_and_die("can't insert '%s': %s", |
971 | *argv, moderror(errno)); | 985 | *argv, moderror(errno)); |
972 | } | 986 | } |
973 | return 0; | 987 | return EXIT_SUCCESS; |
974 | } | 988 | } |
975 | 989 | ||
976 | /* Try to load modprobe.dep.bb */ | 990 | /* Try to load modprobe.dep.bb */ |
977 | if ('r' != applet0) /* not rmmod */ | 991 | if ('r' != applet0) { /* not rmmod */ |
978 | load_dep_bb(); | 992 | load_dep_bb(); |
993 | } | ||
979 | 994 | ||
980 | /* Load/remove modules. | 995 | /* Load/remove modules. |
981 | * Only rmmod/modprobe -r loops here, insmod/modprobe has only argv[0] */ | 996 | * Only rmmod/modprobe -r loops here, insmod/modprobe has only argv[0] */ |
997 | exitcode = EXIT_SUCCESS; | ||
982 | do { | 998 | do { |
983 | process_module(*argv, options); | 999 | exitcode |= process_module(*argv, options); |
984 | } while (*++argv); | 1000 | } while (*++argv); |
985 | 1001 | ||
986 | if (ENABLE_FEATURE_CLEAN_UP) { | 1002 | if (ENABLE_FEATURE_CLEAN_UP) { |
987 | IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(free(options);) | 1003 | IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(free(options);) |
988 | } | 1004 | } |
989 | return EXIT_SUCCESS; | 1005 | return exitcode; |
990 | } | 1006 | } |