X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=kernel%2Fmodule.c;h=91fe6958b6e1b253f98c2ab08518693df00a1497;hb=c8b1ef88d09961078d3c685fcdc1d1659db05231;hp=a389b423c279dcb6e5f2b94ffcf56e534b06875e;hpb=d58ae67813ff97030d2f47ff7d1e5f54e5d7c5b3;p=linux-2.6 diff --git a/kernel/module.c b/kernel/module.c index a389b423c2..91fe6958b6 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -81,7 +81,8 @@ int unregister_module_notifier(struct notifier_block * nb) } EXPORT_SYMBOL(unregister_module_notifier); -/* We require a truly strong try_module_get() */ +/* We require a truly strong try_module_get(): 0 means failure due to + ongoing or failed initialization etc. */ static inline int strong_try_module_get(struct module *mod) { if (mod && mod->state == MODULE_STATE_COMING) @@ -105,7 +106,7 @@ void __module_put_and_exit(struct module *mod, long code) do_exit(code); } EXPORT_SYMBOL(__module_put_and_exit); - + /* Find a module section: 0 means not found. */ static unsigned int find_sec(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, @@ -179,7 +180,7 @@ static unsigned long __find_symbol(const char *name, struct module *mod; const struct kernel_symbol *ks; - /* Core kernel first. */ + /* Core kernel first. */ *owner = NULL; ks = lookup_symbol(name, __start___ksymtab, __stop___ksymtab); if (ks) { @@ -231,7 +232,7 @@ static unsigned long __find_symbol(const char *name, return ks->value; } - /* Now try modules. */ + /* Now try modules. */ list_for_each_entry(mod, &modules, list) { *owner = mod; ks = lookup_symbol(name, mod->syms, mod->syms + mod->num_syms); @@ -285,7 +286,7 @@ static unsigned long __find_symbol(const char *name, } } DEBUGP("Failed to find symbol %s\n", name); - return 0; + return 0; } /* Search for module by name: must hold module_mutex. */ @@ -441,7 +442,7 @@ static int percpu_modinit(void) } return 0; -} +} __initcall(percpu_modinit); #else /* ... !CONFIG_SMP */ static inline void *percpu_modalloc(unsigned long size, unsigned long align, @@ -483,8 +484,8 @@ static int modinfo_##field##_exists(struct module *mod) \ } \ static void free_modinfo_##field(struct module *mod) \ { \ - kfree(mod->field); \ - mod->field = NULL; \ + kfree(mod->field); \ + mod->field = NULL; \ } \ static struct module_attribute modinfo_##field = { \ .attr = { .name = __stringify(field), .mode = 0444 }, \ @@ -952,7 +953,8 @@ static unsigned long resolve_symbol(Elf_Shdr *sechdrs, ret = __find_symbol(name, &owner, &crc, !(mod->taints & TAINT_PROPRIETARY_MODULE)); if (ret) { - /* use_module can fail due to OOM, or module unloading */ + /* use_module can fail due to OOM, + or module initialization or unloading */ if (!check_version(sechdrs, versindex, name, mod, crc) || !use_module(mod, owner)) ret = 0; @@ -990,7 +992,7 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect, struct module_sect_attrs *sect_attrs; struct module_sect_attr *sattr; struct attribute **gattr; - + /* Count loaded sections and allocate structures */ for (i = 0; i < nsect; i++) if (sechdrs[i].sh_flags & SHF_ALLOC) @@ -1348,14 +1350,14 @@ static int verify_export_symbols(struct module *mod) const unsigned long *crc; for (i = 0; i < mod->num_syms; i++) - if (__find_symbol(mod->syms[i].name, &owner, &crc, 1)) { + if (__find_symbol(mod->syms[i].name, &owner, &crc, 1)) { name = mod->syms[i].name; ret = -ENOEXEC; goto dup; } for (i = 0; i < mod->num_gpl_syms; i++) - if (__find_symbol(mod->gpl_syms[i].name, &owner, &crc, 1)) { + if (__find_symbol(mod->gpl_syms[i].name, &owner, &crc, 1)) { name = mod->gpl_syms[i].name; ret = -ENOEXEC; goto dup; @@ -1369,7 +1371,7 @@ dup: return ret; } -/* Change all symbols so that sh_value encodes the pointer directly. */ +/* Change all symbols so that st_value encodes the pointer directly. */ static int simplify_symbols(Elf_Shdr *sechdrs, unsigned int symindex, const char *strtab, @@ -1673,6 +1675,8 @@ static struct module *load_module(void __user *umod, unsigned int unusedcrcindex; unsigned int unusedgplindex; unsigned int unusedgplcrcindex; + unsigned int markersindex; + unsigned int markersstringsindex; struct module *mod; long err = 0; void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ @@ -1929,7 +1933,7 @@ static struct module *load_module(void __user *umod, mod->unused_crcs = (void *)sechdrs[unusedgplcrcindex].sh_addr; #ifdef CONFIG_MODVERSIONS - if ((mod->num_syms && !crcindex) || + if ((mod->num_syms && !crcindex) || (mod->num_gpl_syms && !gplcrcindex) || (mod->num_gpl_future_syms && !gplfuturecrcindex) || (mod->num_unused_syms && !unusedcrcindex) || @@ -1939,6 +1943,9 @@ static struct module *load_module(void __user *umod, add_taint_module(mod, TAINT_FORCED_MODULE); } #endif + markersindex = find_sec(hdr, sechdrs, secstrings, "__markers"); + markersstringsindex = find_sec(hdr, sechdrs, secstrings, + "__markers_strings"); /* Now do relocations. */ for (i = 1; i < hdr->e_shnum; i++) { @@ -1961,6 +1968,11 @@ static struct module *load_module(void __user *umod, if (err < 0) goto cleanup; } +#ifdef CONFIG_MARKERS + mod->markers = (void *)sechdrs[markersindex].sh_addr; + mod->num_markers = + sechdrs[markersindex].sh_size / sizeof(*mod->markers); +#endif /* Find duplicate symbols */ err = verify_export_symbols(mod); @@ -1979,6 +1991,11 @@ static struct module *load_module(void __user *umod, add_kallsyms(mod, sechdrs, symindex, strindex, secstrings); +#ifdef CONFIG_MARKERS + if (!mod->taints) + marker_update_probe_range(mod->markers, + mod->markers + mod->num_markers, NULL, NULL); +#endif err = module_finalize(hdr, sechdrs, mod); if (err < 0) goto cleanup; @@ -2016,7 +2033,7 @@ static struct module *load_module(void __user *umod, if (err < 0) goto arch_cleanup; - err = mod_sysfs_setup(mod, + err = mod_sysfs_setup(mod, (struct kernel_param *) sechdrs[setupindex].sh_addr, sechdrs[setupindex].sh_size @@ -2028,8 +2045,8 @@ static struct module *load_module(void __user *umod, /* Size of section 0 is 0, so this works well if no unwind info. */ mod->unwind_info = unwind_add_table(mod, - (void *)sechdrs[unwindex].sh_addr, - sechdrs[unwindex].sh_size); + (void *)sechdrs[unwindex].sh_addr, + sechdrs[unwindex].sh_size); /* Get rid of temporary copy */ vfree(hdr); @@ -2146,7 +2163,7 @@ static inline int within(unsigned long addr, void *start, unsigned long size) */ static inline int is_arm_mapping_symbol(const char *str) { - return str[0] == '$' && strchr("atd", str[1]) + return str[0] == '$' && strchr("atd", str[1]) && (str[2] == '\0' || str[2] == '.'); } @@ -2161,11 +2178,11 @@ static const char *get_ksymbol(struct module *mod, /* At worse, next value is at end of module */ if (within(addr, mod->module_init, mod->init_size)) nextval = (unsigned long)mod->module_init+mod->init_text_size; - else + else nextval = (unsigned long)mod->module_core+mod->core_text_size; /* Scan for closest preceeding symbol, and next symbol. (ELF - starts real symbols at 1). */ + starts real symbols at 1). */ for (i = 1; i < mod->num_symtab; i++) { if (mod->symtab[i].st_shndx == SHN_UNDEF) continue; @@ -2407,7 +2424,7 @@ const struct exception_table_entry *search_module_extables(unsigned long addr) list_for_each_entry(mod, &modules, list) { if (mod->num_exentries == 0) continue; - + e = search_extable(mod->extable, mod->extable + mod->num_exentries - 1, addr); @@ -2417,7 +2434,7 @@ const struct exception_table_entry *search_module_extables(unsigned long addr) preempt_enable(); /* Now, if we found one, we are running inside it now, hence - we cannot unload the module, hence no refcnt needed. */ + we cannot unload the module, hence no refcnt needed. */ return e; } @@ -2570,3 +2587,18 @@ EXPORT_SYMBOL(module_remove_driver); void struct_module(struct module *mod) { return; } EXPORT_SYMBOL(struct_module); #endif + +#ifdef CONFIG_MARKERS +void module_update_markers(struct module *probe_module, int *refcount) +{ + struct module *mod; + + mutex_lock(&module_mutex); + list_for_each_entry(mod, &modules, list) + if (!mod->taints) + marker_update_probe_range(mod->markers, + mod->markers + mod->num_markers, + probe_module, refcount); + mutex_unlock(&module_mutex); +} +#endif