experimental: try-resolve-unexported-symbol-references-in-modules
PATCH 1/1 experimental: try-resolve-unexported-symbol-references-in-modules
For purely experimental purposes, let the kernel resolve unexported-symbol references in external modules when loading them. Iff used carefully, this helps save time on development cycles. building testing experimenting certain kinds of changes becomes really fast.
---
include/linux/kallsyms.h | 11 +++++++++++ include/linux/module.h | 11 ++++++++--- init/Kconfig | 18 ++++++++++++++++++ kernel/kallsyms.c | 21 ++++++++++++++++++--- kernel/module.c | 31 ++++++++++++++++++++++++++++--- 5 files changed, 83 insertions(+), 9 deletions(-)
include/linux/kallsyms.h +11 -0
@@ -13,8 +13,12 @@ 2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1)#ifdef CONFIG_KALLSYMS +struct module ;/* Lookup the address for a symbol. Returns 0 if not found. */ unsigned long kallsyms_lookup_name (const char *name); +/* Like above, but this also tells which module (owner) defines the symbol, +* NULL if kernel or no symbol */ +unsigned long kallsyms_lookup_name_owner (const char *name,struct module **owner); extern int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize,
@@ -42,6 +46,13 @@ static inline unsigned long kallsyms_lookup_name(const char *name)return 0 ; } +static inline unsigned long kallsyms_lookup_name_owner (const char *name, +struct module **owner) +{ +if (owner) *owner =NULL ; +return 0 ; +} +static inline int kallsyms_lookup_size_offset (unsigned long addr,unsigned long *symbolsize,unsigned long *offset)
include/linux/module.h +8 -3
@@ -365,8 +365,11 @@ int is_module_address(unsigned long addr);int module_get_kallsym (unsigned int symnum,unsigned long *value,char *type,char *name,char *module_name,int *exported); -/* Look for this name: can be of form module:name. */ -unsigned long module_kallsyms_lookup_name (const char *name); +/* Look for this name: can be of form module:name. +* If name is a module symbol, *owner will be set to struct module, NULL +* otherwise */ +unsigned long module_kallsyms_lookup_name (const char *name, +struct module **owner);extern void __module_put_and_exit (struct module *mod,long code) __attribute__((noreturn));
@@ -528,8 +531,10 @@ static inline int module_get_kallsym(unsigned int symnum, unsigned long *value,return -ERANGE ; } -static inline unsigned long module_kallsyms_lookup_name (const char *name) +static inline unsigned long module_kallsyms_lookup_name (const char *name, +struct module **owner) { +if (owner) *owner =NULL ;return 0 ; }
init/Kconfig +18 -0
@@ -892,6 +892,24 @@ config MODULE_SRCVERSION_ALL the version). With this option, such a "srcversion" field will be created for all modules. If unsure, say N. +config RESOLVE_UNEXPORTED_SYMBOL + bool "Try to resolve unexported symbols (experimental use only)" + depends on MODULES && KALLSYMS + default n + help + Say Y here to let the kernel resolve unexported-symbol references + in external modules when loading them. This taints the kernel with + TAINT_PROPRIETARY_MODULE and TAINT_FORCED_MODULE, when the first + unexported symbol gets resolved; this also bypasses version checks, + if enabled, on such symbols. Use carefully. + Building the kernel with KALLSYMS_ALL expands the range of symbols + that can be referenced. + This is purely for experimental purposes. Enable this config if you + prefer experimenting in the kernel using loadable modules. Once the + kernel gets tainted by resolving an unexported symbol, any subsequent + kernel issue becomes the individual's responsibility to worry; do not + report back those issues. + config KMOD bool "Automatic kernel module loading" depends on MODULES
kernel/kallsyms.c +18 -3
@@ -146,7 +146,8 @@ static unsigned int get_symbol_offset(unsigned long pos) }/* Lookup the address for this symbol. Returns 0 if not found. */ -unsigned long kallsyms_lookup_name (const char *name) +static unsigned long __kallsyms_lookup_name_owner (const char *name, +struct module **owner) {char namebuf[KSYM_NAME_LEN ];unsigned long i;
@@ -155,10 +156,24 @@ unsigned long kallsyms_lookup_name(const char *name)for (i =0 , off =0 ; i < kallsyms_num_syms; i++) { off =kallsyms_expand_symbol (off, namebuf); -if (strcmp (namebuf, name) ==0 ) +if (strcmp (namebuf, name) ==0 ) { +if (owner) + *owner =NULL ;return kallsyms_addresses[i]; + } } -return module_kallsyms_lookup_name (name); +return module_kallsyms_lookup_name (name, owner); +} + +unsigned long kallsyms_lookup_name (const char *name) +{ +return __kallsyms_lookup_name_owner (name,NULL ); +} + +unsigned long kallsyms_lookup_name_owner (const char *name, +struct module **owner) +{ +return __kallsyms_lookup_name_owner (name, owner); } static unsigned long get_symbol_pos(unsigned long addr,
kernel/module.c +28 -3
@@ -1001,13 +1001,30 @@ static unsigned long resolve_symbol(Elf_Shdr *sechdrs,struct module *owner;unsigned long ret;const unsigned long *crc; +int check_ver =1 ; ret =find_symbol (name, &owner, &crc, !(mod->taints &TAINT_PROPRIETARY_MODULE ), true); + +#ifdef CONFIG_RESOLVE_UNEXPORTED_SYMBOL +if (IS_ERR_VALUE (ret)) { +unsigned long addr =kallsyms_lookup_name_owner (name, &owner); + check_ver =0 ; +if (addr) { + ret = addr; +printk (KERN_WARNING "%s: Symbol %s not exported.. " +"resolved to %s:%lx - kernel tainted\n" , mod->name, + name, owner ? owner->name :"" , ret); +add_taint (TAINT_FORCED_MODULE ); +add_taint (TAINT_PROPRIETARY_MODULE ); + } + } +#endif +if (!IS_ERR_VALUE (ret)) {/* use_module can fail due to OOM, or module initialization or unloading */ -if (!check_version (sechdrs, versindex, name, mod, crc) || +if ((check_ver && !check_version (sechdrs, versindex, name, mod, crc)) || !use_module (mod, owner)) ret = -EINVAL ; }
@@ -2435,8 +2452,12 @@ static unsigned long mod_find_symname(struct module *mod, const char *name)return 0 ; } -/* Look for this name: can be of form module:name. */ -unsigned long module_kallsyms_lookup_name (const char *name) +/* Look for this name: can be of form module:name. +* if symbol found in a module, *owner will be set to its struct module, +* else NULL +*/ +unsigned long module_kallsyms_lookup_name (const char *name, +struct module **owner) {struct module *mod;char *colon;
@@ -2455,6 +2476,10 @@ unsigned long module_kallsyms_lookup_name(const char *name) break; }preempt_enable (); + +if (owner) + *owner = ret ? mod :NULL ; +return ret; }#endif /* CONFIG_KALLSYMS */
Quoted 4 lines · On Friday 27 June 2008 22:40:50 [email protected] wrote:
For purely experimental purposes, let the kernel resolve unexported-symbol references in external modules when loading them. Iff used carefully, this helps save time on development cycles. building testing experimenting certain kinds of changes becomes really fast.
This is unlikely to ever get into the tree. And that's OK: AFAICT you can do it without any core kernel changes, by building a module which exports the symbols you need.
Cheers,
Rusty.