lkml.org 
[lkml]   [2008]   [Jun]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH] module: make symbol_put_addr() work for all exported symbols
    symbol_put_addr() works only for exported function names (symbols present 
    in text section). This for example means that

    symbol_put_addr(__symbol_get("any_exported_variable_name"))

    triggers a BUG, which really seems wrong.

    This patch introduces generic lookup_symbol_address(), which performs
    lookup on symbol tables of all modules according to the address, and makes
    symbol_put_addr() use this interface to find the module owner instead.

    Signed-off-by: Jiri Kosina <jkosina@suse.cz>

    diff --git a/kernel/module.c b/kernel/module.c
    index 5f80478..77ff23e 100644
    --- a/kernel/module.c
    +++ b/kernel/module.c
    @@ -302,6 +302,64 @@ static unsigned long find_symbol(const char *name,
    return -ENOENT;
    }

    +/* Lookup module symbol by address */
    +const static struct kernel_symbol *lookup_symbol_address(unsigned long addr,
    + struct module **owner)
    +{
    + struct module *mod;
    + const struct kernel_symbol *s;
    + unsigned int i;
    +
    + /* Core kernel first */
    + struct {
    + const struct kernel_symbol *s_start;
    + const struct kernel_symbol *s_end;
    + } kern_syms[] = {
    + { __start___ksymtab, __stop___ksymtab },
    + { __start___ksymtab_gpl, __stop___ksymtab_gpl },
    + { __start___ksymtab_gpl_future, __stop___ksymtab_gpl_future },
    + { __start___ksymtab_unused, __stop___ksymtab_unused },
    + { __start___ksymtab_unused_gpl, __stop___ksymtab_unused_gpl },
    + };
    +
    + for (i = 0; i < ARRAY_SIZE(kern_syms); i++) {
    + for (s = kern_syms[i].s_start; s < kern_syms[i].s_end; s++) {
    + if (s->value == addr) {
    + if (owner)
    + *owner = NULL;
    + return s;
    + }
    + }
    + }
    +
    + /* Now try modules */
    + list_for_each_entry(mod, &modules, list) {
    + struct {
    + const struct kernel_symbol *sym;
    + unsigned int num;
    + } arr[] = {
    + { mod->syms, mod->num_syms },
    + { mod->gpl_syms, mod->num_gpl_syms },
    + { mod->gpl_future_syms, mod->num_gpl_future_syms },
    + { mod->unused_syms, mod->num_unused_syms },
    + { mod->unused_gpl_syms, mod->num_unused_gpl_syms },
    + };
    +
    + for (i = 0; i < ARRAY_SIZE(arr); i++) {
    + for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) {
    + if (s->value == addr) {
    + if (owner)
    + *owner = mod;
    + return s;
    + }
    + }
    + }
    + }
    + return NULL;
    +}
    +
    +
    +
    /* Search for module by name: must hold module_mutex. */
    static struct module *find_module(const char *name)
    {
    @@ -799,13 +857,12 @@ EXPORT_SYMBOL(__symbol_put);
    void symbol_put_addr(void *addr)
    {
    struct module *modaddr;
    -
    - if (core_kernel_text((unsigned long)addr))
    - return;
    -
    - if (!(modaddr = module_text_address((unsigned long)addr)))
    +
    + if (!lookup_symbol_address((unsigned long)addr, &modaddr))
    BUG();
    - module_put(modaddr);
    +
    + if(modaddr)
    + module_put(modaddr);
    }
    EXPORT_SYMBOL_GPL(symbol_put_addr);




    \
     
     \ /
      Last update: 2008-06-19 15:15    [W:0.052 / U:205.124 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site