Hi folks

The attached patch inplements 2.6 support in busybox insmod. Please test
them.

Bastian

-- 
Without freedom of choice there is no creativity.
                -- Kirk, "The return of the Archons", stardate 3157.4
Index: debian/config-udeb-linux
===================================================================
--- debian/config-udeb-linux    (revision 284)
+++ debian/config-udeb-linux    (working copy)
@@ -367,7 +367,6 @@
 #
 # CONFIG_FEATURE_SH_EXTRA_QUIET is not set
 CONFIG_FEATURE_SH_STANDALONE_SHELL=y
-# CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN is not set
 CONFIG_FEATURE_COMMAND_EDITING=y
 CONFIG_FEATURE_COMMAND_HISTORY=15
 # CONFIG_FEATURE_COMMAND_SAVEHISTORY is not set
Index: debian/config-udeb
===================================================================
--- debian/config-udeb  (revision 284)
+++ debian/config-udeb  (working copy)
@@ -359,7 +359,6 @@
 #
 # CONFIG_FEATURE_SH_EXTRA_QUIET is not set
 CONFIG_FEATURE_SH_STANDALONE_SHELL=y
-# CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN is not set
 CONFIG_FEATURE_COMMAND_EDITING=y
 CONFIG_FEATURE_COMMAND_HISTORY=15
 # CONFIG_FEATURE_COMMAND_SAVEHISTORY is not set
Index: debian/config-static
===================================================================
--- debian/config-static        (revision 284)
+++ debian/config-static        (working copy)
@@ -442,7 +442,6 @@
 #
 # CONFIG_FEATURE_SH_EXTRA_QUIET is not set
 CONFIG_FEATURE_SH_STANDALONE_SHELL=y
-CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN=y
 CONFIG_FEATURE_COMMAND_EDITING=y
 CONFIG_FEATURE_COMMAND_HISTORY=15
 CONFIG_FEATURE_COMMAND_SAVEHISTORY=y
Index: modutils/lsmod.c
===================================================================
--- modutils/lsmod.c    (revision 284)
+++ modutils/lsmod.c    (working copy)
@@ -38,16 +38,10 @@
 #include <sys/file.h>
 #include "busybox.h"
 
+#include "obj/module.h"
 
-#ifndef CONFIG_FEATURE_CHECK_TAINTED_MODULE
-static inline void check_tainted(void) { printf("\n"); }
-#else
-#define TAINT_FILENAME                  "/proc/sys/kernel/tainted"
-#define TAINT_PROPRIETORY_MODULE        (1<<0)
-#define TAINT_FORCED_MODULE             (1<<1)
-#define TAINT_UNSAFE_SMP                (1<<2)
-
-static void check_tainted(void)
+#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
+static inline void check_tainted(void)
 {
        int tainted;
        FILE *f;
@@ -67,108 +61,84 @@
                printf("    Not tainted\n");
        }
 }
+#else
+static inline void check_tainted(void)
+{
+       printf("\n");
+}
 #endif
 
-#ifdef CONFIG_FEATURE_QUERY_MODULE_INTERFACE
-
-struct module_info
+static inline int lsmod_query(void)
 {
-       unsigned long addr;
-       unsigned long size;
-       unsigned long flags;
-       long usecount;
-};
+        struct module_info info;
+        char *module_names, *mn, *deps, *dn;
+        size_t bufsize, depsize, nmod, count, i, j;
 
+        module_names = xmalloc(bufsize = 256);
+        if (my_query_module(NULL, QM_MODULES, (void **)&module_names, &bufsize, 
&nmod)) {
+                bb_perror_msg_and_die("QM_MODULES");
+        }
 
-int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret);
+        deps = xmalloc(depsize = 256);
 
-/* Values for query_module's which.  */
-static const int QM_MODULES = 1;
-static const int QM_DEPS = 2;
-static const int QM_REFS = 3;
-static const int QM_SYMBOLS = 4;
-static const int QM_INFO = 5;
+        for (i = 0, mn = module_names; i < nmod; mn += strlen(mn) + 1, i++) {
+                if (query_module(mn, QM_INFO, &info, sizeof(info), &count)) {
+                        if (errno == ENOENT) {
+                                /* The module was removed out from underneath us. */
+                                continue;
+                        }
+                        /* else choke */
+                        bb_perror_msg_and_die("module %s: QM_INFO", mn);
+                }
+                if (my_query_module(mn, QM_REFS, (void **)&deps, &depsize, &count)) {
+                        if (errno == ENOENT) {
+                                /* The module was removed out from underneath us. */
+                                continue;
+                        }
+                        bb_perror_msg_and_die("module %s: QM_REFS", mn);
+                }
+                printf("%-20s%8lu%4ld", mn, info.size, info.usecount);
+                if (info.flags & NEW_MOD_DELETED)
+                        printf(" (deleted)");
+                else if (info.flags & NEW_MOD_INITIALIZING)
+                        printf(" (initializing)");
+                else if (!(info.flags & NEW_MOD_RUNNING))
+                        printf(" (uninitialized)");
+                else {
+                        if (info.flags & NEW_MOD_AUTOCLEAN)
+                                printf(" (autoclean) ");
+                        if (!(info.flags & NEW_MOD_USED_ONCE))
+                                printf(" (unused)");
+                }
+                if (count) printf(" [");
+                for (j = 0, dn = deps; j < count; dn += strlen(dn) + 1, j++) {
+                        printf("%s%s", dn, (j==count-1)? "":" ");
+                }
+                if (count) printf("]");
 
-/* Bits of module.flags.  */
-static const int NEW_MOD_RUNNING = 1;
-static const int NEW_MOD_DELETED = 2;
-static const int NEW_MOD_AUTOCLEAN = 4;
-static const int NEW_MOD_VISITED = 8;
-static const int NEW_MOD_USED_ONCE = 16;
-static const int NEW_MOD_INITIALIZING = 64;
+                printf("\n");
+        }
 
-extern int lsmod_main(int argc, char **argv)
-{
-       struct module_info info;
-       char *module_names, *mn, *deps, *dn;
-       size_t bufsize, depsize, nmod, count, i, j;
-
-       module_names = xmalloc(bufsize = 256);
-       if (my_query_module(NULL, QM_MODULES, (void **)&module_names, &bufsize,
-                               &nmod)) {
-               bb_perror_msg_and_die("QM_MODULES");
-       }
-
-       deps = xmalloc(depsize = 256);
-       printf("Module                  Size  Used by");
-       check_tainted();
-
-       for (i = 0, mn = module_names; i < nmod; mn += strlen(mn) + 1, i++) {
-               if (query_module(mn, QM_INFO, &info, sizeof(info), &count)) {
-                       if (errno == ENOENT) {
-                               /* The module was removed out from underneath us. */
-                               continue;
-                       }
-                       /* else choke */
-                       bb_perror_msg_and_die("module %s: QM_INFO", mn);
-               }
-               if (my_query_module(mn, QM_REFS, (void **)&deps, &depsize, &count)) {
-                       if (errno == ENOENT) {
-                               /* The module was removed out from underneath us. */
-                               continue;
-                       }
-                       bb_perror_msg_and_die("module %s: QM_REFS", mn);
-               }
-               printf("%-20s%8lu%4ld", mn, info.size, info.usecount);
-               if (info.flags & NEW_MOD_DELETED)
-                       printf(" (deleted)");
-               else if (info.flags & NEW_MOD_INITIALIZING)
-                       printf(" (initializing)");
-               else if (!(info.flags & NEW_MOD_RUNNING))
-                       printf(" (uninitialized)");
-               else {
-                       if (info.flags & NEW_MOD_AUTOCLEAN)
-                               printf(" (autoclean) ");
-                       if (!(info.flags & NEW_MOD_USED_ONCE))
-                               printf(" (unused)");
-               }
-               if (count) printf(" [");
-               for (j = 0, dn = deps; j < count; dn += strlen(dn) + 1, j++) {
-                       printf("%s%s", dn, (j==count-1)? "":" ");
-               }
-               if (count) printf("]");
-
-               printf("\n");
-       }
-
-#ifdef CONFIG_FEATURE_CLEAN_UP
-       free(module_names);
-#endif
-
-       return( 0);
+        return( 0);
 }
 
-#else /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */
-
 extern int lsmod_main(int argc, char **argv)
 {
        printf("Module                  Size  Used by");
        check_tainted();
 
+#ifdef CONFIG_FEATURE_QUERY_MODULE_INTERFACE
+        if (getuid() != 0)
+        {
+#endif
        if (bb_xprint_file_by_name("/proc/modules") < 0) {
                return 0;
        }
        return 1;
+#ifdef CONFIG_FEATURE_QUERY_MODULE_INTERFACE
+        }
+        return lsmod_query();
+#endif
 }
 
-#endif /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */
+
Index: modutils/Config.in
===================================================================
--- modutils/Config.in  (revision 284)
+++ modutils/Config.in  (working copy)
@@ -39,14 +39,12 @@
        help
          Support module loading for newer (post 2.1) Linux kernels.
 
-if 0
 config CONFIG_FEATURE_2_6_MODULES
        bool "  Support version 2.6.x Linux kernels"
        default n
        depends on CONFIG_INSMOD
        help
-         Support module loading for newer (post 2.1) Linux kernels.
-endif
+         Support module loading for post 2.6 Linux kernels.
 
 config CONFIG_FEATURE_INSMOD_VERSION_CHECKING
        bool "  Module version checking"
@@ -94,7 +92,7 @@
          lsmod is used to display a list of loaded modules.
 
 config CONFIG_FEATURE_QUERY_MODULE_INTERFACE
-       bool "  Support lsmod query_module interface (add 638 bytes)"
+       bool "  Support lsmod query_module interface"
        default y
        depends on CONFIG_LSMOD && ( CONFIG_FEATURE_2_4_MODULES || 
CONFIG_FEATURE_2_6_MODULES )
        help
Index: modutils/insmod.c
===================================================================
--- modutils/insmod.c   (revision 284)
+++ modutils/insmod.c   (working copy)
@@ -86,6 +86,8 @@
 #include "obj/obj.h"
 #include "obj/kallsyms.h"
 
+#define STRVERSIONLEN   32
+
 static int flag_force_load = 0;
 static int flag_autoclean = 0;
 static int flag_verbose = 0;
@@ -99,9 +101,43 @@
 char *m_filename;
 char *m_fullName;
 
+struct utsname uts_info;
+
 /*======================================================================*/
 
+/* Only use the numeric part of the version string? */
 
+static void use_numeric_only(int major, int minor, char *str)
+{
+       if (((major << 8) + minor) >= 0x0205)   /* kernel 2.5 */
+               *str = '\0';
+}
+
+/* Get the kernel version in the canonical integer form.  */
+
+static int get_kernel_version(char str[STRVERSIONLEN])
+{
+       char *p, *q;
+       int a, b, c;
+
+       strncpy(str, uts_info.release, STRVERSIONLEN-1);
+       str[STRVERSIONLEN-1] = '\0';
+       p = str;
+
+       a = strtoul(p, &p, 10);
+       if (*p != '.')
+               return -1;
+       b = strtoul(p + 1, &p, 10);
+       if (*p != '.')
+               return -1;
+       c = strtoul(p + 1, &q, 10);
+       if (p + 1 == q)
+               return -1;
+       use_numeric_only(a, b, q);
+
+       return a << 16 | b << 8 | c;
+}
+
 static int check_module_name_match(const char *filename, struct stat *statbuf,
                void *userdata)
 {
@@ -127,10 +163,8 @@
 /* Conditionally add the symbols from the given symbol set to the
    new module.  */
 
-static int
-add_symbols_from(
-               struct obj_file *f,
-               int idx, struct module_symbol *syms, size_t nsyms, int gpl)
+static int add_symbols_from(struct obj_file *f, int idx,
+                           struct module_symbol *syms, size_t nsyms, int gpl)
 {
        struct module_symbol *s;
        size_t i;
@@ -160,6 +194,7 @@
                }
 
                sym = obj_find_symbol(f, (char *) s->name);
+
                if (sym && ELFW(ST_BIND) (sym->info) != STB_LOCAL) {
                        sym = obj_add_symbol(f, (char *) s->name, -1,
                                        ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
@@ -222,159 +257,11 @@
 }
 
 
+#ifdef CONFIG_FEATURE_2_2_MODULES
+
 /*======================================================================*/
 /* Functions relating to module loading in pre 2.1 kernels.  */
 
-       static int
-old_process_module_arguments(struct obj_file *f, int argc, char **argv)
-{
-       while (argc > 0) {
-               char *p, *q;
-               struct obj_symbol *sym;
-               int *loc;
-
-               p = *argv;
-               if ((q = strchr(p, '=')) == NULL) {
-                       argc--;
-                       continue;
-               }
-               *q++ = '\0';
-
-               sym = obj_find_symbol(f, p);
-
-               /* Also check that the parameter was not resolved from the kernel.  */
-               if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
-                       bb_error_msg("symbol for parameter %s not found", p);
-                       return 0;
-               }
-
-               loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
-
-               /* Do C quoting if we begin with a ".  */
-               if (*q == '"') {
-                       char *r, *str;
-
-                       str = alloca(strlen(q));
-                       for (r = str, q++; *q != '"'; ++q, ++r) {
-                               if (*q == '\0') {
-                                       bb_error_msg("improperly terminated string 
argument for %s", p);
-                                       return 0;
-                               } else if (*q == '\\')
-                                       switch (*++q) {
-                                               case 'a':
-                                                       *r = '\a';
-                                                       break;
-                                               case 'b':
-                                                       *r = '\b';
-                                                       break;
-                                               case 'e':
-                                                       *r = '\033';
-                                                       break;
-                                               case 'f':
-                                                       *r = '\f';
-                                                       break;
-                                               case 'n':
-                                                       *r = '\n';
-                                                       break;
-                                               case 'r':
-                                                       *r = '\r';
-                                                       break;
-                                               case 't':
-                                                       *r = '\t';
-                                                       break;
-
-                                               case '0':
-                                               case '1':
-                                               case '2':
-                                               case '3':
-                                               case '4':
-                                               case '5':
-                                               case '6':
-                                               case '7':
-                                                       {
-                                                               int c = *q - '0';
-                                                               if (q[1] >= '0' && 
q[1] <= '7') {
-                                                                       c = (c * 8) + 
*++q - '0';
-                                                                       if (q[1] >= 
'0' && q[1] <= '7')
-                                                                               c = (c 
* 8) + *++q - '0';
-                                                               }
-                                                               *r = c;
-                                                       }
-                                                       break;
-
-                                               default:
-                                                       *r = *q;
-                                                       break;
-                                       } else
-                                               *r = *q;
-                       }
-                       *r = '\0';
-                       obj_string_patch(f, sym->secidx, sym->value, str);
-               } else if (*q >= '0' && *q <= '9') {
-                       do
-                               *loc++ = strtoul(q, &q, 0);
-                       while (*q++ == ',');
-               } else {
-                       char *contents = f->sections[sym->secidx]->contents;
-                       char *myloc = contents + sym->value;
-                       char *r;                        /* To search for commas */
-
-                       /* Break the string with comas */
-                       while ((r = strchr(q, ',')) != (char *) NULL) {
-                               *r++ = '\0';
-                               obj_string_patch(f, sym->secidx, myloc - contents, q);
-                               myloc += sizeof(char *);
-                               q = r;
-                       }
-
-                       /* last part */
-                       obj_string_patch(f, sym->secidx, myloc - contents, q);
-               }
-
-               argc--, argv++;
-       }
-
-       return 1;
-}
-
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
-static int old_is_module_checksummed(struct obj_file *f)
-{
-       return obj_find_symbol(f, "Using_Versions") != NULL;
-}
-/* Get the module's kernel version in the canonical integer form.  */
-
-       static int
-old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
-{
-       struct obj_symbol *sym;
-       char *p, *q;
-       int a, b, c;
-
-       sym = obj_find_symbol(f, "kernel_version");
-       if (sym == NULL)
-               return -1;
-
-       p = f->sections[sym->secidx]->contents + sym->value;
-       safe_strncpy(str, p, STRVERSIONLEN);
-
-       a = strtoul(p, &p, 10);
-       if (*p != '.')
-               return -1;
-       b = strtoul(p + 1, &p, 10);
-       if (*p != '.')
-               return -1;
-       c = strtoul(p + 1, &q, 10);
-       if (p + 1 == q)
-               return -1;
-
-       return a << 16 | b << 8 | c;
-}
-
-#endif   /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
-
-#ifdef CONFIG_FEATURE_2_2_MODULES
-
 /* Fetch all the symbols and divvy them up as appropriate for the modules.  */
 
 static int old_get_kernel_symbols(const char *m_name)
@@ -449,19 +336,6 @@
        return 1;
 }
 
-/* Return the kernel symbol checksum version, or zero if not used.  */
-
-static int old_is_kernel_checksummed(void)
-{
-       /* Using_Versions is the first symbol.  */
-       if (nksyms > 0
-                       && strcmp((char *) ksyms[0].name,
-                               "Using_Versions") == 0) return ksyms[0].value;
-       else
-               return 0;
-}
-
-
 static int old_create_mod_use_count(struct obj_file *f)
 {
        struct obj_section *sec;
@@ -585,292 +459,11 @@
 
 #endif                                                 /* CONFIG_FEATURE_2_2_MODULES 
*/
 
+#ifdef CONFIG_FEATURE_2_4_MODULES
 
-
 /*======================================================================*/
 /* Functions relating to module loading after 2.1.18.  */
 
-       static int
-new_process_module_arguments(struct obj_file *f, int argc, char **argv)
-{
-       while (argc > 0) {
-               char *p, *q, *key, *sym_name;
-               struct obj_symbol *sym;
-               char *contents, *loc;
-               int min, max, n;
-
-               p = *argv;
-               if ((q = strchr(p, '=')) == NULL) {
-                       argc--;
-                       continue;
-               }
-
-               key = alloca(q - p + 6);
-               memcpy(key, "parm_", 5);
-               memcpy(key + 5, p, q - p);
-               key[q - p + 5] = 0;
-
-               p = get_modinfo_value(f, key);
-               key += 5;
-               if (p == NULL) {
-                       bb_error_msg("invalid parameter %s", key);
-                       return 0;
-               }
-
-#ifdef SYMBOL_PREFIX
-               sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
-               strcpy (sym_name, SYMBOL_PREFIX);
-               strcat (sym_name, key);
-#else
-               sym_name = key;
-#endif
-               sym = obj_find_symbol(f, sym_name);
-
-               /* Also check that the parameter was not resolved from the kernel.  */
-               if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
-                       bb_error_msg("symbol for parameter %s not found", key);
-                       return 0;
-               }
-
-               if (isdigit(*p)) {
-                       min = strtoul(p, &p, 10);
-                       if (*p == '-')
-                               max = strtoul(p + 1, &p, 10);
-                       else
-                               max = min;
-               } else
-                       min = max = 1;
-
-               contents = f->sections[sym->secidx]->contents;
-               loc = contents + sym->value;
-               n = (*++q != '\0');
-
-               while (1) {
-                       if ((*p == 's') || (*p == 'c')) {
-                               char *str;
-
-                               /* Do C quoting if we begin with a ", else slurp the 
lot.  */
-                               if (*q == '"') {
-                                       char *r;
-
-                                       str = alloca(strlen(q));
-                                       for (r = str, q++; *q != '"'; ++q, ++r) {
-                                               if (*q == '\0') {
-                                                       bb_error_msg("improperly 
terminated string argument for %s",
-                                                                       key);
-                                                       return 0;
-                                               } else if (*q == '\\')
-                                                       switch (*++q) {
-                                                               case 'a':
-                                                                       *r = '\a';
-                                                                       break;
-                                                               case 'b':
-                                                                       *r = '\b';
-                                                                       break;
-                                                               case 'e':
-                                                                       *r = '\033';
-                                                                       break;
-                                                               case 'f':
-                                                                       *r = '\f';
-                                                                       break;
-                                                               case 'n':
-                                                                       *r = '\n';
-                                                                       break;
-                                                               case 'r':
-                                                                       *r = '\r';
-                                                                       break;
-                                                               case 't':
-                                                                       *r = '\t';
-                                                                       break;
-
-                                                               case '0':
-                                                               case '1':
-                                                               case '2':
-                                                               case '3':
-                                                               case '4':
-                                                               case '5':
-                                                               case '6':
-                                                               case '7':
-                                                                       {
-                                                                               int c 
= *q - '0';
-                                                                               if 
(q[1] >= '0' && q[1] <= '7') {
-                                                                                      
 c = (c * 8) + *++q - '0';
-                                                                                      
 if (q[1] >= '0' && q[1] <= '7')
-                                                                                      
         c = (c * 8) + *++q - '0';
-                                                                               }
-                                                                               *r = c;
-                                                                       }
-                                                                       break;
-
-                                                               default:
-                                                                       *r = *q;
-                                                                       break;
-                                                       } else
-                                                               *r = *q;
-                                       }
-                                       *r = '\0';
-                                       ++q;
-                               } else {
-                                       char *r;
-
-                                       /* In this case, the string is not quoted. We 
will break
-                                          it using the coma (like for ints). If the 
user wants to
-                                          include comas in a string, he just has to 
quote it */
-
-                                       /* Search the next coma */
-                                       r = strchr(q, ',');
-
-                                       /* Found ? */
-                                       if (r != (char *) NULL) {
-                                               /* Recopy the current field */
-                                               str = alloca(r - q + 1);
-                                               memcpy(str, q, r - q);
-
-                                               /* I don't know if it is usefull, as 
the previous case
-                                                  doesn't null terminate the string 
??? */
-                                               str[r - q] = '\0';
-
-                                               /* Keep next fields */
-                                               q = r;
-                                       } else {
-                                               /* last string */
-                                               str = q;
-                                               q = "";
-                                       }
-                               }
-
-                               if (*p == 's') {
-                                       /* Normal string */
-                                       obj_string_patch(f, sym->secidx, loc - 
contents, str);
-                                       loc += tgt_sizeof_char_p;
-                               } else {
-                                       /* Array of chars (in fact, matrix !) */
-                                       unsigned long charssize;        /* size of 
each member */
-
-                                       /* Get the size of each member */
-                                       /* Probably we should do that outside the loop 
? */
-                                       if (!isdigit(*(p + 1))) {
-                                               bb_error_msg("parameter type 'c' for 
%s must be followed by"
-                                                               " the maximum size", 
key);
-                                               return 0;
-                                       }
-                                       charssize = strtoul(p + 1, (char **) NULL, 10);
-
-                                       /* Check length */
-                                       if (strlen(str) >= charssize) {
-                                               bb_error_msg("string too long for %s 
(max %ld)", key,
-                                                               charssize - 1);
-                                               return 0;
-                                       }
-
-                                       /* Copy to location */
-                                       strcpy((char *) loc, str);
-                                       loc += charssize;
-                               }
-                       } else {
-                               long v = strtoul(q, &q, 0);
-                               switch (*p) {
-                                       case 'b':
-                                               *loc++ = v;
-                                               break;
-                                       case 'h':
-                                               *(short *) loc = v;
-                                               loc += tgt_sizeof_short;
-                                               break;
-                                       case 'i':
-                                               *(int *) loc = v;
-                                               loc += tgt_sizeof_int;
-                                               break;
-                                       case 'l':
-                                               *(long *) loc = v;
-                                               loc += tgt_sizeof_long;
-                                               break;
-
-                                       default:
-                                               bb_error_msg("unknown parameter type 
'%c' for %s", *p, key);
-                                               return 0;
-                               }
-                       }
-
-retry_end_of_value:
-                       switch (*q) {
-                               case '\0':
-                                       goto end_of_arg;
-
-                               case ' ':
-                               case '\t':
-                               case '\n':
-                               case '\r':
-                                       ++q;
-                                       goto retry_end_of_value;
-
-                               case ',':
-                                       if (++n > max) {
-                                               bb_error_msg("too many values for %s 
(max %d)", key, max);
-                                               return 0;
-                                       }
-                                       ++q;
-                                       break;
-
-                               default:
-                                       bb_error_msg("invalid argument syntax for %s", 
key);
-                                       return 0;
-                       }
-               }
-
-end_of_arg:
-               if (n < min) {
-                       bb_error_msg("too few values for %s (min %d)", key, min);
-                       return 0;
-               }
-
-               argc--, argv++;
-       }
-
-       return 1;
-}
-
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
-static int new_is_module_checksummed(struct obj_file *f)
-{
-       const char *p = get_modinfo_value(f, "using_checksums");
-       if (p)
-               return atoi(p);
-       else
-               return 0;
-}
-
-/* Get the module's kernel version in the canonical integer form.  */
-
-       static int
-new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
-{
-       char *p, *q;
-       int a, b, c;
-
-       p = get_modinfo_value(f, "kernel_version");
-       if (p == NULL)
-               return -1;
-       safe_strncpy(str, p, STRVERSIONLEN);
-
-       a = strtoul(p, &p, 10);
-       if (*p != '.')
-               return -1;
-       b = strtoul(p + 1, &p, 10);
-       if (*p != '.')
-               return -1;
-       c = strtoul(p + 1, &q, 10);
-       if (p + 1 == q)
-               return -1;
-
-       return a << 16 | b << 8 | c;
-}
-
-#endif   /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
-
-
-#ifdef CONFIG_FEATURE_2_4_MODULES
-
 /* Fetch the loaded modules, and all currently exported symbols.  */
 
 static int new_get_kernel_symbols(void)
@@ -963,23 +556,6 @@
 }
 
 
-/* Return the kernel symbol checksum version, or zero if not used.  */
-
-static int new_is_kernel_checksummed(void)
-{
-       struct module_symbol *s;
-       size_t i;
-
-       /* Using_Versions is not the first symbol, but it should be in there.  */
-
-       for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
-               if (strcmp((char *) s->name, "Using_Versions") == 0)
-                       return s->value;
-
-       return 0;
-}
-
-
 static int new_create_this_module(struct obj_file *f, const char *m_name)
 {
        struct obj_section *sec;
@@ -1274,29 +850,84 @@
        if (fd >= 0)
                close(fd);
 }
-#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
-#define check_tainted_module(x, y) do { } while(0);
 #endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
 
-#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
-/* add module source, timestamp, kernel version and a symbol for the
- * start of some sections.  this info is used by ksymoops to do better
- * debugging.
- */
-       static int
-get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
-{
 #ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
-       if (get_modinfo_value(f, "kernel_version") == NULL)
-               return old_get_module_version(f, str);
-       else
-               return new_get_module_version(f, str);
-#else  /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
-       strncpy(str, "???", sizeof(str));
+/* Get the module's kernel version in the canonical integer form.  */
+static int get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
+{
+       int a, b, c;
+       char *p, *q;
+
+       if ((p = get_modinfo_value(f, "kernel_version")) == NULL) {
+               struct obj_symbol *sym;
+
+               m_has_modinfo = 0;
+               if ((sym = obj_find_symbol(f, "kernel_version")) == NULL)
+                       sym = obj_find_symbol(f, "__module_kernel_version");
+               if (sym == NULL)
+                       return -1;
+               p = f->sections[sym->secidx]->contents + sym->value;
+       } else
+               m_has_modinfo = 1;
+
+       strncpy(str, p, STRVERSIONLEN-1);
+       str[STRVERSIONLEN-1] = '\0';
+       p = str;
+
+       a = strtoul(p, &p, 10);
+       if (*p != '.')
+               return -1;
+       b = strtoul(p + 1, &p, 10);
+       if (*p != '.')
+               return -1;
+       c = strtoul(p + 1, &q, 10);
+       if (p + 1 == q)
+               return -1;
+       use_numeric_only(a, b, q);
+
+       return a << 16 | b << 8 | c;
+}
+#else
+static int get_module_version(struct obj_file *f, char str[STRVERSIONLEN]) 
__attribute__((unused));
+static int get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
+{
        return -1;
+}
 #endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+
+#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+/* Return the kernel symbol checksum version, or zero if not used. */
+static int is_kernel_checksummed(void)
+{
+       struct module_symbol *s;
+       size_t i;
+
+       /*
+        * Using_Versions might not be the first symbol,
+        * but it should be in there.
+        */
+       for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
+               if (strcmp((char *) s->name, "Using_Versions") == 0)
+                       return s->value;
+
+       return 0;
 }
 
+static int is_module_checksummed(struct obj_file *f)
+{
+       if (m_has_modinfo) {
+               const char *p = get_modinfo_value(f, "using_checksums");
+               if (p)
+                       return atoi(p);
+               else
+                       return 0;
+       } else
+               return obj_find_symbol(f, "Using_Versions") != NULL;
+}
+#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+
+#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
 /* add module source, timestamp, kernel version and a symbol for the
  * start of some sections.  this info is used by ksymoops to do better
  * debugging.
@@ -1371,7 +1002,7 @@
                        new_add_ksymtab(f, sym);
        }
        free(absolute_filename);
-#ifdef _NOT_SUPPORTED_
+
        /* record where the persistent data is going, same address as previous symbol 
*/
 
        if (f->persist) {
@@ -1388,7 +1019,7 @@
                if (use_ksymtab)
                        new_add_ksymtab(f, sym);
        }
-#endif /* _NOT_SUPPORTED_ */
+
        /* tag the desired sections if size is non-zero */
 
        for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
@@ -1414,6 +1045,246 @@
 }
 #endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
 
+static int process_module_arguments(struct obj_file *f, int argc, char **argv, int 
required)
+{
+       for (; argc > 0; ++argv, --argc) {
+               struct obj_symbol *sym;
+               int c;
+               int min, max;
+               int n;
+               char *contents;
+               char *input;
+               char *fmt;
+               char *key;
+               char *loc;
+
+               if ((input = strchr(*argv, '=')) == NULL)
+                       continue;
+
+               n = input - *argv;
+               input += 1; /* skip '=' */
+
+               key = alloca(n + 6);
+
+               if (m_has_modinfo) {
+                       memcpy(key, "parm_", 5);
+                       memcpy(key + 5, *argv, n);
+                       key[n + 5] = '\0';
+                       if ((fmt = get_modinfo_value(f, key)) == NULL) {
+                               if (required || flag_verbose) {
+                                       bb_error_msg("Warning: ignoring %s, no such 
parameter in this module", *argv);
+                                       continue;
+                               }
+                       }
+                       key += 5;
+
+                       if (isdigit(*fmt)) {
+                               min = strtoul(fmt, &fmt, 10);
+                               if (*fmt == '-')
+                                       max = strtoul(fmt + 1, &fmt, 10);
+                               else
+                                       max = min;
+                       } else
+                               min = max = 1;
+               } else { /* not m_has_modinfo */
+                       memcpy(key, *argv, n);
+                       key[n] = '\0';
+
+                       if (isdigit(*input))
+                               fmt = "i";
+                       else
+                               fmt = "s";
+                       min = max = 0;
+               }
+
+               sym = obj_find_symbol(f, key);
+
+               /*
+                * Also check that the parameter was not
+                * resolved from the kernel.
+                */
+               if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
+                       bb_error_msg("symbol for parameter %s not found", key);
+                       return 0;
+               }
+
+               contents = f->sections[sym->secidx]->contents;
+               loc = contents + sym->value;
+               n = 1;
+
+               while (*input) {
+                       char *str;
+
+                       switch (*fmt) {
+                               case 's':
+                               case 'c':
+                                       /*
+                                        * Do C quoting if we begin with a ",
+                                        * else slurp the lot.
+                                        */
+                                       if (*input == '"') {
+                                               char *r;
+
+                                               str = alloca(strlen(input));
+                                               for (r = str, input++; *input != '"'; 
++input, ++r) {
+                                                       if (*input == '\0') {
+                                                               
bb_error_msg("improperly terminated string argument for %s", key);
+                                                               return 0;
+                                                       }
+                                                       /* else */
+                                                       if (*input != '\\') {
+                                                               *r = *input;
+                                                               continue;
+                                                       }
+                                                       /* else  handle \ */
+                                                       switch (*++input) {
+                                                               case 'a': *r = '\a'; 
break;
+                                                               case 'b': *r = '\b'; 
break;
+                                                               case 'e': *r = '\033'; 
break;
+                                                               case 'f': *r = '\f'; 
break;
+                                                               case 'n': *r = '\n'; 
break;
+                                                               case 'r': *r = '\r'; 
break;
+                                                               case 't': *r = '\t'; 
break;
+
+                                                               case '0':
+                                                               case '1':
+                                                               case '2':
+                                                               case '3':
+                                                               case '4':
+                                                               case '5':
+                                                               case '6':
+                                                               case '7':
+                                                                         c = *input - 
'0';
+                                                                         if ('0' <= 
input[1] && input[1] <= '7') {
+                                                                                 c = 
(c * 8) + *++input - '0';
+                                                                                 if 
('0' <= input[1] && input[1] <= '7')
+                                                                                      
   c = (c * 8) + *++input - '0';
+                                                                         }
+                                                                         *r = c;
+                                                                         break;
+
+                                                               default: *r = *input; 
break;
+                                                       }
+                                               }
+                                               *r = '\0';
+                                               ++input;
+                                       } else {
+                                               /*
+                                                * The string is not quoted.
+                                                * We will break it using the comma
+                                                * (like for ints).
+                                                * If the user wants to include commas
+                                                * in a string, he just has to quote it
+                                                */
+                                               char *r;
+
+                                               /* Search the next comma */
+                                               if ((r = strchr(input, ',')) != NULL) {
+                                                       /*
+                                                        * Found a comma
+                                                        * Recopy the current field
+                                                        */
+                                                       str = alloca(r - input + 1);
+                                                       memcpy(str, input, r - input);
+                                                       str[r - input] = '\0';
+                                                       /* Keep next fields */
+                                                       input = r;
+                                               } else {
+                                                       /* last string */
+                                                       str = input;
+                                                       input = "";
+                                               }
+                                       }
+
+                                       if (*fmt == 's') {
+                                               /* Normal string */
+                                               obj_string_patch(f, sym->secidx, loc - 
contents, str);
+                                               loc += tgt_sizeof_char_p;
+                                       } else {
+                                               /* Array of chars (in fact, matrix !) 
*/
+                                               long charssize; /* size of each member 
*/
+
+                                               /* Get the size of each member */
+                                               /* Probably we should do that outside 
the loop ? */
+                                               if (!isdigit(*(fmt + 1))) {
+                                                       bb_error_msg("parameter type 
'c' for %s must be followed by"
+                                                                       " the maximum 
size", key);
+                                                       return 0;
+                                               }
+                                               charssize = strtoul(fmt + 1, (char **) 
NULL, 10);
+
+                                               /* Check length */
+                                               if (strlen(str) >= charssize-1) {
+                                                       bb_error_msg("string too long 
for %s (max %ld)",
+                                                                       key, charssize 
- 1);
+                                                       return 0;
+                                               }
+                                               /* Copy to location */
+                                               strcpy((char *) loc, str);      /* 
safe, see check above */
+                                               loc += charssize;
+                                       }
+                                       /*
+                                        * End of 's' and 'c'
+                                        */
+                                       break;
+
+                               case 'b':
+                                       *loc++ = strtoul(input, &input, 0);
+                                       break;
+
+                               case 'h':
+                                       *(short *) loc = strtoul(input, &input, 0);
+                                       loc += tgt_sizeof_short;
+                                       break;
+
+                               case 'i':
+                                       *(int *) loc = strtoul(input, &input, 0);
+                                       loc += tgt_sizeof_int;
+                                       break;
+
+                               case 'l':
+                                       *(long *) loc = strtoul(input, &input, 0);
+                                       loc += tgt_sizeof_long;
+                                       break;
+
+                               default:
+                                       bb_error_msg("unknown parameter type '%c' for 
%s",
+                                                       *fmt, key);
+                                       return 0;
+                       }
+                       /*
+                        * end of switch (*fmt)
+                        */
+
+                       while (*input && isspace(*input))
+                               ++input;
+                       if (*input == '\0')
+                               break; /* while (*input) */
+                       /* else */
+
+                       if (*input == ',') {
+                               if (max && (++n > max)) {
+                                       bb_error_msg("too many values for %s (max 
%d)", key, max);
+                                       return 0;
+                               }
+                               ++input;
+                               /* continue with while (*input) */
+                       } else {
+                               bb_error_msg("invalid argument syntax for %s: '%c'",
+                                               key, *input);
+                               return 0;
+                       }
+               } /* end of while (*input) */
+
+               if (min && (n < min)) {
+                       bb_error_msg("too few values for %s (min %d)", key, min);
+                       return 0;
+               }
+       } /* end of for (;argc > 0;) */
+
+       return 1;
+}
+
 #ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
 static void print_load_map(struct obj_file *f)
 {
@@ -1506,77 +1377,76 @@
 
 #endif
 
+#if defined(CONFIG_FEATURE_2_2_MODULES) || defined (CONFIG_FEATURE_2_4_MODULES)
+static int do_2_0_and_2_4(int fp, int argc, char **argv, char *m_name);
+#endif
+#ifdef CONFIG_FEATURE_2_6_MODULES
+static int do_2_6(int fp, int argc, char **argv);
+#endif
+
 extern int insmod_main( int argc, char **argv)
 {
        int opt;
-       int k_crcs;
        int len;
        char *tmp, *tmp1;
-       unsigned long m_size;
-       ElfW(Addr) m_addr;
-       struct obj_file *f;
        struct stat st;
        char *m_name = 0;
-       int exit_status = EXIT_FAILURE;
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
-       struct utsname uts_info;
-       char m_strversion[STRVERSIONLEN];
-       int m_version;
-       int m_crcs;
-#endif
-       int fp = 0;
+       int fp;
 #ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
        int flag_print_load_map = 0;
 #endif
-       int gpl;
+       int k_version;
+       char k_strversion[STRVERSIONLEN];
+        uname(&uts_info);
 
        /* Parse any options */
 #ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
-       while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0) {
+       while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0)
 #else
-       while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0) {
+       while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0)
 #endif
-               switch (opt) {
-                       case 'f':                       /* force loading */
-                               flag_force_load = 1;
-                               break;
-                       case 'k':                       /* module loaded by kerneld, 
auto-cleanable */
-                               flag_autoclean = 1;
-                               break;
-                       case 's':                       /* log to syslog */
-                               /* log to syslog -- not supported              */
-                               /* but kernel needs this for request_module(), */
-                               /* as this calls: modprobe -k -s -- <module>   */
-                               /* so silently ignore this flag                */
-                               break;
-                       case 'v':                       /* verbose output */
-                               flag_verbose = 1;
-                               break;
-                       case 'q':                       /* silent */
-                               flag_quiet = 1;
-                               break;
-                       case 'x':                       /* do not export externs */
-                               flag_export = 0;
-                               break;
-                       case 'o':                       /* name the output module */
-                               free(m_name);
-                               m_name = bb_xstrdup(optarg);
-                               break;
-                       case 'L':                       /* Stub warning */
-                               /* This is needed for compatibility with modprobe.
-                                * In theory, this does locking, but we don't do
-                                * that.  So be careful and plan your life around not
-                                * loading the same module 50 times concurrently. */
-                               break;
+               {
+                       switch (opt) {
+                               case 'f':                       /* force loading */
+                                       flag_force_load = 1;
+                                       break;
+                               case 'k':                       /* module loaded by 
kerneld, auto-cleanable */
+                                       flag_autoclean = 1;
+                                       break;
+                               case 's':                       /* log to syslog */
+                                       /* log to syslog -- not supported              
*/
+                                       /* but kernel needs this for request_module(), 
*/
+                                       /* as this calls: modprobe -k -s -- <module>   
*/
+                                       /* so silently ignore this flag                
*/
+                                       break;
+                               case 'v':                       /* verbose output */
+                                       flag_verbose = 1;
+                                       break;
+                               case 'q':                       /* silent */
+                                       flag_quiet = 1;
+                                       break;
+                               case 'x':                       /* do not export 
externs */
+                                       flag_export = 0;
+                                       break;
+                               case 'o':                       /* name the output 
module */
+                                       free(m_name);
+                                       m_name = bb_xstrdup(optarg);
+                                       break;
+                               case 'L':                       /* Stub warning */
+                                       /* This is needed for compatibility with 
modprobe.
+                                        * In theory, this does locking, but we don't 
do
+                                        * that.  So be careful and plan your life 
around not
+                                        * loading the same module 50 times 
concurrently. */
+                                       break;
 #ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
-                       case 'm':                       /* print module load map */
-                               flag_print_load_map = 1;
-                               break;
+                               case 'm':                       /* print module load 
map */
+                                       flag_print_load_map = 1;
+                                       break;
 #endif
-                       default:
-                               bb_show_usage();
+                               default:
+                                       bb_show_usage();
+                       }
                }
-       }
 
        if (argv[optind] == NULL) {
                bb_show_usage();
@@ -1587,15 +1457,24 @@
        tmp = basename(tmp1);
        len = strlen(tmp);
 
-       if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
-               len-=2;
+       k_version = get_kernel_version(k_strversion);
+
+#if defined(CONFIG_FEATURE_2_6_MODULES)
+       if (k_version > 0x20500 && len > 3 && tmp[len - 3] == '.' &&
+                       tmp[len - 2] == 'k' && tmp[len - 1] == 'o') {
+               len-=3;
                tmp[len] = '\0';
        }
+       else
+#endif
+               if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
+                       len-=2;
+                       tmp[len] = '\0';
+               }
 
-       bb_xasprintf(&m_fullName, "%s.o", tmp);
 
 #if defined(CONFIG_FEATURE_2_6_MODULES)
-       if (k_version > 4)
+       if (k_version > 0x20500)
                bb_xasprintf(&m_fullName, "%s.ko", tmp);
        else
 #endif
@@ -1605,22 +1484,19 @@
                m_name = tmp;
        } else {
                free(tmp1);
-               tmp1 = 0;       /* flag for free(m_name) before exit() */
        }
 
        /* Get a filedesc for the module.  Check we we have a complete path */
        if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
-                       (fp = open(argv[optind], O_RDONLY)) == 0) {
-               struct utsname myuname;
-
+                       (fp = open(argv[optind], O_RDONLY)) < 0) {
                /* Hmm.  Could not open it.  First search under /lib/modules/`uname 
-r`,
                 * but do not error out yet if we fail to find it... */
-               if (uname(&myuname) == 0) {
+               if (k_version) {        /* uname succeedd */
                        char *module_dir;
                        char *tmdn;
                        char real_module_dir[FILENAME_MAX];
 
-                       tmdn = concat_path_file(_PATH_MODULES, myuname.release);
+                       tmdn = concat_path_file(_PATH_MODULES, k_strversion);
                        /* Jump through hoops in case /lib/modules/`uname -r`
                         * is a symlink.  We do not want recursive_action to
                         * follow symlinks, but we do want to follow the
@@ -1636,7 +1512,7 @@
                }
 
                /* Check if we have found anything yet */
-               if (m_filename == 0 || ((fp = open(m_filename, O_RDONLY)) == 0))
+               if (m_filename == 0 || ((fp = open(m_filename, O_RDONLY)) < 0))
                {
                        char module_dir[FILENAME_MAX];
 
@@ -1647,94 +1523,107 @@
                        /* No module found under /lib/modules/`uname -r`, this
                         * time cast the net a bit wider.  Search /lib/modules/ */
                        if (! recursive_action(module_dir, TRUE, FALSE, FALSE,
-                                               check_module_name_match, 0, 
m_fullName)) 
+                                               check_module_name_match, 0, 
m_fullName))
                        {
                                if (m_filename == 0
-                                               || ((fp = open(m_filename, O_RDONLY)) 
== 0)) 
+                                               || ((fp = open(m_filename, O_RDONLY)) 
< 0))
                                {
                                        bb_error_msg("%s: no module by that name 
found", m_fullName);
-                                       goto out;
+                                       return EXIT_FAILURE;
                                }
                        } else
                                bb_error_msg_and_die("%s: no module by that name 
found", m_fullName);
                }
-       } else 
+       } else
                m_filename = bb_xstrdup(argv[optind]);
 
        if (!flag_quiet)
                printf("Using %s\n", m_filename);
 
+       if (k_version > 0x20500)
+       {
+#ifdef CONFIG_FEATURE_2_6_MODULES
+               return do_2_6(fp, argc - optind, argv + optind);
+#endif
+       }
+       else if (k_version > 0x20100)
+       {
+#ifdef CONFIG_FEATURE_2_4_MODULES
+               return do_2_0_and_2_4(fp, argc - optind, argv + optind, m_name);
+#endif
+       }
+       else if (k_version > 0x20000)
+       {
+#ifdef CONFIG_FEATURE_2_2_MODULES
+               return do_2_0_and_2_4(fp, argc - optind, argv + optind, m_name);
+#endif
+       }
+       return EXIT_FAILURE;
+}
+
+#if defined(CONFIG_FEATURE_2_2_MODULES) || defined (CONFIG_FEATURE_2_4_MODULES)
+static int do_2_0_and_2_4(int fp, int argc, char **argv, char *m_name)
+{
+       struct obj_file *f;
+       char k_strversion[STRVERSIONLEN];
+       int k_version = 0;
+#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+       char m_strversion[STRVERSIONLEN];
+       int m_version;
+       int m_crcs;
+#endif
+       unsigned long m_size;
+       ElfW(Addr) m_addr;
+       int gpl;
+
        if ((f = obj_load(fp, ET_REL, m_filename)) == NULL)
                bb_perror_msg_and_die("Could not load the module");
 
-       if (get_modinfo_value(f, "kernel_version") == NULL)
-               m_has_modinfo = 0;
-       else
-               m_has_modinfo = 1;
-
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
        /* Version correspondence?  */
-       if (!flag_quiet) {
-               if (uname(&uts_info) < 0)
-                       uts_info.release[0] = '\0';
-               if (m_has_modinfo) {
-                       m_version = new_get_module_version(f, m_strversion);
-               } else {
-                       m_version = old_get_module_version(f, m_strversion);
-                       if (m_version == -1) {
-                               bb_error_msg("couldn't find the kernel version the 
module was "
-                                               "compiled for");
-                               goto out;
-                       }
-               }
-
-               if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
-                       if (flag_force_load) {
-                               bb_error_msg("Warning: kernel-module version 
mismatch\n"
-                                               "\t%s was compiled for kernel version 
%s\n"
-                                               "\twhile this kernel is version %s",
-                                               m_filename, m_strversion, 
uts_info.release);
-                       } else {
-                               bb_error_msg("kernel-module version mismatch\n"
-                                               "\t%s was compiled for kernel version 
%s\n"
-                                               "\twhile this kernel is version %s.",
-                                               m_filename, m_strversion, 
uts_info.release);
-                               goto out;
-                       }
-               }
+       k_version = get_kernel_version(k_strversion);
+#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+       m_version = get_module_version(f, m_strversion);
+       if (m_version == -1) {
+               error("couldn't find the kernel version the module was compiled for");
+               return EXIT_FAILURE;
        }
-
-       k_crcs = 0;
 #endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
 
-       k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
-
-       if (k_new_syscalls) {
+       if (k_version > 0x20100)
+       {
 #ifdef CONFIG_FEATURE_2_4_MODULES
                if (!new_get_kernel_symbols())
-                       goto out;
-               k_crcs = new_is_kernel_checksummed();
-#else
-               bb_error_msg("Not configured to support new kernels");
-               goto out;
+                       return EXIT_FAILURE;
 #endif
-       } else {
+       }
+       else
+       {
 #ifdef CONFIG_FEATURE_2_2_MODULES
-               if (!old_get_kernel_symbols(m_name))
-                       goto out;
-               k_crcs = old_is_kernel_checksummed();
-#else
-               bb_error_msg("Not configured to support old kernels");
-               goto out;
+               if (!old_get_kernel_symbols())
+                       return EXIT_FAILURE;
 #endif
        }
 
 #ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
-       if (m_has_modinfo)
-               m_crcs = new_is_module_checksummed(f);
-       else
-               m_crcs = old_is_module_checksummed(f);
-
+       k_crcs = is_kernel_checksummed();
+       m_crcs = is_module_checksummed(f);
+       if ((m_crcs == 0 || k_crcs == 0) &&
+                       strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
+               if (flag_force_load) {
+                       lprintf("Warning: kernel-module version mismatch\n"
+                                       "\t%s was compiled for kernel version %s\n"
+                                       "\twhile this kernel is version %s",
+                                       filename, m_strversion, k_strversion);
+                       ++warnings;
+               } else {
+                       if (!quiet)
+                               error("kernel-module version mismatch\n"
+                                               "\t%s was compiled for kernel version 
%s\n"
+                                               "\twhile this kernel is version %s.",
+                                               filename, m_strversion, k_strversion);
+                       return EXIT_FAILURE;
+               }
+       }
        if (m_crcs != k_crcs)
                obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
 #endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
@@ -1745,29 +1634,27 @@
 
        /* Allocate common symbols, symbol tables, and string tables.  */
 
-       if (k_new_syscalls 
+       if (k_new_syscalls
                        ? !new_create_this_module(f, m_name)
-                       : !old_create_mod_use_count(f)) 
+                       : !old_create_mod_use_count(f))
        {
-               goto out;
+               return EXIT_FAILURE;
        }
 
        if (!obj_check_undefineds(f, 0)) {
-               goto out;
+               return EXIT_FAILURE;
        }
        obj_allocate_commons(f);
+#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
        check_tainted_module(f, m_name);
+#endif
 
        /* done with the module name, on to the optional var=value arguments */
        ++optind;
 
        if (optind < argc) {
-               if (m_has_modinfo
-                               ? !new_process_module_arguments(f, argc - optind, argv 
+ optind) 
-                               : !old_process_module_arguments(f, argc - optind, argv 
+ optind)) 
-               {
-                       goto out;
-               }
+               if (!process_module_arguments(f, argc - optind, argv + optind, 1))
+                       return EXIT_FAILURE;
        }
 
        arch_create_got(f);
@@ -1787,26 +1674,26 @@
        if (m_addr == -1) switch (errno) {
                case EEXIST:
                        bb_error_msg("A module named %s already exists", m_name);
-                       goto out;
+                       return EXIT_FAILURE;
                case ENOMEM:
                        bb_error_msg("Can't allocate kernel memory for module; needed 
%lu bytes", m_size);
-                       goto out;
+                       return EXIT_FAILURE;
                default:
                        bb_perror_msg("create_module: %s", m_name);
-                       goto out;
+                       return EXIT_FAILURE;
        }
 
        if (!obj_relocate(f, m_addr)) {
                delete_module(m_name);
-               goto out;
+               return EXIT_FAILURE;
        }
 
-       if (k_new_syscalls 
+       if (k_new_syscalls
                        ? !new_init_module(m_name, f, m_size)
-                       : !old_init_module(m_name, f, m_size)) 
+                       : !old_init_module(m_name, f, m_size))
        {
                delete_module(m_name);
-               goto out;
+               return EXIT_FAILURE;
        }
 
 #ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
@@ -1814,22 +1701,71 @@
                print_load_map(f);
 #endif
 
-       exit_status = EXIT_SUCCESS;
+       return EXIT_SUCCESS;
+}
+#endif /* CONFIG_FEATURE_2_2_MODULES || CONFIG_FEATURE_2_4_MODULES */
 
-out:
-#ifdef CONFIG_FEATURE_CLEAN_UP
-       if(fp)
-               fclose(fp);
-       if(tmp1) {
-               free(tmp1);
-       } else {
-               free(m_name);
+#ifdef CONFIG_FEATURE_2_6_MODULES
+#include <sys/mman.h>
+#include <sys/syscall.h>
+
+/* We use error numbers in a loose translation... */
+static const char *moderror(int err)
+{
+       switch (err) {
+               case ENOEXEC:
+                       return "Invalid module format";
+               case ENOENT:
+                       return "Unknown symbol in module";
+               case ESRCH:
+                       return "Module has wrong symbol version";
+               case EINVAL:
+                       return "Invalid parameters";
+               default:
+                       return strerror(err);
        }
-       free(m_filename);
-#endif
-       return(exit_status);
 }
 
+static int do_2_6(int fd, int argc, char **argv)
+{
+       int i;
+       long int ret;
+       struct stat st;
+       unsigned long len;
+       void *map;
+       char *options = bb_xstrdup("");
+
+       /* Rest is options */
+       for (i = 2; i < argc; i++) {
+               options = xrealloc(options, strlen(options) + 2 + strlen(argv[i]) + 2);
+               /* Spaces handled by "" pairs, but no way of escaping quotes */
+               if (strchr(argv[i], ' ')) {
+                       strcat(options, "\"");
+                       strcat(options, argv[i]);
+                       strcat(options, "\"");
+               } else {
+                       strcat(options, argv[i]);
+               }
+               strcat(options, " ");
+       }
+
+       fstat(fd, &st);
+       len = st.st_size;
+       map = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
+       if (map == MAP_FAILED) {
+               bb_perror_msg_and_die("cannot mmap `%s'", m_filename);
+       }
+
+       ret = syscall(__NR_init_module, map, len, options);
+       if (ret != 0) {
+               bb_perror_msg_and_die("cannot insert `%s': %s (%li)",
+                               m_filename, moderror(errno), ret);
+       }
+
+       return 0;
+}
+#endif /* CONFIG_FEATURE_2_6_MODULES */
+
 int check_module (const char *mod)
 {
        k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
@@ -1842,3 +1778,4 @@
        return -1;
 }
 
+

Attachment: signature.asc
Description: Digital signature

Reply via email to