diff options
Diffstat (limited to 'modutils')
-rw-r--r-- | modutils/Config.in | 36 | ||||
-rw-r--r-- | modutils/insmod.c | 127 | ||||
-rw-r--r-- | modutils/rmmod.c | 11 |
3 files changed, 138 insertions, 36 deletions
diff --git a/modutils/Config.in b/modutils/Config.in index 96040cd69..d9f76d1b4 100644 --- a/modutils/Config.in +++ b/modutils/Config.in @@ -11,32 +11,31 @@ config CONFIG_INSMOD help insmod is used to load specified modules in the running kernel. -config CONFIG_FEATURE_OLD_MODULE_INTERFACE +config CONFIG_FEATURE_2_2_MODULES bool " Support older (pre 2.1) Linux kernels" default n depends on CONFIG_INSMOD help Provide insmod support for older (pre 2.1) Linux kernels. -if CONFIG_INSMOD && !CONFIG_FEATURE_OLD_MODULE_INTERFACE - config CONFIG_FEATURE_NEW_MODULE_INTERFACE - default y - comment " Support new (post 2.1) Linux kernels (Forced enabled)" -endif - -if CONFIG_FEATURE_OLD_MODULE_INTERFACE -config CONFIG_FEATURE_NEW_MODULE_INTERFACE - bool " Support new (post 2.1) Linux kernels" +config CONFIG_FEATURE_2_4_MODULES + bool " Support version 2.1.x to 2.4.x Linux kernels" default y depends on CONFIG_INSMOD help Support module loading for newer (post 2.1) Linux kernels. -endif + +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. config CONFIG_FEATURE_INSMOD_VERSION_CHECKING bool " Module version checking" default n - depends on CONFIG_INSMOD + depends on CONFIG_INSMOD && ( CONFIG_FEATURE_2_2_MODULES || CONFIG_FEATURE_2_4_MODULES ) help Support checking of versions for modules. This is used to ensure that the kernel and module are made for each other. @@ -44,7 +43,7 @@ config CONFIG_FEATURE_INSMOD_VERSION_CHECKING config CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS bool " Add module symbols to kernel symbol table" default n - depends on CONFIG_INSMOD + depends on CONFIG_INSMOD && ( CONFIG_FEATURE_2_2_MODULES || CONFIG_FEATURE_2_4_MODULES ) help By adding module symbols to the kernel symbol table, Oops messages occuring within kernel modules can be properly debugged. By enabling @@ -55,7 +54,7 @@ config CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS config CONFIG_FEATURE_INSMOD_LOADINKMEM bool " In kernel memory optimization (uClinux only)" default n - depends on CONFIG_INSMOD + depends on CONFIG_INSMOD && ( CONFIG_FEATURE_2_2_MODULES || CONFIG_FEATURE_2_4_MODULES ) help This is a special uClinux only memory optimization that lets insmod load the specified kernel module directly into kernel space, reducing @@ -65,7 +64,7 @@ config CONFIG_FEATURE_INSMOD_LOADINKMEM config CONFIG_FEATURE_INSMOD_LOAD_MAP bool " Enable load map (-m) option" default n - depends on CONFIG_INSMOD + depends on CONFIG_INSMOD && ( CONFIG_FEATURE_2_2_MODULES || CONFIG_FEATURE_2_4_MODULES ) help Enabling this, one would be able to get a load map output on stdout. This makes kernel module debugging @@ -79,9 +78,8 @@ config CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL depends on CONFIG_FEATURE_INSMOD_LOAD_MAP help Without this option, -m will only output section - load map. - With this option, -m will also output symbols - load map. + load map. With this option, -m will also output + symbols load map. config CONFIG_LSMOD bool "lsmod" @@ -92,7 +90,7 @@ config CONFIG_LSMOD config CONFIG_FEATURE_QUERY_MODULE_INTERFACE bool " Support lsmod query_module interface (add 638 bytes)" default y - depends on CONFIG_LSMOD && CONFIG_FEATURE_NEW_MODULE_INTERFACE + depends on CONFIG_LSMOD && ( CONFIG_FEATURE_2_4_MODULES || CONFIG_FEATURE_2_6_MODULES ) help This will provide some extra information about each module when running lsmod. The fields provided are address, size, flags and diff --git a/modutils/insmod.c b/modutils/insmod.c index e2ca64169..979c41f78 100644 --- a/modutils/insmod.c +++ b/modutils/insmod.c @@ -80,8 +80,24 @@ #include <sys/utsname.h> #include "busybox.h" -#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE -# undef CONFIG_FEATURE_OLD_MODULE_INTERFACE +#if !defined(CONFIG_FEATURE_2_4_MODULES) && \ + !defined(CONFIG_FEATURE_2_2_MODULES) && \ + !defined(CONFIG_FEATURE_2_6_MODULES) +#define CONFIG_FEATURE_2_4_MODULES +#endif + +#if !defined(CONFIG_FEATURE_2_4_MODULES) && !defined(CONFIG_FEATURE_2_2_MODULES) +#define insmod_ng_main insmod_main +#endif + +#if defined(CONFIG_FEATURE_2_4_MODULES) || defined(CONFIG_FEATURE_2_2_MODULES) + +#if defined(CONFIG_FEATURE_2_6_MODULES) +extern int insmod_ng_main( int argc, char **argv); +#endif + +#ifdef CONFIG_FEATURE_2_4_MODULES +# undef CONFIG_FEATURE_2_2_MODULES # define new_sys_init_module init_module #else # define old_sys_init_module init_module @@ -266,7 +282,7 @@ #ifndef MODUTILS_MODULE_H static const int MODUTILS_MODULE_H = 1; -#ident "$Id: insmod.c,v 1.106 2003/12/04 15:02:57 mjn3 Exp $" +#ident "$Id: insmod.c,v 1.107 2003/12/11 01:42:13 andersen Exp $" /* This file contains the structures used by the 2.0 and 2.1 kernels. We do not use the kernel headers directly because we do not wish @@ -399,7 +415,7 @@ struct new_module unsigned tgt_long persist_end; unsigned tgt_long can_unload; unsigned tgt_long runsize; -#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE +#ifdef CONFIG_FEATURE_2_4_MODULES const char *kallsyms_start; /* All symbols for kernel debugging */ const char *kallsyms_end; const char *archdata_start; /* arch specific data for module */ @@ -487,7 +503,7 @@ int delete_module(const char *); #ifndef MODUTILS_OBJ_H static const int MODUTILS_OBJ_H = 1; -#ident "$Id: insmod.c,v 1.106 2003/12/04 15:02:57 mjn3 Exp $" +#ident "$Id: insmod.c,v 1.107 2003/12/11 01:42:13 andersen Exp $" /* The relocatable object is manipulated using elfin types. */ @@ -630,7 +646,7 @@ static void *obj_extend_section (struct obj_section *sec, unsigned long more); static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, const char *string); -#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE +#ifdef CONFIG_FEATURE_2_4_MODULES static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, struct obj_symbol *sym); #endif @@ -665,7 +681,7 @@ static void arch_create_got (struct obj_file *f); static int obj_gpl_license(struct obj_file *f, const char **license); -#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE +#ifdef CONFIG_FEATURE_2_4_MODULES static int arch_init_module (struct obj_file *f, struct new_module *); #endif @@ -1626,7 +1642,7 @@ static void arch_create_got(struct obj_file *f) #endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */ } -#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE +#ifdef CONFIG_FEATURE_2_4_MODULES static int arch_init_module(struct obj_file *f, struct new_module *mod) { return 1; @@ -2224,7 +2240,7 @@ old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN]) #endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */ -#ifdef CONFIG_FEATURE_OLD_MODULE_INTERFACE +#ifdef CONFIG_FEATURE_2_2_MODULES /* Fetch all the symbols and divvy them up as appropriate for the modules. */ @@ -2434,7 +2450,7 @@ old_init_module(const char *m_name, struct obj_file *f, #define old_create_mod_use_count(x) TRUE #define old_init_module(x, y, z) TRUE -#endif /* CONFIG_FEATURE_OLD_MODULE_INTERFACE */ +#endif /* CONFIG_FEATURE_2_2_MODULES */ @@ -2720,7 +2736,7 @@ new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN]) #endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */ -#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE +#ifdef CONFIG_FEATURE_2_4_MODULES /* Fetch the loaded modules, and all currently exported symbols. */ @@ -3041,7 +3057,7 @@ new_init_module(const char *m_name, struct obj_file *f, #define new_create_module_ksymtab(x) #define query_module(v, w, x, y, z) -1 -#endif /* CONFIG_FEATURE_NEW_MODULE_INTERFACE */ +#endif /* CONFIG_FEATURE_2_4_MODULES */ /*======================================================================*/ @@ -3075,7 +3091,7 @@ obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, return 1; } -#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE +#ifdef CONFIG_FEATURE_2_4_MODULES static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, struct obj_symbol *sym) @@ -4161,7 +4177,7 @@ extern int insmod_main( int argc, char **argv) printf("Using %s\n", m_filename); -#ifdef CONFIG_FEATURE_REALLY_NEW_MODULE_INTERFACE +#ifdef CONFIG_FEATURE_2_6_MODULES if (create_module(NULL, 0) < 0 && errno == ENOSYS) { optind--; argv[optind] = m_filename; @@ -4214,7 +4230,7 @@ extern int insmod_main( int argc, char **argv) k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL); if (k_new_syscalls) { -#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE +#ifdef CONFIG_FEATURE_2_4_MODULES if (!new_get_kernel_symbols()) goto out; k_crcs = new_is_kernel_checksummed(); @@ -4223,7 +4239,7 @@ extern int insmod_main( int argc, char **argv) goto out; #endif } else { -#ifdef CONFIG_FEATURE_OLD_MODULE_INTERFACE +#ifdef CONFIG_FEATURE_2_2_MODULES if (!old_get_kernel_symbols(m_name)) goto out; k_crcs = old_is_kernel_checksummed(); @@ -4345,3 +4361,82 @@ out: #endif return(exit_status); } + + +#endif + + +#ifdef CONFIG_FEATURE_2_6_MODULES + +#include <sys/mman.h> +#include <asm/unistd.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); + } +} + +extern int insmod_ng_main( int argc, char **argv) +{ + int i; + int fd; + long int ret; + struct stat st; + unsigned long len; + void *map; + char *filename, *options = bb_xstrdup(""); + + filename = argv[1]; + if (!filename) { + bb_show_usage(); + return -1; + } + + /* 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, " "); + } + + if ((fd = open(filename, O_RDONLY, 0)) < 0) { + bb_perror_msg_and_die("cannot open module `%s'", filename); + } + + 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'", filename); + } + + ret = syscall(__NR_init_module, map, len, options); + if (ret != 0) { + bb_perror_msg_and_die("cannot insert `%s': %s (%li)", + filename, moderror(errno), ret); + } + + return 0; +} + +#endif diff --git a/modutils/rmmod.c b/modutils/rmmod.c index a4ea70410..311b03dc4 100644 --- a/modutils/rmmod.c +++ b/modutils/rmmod.c @@ -25,6 +25,8 @@ #include <unistd.h> #include <stdlib.h> #include <getopt.h> +#include <fcntl.h> +#include <sys/syscall.h> #include "busybox.h" extern int delete_module(const char * name); @@ -37,10 +39,17 @@ extern int rmmod_main(int argc, char **argv) size_t pnmod = -1; /* previous number of modules */ void *buf; /* hold the module names which we ignore but must get */ size_t bufsize = 0; + unsigned int flags = O_NONBLOCK|O_EXCL; /* Parse command line. */ while ((n = getopt(argc, argv, "a")) != EOF) { switch (n) { + case 'w': // --wait + flags &= ~O_NONBLOCK; + break; + case 'f': // --force + flags |= O_TRUNC; + break; case 'a': /* Unload _all_ unused modules via NULL delete_module() call */ /* until the number of modules does not change */ @@ -67,7 +76,7 @@ extern int rmmod_main(int argc, char **argv) bb_show_usage(); for (n = optind; n < argc; n++) { - if (delete_module(argv[n]) < 0) { + if (syscall(__NR_delete_module, argv[n], flags) < 0) { bb_perror_msg("%s", argv[n]); ret = EXIT_FAILURE; } |