X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=modutils%2Finsmod.c;h=3b55451181a84e3c3a3602b0328843ffdc2e9964;hb=29ec0b94a4da0eb92e9994fed181e895e3fb2910;hp=adfbd33feee6a8179ea25e03adafce540212e14e;hpb=51742f4bb0c57a4d5063ece9437a2f34a42e52c8;p=oweals%2Fbusybox.git diff --git a/modutils/insmod.c b/modutils/insmod.c index adfbd33fe..3b5545118 100644 --- a/modutils/insmod.c +++ b/modutils/insmod.c @@ -58,7 +58,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ -#include "busybox.h" +#include "libbb.h" #include #include @@ -67,25 +67,21 @@ #define ENABLE_FEATURE_2_4_MODULES 1 #endif -#if !ENABLE_FEATURE_2_4_MODULES -#define insmod_ng_main insmod_main -#endif +/* + * Big piece of 2.4-specific code + */ +#if ENABLE_FEATURE_2_4_MODULES #if ENABLE_FEATURE_2_6_MODULES -extern int insmod_ng_main( int argc, char **argv); +static int insmod_ng_main(int argc, char **argv); #endif - -#if ENABLE_FEATURE_2_4_MODULES - - #if ENABLE_FEATURE_INSMOD_LOADINKMEM #define LOADBITS 0 #else #define LOADBITS 1 #endif - /* Alpha */ #if defined(__alpha__) #define MATCH_MACHINE(x) (x == EM_ALPHA) @@ -188,6 +184,7 @@ extern int insmod_ng_main( int argc, char **argv); /* Microblaze */ #if defined(__microblaze__) #define USE_SINGLE +#include #define MATCH_MACHINE(x) (x == EM_XILINX_MICROBLAZE) #define SHT_RELM SHT_RELA #define Elf32_RelM Elf32_Rela @@ -455,7 +452,7 @@ enum { /* The system calls unchanged between 2.0 and 2.1. */ unsigned long create_module(const char *, size_t); -int delete_module(const char *); +int delete_module(const char *module, unsigned int flags); #endif /* module.h */ @@ -496,7 +493,6 @@ int delete_module(const char *); /* The relocatable object is manipulated using elfin types. */ -#include #include #include @@ -628,13 +624,13 @@ static struct obj_section *obj_create_alloced_section_first(struct obj_file *f, 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, +static void obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, const char *string); -static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, +static void obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, struct obj_symbol *sym); -static int obj_check_undefineds(struct obj_file *f); +static void obj_check_undefineds(struct obj_file *f); static void obj_allocate_commons(struct obj_file *f); @@ -656,7 +652,7 @@ static struct obj_symbol *arch_new_symbol(void); static enum obj_reloc arch_apply_relocation(struct obj_file *f, struct obj_section *targsec, - struct obj_section *symsec, + /*struct obj_section *symsec,*/ struct obj_symbol *sym, ElfW(RelM) *rel, ElfW(Addr) value); @@ -677,8 +673,6 @@ static int obj_gpl_license(struct obj_file *f, const char **license); #define SPFX "" #endif - -#define _PATH_MODULES "/lib/modules" enum { STRVERSIONLEN = 64 }; /*======================================================================*/ @@ -789,7 +783,6 @@ static size_t nksyms; static struct external_module *ext_modules; static int n_ext_modules; static int n_ext_modules_used; -extern int delete_module(const char *); static char *m_filename; static char *m_fullName; @@ -798,23 +791,21 @@ static char *m_fullName; /*======================================================================*/ -static int check_module_name_match(const char *filename, struct stat *statbuf, - void *userdata, int depth) +static int FAST_FUNC check_module_name_match(const char *filename, + struct stat *statbuf UNUSED_PARAM, + void *userdata, int depth UNUSED_PARAM) { char *fullname = (char *) userdata; + char *tmp; if (fullname[0] == '\0') return FALSE; - else { - char *tmp, *tmp1 = xstrdup(filename); - tmp = bb_get_last_path_component(tmp1); - if (strcmp(tmp, fullname) == 0) { - free(tmp1); - /* Stop searching if we find a match */ - m_filename = xstrdup(filename); - return FALSE; - } - free(tmp1); + + tmp = bb_get_last_path_component_nostrip(filename); + if (strcmp(tmp, fullname) == 0) { + /* Stop searching if we find a match */ + m_filename = xstrdup(filename); + return FALSE; } return TRUE; } @@ -825,43 +816,46 @@ static int check_module_name_match(const char *filename, struct stat *statbuf, static struct obj_file *arch_new_file(void) { struct arch_file *f; - f = xmalloc(sizeof(*f)); - - memset(f, 0, sizeof(*f)); - - return &f->root; + f = xzalloc(sizeof(*f)); + return &f->root; /* it's a first member */ } static struct obj_section *arch_new_section(void) { - return xmalloc(sizeof(struct obj_section)); + return xzalloc(sizeof(struct obj_section)); } static struct obj_symbol *arch_new_symbol(void) { struct arch_symbol *sym; - sym = xmalloc(sizeof(*sym)); - - memset(sym, 0, sizeof(*sym)); - + sym = xzalloc(sizeof(*sym)); return &sym->root; } static enum obj_reloc arch_apply_relocation(struct obj_file *f, struct obj_section *targsec, - struct obj_section *symsec, + /*struct obj_section *symsec,*/ struct obj_symbol *sym, ElfW(RelM) *rel, ElfW(Addr) v) { +#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) \ + || defined(__sh__) || defined(__s390__) || defined(__x86_64__) struct arch_file *ifile = (struct arch_file *) f; +#endif enum obj_reloc ret = obj_reloc_ok; ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset); +#if defined(__arm__) || defined(__H8300H__) || defined(__H8300S__) \ + || defined(__i386__) || defined(__mc68000__) || defined(__microblaze__) \ + || defined(__mips__) || defined(__nios2__) || defined(__powerpc__) \ + || defined(__s390__) || defined(__sh__) || defined(__x86_64__) ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset; +#endif #if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) struct arch_symbol *isym = (struct arch_symbol *) sym; #endif -#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) || defined(__sh__) || defined(__s390__) +#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) \ + || defined(__sh__) || defined(__s390__) #if defined(USE_GOT_ENTRIES) ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0; #endif @@ -959,6 +953,7 @@ arch_apply_relocation(struct obj_file *f, case R_386_PLT32: case R_386_PC32: + case R_386_GOTOFF: *loc += v - dot; break; @@ -977,9 +972,6 @@ arch_apply_relocation(struct obj_file *f, case R_386_GOT32: goto bb_use_got; - - case R_386_GOTOFF: - *loc += v - got; break; #elif defined(__microblaze__) @@ -1766,7 +1758,7 @@ static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list, #if defined(USE_SINGLE) -static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single, +static int arch_single_init(/*ElfW(RelM) *rel,*/ struct arch_single_entry *single, int offset, int size) { if (single->allocated == 0) { @@ -1914,7 +1906,7 @@ static void arch_create_got(struct obj_file *f) #if defined(USE_GOT_ENTRIES) if (got_allocate) { got_offset += arch_single_init( - rel, &intsym->gotent, + /*rel,*/ &intsym->gotent, got_offset, GOT_ENTRY_SIZE); got_needed = 1; @@ -1928,7 +1920,7 @@ static void arch_create_got(struct obj_file *f) plt_offset, PLT_ENTRY_SIZE); #else plt_offset += arch_single_init( - rel, &intsym->pltent, + /*rel,*/ &intsym->pltent, plt_offset, PLT_ENTRY_SIZE); #endif plt_needed = 1; @@ -1966,7 +1958,8 @@ static unsigned long obj_elf_hash_n(const char *name, unsigned long n) while (n > 0) { ch = *name++; h = (h << 4) + ch; - if ((g = (h & 0xf0000000)) != 0) { + g = (h & 0xf0000000); + if (g != 0) { h ^= g >> 24; h &= ~g; } @@ -2045,7 +2038,7 @@ obj_add_symbol(struct obj_file *f, const char *name, int n_type = ELF_ST_TYPE(info); int n_binding = ELF_ST_BIND(info); - for (sym = f->symtab[hash]; sym; sym = sym->next) + for (sym = f->symtab[hash]; sym; sym = sym->next) { if (f->symbol_cmp(sym->name, name) == 0) { int o_secidx = sym->secidx; int o_info = sym->info; @@ -2104,14 +2097,14 @@ obj_add_symbol(struct obj_file *f, const char *name, return sym; } } + } /* Completely new symbol. */ sym = arch_new_symbol(); sym->next = f->symtab[hash]; f->symtab[hash] = sym; sym->ksymidx = -1; - - if (ELF_ST_BIND(info) == STB_LOCAL && symidx != -1) { + if (ELF_ST_BIND(info) == STB_LOCAL && symidx != (unsigned long)(-1)) { if (symidx >= f->local_symtab_size) bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld", name, (long) symidx, (long) f->local_symtab_size); @@ -2208,10 +2201,9 @@ static struct obj_section *obj_create_alloced_section(struct obj_file *f, int newidx = f->header.e_shnum++; struct obj_section *sec; - f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec)); + f->sections = xrealloc_vector(f->sections, 2, newidx); f->sections[newidx] = sec = arch_new_section(); - memset(sec, 0, sizeof(*sec)); sec->header.sh_type = SHT_PROGBITS; sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; sec->header.sh_size = size; @@ -2237,7 +2229,6 @@ static struct obj_section *obj_create_alloced_section_first(struct obj_file *f, f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec)); f->sections[newidx] = sec = arch_new_section(); - memset(sec, 0, sizeof(*sec)); sec->header.sh_type = SHT_PROGBITS; sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; sec->header.sh_size = size; @@ -2259,7 +2250,8 @@ static void *obj_extend_section(struct obj_section *sec, unsigned long more) { unsigned long oldsize = sec->header.sh_size; if (more) { - sec->contents = xrealloc(sec->contents, sec->header.sh_size += more); + sec->header.sh_size += more; + sec->contents = xrealloc(sec->contents, sec->header.sh_size); } return sec->contents + oldsize; } @@ -2399,7 +2391,7 @@ static char *get_modinfo_value(struct obj_file *f, const char *key) /*======================================================================*/ /* Functions relating to module loading after 2.1.18. */ -static int +static void new_process_module_arguments(struct obj_file *f, int argc, char **argv) { while (argc > 0) { @@ -2409,7 +2401,8 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) int min, max, n; p = *argv; - if ((q = strchr(p, '=')) == NULL) { + q = strchr(p, '='); + if (q == NULL) { argc--; continue; } @@ -2422,8 +2415,7 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) p = get_modinfo_value(f, key); key += 5; if (p == NULL) { - bb_error_msg("invalid parameter %s", key); - return 0; + bb_error_msg_and_die("invalid parameter %s", key); } #ifdef SYMBOL_PREFIX @@ -2437,8 +2429,7 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) /* 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; + bb_error_msg_and_die("symbol for parameter %s not found", key); } if (isdigit(*p)) { @@ -2464,11 +2455,10 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) str = alloca(strlen(q)); for (r = str, q++; *q != '"'; ++q, ++r) { - if (*q == '\0') { - bb_error_msg("improperly terminated string argument for %s", + if (*q == '\0') + bb_error_msg_and_die("improperly terminated string argument for %s", key); - return 0; - } else if (*q == '\\') + if (*q == '\\') switch (*++q) { case 'a': *r = '\a'; @@ -2514,8 +2504,9 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) default: *r = *q; break; - } else - *r = *q; + } + else + *r = *q; } *r = '\0'; ++q; @@ -2559,17 +2550,15 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) /* 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" + bb_error_msg_and_die("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, + bb_error_msg_and_die("string too long for %s (max %ld)", key, charssize - 1); - return 0; } /* Copy to location */ @@ -2596,12 +2585,10 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) break; default: - bb_error_msg("unknown parameter type '%c' for %s", *p, key); - return 0; + bb_error_msg_and_die("unknown parameter type '%c' for %s", *p, key); } } - -retry_end_of_value: + retry_end_of_value: switch (*q) { case '\0': goto end_of_arg; @@ -2615,28 +2602,23 @@ retry_end_of_value: case ',': if (++n > max) { - bb_error_msg("too many values for %s (max %d)", key, max); - return 0; + bb_error_msg_and_die("too many values for %s (max %d)", key, max); } ++q; break; default: - bb_error_msg("invalid argument syntax for %s", key); - return 0; + bb_error_msg_and_die("invalid argument syntax for %s", key); } } - -end_of_arg: + end_of_arg: if (n < min) { - bb_error_msg("too few values for %s (min %d)", key, min); - return 0; + bb_error_msg_and_die("too few values for %s (min %d)", key, min); } - argc--, argv++; + argc--; + argv++; } - - return 1; } #if ENABLE_FEATURE_INSMOD_VERSION_CHECKING @@ -2645,8 +2627,7 @@ static int new_is_module_checksummed(struct obj_file *f) const char *p = get_modinfo_value(f, "using_checksums"); if (p) return xatoi(p); - else - return 0; + return 0; } /* Get the module's kernel version in the canonical integer form. */ @@ -2680,7 +2661,7 @@ new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN]) /* Fetch the loaded modules, and all currently exported symbols. */ -static int new_get_kernel_symbols(void) +static void new_get_kernel_symbols(void) { char *module_names, *mn; struct external_module *modules, *m; @@ -2689,15 +2670,17 @@ static int new_get_kernel_symbols(void) /* Collect the loaded modules. */ - module_names = xmalloc(bufsize = 256); -retry_modules_load: + bufsize = 256; + module_names = xmalloc(bufsize); + + retry_modules_load: if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) { if (errno == ENOSPC && bufsize < ret) { - module_names = xrealloc(module_names, bufsize = ret); + bufsize = ret; + module_names = xrealloc(module_names, bufsize); goto retry_modules_load; } - bb_perror_msg("QM_MODULES"); - return 0; + bb_perror_msg_and_die("QM_MODULES"); } n_ext_modules = nmod = ret; @@ -2716,23 +2699,23 @@ retry_modules_load: /* The module was removed out from underneath us. */ continue; } - bb_perror_msg("query_module: QM_INFO: %s", mn); - return 0; + bb_perror_msg_and_die("query_module: QM_INFO: %s", mn); } - syms = xmalloc(bufsize = 1024); -retry_mod_sym_load: + bufsize = 1024; + syms = xmalloc(bufsize); + retry_mod_sym_load: if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) { switch (errno) { case ENOSPC: - syms = xrealloc(syms, bufsize = ret); + bufsize = ret; + syms = xrealloc(syms, bufsize); goto retry_mod_sym_load; case ENOENT: /* The module was removed out from underneath us. */ continue; default: - bb_perror_msg("query_module: QM_SYMBOLS: %s", mn); - return 0; + bb_perror_msg_and_die("query_module: QM_SYMBOLS: %s", mn); } } nsyms = ret; @@ -2751,14 +2734,14 @@ retry_mod_sym_load: /* Collect the kernel's symbols. */ syms = xmalloc(bufsize = 16 * 1024); -retry_kern_sym_load: + retry_kern_sym_load: if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) { if (errno == ENOSPC && bufsize < ret) { - syms = xrealloc(syms, bufsize = ret); + bufsize = ret; + syms = xrealloc(syms, bufsize); goto retry_kern_sym_load; } - bb_perror_msg("kernel: QM_SYMBOLS"); - return 0; + bb_perror_msg_and_die("kernel: QM_SYMBOLS"); } nksyms = nsyms = ret; ksyms = syms; @@ -2766,7 +2749,6 @@ retry_kern_sym_load: for (j = 0, s = syms; j < nsyms; ++j, ++s) { s->name += (unsigned long) syms; } - return 1; } @@ -2787,7 +2769,7 @@ static int new_is_kernel_checksummed(void) } -static int new_create_this_module(struct obj_file *f, const char *m_name) +static void new_create_this_module(struct obj_file *f, const char *m_name) { struct obj_section *sec; @@ -2801,8 +2783,6 @@ static int new_create_this_module(struct obj_file *f, const char *m_name) obj_string_patch(f, sec->idx, offsetof(struct new_module, name), m_name); - - return 1; } #if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS @@ -2915,7 +2895,7 @@ new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size) sec = obj_find_section(f, ".this"); if (!sec || !sec->contents) { - bb_perror_msg_and_die("corrupt module %s?",m_name); + bb_perror_msg_and_die("corrupt module %s?", m_name); } module = (struct new_module *) sec->contents; m_addr = sec->header.sh_addr; @@ -2986,7 +2966,7 @@ new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size) /*======================================================================*/ -static int +static void obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, const char *string) { @@ -3011,11 +2991,9 @@ obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, loc = obj_extend_section(strsec, len); } memcpy(loc, string, len); - - return 1; } -static int +static void obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, struct obj_symbol *sym) { @@ -3027,14 +3005,11 @@ obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, p->reloc_offset = offset; p->sym = sym; f->symbol_patches = p; - - return 1; } -static int obj_check_undefineds(struct obj_file *f) +static void obj_check_undefineds(struct obj_file *f) { - unsigned long i; - int ret = 1; + unsigned i; for (i = 0; i < HASH_BUCKETS; ++i) { struct obj_symbol *sym; @@ -3044,15 +3019,11 @@ static int obj_check_undefineds(struct obj_file *f) sym->secidx = SHN_ABS; sym->value = 0; } else { - if (!flag_quiet) { - bb_error_msg("unresolved symbol %s", sym->name); - } - ret = 0; + if (!flag_quiet) + bb_error_msg_and_die("unresolved symbol %s", sym->name); } } } - - return ret; } static void obj_allocate_commons(struct obj_file *f) @@ -3111,11 +3082,10 @@ static void obj_allocate_commons(struct obj_file *f) if (i == f->header.e_shnum) { struct obj_section *sec; - f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec)); + f->sections = xrealloc_vector(f->sections, 2, i); f->sections[i] = sec = arch_new_section(); f->header.e_shnum = i + 1; - memset(sec, 0, sizeof(*sec)); sec->header.sh_type = SHT_PROGBITS; sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; sec->name = ".bss"; @@ -3259,7 +3229,7 @@ static int obj_relocate(struct obj_file *f, ElfW(Addr) base) /* Do it! */ switch (arch_apply_relocation - (f, targsec, symsec, intsym, rel, value) + (f, targsec, /*symsec,*/ intsym, rel, value) ) { case obj_reloc_ok: break; @@ -3338,54 +3308,48 @@ static int obj_create_image(struct obj_file *f, char *image) /*======================================================================*/ -static struct obj_file *obj_load(FILE * fp, int loadprogbits) +static struct obj_file *obj_load(FILE *fp, int loadprogbits UNUSED_PARAM) { struct obj_file *f; ElfW(Shdr) * section_headers; - int shnum, i; + size_t shnum, i; char *shstrtab; /* Read the file header. */ f = arch_new_file(); - memset(f, 0, sizeof(*f)); f->symbol_cmp = strcmp; f->symbol_hash = obj_elf_hash; f->load_order_search_start = &f->load_order; fseek(fp, 0, SEEK_SET); if (fread(&f->header, sizeof(f->header), 1, fp) != 1) { - bb_perror_msg("error reading ELF header"); - return NULL; + bb_perror_msg_and_die("error reading ELF header"); } if (f->header.e_ident[EI_MAG0] != ELFMAG0 || f->header.e_ident[EI_MAG1] != ELFMAG1 || f->header.e_ident[EI_MAG2] != ELFMAG2 || f->header.e_ident[EI_MAG3] != ELFMAG3) { - bb_error_msg("not an ELF file"); - return NULL; + bb_error_msg_and_die("not an ELF file"); } if (f->header.e_ident[EI_CLASS] != ELFCLASSM || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB) || f->header.e_ident[EI_VERSION] != EV_CURRENT || !MATCH_MACHINE(f->header.e_machine)) { - bb_error_msg("ELF file not for this architecture"); - return NULL; + bb_error_msg_and_die("ELF file not for this architecture"); } if (f->header.e_type != ET_REL) { - bb_error_msg("ELF file not a relocatable object"); - return NULL; + bb_error_msg_and_die("ELF file not a relocatable object"); } /* Read the section headers. */ if (f->header.e_shentsize != sizeof(ElfW(Shdr))) { - bb_error_msg("section header size mismatch: %lu != %lu", + bb_error_msg_and_die("section header size mismatch: %lu != %lu", (unsigned long) f->header.e_shentsize, (unsigned long) sizeof(ElfW(Shdr))); - return NULL; } shnum = f->header.e_shnum; @@ -3395,8 +3359,7 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) section_headers = alloca(sizeof(ElfW(Shdr)) * shnum); fseek(fp, f->header.e_shoff, SEEK_SET); if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) { - bb_perror_msg("error reading ELF section headers"); - return NULL; + bb_perror_msg_and_die("error reading ELF section headers"); } /* Read the section data. */ @@ -3405,7 +3368,6 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) struct obj_section *sec; f->sections[i] = sec = arch_new_section(); - memset(sec, 0, sizeof(*sec)); sec->header = section_headers[i]; sec->idx = i; @@ -3432,8 +3394,7 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) sec->contents = xmalloc(sec->header.sh_size); fseek(fp, sec->header.sh_offset, SEEK_SET); if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) { - bb_perror_msg("error reading ELF section data"); - return NULL; + bb_perror_msg_and_die("error reading ELF section data"); } } else { sec->contents = NULL; @@ -3442,14 +3403,11 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) #if SHT_RELM == SHT_REL case SHT_RELA: - bb_error_msg("RELA relocations not supported on this architecture"); - return NULL; + bb_error_msg_and_die("RELA relocations not supported on this architecture"); #else case SHT_REL: - bb_error_msg("REL relocations not supported on this architecture"); - return NULL; + bb_error_msg_and_die("REL relocations not supported on this architecture"); #endif - default: if (sec->header.sh_type >= SHT_LOPROC) { /* Assume processor specific section types are debug @@ -3459,9 +3417,8 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) break; } - bb_error_msg("can't handle sections of type %ld", + bb_error_msg_and_die("can't handle sections of type %ld", (long) sec->header.sh_type); - return NULL; } } } @@ -3495,10 +3452,9 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) ElfW(Sym) * sym; if (sec->header.sh_entsize != sizeof(ElfW(Sym))) { - bb_error_msg("symbol size mismatch: %lu != %lu", + bb_error_msg_and_die("symbol size mismatch: %lu != %lu", (unsigned long) sec->header.sh_entsize, (unsigned long) sizeof(ElfW(Sym))); - return NULL; } nsym = sec->header.sh_size / sizeof(ElfW(Sym)); @@ -3529,7 +3485,6 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) */ val |= sym->st_other & 4; #endif - obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx, val, sym->st_size); } @@ -3538,10 +3493,9 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) case SHT_RELM: if (sec->header.sh_entsize != sizeof(ElfW(RelM))) { - bb_error_msg("relocation entry size mismatch: %lu != %lu", + bb_error_msg_and_die("relocation entry size mismatch: %lu != %lu", (unsigned long) sec->header.sh_entsize, (unsigned long) sizeof(ElfW(RelM))); - return NULL; } break; /* XXX Relocation code from modutils-2.3.19 is not here. @@ -3560,7 +3514,7 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) * kernel for the module */ -static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase) +static int obj_load_progbits(FILE *fp, struct obj_file *f, char *imagebase) { ElfW(Addr) base = f->baseaddr; struct obj_section* sec; @@ -3614,12 +3568,12 @@ static int obj_gpl_license(struct obj_file *f, const char **license) * linux/include/linux/module.h. Checking for leading "GPL" will not * work, somebody will use "GPL sucks, this is proprietary". */ - static const char * const gpl_licenses[] = { + static const char *const gpl_licenses[] = { "GPL", "GPL v2", "GPL and additional rights", "Dual BSD/GPL", - "Dual MPL/GPL", + "Dual MPL/GPL" }; sec = obj_find_section(f, ".modinfo"); @@ -3630,17 +3584,18 @@ static int obj_gpl_license(struct obj_file *f, const char **license) while (ptr < endptr) { value = strchr(ptr, '='); if (value && strncmp(ptr, "license", value-ptr) == 0) { - int i; + unsigned i; if (license) *license = value+1; - for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) { + for (i = 0; i < ARRAY_SIZE(gpl_licenses); ++i) { if (strcmp(value+1, gpl_licenses[i]) == 0) return 0; } return 2; } - if (strchr(ptr, '\0')) - ptr = strchr(ptr, '\0') + 1; + ptr = strchr(ptr, '\0'); + if (ptr) + ptr++; else ptr = endptr; } @@ -3649,24 +3604,26 @@ static int obj_gpl_license(struct obj_file *f, const char **license) } #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) +#define TAINT_PROPRIETORY_MODULE (1 << 0) +#define TAINT_FORCED_MODULE (1 << 1) +#define TAINT_UNSAFE_SMP (1 << 2) #define TAINT_URL "http://www.tux.org/lkml/#export-tainted" -static void set_tainted(struct obj_file *f, int fd, char *m_name, +static void set_tainted(int fd, char *m_name, int kernel_has_tainted, int taint, const char *text1, const char *text2) { + static smallint printed_info; + char buf[80]; int oldval; - static int first = 1; + if (fd < 0 && !kernel_has_tainted) return; /* New modutils on old kernel */ printf("Warning: loading %s will taint the kernel: %s%s\n", m_name, text1, text2); - if (first) { + if (!printed_info) { printf(" See %s for information about tainted modules\n", TAINT_URL); - first = 0; + printed_info = 1; } if (fd >= 0) { read(fd, buf, sizeof(buf)-1); @@ -3680,7 +3637,8 @@ static void set_tainted(struct obj_file *f, int fd, char *m_name, /* Check if loading this module will taint the kernel. */ static void check_tainted_module(struct obj_file *f, char *m_name) { - static const char tainted_file[] = TAINT_FILENAME; + static const char tainted_file[] ALIGN1 = TAINT_FILENAME; + int fd, kernel_has_tainted; const char *ptr; @@ -3701,22 +3659,22 @@ static void check_tainted_module(struct obj_file *f, char *m_name) case 0: break; case 1: - set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", ""); + set_tainted(fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", ""); break; case 2: /* The module has a non-GPL license so we pretend that the * kernel always has a taint flag to get a warning even on * kernels without the proc flag. */ - set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr); + set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr); break; default: - set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", ""); + set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", ""); break; } if (flag_force_load) - set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", ""); + set_tainted(fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", ""); if (fd >= 0) close(fd); @@ -3730,6 +3688,9 @@ static void check_tainted_module(struct obj_file *f, char *m_name) * start of some sections. this info is used by ksymoops to do better * debugging. */ +#if !ENABLE_FEATURE_INSMOD_VERSION_CHECKING +#define get_module_version(f, str) get_module_version(str) +#endif static int get_module_version(struct obj_file *f, char str[STRVERSIONLEN]) { @@ -3749,15 +3710,8 @@ static void add_ksymoops_symbols(struct obj_file *f, const char *filename, const char *m_name) { - static const char symprefix[] = "__insmod_"; - struct obj_section *sec; - struct obj_symbol *sym; - char *name, *absolute_filename; - char str[STRVERSIONLEN], real[PATH_MAX]; - int i, l, lm_name, lfilename, use_ksymtab, version; - struct stat statbuf; - - static const char *section_names[] = { + static const char symprefix[] ALIGN1 = "__insmod_"; + static const char section_names[][8] = { ".text", ".rodata", ".data", @@ -3765,12 +3719,19 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename, ".sbss" }; - if (realpath(filename, real)) { - absolute_filename = xstrdup(real); - } else { - bb_perror_msg("cannot get realpath for %s", filename); + struct obj_section *sec; + struct obj_symbol *sym; + char *name, *absolute_filename; + char str[STRVERSIONLEN]; + unsigned i; + int l, lm_name, lfilename, use_ksymtab, version; + struct stat statbuf; + + /* WARNING: was using realpath, but replaced by readlink to stop using + * lots of stack. But here it seems to be able to cause problems? */ + absolute_filename = xmalloc_readlink(filename); + if (!absolute_filename) absolute_filename = xstrdup(filename); - } lm_name = strlen(m_name); lfilename = strlen(absolute_filename); @@ -3788,22 +3749,22 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename, * is 0xffffff, decimal 16777215. putting all three fields in * one symbol is less readable but saves kernel space. */ - l = sizeof(symprefix)+ /* "__insmod_" */ - lm_name+ /* module name */ - 2+ /* "_O" */ - lfilename+ /* object filename */ - 2+ /* "_M" */ - 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */ - 2+ /* "_V" */ - 8+ /* version in dec */ - 1; /* nul */ + l = sizeof(symprefix) + /* "__insmod_" */ + lm_name + /* module name */ + 2 + /* "_O" */ + lfilename + /* object filename */ + 2 + /* "_M" */ + 2 * sizeof(statbuf.st_mtime) + /* mtime in hex */ + 2 + /* "_V" */ + 8 + /* version in dec */ + 1; /* nul */ name = xmalloc(l); if (stat(absolute_filename, &statbuf) != 0) statbuf.st_mtime = 0; version = get_module_version(f, str); /* -1 if not found */ snprintf(name, l, "%s%s_O%s_M%0*lX_V%d", symprefix, m_name, absolute_filename, - (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime, + (int)(2 * sizeof(statbuf.st_mtime)), statbuf.st_mtime, version); sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE), @@ -3816,11 +3777,11 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename, /* record where the persistent data is going, same address as previous symbol */ if (f->persist) { - l = sizeof(symprefix)+ /* "__insmod_" */ - lm_name+ /* module name */ - 2+ /* "_P" */ - strlen(f->persist)+ /* data store */ - 1; /* nul */ + l = sizeof(symprefix) + /* "__insmod_" */ + lm_name + /* module name */ + 2 + /* "_P" */ + strlen(f->persist) + /* data store */ + 1; /* nul */ name = xmalloc(l); snprintf(name, l, "%s%s_P%s", symprefix, m_name, f->persist); @@ -3832,16 +3793,16 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename, #endif /* _NOT_SUPPORTED_ */ /* tag the desired sections if size is non-zero */ - for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) { + for (i = 0; i < ARRAY_SIZE(section_names); ++i) { sec = obj_find_section(f, section_names[i]); if (sec && sec->header.sh_size) { - l = sizeof(symprefix)+ /* "__insmod_" */ - lm_name+ /* module name */ - 2+ /* "_S" */ - strlen(sec->name)+ /* section name */ - 2+ /* "_L" */ - 8+ /* length in dec */ - 1; /* nul */ + l = sizeof(symprefix) + /* "__insmod_" */ + lm_name + /* module name */ + 2 + /* "_S" */ + strlen(sec->name) + /* section name */ + 2 + /* "_L" */ + 8 + /* length in dec */ + 1; /* nul */ name = xmalloc(l); snprintf(name, l, "%s%s_S%s_L%ld", symprefix, m_name, sec->name, @@ -3888,9 +3849,10 @@ static void print_load_map(struct obj_file *f) #if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL /* Quick reference which section indicies are loaded. */ - loaded = alloca(sizeof(int) * (i = f->header.e_shnum)); + i = f->header.e_shnum; + loaded = alloca(sizeof(int) * i); while (--i >= 0) - loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0; + loaded[i] = ((f->sections[i]->header.sh_flags & SHF_ALLOC) != 0); /* Collect the symbols we'll be listing. */ @@ -3949,8 +3911,8 @@ static void print_load_map(struct obj_file *f) void print_load_map(struct obj_file *f); #endif -int insmod_main( int argc, char **argv); -int insmod_main( int argc, char **argv) +int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int insmod_main(int argc, char **argv) { char *opt_o, *arg1; int len; @@ -3960,7 +3922,7 @@ int insmod_main( int argc, char **argv) ElfW(Addr) m_addr; struct obj_file *f; struct stat st; - char *m_name = 0; + char *m_name = NULL; int exit_status = EXIT_FAILURE; int m_has_modinfo; #if ENABLE_FEATURE_INSMOD_VERSION_CHECKING @@ -3969,7 +3931,7 @@ int insmod_main( int argc, char **argv) int m_version, m_crcs; #endif #if ENABLE_FEATURE_CLEAN_UP - FILE *fp = 0; + FILE *fp = NULL; #else FILE *fp; #endif @@ -3977,7 +3939,7 @@ int insmod_main( int argc, char **argv) struct utsname myuname; /* Parse any options */ - getopt32(argc, argv, OPTION_STR, &opt_o); + getopt32(argv, OPTION_STR, &opt_o); arg1 = argv[optind]; if (option_mask32 & OPT_o) { // -o /* name the output module */ free(m_name); @@ -4024,10 +3986,10 @@ int insmod_main( int argc, char **argv) m_name = tmp; } else { free(tmp1); - tmp1 = 0; /* flag for free(m_name) before exit() */ + tmp1 = NULL; /* flag for free(m_name) before exit() */ } - /* Get a filedesc for the module. Check we we have a complete path */ + /* Get a filedesc for the module. Check that we have a complete path */ if (stat(arg1, &st) < 0 || !S_ISREG(st.st_mode) || (fp = fopen(arg1, "r")) == NULL ) { @@ -4036,44 +3998,44 @@ int insmod_main( int argc, char **argv) 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(CONFIG_DEFAULT_MODULES_DIR, myuname.release); /* 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 * /lib/modules/`uname -r` dir, So resolve it ourselves * if it is a link... */ - if (realpath(tmdn, real_module_dir) == NULL) - module_dir = tmdn; - else - module_dir = real_module_dir; + module_dir = xmalloc_readlink(tmdn); + if (!module_dir) + module_dir = xstrdup(tmdn); recursive_action(module_dir, ACTION_RECURSE, - check_module_name_match, 0, m_fullName, 0); + check_module_name_match, NULL, m_fullName, 0); + free(module_dir); free(tmdn); } /* Check if we have found anything yet */ - if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL)) { - char module_dir[FILENAME_MAX]; + if (!m_filename || ((fp = fopen(m_filename, "r")) == NULL)) { + int r; + char *module_dir; free(m_filename); - m_filename = 0; - if (realpath (_PATH_MODULES, module_dir) == NULL) - strcpy(module_dir, _PATH_MODULES); + m_filename = NULL; + module_dir = xmalloc_readlink(CONFIG_DEFAULT_MODULES_DIR); + if (!module_dir) + module_dir = xstrdup(CONFIG_DEFAULT_MODULES_DIR); /* No module found under /lib/modules/`uname -r`, this * time cast the net a bit wider. Search /lib/modules/ */ - if (!recursive_action(module_dir, ACTION_RECURSE, - check_module_name_match, 0, m_fullName, 0) + r = recursive_action(module_dir, ACTION_RECURSE, + check_module_name_match, NULL, m_fullName, 0); + if (r) + bb_error_msg_and_die("%s: module not found", m_fullName); + free(module_dir); + if (m_filename == NULL + || ((fp = fopen(m_filename, "r")) == NULL) ) { - if (m_filename == 0 - || ((fp = fopen(m_filename, "r")) == NULL) - ) { - bb_error_msg("%s: no module by that name found", m_fullName); - goto out; - } - } else - bb_error_msg_and_die("%s: no module by that name found", m_fullName); + bb_error_msg_and_die("%s: module not found", m_fullName); + } } } else m_filename = xstrdup(arg1); @@ -4090,8 +4052,6 @@ int insmod_main( int argc, char **argv) #endif f = obj_load(fp, LOADBITS); - if (f == NULL) - bb_perror_msg_and_die("cannot load the module"); if (get_modinfo_value(f, "kernel_version") == NULL) m_has_modinfo = 0; @@ -4106,38 +4066,28 @@ int insmod_main( int argc, char **argv) if (m_has_modinfo) { m_version = new_get_module_version(f, m_strversion); if (m_version == -1) { - bb_error_msg("cannot find the kernel version the module was " + bb_error_msg_and_die("cannot 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); + bb_error_msg("%skernel-module version mismatch\n" + "\t%s was compiled for kernel version %s\n" + "\twhile this kernel is version %s", + flag_force_load ? "warning: " : "", + m_filename, m_strversion, uts_info.release); + if (!flag_force_load) goto out; - } } } k_crcs = 0; #endif /* FEATURE_INSMOD_VERSION_CHECKING */ - if (!query_module(NULL, 0, NULL, 0, NULL)) { - if (!new_get_kernel_symbols()) - goto out; - k_crcs = new_is_kernel_checksummed(); - } else { - bb_error_msg("not configured to support old kernels"); - goto out; - } + if (query_module(NULL, 0, NULL, 0, NULL)) + bb_error_msg_and_die("not configured to support old kernels"); + new_get_kernel_symbols(); + k_crcs = new_is_kernel_checksummed(); #if ENABLE_FEATURE_INSMOD_VERSION_CHECKING m_crcs = 0; @@ -4153,22 +4103,15 @@ int insmod_main( int argc, char **argv) /* Allocate common symbols, symbol tables, and string tables. */ - if (!new_create_this_module(f, m_name)) { - goto out; - } - - if (!obj_check_undefineds(f)) { - goto out; - } + new_create_this_module(f, m_name); + obj_check_undefineds(f); obj_allocate_commons(f); check_tainted_module(f, m_name); /* done with the module name, on to the optional var=value arguments */ ++optind; if (optind < argc) { - if (!new_process_module_arguments(f, argc - optind, argv + optind)) { - goto out; - } + new_process_module_arguments(f, argc - optind, argv + optind); } arch_create_got(f); @@ -4183,39 +4126,35 @@ int insmod_main( int argc, char **argv) /* Find current size of the module */ m_size = obj_load_size(f); - m_addr = create_module(m_name, m_size); - if (m_addr == -1) switch (errno) { + if (m_addr == (ElfW(Addr))(-1)) switch (errno) { case EEXIST: - bb_error_msg("a module named %s already exists", m_name); - goto out; + bb_error_msg_and_die("a module named %s already exists", m_name); case ENOMEM: - bb_error_msg("can't allocate kernel memory for module; needed %lu bytes", + bb_error_msg_and_die("can't allocate kernel memory for module; needed %lu bytes", m_size); - goto out; default: - bb_perror_msg("create_module: %s", m_name); - goto out; + bb_perror_msg_and_die("create_module: %s", m_name); } -#if !LOADBITS +#if !LOADBITS /* * the PROGBITS section was not loaded by the obj_load * now we can load them directly into the kernel memory */ if (!obj_load_progbits(fp, f, (char*)m_addr)) { - delete_module(m_name); + delete_module(m_name, 0); goto out; } #endif if (!obj_relocate(f, m_addr)) { - delete_module(m_name); + delete_module(m_name, 0); goto out; } if (!new_init_module(m_name, f, m_size)) { - delete_module(m_name); + delete_module(m_name, 0); goto out; } @@ -4224,7 +4163,7 @@ int insmod_main( int argc, char **argv) exit_status = EXIT_SUCCESS; -out: + out: #if ENABLE_FEATURE_CLEAN_UP if (fp) fclose(fp); @@ -4236,38 +4175,51 @@ out: return exit_status; } - -#endif +#endif /* ENABLE_FEATURE_2_4_MODULES */ +/* + * End of big piece of 2.4-specific code + */ #if ENABLE_FEATURE_2_6_MODULES #include + +#if defined __UCLIBC__ && !ENABLE_FEATURE_2_4_MODULES +/* big time suckage. The old prototype above renders our nice fwd-decl wrong */ +extern int init_module(void *module, unsigned long len, const char *options); +#else #include #include +#define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts) +#endif /* We use error numbers in a loose translation... */ static const char *moderror(int err) { switch (err) { case ENOEXEC: - return "Invalid module format"; + return "invalid module format"; case ENOENT: - return "Unknown symbol in module"; + return "unknown symbol in module"; case ESRCH: - return "Module has wrong symbol version"; + return "module has wrong symbol version"; case EINVAL: - return "Invalid parameters"; + return "invalid parameters"; default: return strerror(err); } } -int insmod_ng_main(int argc, char **argv); -int insmod_ng_main(int argc, char **argv) +#if !ENABLE_FEATURE_2_4_MODULES +int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int insmod_main(int argc UNUSED_PARAM, char **argv) +#else +static int insmod_ng_main(int argc UNUSED_PARAM, char **argv) +#endif { - long ret; size_t len; + int optlen; void *map; char *filename, *options; @@ -4276,16 +4228,24 @@ int insmod_ng_main(int argc, char **argv) bb_show_usage(); /* Rest is options */ - options = xstrdup(""); + options = xzalloc(1); + optlen = 0; while (*++argv) { - int optlen = strlen(options); options = xrealloc(options, optlen + 2 + strlen(*argv) + 2); /* Spaces handled by "" pairs, but no way of escaping quotes */ - sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv); + optlen += sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv); } #if 0 - /* Any special reason why mmap? It isn't performace critical... */ + /* Any special reason why mmap? It isn't performance critical. -vda */ + /* Yes, xmalloc'ing can use *alot* of RAM. Don't forget that there are + * modules out there that are half a megabyte! mmap()ing is way nicer + * for small mem boxes, i guess. */ + /* But after load, these modules will take up that 0.5mb in kernel + * anyway. Using malloc here causes only a transient spike to 1mb, + * after module is loaded, we go back to normal 0.5mb usage + * (in kernel). Also, mmap isn't magic - when we touch mapped data, + * we use memory. -vda */ int fd; struct stat st; unsigned long len; @@ -4307,12 +4267,9 @@ int insmod_ng_main(int argc, char **argv) map = xmalloc_open_read_close(filename, &len); #endif - 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); - } - + if (init_module(map, len, options) != 0) + bb_error_msg_and_die("cannot insert '%s': %s", + filename, moderror(errno)); return 0; }