Commit 8e4f2cd3 authored by Rusty Russell's avatar Rusty Russell Committed by Linus Torvalds

[PATCH] Remove mod_bound macro and unify kernel_text_address().

Various archs (i386, m68k, s390, s390x, m68k, parisc, um, x86_64)
implement kernel_text_address.  Put this in kernel/extable.c, and the
module iteration inside module.c.

Other than cleanliness, this finally allows the module list and lock
to be static to kernel/module.c (you didn't think I actually cared
about those archs did you?)

It also drops the module->init_size to zero when it's discarded, so
bounds checking is simplified (and the /proc/modules size statistic
will be more accurate, too).
parent 18f50759
...@@ -87,50 +87,6 @@ asmlinkage void machine_check(void); ...@@ -87,50 +87,6 @@ asmlinkage void machine_check(void);
static int kstack_depth_to_print = 24; static int kstack_depth_to_print = 24;
/*
* If the address is either in the .text section of the
* kernel, or in the vmalloc'ed module regions, it *may*
* be the address of a calling routine
*/
#ifdef CONFIG_MODULES
/* FIXME: Accessed without a lock --RR */
extern struct list_head modules;
static inline int kernel_text_address(unsigned long addr)
{
int retval = 0;
struct module *mod;
if (addr >= (unsigned long) &_stext &&
addr <= (unsigned long) &_etext)
return 1;
list_for_each_entry(mod, &modules, list) {
/* mod_bound tests for addr being inside the vmalloc'ed
* module area. Of course it'd be better to test only
* for the .text subset... */
if (mod_bound((void *)addr, 0, mod)) {
retval = 1;
break;
}
}
return retval;
}
#else
static inline int kernel_text_address(unsigned long addr)
{
return (addr >= (unsigned long) &_stext &&
addr <= (unsigned long) &_etext);
}
#endif
void show_trace(unsigned long * stack) void show_trace(unsigned long * stack)
{ {
int i; int i;
......
...@@ -821,42 +821,6 @@ asmlinkage void buserr_c(struct frame *fp) ...@@ -821,42 +821,6 @@ asmlinkage void buserr_c(struct frame *fp)
static int kstack_depth_to_print = 48; static int kstack_depth_to_print = 48;
extern char _stext, _etext;
#ifdef CONFIG_MODULES
/* FIXME: Accessed without a lock --RR */
extern struct list_head modules;
static inline int kernel_text_address(unsigned long addr)
{
struct module *mod;
if (addr >= (unsigned long) &_stext &&
addr <= (unsigned long) &_etext)
return 1;
list_for_each_entry(mod, &modules, list) {
/* mod_bound tests for addr being inside the vmalloc'ed
* module area. Of course it'd be better to test only
* for the .text subset... */
if (mod_bound((void *)addr, 0, mod))
return 1;
}
return 0;
}
#else // !CONFIG_MODULES
static inline int kernel_text_address(unsigned long addr)
{
return (addr >= (unsigned long) &_stext &&
addr <= (unsigned long) &_etext);
}
#endif // !CONFIG_MODULES
void show_trace(unsigned long *stack) void show_trace(unsigned long *stack)
{ {
unsigned long *endstack; unsigned long *endstack;
......
...@@ -123,31 +123,6 @@ void dump_stack(void) ...@@ -123,31 +123,6 @@ void dump_stack(void)
static int kstack_depth_to_print = 48; static int kstack_depth_to_print = 48;
extern struct module kernel_module;
static inline int kernel_text_address(unsigned long addr)
{
#ifdef CONFIG_MODULES
struct module *mod;
#endif
extern char _stext, _etext;
if (addr >= (unsigned long) &_stext &&
addr <= (unsigned long) &_etext)
return 1;
#ifdef CONFIG_MODULES
for (mod = module_list; mod != &kernel_module; mod = mod->next) {
/* mod_bound tests for addr being inside the vmalloc'ed
* module area. Of course it'd be better to test only
* for the .text subset... */
if (mod_bound(addr, 0, mod))
return 1;
}
#endif
return 0;
}
void show_stack(unsigned long *sp) void show_stack(unsigned long *sp)
{ {
......
...@@ -63,50 +63,6 @@ static ext_int_info_t ext_int_pfault; ...@@ -63,50 +63,6 @@ static ext_int_info_t ext_int_pfault;
static int kstack_depth_to_print = 12; static int kstack_depth_to_print = 12;
/*
* If the address is either in the .text section of the
* kernel, or in the vmalloc'ed module regions, it *may*
* be the address of a calling routine
*/
extern char _stext, _etext;
#ifdef CONFIG_MODULES
/* FIXME: Accessed without a lock --RR */
extern struct list_head modules;
static inline int kernel_text_address(unsigned long addr)
{
int retval = 0;
struct module *mod;
if (addr >= (unsigned long) &_stext &&
addr <= (unsigned long) &_etext)
return 1;
list_for_each_entry(mod, &modules, list) {
/* mod_bound tests for addr being inside the vmalloc'ed
* module area. Of course it'd be better to test only
* for the .text subset... */
if (mod_bound((void*)addr, 0, mod)) {
retval = 1;
break;
}
}
return retval;
}
#else
static inline int kernel_text_address(unsigned long addr)
{
return (addr >= (unsigned long) &_stext &&
addr <= (unsigned long) &_etext);
}
#endif
void show_trace(unsigned long * stack) void show_trace(unsigned long * stack)
{ {
unsigned long backchain, low_addr, high_addr, ret_addr; unsigned long backchain, low_addr, high_addr, ret_addr;
......
...@@ -65,50 +65,6 @@ static ext_int_info_t ext_int_pfault; ...@@ -65,50 +65,6 @@ static ext_int_info_t ext_int_pfault;
static int kstack_depth_to_print = 20; static int kstack_depth_to_print = 20;
/*
* If the address is either in the .text section of the
* kernel, or in the vmalloc'ed module regions, it *may*
* be the address of a calling routine
*/
extern char _stext, _etext;
#ifdef CONFIG_MODULES
/* FIXME: Accessed without a lock --RR */
extern struct list_head modules;
static inline int kernel_text_address(unsigned long addr)
{
int retval = 0;
struct module *mod;
if (addr >= (unsigned long) &_stext &&
addr <= (unsigned long) &_etext)
return 1;
list_for_each_entry(mod, &modules, list) {
/* mod_bound tests for addr being inside the vmalloc'ed
* module area. Of course it'd be better to test only
* for the .text subset... */
if (mod_bound((void*)addr, 0, mod)) {
retval = 1;
break;
}
}
return retval;
}
#else
static inline int kernel_text_address(unsigned long addr)
{
return (addr >= (unsigned long) &_stext &&
addr <= (unsigned long) &_etext);
}
#endif
void show_trace(unsigned long * stack) void show_trace(unsigned long * stack)
{ {
unsigned long backchain, low_addr, high_addr, ret_addr; unsigned long backchain, low_addr, high_addr, ret_addr;
......
...@@ -11,49 +11,6 @@ ...@@ -11,49 +11,6 @@
#include "sysrq.h" #include "sysrq.h"
#include "user_util.h" #include "user_util.h"
/*
* If the address is either in the .text section of the
* kernel, or in the vmalloc'ed module regions, it *may*
* be the address of a calling routine
*/
#ifdef CONFIG_MODULES
/* FIXME: Accessed without a lock --RR */
extern struct list_head modules;
static inline int kernel_text_address(unsigned long addr)
{
int retval = 0;
struct module *mod;
if (addr >= (unsigned long) &_stext &&
addr <= (unsigned long) &_etext)
return 1;
list_for_each_entry(mod, &modules, list) {
/* mod_bound tests for addr being inside the vmalloc'ed
* module area. Of course it'd be better to test only
* for the .text subset... */
if (mod_bound((void *) addr, 0, mod)) {
retval = 1;
break;
}
}
return retval;
}
#else
static inline int kernel_text_address(unsigned long addr)
{
return (addr >= (unsigned long) &_stext &&
addr <= (unsigned long) &_etext);
}
#endif
void show_trace(unsigned long * stack) void show_trace(unsigned long * stack)
{ {
int i; int i;
......
...@@ -104,44 +104,6 @@ int printk_address(unsigned long address) ...@@ -104,44 +104,6 @@ int printk_address(unsigned long address)
} }
#endif #endif
#ifdef CONFIG_MODULES
/* FIXME: Accessed without a lock --RR */
extern struct list_head modules;
static inline int kernel_text_address(unsigned long addr)
{
int retval = 0;
struct module *mod;
if (addr >= (unsigned long) &_stext &&
addr <= (unsigned long) &_etext)
return 1;
list_for_each_entry(mod, &modules, list) {
/* mod_bound tests for addr being inside the vmalloc'ed
* module area. Of course it'd be better to test only
* for the .text subset... */
if (mod_bound((void *)addr, 0, mod)) {
retval = 1;
break;
}
}
return retval;
}
#else
static inline int kernel_text_address(unsigned long addr)
{
return (addr >= (unsigned long) &_stext &&
addr <= (unsigned long) &_etext);
}
#endif
static inline unsigned long *in_exception_stack(int cpu, unsigned long stack) static inline unsigned long *in_exception_stack(int cpu, unsigned long stack)
{ {
int k; int k;
......
...@@ -84,6 +84,7 @@ extern unsigned long long memparse(char *ptr, char **retptr); ...@@ -84,6 +84,7 @@ extern unsigned long long memparse(char *ptr, char **retptr);
extern void dev_probe_lock(void); extern void dev_probe_lock(void);
extern void dev_probe_unlock(void); extern void dev_probe_unlock(void);
extern int kernel_text_address(unsigned long addr);
extern int session_of_pgrp(int pgrp); extern int session_of_pgrp(int pgrp);
asmlinkage int printk(const char * fmt, ...) asmlinkage int printk(const char * fmt, ...)
......
...@@ -234,6 +234,9 @@ static inline int module_is_live(struct module *mod) ...@@ -234,6 +234,9 @@ static inline int module_is_live(struct module *mod)
return mod->state != MODULE_STATE_GOING; return mod->state != MODULE_STATE_GOING;
} }
/* Is this address in a module? */
int module_text_address(unsigned long addr);
#ifdef CONFIG_MODULE_UNLOAD #ifdef CONFIG_MODULE_UNLOAD
void __symbol_put(const char *symbol); void __symbol_put(const char *symbol);
...@@ -324,6 +327,12 @@ search_module_extables(unsigned long addr) ...@@ -324,6 +327,12 @@ search_module_extables(unsigned long addr)
return NULL; return NULL;
} }
/* Is this address in a module? */
static int module_text_address(unsigned long addr)
{
return 0;
}
/* Get/put a kernel symbol (calls should be symmetric) */ /* Get/put a kernel symbol (calls should be symmetric) */
#define symbol_get(x) (&(x)) #define symbol_get(x) (&(x))
#define symbol_put(x) do { } while(0) #define symbol_put(x) do { } while(0)
...@@ -426,14 +435,6 @@ extern int module_dummy_usage; ...@@ -426,14 +435,6 @@ extern int module_dummy_usage;
#define GET_USE_COUNT(module) (module_dummy_usage) #define GET_USE_COUNT(module) (module_dummy_usage)
#define MOD_IN_USE 0 #define MOD_IN_USE 0
#define __MODULE_STRING(x) __stringify(x) #define __MODULE_STRING(x) __stringify(x)
#define __mod_between(a_start, a_len, b_start, b_len) \
(((a_start) >= (b_start) && (a_start) <= (b_start)+(b_len)) \
|| ((a_start)+(a_len) >= (b_start) \
&& (a_start)+(a_len) <= (b_start)+(b_len)))
#define mod_bound(p, n, m) \
(((m)->module_init \
&& __mod_between((p),(n),(m)->module_init,(m)->init_size)) \
|| __mod_between((p),(n),(m)->module_core,(m)->core_size))
/* /*
* The exception and symbol tables, and the lock * The exception and symbol tables, and the lock
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
extern const struct exception_table_entry __start___ex_table[]; extern const struct exception_table_entry __start___ex_table[];
extern const struct exception_table_entry __stop___ex_table[]; extern const struct exception_table_entry __stop___ex_table[];
extern char _stext[], _etext[];
/* Given an address, look for it in the exception tables. */ /* Given an address, look for it in the exception tables. */
const struct exception_table_entry *search_exception_tables(unsigned long addr) const struct exception_table_entry *search_exception_tables(unsigned long addr)
...@@ -30,3 +31,12 @@ const struct exception_table_entry *search_exception_tables(unsigned long addr) ...@@ -30,3 +31,12 @@ const struct exception_table_entry *search_exception_tables(unsigned long addr)
e = search_module_extables(addr); e = search_module_extables(addr);
return e; return e;
} }
int kernel_text_address(unsigned long addr)
{
if (addr >= (unsigned long)_stext &&
addr <= (unsigned long)_etext)
return 1;
return module_text_address(addr);
}
...@@ -54,9 +54,9 @@ ...@@ -54,9 +54,9 @@
/* Protects extables and symbols lists */ /* Protects extables and symbols lists */
static spinlock_t modlist_lock = SPIN_LOCK_UNLOCKED; static spinlock_t modlist_lock = SPIN_LOCK_UNLOCKED;
/* List of modules, protected by module_mutex */ /* List of modules, protected by module_mutex AND modlist_lock */
static DECLARE_MUTEX(module_mutex); static DECLARE_MUTEX(module_mutex);
LIST_HEAD(modules); /* FIXME: Accessed w/o lock on oops by some archs */ static LIST_HEAD(modules);
static LIST_HEAD(symbols); static LIST_HEAD(symbols);
static LIST_HEAD(extables); static LIST_HEAD(extables);
...@@ -754,8 +754,8 @@ unsigned long find_symbol_internal(Elf_Shdr *sechdrs, ...@@ -754,8 +754,8 @@ unsigned long find_symbol_internal(Elf_Shdr *sechdrs,
static void free_module(struct module *mod) static void free_module(struct module *mod)
{ {
/* Delete from various lists */ /* Delete from various lists */
list_del(&mod->list);
spin_lock_irq(&modlist_lock); spin_lock_irq(&modlist_lock);
list_del(&mod->list);
list_del(&mod->symbols.list); list_del(&mod->symbols.list);
list_del(&mod->gpl_symbols.list); list_del(&mod->gpl_symbols.list);
list_del(&mod->extable.list); list_del(&mod->extable.list);
...@@ -1290,8 +1290,8 @@ sys_init_module(void *umod, ...@@ -1290,8 +1290,8 @@ sys_init_module(void *umod,
list_add(&mod->extable.list, &extables); list_add(&mod->extable.list, &extables);
list_add_tail(&mod->symbols.list, &symbols); list_add_tail(&mod->symbols.list, &symbols);
list_add_tail(&mod->gpl_symbols.list, &symbols); list_add_tail(&mod->gpl_symbols.list, &symbols);
spin_unlock_irq(&modlist_lock);
list_add(&mod->list, &modules); list_add(&mod->list, &modules);
spin_unlock_irq(&modlist_lock);
/* Drop lock so they can recurse */ /* Drop lock so they can recurse */
up(&module_mutex); up(&module_mutex);
...@@ -1318,28 +1318,17 @@ sys_init_module(void *umod, ...@@ -1318,28 +1318,17 @@ sys_init_module(void *umod,
mod->state = MODULE_STATE_LIVE; mod->state = MODULE_STATE_LIVE;
module_free(mod, mod->module_init); module_free(mod, mod->module_init);
mod->module_init = NULL; mod->module_init = NULL;
mod->init_size = 0;
return 0; return 0;
} }
#ifdef CONFIG_KALLSYMS static inline int within(unsigned long addr, void *start, unsigned long size)
static inline int inside_init(struct module *mod, unsigned long addr)
{
if (mod->module_init
&& (unsigned long)mod->module_init <= addr
&& (unsigned long)mod->module_init + mod->init_size > addr)
return 1;
return 0;
}
static inline int inside_core(struct module *mod, unsigned long addr)
{ {
if ((unsigned long)mod->module_core <= addr return ((void *)addr >= start && (void *)addr < start + size);
&& (unsigned long)mod->module_core + mod->core_size > addr)
return 1;
return 0;
} }
#ifdef CONFIG_KALLSYMS
static const char *get_ksymbol(struct module *mod, static const char *get_ksymbol(struct module *mod,
unsigned long addr, unsigned long addr,
unsigned long *size, unsigned long *size,
...@@ -1349,7 +1338,7 @@ static const char *get_ksymbol(struct module *mod, ...@@ -1349,7 +1338,7 @@ static const char *get_ksymbol(struct module *mod,
unsigned long nextval; unsigned long nextval;
/* At worse, next value is at end of module */ /* At worse, next value is at end of module */
if (inside_core(mod, addr)) if (within(addr, mod->module_init, mod->init_size))
nextval = (unsigned long)mod->module_core+mod->core_size; nextval = (unsigned long)mod->module_core+mod->core_size;
else else
nextval = (unsigned long)mod->module_init+mod->init_size; nextval = (unsigned long)mod->module_init+mod->init_size;
...@@ -1387,7 +1376,8 @@ const char *module_address_lookup(unsigned long addr, ...@@ -1387,7 +1376,8 @@ const char *module_address_lookup(unsigned long addr,
struct module *mod; struct module *mod;
list_for_each_entry(mod, &modules, list) { list_for_each_entry(mod, &modules, list) {
if (inside_core(mod, addr) || inside_init(mod, addr)) { if (within(addr, mod->module_init, mod->init_size)
|| within(addr, mod->module_core, mod->core_size)) {
*modname = mod->name; *modname = mod->name;
return get_ksymbol(mod, addr, size, offset); return get_ksymbol(mod, addr, size, offset);
} }
...@@ -1471,6 +1461,18 @@ const struct exception_table_entry *search_module_extables(unsigned long addr) ...@@ -1471,6 +1461,18 @@ const struct exception_table_entry *search_module_extables(unsigned long addr)
return e; return e;
} }
/* Is this a valid kernel address? We don't grab the lock: we are oopsing. */
int module_text_address(unsigned long addr)
{
struct module *mod;
list_for_each_entry(mod, &modules, list)
if (within(addr, mod->module_init, mod->init_size)
|| within(addr, mod->module_core, mod->core_size))
return 1;
return 0;
}
/* Provided by the linker */ /* Provided by the linker */
extern const struct kernel_symbol __start___ksymtab[]; extern const struct kernel_symbol __start___ksymtab[];
extern const struct kernel_symbol __stop___ksymtab[]; extern const struct kernel_symbol __stop___ksymtab[];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment