Fix race between rmmod and cat /proc/kallsyms

module_get_kallsym() leaks "struct module *" outside of module_mutex which is
no-no, because module can dissapear right after mutex unlock.

Copy all needed information from inside module_mutex into caller-supplied
space.

[bunk@stusta.de: is_exported() can now become static]
Signed-off-by: Alexey Dobriyan <adobriyan@sw.ru>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Adrian Bunk <bunk@stusta.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Alexey Dobriyan
2007-05-08 00:28:39 -07:00
committed by Linus Torvalds
parent ae84e32470
commit ea07890a68
3 changed files with 29 additions and 34 deletions

View File

@@ -370,16 +370,14 @@ struct module *module_text_address(unsigned long addr);
struct module *__module_text_address(unsigned long addr);
int is_module_address(unsigned long addr);
/* Returns module and fills in value, defined and namebuf, or NULL if
/* Returns 0 and fills in value, defined and namebuf, or -ERANGE if
symnum out of range. */
struct module *module_get_kallsym(unsigned int symnum, unsigned long *value,
char *type, char *name);
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);
int is_exported(const char *name, const struct module *mod);
extern void __module_put_and_exit(struct module *mod, long code)
__attribute__((noreturn));
#define module_put_and_exit(code) __module_put_and_exit(THIS_MODULE, code);
@@ -527,11 +525,11 @@ static inline const char *module_address_lookup(unsigned long addr,
return NULL;
}
static inline struct module *module_get_kallsym(unsigned int symnum,
unsigned long *value,
char *type, char *name)
static inline int module_get_kallsym(unsigned int symnum, unsigned long *value,
char *type, char *name,
char *module_name, int *exported)
{
return NULL;
return -ERANGE;
}
static inline unsigned long module_kallsyms_lookup_name(const char *name)
@@ -539,11 +537,6 @@ static inline unsigned long module_kallsyms_lookup_name(const char *name)
return 0;
}
static inline int is_exported(const char *name, const struct module *mod)
{
return 0;
}
static inline int register_module_notifier(struct notifier_block * nb)
{
/* no events will happen anyway, so this can always succeed */