| 1 | --- a/modutils/insmod.c |
| 2 | +++ b/modutils/insmod.c |
| 3 | @@ -11,6 +11,106 @@ |
| 4 | |
| 5 | #include "libbb.h" |
| 6 | #include "modutils.h" |
| 7 | +#include <sys/utsname.h> |
| 8 | +#ifndef CONFIG_FEATURE_2_4_MODULES |
| 9 | +#include <sys/mman.h> |
| 10 | +#include <asm/unistd.h> |
| 11 | +#include <sys/syscall.h> |
| 12 | +#endif |
| 13 | + |
| 14 | +static char *g_filename = NULL; |
| 15 | + |
| 16 | +static int FAST_FUNC check_module_name_match(const char *filename, struct stat *statbuf, |
| 17 | + void *userdata, int depth) |
| 18 | +{ |
| 19 | + char *fullname = (char *) userdata; |
| 20 | + char *tmp; |
| 21 | + |
| 22 | + if (fullname[0] == '\0') |
| 23 | + return FALSE; |
| 24 | + |
| 25 | + tmp = bb_get_last_path_component_nostrip(filename); |
| 26 | + if (strcmp(tmp, fullname) == 0) { |
| 27 | + /* Stop searching if we find a match */ |
| 28 | + g_filename = xstrdup(filename); |
| 29 | + return FALSE; |
| 30 | + } |
| 31 | + |
| 32 | + return TRUE; |
| 33 | +} |
| 34 | + |
| 35 | +static int find_module(char *filename) |
| 36 | +{ |
| 37 | + char *module_dir, real_module_dir[FILENAME_MAX]; |
| 38 | + int len, slen, ret = ENOENT, k_version; |
| 39 | + struct utsname myuname; |
| 40 | + const char *suffix = ".ko"; |
| 41 | + struct stat st; |
| 42 | + |
| 43 | + /* check the kernel version */ |
| 44 | + if (uname(&myuname) != 0) |
| 45 | + return EINVAL; |
| 46 | + |
| 47 | + k_version = myuname.release[0] - '0'; |
| 48 | + |
| 49 | + if (k_version < 2 || k_version > 9) |
| 50 | + return EINVAL; |
| 51 | + |
| 52 | + if (k_version == 2) { |
| 53 | + int k_patchlevel = myuname.release[2] - '0'; |
| 54 | + if (k_patchlevel <= 4) |
| 55 | +#if ENABLE_FEATURE_2_4_MODULES |
| 56 | + suffix = ".o"; |
| 57 | +#else |
| 58 | + return EINVAL; |
| 59 | +#endif |
| 60 | + } |
| 61 | + |
| 62 | + len = strlen(filename); |
| 63 | + slen = strlen(suffix); |
| 64 | + |
| 65 | + /* check for suffix and absolute path first */ |
| 66 | + if ((len < slen + 2) || (strcmp(filename + len - slen, suffix) != 0)) { |
| 67 | + filename = xasprintf("%s%s", filename, suffix); |
| 68 | + } else { |
| 69 | + filename = strdup(filename); |
| 70 | + if ((stat(filename, &st) == 0) && S_ISREG(st.st_mode)) { |
| 71 | + g_filename = filename; |
| 72 | + return 0; |
| 73 | + } |
| 74 | + free(filename); |
| 75 | + return ENOENT; |
| 76 | + } |
| 77 | + |
| 78 | + /* next: scan /lib/modules/<release> */ |
| 79 | + /* Jump through hoops in case /lib/modules/`uname -r` |
| 80 | + * is a symlink. We do not want recursive_action to |
| 81 | + * follow symlinks, but we do want to follow the |
| 82 | + * /lib/modules/`uname -r` dir, So resolve it ourselves |
| 83 | + * if it is a link... */ |
| 84 | + module_dir = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, myuname.release); |
| 85 | + if (realpath(module_dir, real_module_dir) != NULL) { |
| 86 | + free(module_dir); |
| 87 | + module_dir = real_module_dir; |
| 88 | + } |
| 89 | + |
| 90 | + recursive_action(module_dir, ACTION_RECURSE, |
| 91 | + check_module_name_match, 0, filename, 0); |
| 92 | + |
| 93 | + /* Check if we have a complete path */ |
| 94 | + if (g_filename == NULL) |
| 95 | + goto done; |
| 96 | + |
| 97 | + if ((stat(g_filename, &st) == 0) && S_ISREG(st.st_mode)) |
| 98 | + ret = 0; |
| 99 | + else |
| 100 | + free(g_filename); |
| 101 | + |
| 102 | +done: |
| 103 | + free(filename); |
| 104 | + |
| 105 | + return ret; |
| 106 | +} |
| 107 | |
| 108 | /* 2.6 style insmod has no options and required filename |
| 109 | * (not module name - .ko can't be omitted) */ |
| 110 | @@ -59,9 +159,15 @@ int insmod_main(int argc UNUSED_PARAM, c |
| 111 | if (!filename) |
| 112 | bb_show_usage(); |
| 113 | |
| 114 | - rc = bb_init_module(filename, parse_cmdline_module_options(argv)); |
| 115 | + rc = find_module(filename); |
| 116 | + if (rc || (g_filename == NULL)) |
| 117 | + goto done; |
| 118 | + |
| 119 | + rc = bb_init_module(g_filename, parse_cmdline_module_options(argv)); |
| 120 | if (rc) |
| 121 | bb_error_msg("can't insert '%s': %s", filename, moderror(rc)); |
| 122 | + free (g_filename); |
| 123 | |
| 124 | +done: |
| 125 | return rc; |
| 126 | } |
| 127 | --- a/modutils/Config.src |
| 128 | +++ b/modutils/Config.src |
| 129 | @@ -229,7 +229,7 @@ config FEATURE_MODUTILS_SYMBOLS |
| 130 | config DEFAULT_MODULES_DIR |
| 131 | string "Default directory containing modules" |
| 132 | default "/lib/modules" |
| 133 | - depends on DEPMOD || MODPROBE || MODPROBE_SMALL || MODINFO |
| 134 | + depends on DEPMOD || INSMOD || MODPROBE || MODPROBE_SMALL || MODINFO |
| 135 | help |
| 136 | Directory that contains kernel modules. |
| 137 | Defaults to "/lib/modules" |
| 138 | |