mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-module-and-param
* git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-module-and-param: module: use strstarts() strstarts: helper function for !strncmp(str, prefix, strlen(prefix)) arm: allow usage of string functions in linux/string.h module: don't use stop_machine on module load module: create a request_module_nowait() module: include other structures in module version check module: remove the SHF_ALLOC flag on the __versions section. module: clarify the force-loading taint message. module: Export symbols needed for Ksplice Ksplice: Add functions for walking kallsyms symbols module: remove module_text_address() module: __module_address module: Make find_symbol return a struct kernel_symbol kernel/module.c: fix an unused goto label param: fix charp parameters set via sysfs Fix trivial conflicts in kernel/extable.c manually.
This commit is contained in:
commit
cab4e4c43f
13 changed files with 319 additions and 137 deletions
|
@ -18,7 +18,10 @@
|
|||
|
||||
unsigned int __machine_arch_type;
|
||||
|
||||
#include <linux/string.h>
|
||||
#include <linux/compiler.h> /* for inline */
|
||||
#include <linux/types.h> /* for size_t */
|
||||
#include <linux/stddef.h> /* for NULL */
|
||||
#include <asm/string.h>
|
||||
|
||||
#ifdef STANDALONE_DEBUG
|
||||
#define putstr printf
|
||||
|
|
|
@ -2720,14 +2720,14 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|||
return chip->scan_bbt(mtd);
|
||||
}
|
||||
|
||||
/* module_text_address() isn't exported, and it's mostly a pointless
|
||||
/* is_module_text_address() isn't exported, and it's mostly a pointless
|
||||
test if this is a module _anyway_ -- they'd have to try _really_ hard
|
||||
to call us from in-kernel code if the core NAND support is modular. */
|
||||
#ifdef MODULE
|
||||
#define caller_is_module() (1)
|
||||
#else
|
||||
#define caller_is_module() \
|
||||
module_text_address((unsigned long)__builtin_return_address(0))
|
||||
is_module_text_address((unsigned long)__builtin_return_address(0))
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,10 +13,17 @@
|
|||
#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \
|
||||
2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1)
|
||||
|
||||
struct module;
|
||||
|
||||
#ifdef CONFIG_KALLSYMS
|
||||
/* Lookup the address for a symbol. Returns 0 if not found. */
|
||||
unsigned long kallsyms_lookup_name(const char *name);
|
||||
|
||||
/* Call a function on each kallsyms symbol in the core kernel */
|
||||
int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
|
||||
unsigned long),
|
||||
void *data);
|
||||
|
||||
extern int kallsyms_lookup_size_offset(unsigned long addr,
|
||||
unsigned long *symbolsize,
|
||||
unsigned long *offset);
|
||||
|
@ -43,6 +50,14 @@ static inline unsigned long kallsyms_lookup_name(const char *name)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int kallsyms_on_each_symbol(int (*fn)(void *, const char *,
|
||||
struct module *,
|
||||
unsigned long),
|
||||
void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int kallsyms_lookup_size_offset(unsigned long addr,
|
||||
unsigned long *symbolsize,
|
||||
unsigned long *offset)
|
||||
|
|
|
@ -29,10 +29,15 @@
|
|||
#ifdef CONFIG_MODULES
|
||||
/* modprobe exit status on success, -ve on error. Return value
|
||||
* usually useless though. */
|
||||
extern int request_module(const char * name, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
#define try_then_request_module(x, mod...) ((x) ?: (request_module(mod), (x)))
|
||||
extern int __request_module(bool wait, const char *name, ...) \
|
||||
__attribute__((format(printf, 2, 3)));
|
||||
#define request_module(mod...) __request_module(true, mod)
|
||||
#define request_module_nowait(mod...) __request_module(false, mod)
|
||||
#define try_then_request_module(x, mod...) \
|
||||
((x) ?: (__request_module(false, mod), (x)))
|
||||
#else
|
||||
static inline int request_module(const char *name, ...) { return -ENOSYS; }
|
||||
static inline int request_module_nowait(const char *name, ...) { return -ENOSYS; }
|
||||
#define try_then_request_module(x, mod...) (x)
|
||||
#endif
|
||||
|
||||
|
|
|
@ -248,6 +248,10 @@ struct module
|
|||
const unsigned long *crcs;
|
||||
unsigned int num_syms;
|
||||
|
||||
/* Kernel parameters. */
|
||||
struct kernel_param *kp;
|
||||
unsigned int num_kp;
|
||||
|
||||
/* GPL-only exported symbols. */
|
||||
unsigned int num_gpl_syms;
|
||||
const struct kernel_symbol *gpl_syms;
|
||||
|
@ -350,6 +354,8 @@ struct module
|
|||
#define MODULE_ARCH_INIT {}
|
||||
#endif
|
||||
|
||||
extern struct mutex module_mutex;
|
||||
|
||||
/* FIXME: It'd be nice to isolate modules during init, too, so they
|
||||
aren't used before they (may) fail. But presently too much code
|
||||
(IDE & SCSI) require entry into the module during init.*/
|
||||
|
@ -358,10 +364,10 @@ static inline int module_is_live(struct module *mod)
|
|||
return mod->state != MODULE_STATE_GOING;
|
||||
}
|
||||
|
||||
/* Is this address in a module? (second is with no locks, for oops) */
|
||||
struct module *module_text_address(unsigned long addr);
|
||||
struct module *__module_text_address(unsigned long addr);
|
||||
int is_module_address(unsigned long addr);
|
||||
struct module *__module_address(unsigned long addr);
|
||||
bool is_module_address(unsigned long addr);
|
||||
bool is_module_text_address(unsigned long addr);
|
||||
|
||||
static inline int within_module_core(unsigned long addr, struct module *mod)
|
||||
{
|
||||
|
@ -375,6 +381,31 @@ static inline int within_module_init(unsigned long addr, struct module *mod)
|
|||
addr < (unsigned long)mod->module_init + mod->init_size;
|
||||
}
|
||||
|
||||
/* Search for module by name: must hold module_mutex. */
|
||||
struct module *find_module(const char *name);
|
||||
|
||||
struct symsearch {
|
||||
const struct kernel_symbol *start, *stop;
|
||||
const unsigned long *crcs;
|
||||
enum {
|
||||
NOT_GPL_ONLY,
|
||||
GPL_ONLY,
|
||||
WILL_BE_GPL_ONLY,
|
||||
} licence;
|
||||
bool unused;
|
||||
};
|
||||
|
||||
/* Search for an exported symbol by name. */
|
||||
const struct kernel_symbol *find_symbol(const char *name,
|
||||
struct module **owner,
|
||||
const unsigned long **crc,
|
||||
bool gplok,
|
||||
bool warn);
|
||||
|
||||
/* Walk the exported symbol table */
|
||||
bool each_symbol(bool (*fn)(const struct symsearch *arr, struct module *owner,
|
||||
unsigned int symnum, void *data), void *data);
|
||||
|
||||
/* Returns 0 and fills in value, defined and namebuf, or -ERANGE if
|
||||
symnum out of range. */
|
||||
int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
|
||||
|
@ -383,6 +414,10 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
|
|||
/* Look for this name: can be of form module:name. */
|
||||
unsigned long module_kallsyms_lookup_name(const char *name);
|
||||
|
||||
int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
|
||||
struct module *, unsigned long),
|
||||
void *data);
|
||||
|
||||
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);
|
||||
|
@ -444,6 +479,7 @@ static inline void __module_get(struct module *module)
|
|||
#define symbol_put_addr(p) do { } while(0)
|
||||
|
||||
#endif /* CONFIG_MODULE_UNLOAD */
|
||||
int use_module(struct module *a, struct module *b);
|
||||
|
||||
/* This is a #define so the string doesn't get put in every .o file */
|
||||
#define module_name(mod) \
|
||||
|
@ -490,21 +526,24 @@ search_module_extables(unsigned long addr)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Is this address in a module? */
|
||||
static inline struct module *module_text_address(unsigned long addr)
|
||||
static inline struct module *__module_address(unsigned long addr)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Is this address in a module? (don't take a lock, we're oopsing) */
|
||||
static inline struct module *__module_text_address(unsigned long addr)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int is_module_address(unsigned long addr)
|
||||
static inline bool is_module_address(unsigned long addr)
|
||||
{
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool is_module_text_address(unsigned long addr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Get/put a kernel symbol (calls should be symmetric) */
|
||||
|
@ -559,6 +598,14 @@ static inline unsigned long module_kallsyms_lookup_name(const char *name)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
|
||||
struct module *,
|
||||
unsigned long),
|
||||
void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int register_module_notifier(struct notifier_block * nb)
|
||||
{
|
||||
/* no events will happen anyway, so this can always succeed */
|
||||
|
|
|
@ -138,6 +138,16 @@ extern int parse_args(const char *name,
|
|||
unsigned num,
|
||||
int (*unknown)(char *param, char *val));
|
||||
|
||||
/* Called by module remove. */
|
||||
#ifdef CONFIG_SYSFS
|
||||
extern void destroy_params(const struct kernel_param *params, unsigned num);
|
||||
#else
|
||||
static inline void destroy_params(const struct kernel_param *params,
|
||||
unsigned num)
|
||||
{
|
||||
}
|
||||
#endif /* !CONFIG_SYSFS */
|
||||
|
||||
/* All the helper functions */
|
||||
/* The macros to do compile-time type checking stolen from Jakub
|
||||
Jelinek, who IIRC came up with this idea for the 2.4 module init code. */
|
||||
|
|
|
@ -122,5 +122,14 @@ int bprintf(u32 *bin_buf, size_t size, const char *fmt, ...) __printf(3, 4);
|
|||
extern ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos,
|
||||
const void *from, size_t available);
|
||||
|
||||
/**
|
||||
* strstarts - does @str start with @prefix?
|
||||
* @str: string to examine
|
||||
* @prefix: prefix to look for.
|
||||
*/
|
||||
static inline bool strstarts(const char *str, const char *prefix)
|
||||
{
|
||||
return strncmp(str, prefix, strlen(prefix)) == 0;
|
||||
}
|
||||
#endif
|
||||
#endif /* _LINUX_STRING_H_ */
|
||||
|
|
|
@ -65,7 +65,7 @@ __notrace_funcgraph int __kernel_text_address(unsigned long addr)
|
|||
{
|
||||
if (core_kernel_text(addr))
|
||||
return 1;
|
||||
if (__module_text_address(addr))
|
||||
if (is_module_text_address(addr))
|
||||
return 1;
|
||||
/*
|
||||
* There might be init symbols in saved stacktraces.
|
||||
|
@ -84,7 +84,7 @@ int kernel_text_address(unsigned long addr)
|
|||
{
|
||||
if (core_kernel_text(addr))
|
||||
return 1;
|
||||
return module_text_address(addr) != NULL;
|
||||
return is_module_text_address(addr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -100,5 +100,5 @@ int func_ptr_is_kernel_text(void *ptr)
|
|||
addr = (unsigned long) dereference_function_descriptor(ptr);
|
||||
if (core_kernel_text(addr))
|
||||
return 1;
|
||||
return module_text_address(addr) != NULL;
|
||||
return is_module_text_address(addr);
|
||||
}
|
||||
|
|
|
@ -161,6 +161,25 @@ unsigned long kallsyms_lookup_name(const char *name)
|
|||
return module_kallsyms_lookup_name(name);
|
||||
}
|
||||
|
||||
int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
|
||||
unsigned long),
|
||||
void *data)
|
||||
{
|
||||
char namebuf[KSYM_NAME_LEN];
|
||||
unsigned long i;
|
||||
unsigned int off;
|
||||
int ret;
|
||||
|
||||
for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
|
||||
off = kallsyms_expand_symbol(off, namebuf);
|
||||
ret = fn(data, namebuf, NULL, kallsyms_addresses[i]);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
return module_kallsyms_on_each_symbol(fn, data);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kallsyms_on_each_symbol);
|
||||
|
||||
static unsigned long get_symbol_pos(unsigned long addr,
|
||||
unsigned long *symbolsize,
|
||||
unsigned long *offset)
|
||||
|
|
|
@ -50,7 +50,8 @@ static struct workqueue_struct *khelper_wq;
|
|||
char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe";
|
||||
|
||||
/**
|
||||
* request_module - try to load a kernel module
|
||||
* __request_module - try to load a kernel module
|
||||
* @wait: wait (or not) for the operation to complete
|
||||
* @fmt: printf style format string for the name of the module
|
||||
* @...: arguments as specified in the format string
|
||||
*
|
||||
|
@ -63,7 +64,7 @@ char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe";
|
|||
* If module auto-loading support is disabled then this function
|
||||
* becomes a no-operation.
|
||||
*/
|
||||
int request_module(const char *fmt, ...)
|
||||
int __request_module(bool wait, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char module_name[MODULE_NAME_LEN];
|
||||
|
@ -108,11 +109,12 @@ int request_module(const char *fmt, ...)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = call_usermodehelper(modprobe_path, argv, envp, 1);
|
||||
ret = call_usermodehelper(modprobe_path, argv, envp,
|
||||
wait ? UMH_WAIT_PROC : UMH_WAIT_EXEC);
|
||||
atomic_dec(&kmod_concurrent);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(request_module);
|
||||
EXPORT_SYMBOL(__request_module);
|
||||
#endif /* CONFIG_MODULES */
|
||||
|
||||
struct subprocess_info {
|
||||
|
|
254
kernel/module.c
254
kernel/module.c
|
@ -68,7 +68,8 @@
|
|||
|
||||
/* List of modules, protected by module_mutex or preempt_disable
|
||||
* (delete uses stop_machine/add uses RCU list operations). */
|
||||
static DEFINE_MUTEX(module_mutex);
|
||||
DEFINE_MUTEX(module_mutex);
|
||||
EXPORT_SYMBOL_GPL(module_mutex);
|
||||
static LIST_HEAD(modules);
|
||||
|
||||
/* Waiting for a module to finish initializing? */
|
||||
|
@ -76,7 +77,7 @@ static DECLARE_WAIT_QUEUE_HEAD(module_wq);
|
|||
|
||||
static BLOCKING_NOTIFIER_HEAD(module_notify_list);
|
||||
|
||||
/* Bounds of module allocation, for speeding __module_text_address */
|
||||
/* Bounds of module allocation, for speeding __module_address */
|
||||
static unsigned long module_addr_min = -1UL, module_addr_max = 0;
|
||||
|
||||
int register_module_notifier(struct notifier_block * nb)
|
||||
|
@ -186,17 +187,6 @@ extern const unsigned long __start___kcrctab_unused_gpl[];
|
|||
#define symversion(base, idx) ((base != NULL) ? ((base) + (idx)) : NULL)
|
||||
#endif
|
||||
|
||||
struct symsearch {
|
||||
const struct kernel_symbol *start, *stop;
|
||||
const unsigned long *crcs;
|
||||
enum {
|
||||
NOT_GPL_ONLY,
|
||||
GPL_ONLY,
|
||||
WILL_BE_GPL_ONLY,
|
||||
} licence;
|
||||
bool unused;
|
||||
};
|
||||
|
||||
static bool each_symbol_in_section(const struct symsearch *arr,
|
||||
unsigned int arrsize,
|
||||
struct module *owner,
|
||||
|
@ -217,10 +207,8 @@ static bool each_symbol_in_section(const struct symsearch *arr,
|
|||
}
|
||||
|
||||
/* Returns true as soon as fn returns true, otherwise false. */
|
||||
static bool each_symbol(bool (*fn)(const struct symsearch *arr,
|
||||
struct module *owner,
|
||||
unsigned int symnum, void *data),
|
||||
void *data)
|
||||
bool each_symbol(bool (*fn)(const struct symsearch *arr, struct module *owner,
|
||||
unsigned int symnum, void *data), void *data)
|
||||
{
|
||||
struct module *mod;
|
||||
const struct symsearch arr[] = {
|
||||
|
@ -273,6 +261,7 @@ static bool each_symbol(bool (*fn)(const struct symsearch *arr,
|
|||
}
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(each_symbol);
|
||||
|
||||
struct find_symbol_arg {
|
||||
/* Input */
|
||||
|
@ -283,7 +272,7 @@ struct find_symbol_arg {
|
|||
/* Output */
|
||||
struct module *owner;
|
||||
const unsigned long *crc;
|
||||
unsigned long value;
|
||||
const struct kernel_symbol *sym;
|
||||
};
|
||||
|
||||
static bool find_symbol_in_section(const struct symsearch *syms,
|
||||
|
@ -324,13 +313,13 @@ static bool find_symbol_in_section(const struct symsearch *syms,
|
|||
|
||||
fsa->owner = owner;
|
||||
fsa->crc = symversion(syms->crcs, symnum);
|
||||
fsa->value = syms->start[symnum].value;
|
||||
fsa->sym = &syms->start[symnum];
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Find a symbol, return value, (optional) crc and (optional) module
|
||||
* which owns it */
|
||||
static unsigned long find_symbol(const char *name,
|
||||
/* Find a symbol and return it, along with, (optional) crc and
|
||||
* (optional) module which owns it */
|
||||
const struct kernel_symbol *find_symbol(const char *name,
|
||||
struct module **owner,
|
||||
const unsigned long **crc,
|
||||
bool gplok,
|
||||
|
@ -347,15 +336,16 @@ static unsigned long find_symbol(const char *name,
|
|||
*owner = fsa.owner;
|
||||
if (crc)
|
||||
*crc = fsa.crc;
|
||||
return fsa.value;
|
||||
return fsa.sym;
|
||||
}
|
||||
|
||||
DEBUGP("Failed to find symbol %s\n", name);
|
||||
return -ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(find_symbol);
|
||||
|
||||
/* Search for module by name: must hold module_mutex. */
|
||||
static struct module *find_module(const char *name)
|
||||
struct module *find_module(const char *name)
|
||||
{
|
||||
struct module *mod;
|
||||
|
||||
|
@ -365,6 +355,7 @@ static struct module *find_module(const char *name)
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(find_module);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
|
@ -641,7 +632,7 @@ static int already_uses(struct module *a, struct module *b)
|
|||
}
|
||||
|
||||
/* Module a uses b */
|
||||
static int use_module(struct module *a, struct module *b)
|
||||
int use_module(struct module *a, struct module *b)
|
||||
{
|
||||
struct module_use *use;
|
||||
int no_warn, err;
|
||||
|
@ -674,6 +665,7 @@ static int use_module(struct module *a, struct module *b)
|
|||
no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name);
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(use_module);
|
||||
|
||||
/* Clear the unload stuff of the module. */
|
||||
static void module_unload_free(struct module *mod)
|
||||
|
@ -894,7 +886,7 @@ void __symbol_put(const char *symbol)
|
|||
struct module *owner;
|
||||
|
||||
preempt_disable();
|
||||
if (IS_ERR_VALUE(find_symbol(symbol, &owner, NULL, true, false)))
|
||||
if (!find_symbol(symbol, &owner, NULL, true, false))
|
||||
BUG();
|
||||
module_put(owner);
|
||||
preempt_enable();
|
||||
|
@ -908,8 +900,10 @@ void symbol_put_addr(void *addr)
|
|||
if (core_kernel_text((unsigned long)addr))
|
||||
return;
|
||||
|
||||
if (!(modaddr = module_text_address((unsigned long)addr)))
|
||||
BUG();
|
||||
/* module_text_address is safe here: we're supposed to have reference
|
||||
* to module from symbol_get, so it can't go away. */
|
||||
modaddr = __module_text_address((unsigned long)addr);
|
||||
BUG_ON(!modaddr);
|
||||
module_put(modaddr);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(symbol_put_addr);
|
||||
|
@ -949,10 +943,11 @@ static inline void module_unload_free(struct module *mod)
|
|||
{
|
||||
}
|
||||
|
||||
static inline int use_module(struct module *a, struct module *b)
|
||||
int use_module(struct module *a, struct module *b)
|
||||
{
|
||||
return strong_try_module_get(b) == 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(use_module);
|
||||
|
||||
static inline void module_unload_init(struct module *mod)
|
||||
{
|
||||
|
@ -995,12 +990,12 @@ static struct module_attribute *modinfo_attrs[] = {
|
|||
|
||||
static const char vermagic[] = VERMAGIC_STRING;
|
||||
|
||||
static int try_to_force_load(struct module *mod, const char *symname)
|
||||
static int try_to_force_load(struct module *mod, const char *reason)
|
||||
{
|
||||
#ifdef CONFIG_MODULE_FORCE_LOAD
|
||||
if (!test_taint(TAINT_FORCED_MODULE))
|
||||
printk("%s: no version for \"%s\" found: kernel tainted.\n",
|
||||
mod->name, symname);
|
||||
printk(KERN_WARNING "%s: %s: kernel tainted.\n",
|
||||
mod->name, reason);
|
||||
add_taint_module(mod, TAINT_FORCED_MODULE);
|
||||
return 0;
|
||||
#else
|
||||
|
@ -1057,9 +1052,9 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs,
|
|||
{
|
||||
const unsigned long *crc;
|
||||
|
||||
if (IS_ERR_VALUE(find_symbol("struct_module", NULL, &crc, true, false)))
|
||||
if (!find_symbol("module_layout", NULL, &crc, true, false))
|
||||
BUG();
|
||||
return check_version(sechdrs, versindex, "struct_module", mod, crc);
|
||||
return check_version(sechdrs, versindex, "module_layout", mod, crc);
|
||||
}
|
||||
|
||||
/* First part is kernel version, which we ignore if module has crcs. */
|
||||
|
@ -1098,25 +1093,25 @@ static inline int same_magic(const char *amagic, const char *bmagic,
|
|||
|
||||
/* Resolve a symbol for this module. I.e. if we find one, record usage.
|
||||
Must be holding module_mutex. */
|
||||
static unsigned long resolve_symbol(Elf_Shdr *sechdrs,
|
||||
static const struct kernel_symbol *resolve_symbol(Elf_Shdr *sechdrs,
|
||||
unsigned int versindex,
|
||||
const char *name,
|
||||
struct module *mod)
|
||||
{
|
||||
struct module *owner;
|
||||
unsigned long ret;
|
||||
const struct kernel_symbol *sym;
|
||||
const unsigned long *crc;
|
||||
|
||||
ret = find_symbol(name, &owner, &crc,
|
||||
sym = find_symbol(name, &owner, &crc,
|
||||
!(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true);
|
||||
if (!IS_ERR_VALUE(ret)) {
|
||||
/* use_module can fail due to OOM,
|
||||
or module initialization or unloading */
|
||||
if (sym) {
|
||||
if (!check_version(sechdrs, versindex, name, mod, crc) ||
|
||||
!use_module(mod, owner))
|
||||
ret = -EINVAL;
|
||||
sym = NULL;
|
||||
}
|
||||
return ret;
|
||||
return sym;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1491,6 +1486,9 @@ static void free_module(struct module *mod)
|
|||
/* Module unload stuff */
|
||||
module_unload_free(mod);
|
||||
|
||||
/* Free any allocated parameters. */
|
||||
destroy_params(mod->kp, mod->num_kp);
|
||||
|
||||
/* release any pointers to mcount in this module */
|
||||
ftrace_release(mod->module_core, mod->core_size);
|
||||
|
||||
|
@ -1513,17 +1511,15 @@ static void free_module(struct module *mod)
|
|||
void *__symbol_get(const char *symbol)
|
||||
{
|
||||
struct module *owner;
|
||||
unsigned long value;
|
||||
const struct kernel_symbol *sym;
|
||||
|
||||
preempt_disable();
|
||||
value = find_symbol(symbol, &owner, NULL, true, true);
|
||||
if (IS_ERR_VALUE(value))
|
||||
value = 0;
|
||||
else if (strong_try_module_get(owner))
|
||||
value = 0;
|
||||
sym = find_symbol(symbol, &owner, NULL, true, true);
|
||||
if (sym && strong_try_module_get(owner))
|
||||
sym = NULL;
|
||||
preempt_enable();
|
||||
|
||||
return (void *)value;
|
||||
return sym ? (void *)sym->value : NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__symbol_get);
|
||||
|
||||
|
@ -1551,8 +1547,7 @@ static int verify_export_symbols(struct module *mod)
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(arr); i++) {
|
||||
for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) {
|
||||
if (!IS_ERR_VALUE(find_symbol(s->name, &owner,
|
||||
NULL, true, false))) {
|
||||
if (find_symbol(s->name, &owner, NULL, true, false)) {
|
||||
printk(KERN_ERR
|
||||
"%s: exports duplicate symbol %s"
|
||||
" (owned by %s)\n",
|
||||
|
@ -1576,6 +1571,7 @@ static int simplify_symbols(Elf_Shdr *sechdrs,
|
|||
unsigned long secbase;
|
||||
unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
|
||||
int ret = 0;
|
||||
const struct kernel_symbol *ksym;
|
||||
|
||||
for (i = 1; i < n; i++) {
|
||||
switch (sym[i].st_shndx) {
|
||||
|
@ -1595,13 +1591,14 @@ static int simplify_symbols(Elf_Shdr *sechdrs,
|
|||
break;
|
||||
|
||||
case SHN_UNDEF:
|
||||
sym[i].st_value
|
||||
= resolve_symbol(sechdrs, versindex,
|
||||
ksym = resolve_symbol(sechdrs, versindex,
|
||||
strtab + sym[i].st_name, mod);
|
||||
|
||||
/* Ok if resolved. */
|
||||
if (!IS_ERR_VALUE(sym[i].st_value))
|
||||
if (ksym) {
|
||||
sym[i].st_value = ksym->value;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Ok if weak. */
|
||||
if (ELF_ST_BIND(sym[i].st_info) == STB_WEAK)
|
||||
break;
|
||||
|
@ -1676,8 +1673,7 @@ static void layout_sections(struct module *mod,
|
|||
if ((s->sh_flags & masks[m][0]) != masks[m][0]
|
||||
|| (s->sh_flags & masks[m][1])
|
||||
|| s->sh_entsize != ~0UL
|
||||
|| strncmp(secstrings + s->sh_name,
|
||||
".init", 5) == 0)
|
||||
|| strstarts(secstrings + s->sh_name, ".init"))
|
||||
continue;
|
||||
s->sh_entsize = get_offset(mod, &mod->core_size, s, i);
|
||||
DEBUGP("\t%s\n", secstrings + s->sh_name);
|
||||
|
@ -1694,8 +1690,7 @@ static void layout_sections(struct module *mod,
|
|||
if ((s->sh_flags & masks[m][0]) != masks[m][0]
|
||||
|| (s->sh_flags & masks[m][1])
|
||||
|| s->sh_entsize != ~0UL
|
||||
|| strncmp(secstrings + s->sh_name,
|
||||
".init", 5) != 0)
|
||||
|| !strstarts(secstrings + s->sh_name, ".init"))
|
||||
continue;
|
||||
s->sh_entsize = (get_offset(mod, &mod->init_size, s, i)
|
||||
| INIT_OFFSET_MASK);
|
||||
|
@ -1828,8 +1823,7 @@ static char elf_type(const Elf_Sym *sym,
|
|||
else
|
||||
return 'b';
|
||||
}
|
||||
if (strncmp(secstrings + sechdrs[sym->st_shndx].sh_name,
|
||||
".debug", strlen(".debug")) == 0)
|
||||
if (strstarts(secstrings + sechdrs[sym->st_shndx].sh_name, ".debug"))
|
||||
return 'n';
|
||||
return '?';
|
||||
}
|
||||
|
@ -1898,8 +1892,7 @@ static noinline struct module *load_module(void __user *umod,
|
|||
unsigned int symindex = 0;
|
||||
unsigned int strindex = 0;
|
||||
unsigned int modindex, versindex, infoindex, pcpuindex;
|
||||
unsigned int num_kp, num_mcount;
|
||||
struct kernel_param *kp;
|
||||
unsigned int num_mcount;
|
||||
struct module *mod;
|
||||
long err = 0;
|
||||
void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
|
||||
|
@ -1916,12 +1909,6 @@ static noinline struct module *load_module(void __user *umod,
|
|||
if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/* Create stop_machine threads since the error path relies on
|
||||
* a non-failing stop_machine call. */
|
||||
err = stop_machine_create();
|
||||
if (err)
|
||||
goto free_hdr;
|
||||
|
||||
if (copy_from_user(hdr, umod, len) != 0) {
|
||||
err = -EFAULT;
|
||||
goto free_hdr;
|
||||
|
@ -1962,9 +1949,12 @@ static noinline struct module *load_module(void __user *umod,
|
|||
}
|
||||
#ifndef CONFIG_MODULE_UNLOAD
|
||||
/* Don't load .exit sections */
|
||||
if (strncmp(secstrings+sechdrs[i].sh_name, ".exit", 5) == 0)
|
||||
if (strstarts(secstrings+sechdrs[i].sh_name, ".exit"))
|
||||
sechdrs[i].sh_flags &= ~(unsigned long)SHF_ALLOC;
|
||||
#endif
|
||||
/* Don't keep __versions around; it's just for loading. */
|
||||
if (strcmp(secstrings + sechdrs[i].sh_name, "__versions") == 0)
|
||||
sechdrs[i].sh_flags &= ~(unsigned long)SHF_ALLOC;
|
||||
}
|
||||
|
||||
modindex = find_sec(hdr, sechdrs, secstrings,
|
||||
|
@ -2006,7 +1996,7 @@ static noinline struct module *load_module(void __user *umod,
|
|||
modmagic = get_modinfo(sechdrs, infoindex, "vermagic");
|
||||
/* This is allowed: modprobe --force will invalidate it. */
|
||||
if (!modmagic) {
|
||||
err = try_to_force_load(mod, "magic");
|
||||
err = try_to_force_load(mod, "bad vermagic");
|
||||
if (err)
|
||||
goto free_hdr;
|
||||
} else if (!same_magic(modmagic, vermagic, versindex)) {
|
||||
|
@ -2144,8 +2134,8 @@ static noinline struct module *load_module(void __user *umod,
|
|||
|
||||
/* Now we've got everything in the final locations, we can
|
||||
* find optional sections. */
|
||||
kp = section_objs(hdr, sechdrs, secstrings, "__param", sizeof(*kp),
|
||||
&num_kp);
|
||||
mod->kp = section_objs(hdr, sechdrs, secstrings, "__param",
|
||||
sizeof(*mod->kp), &mod->num_kp);
|
||||
mod->syms = section_objs(hdr, sechdrs, secstrings, "__ksymtab",
|
||||
sizeof(*mod->syms), &mod->num_syms);
|
||||
mod->crcs = section_addr(hdr, sechdrs, secstrings, "__kcrctab");
|
||||
|
@ -2195,8 +2185,8 @@ static noinline struct module *load_module(void __user *umod,
|
|||
|| (mod->num_unused_gpl_syms && !mod->unused_gpl_crcs)
|
||||
#endif
|
||||
) {
|
||||
printk(KERN_WARNING "%s: No versions for exported symbols.\n", mod->name);
|
||||
err = try_to_force_load(mod, "nocrc");
|
||||
err = try_to_force_load(mod,
|
||||
"no versions for exported symbols");
|
||||
if (err)
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -2291,11 +2281,11 @@ static noinline struct module *load_module(void __user *umod,
|
|||
*/
|
||||
list_add_rcu(&mod->list, &modules);
|
||||
|
||||
err = parse_args(mod->name, mod->args, kp, num_kp, NULL);
|
||||
err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, NULL);
|
||||
if (err < 0)
|
||||
goto unlink;
|
||||
|
||||
err = mod_sysfs_setup(mod, kp, num_kp);
|
||||
err = mod_sysfs_setup(mod, mod->kp, mod->num_kp);
|
||||
if (err < 0)
|
||||
goto unlink;
|
||||
add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
|
||||
|
@ -2304,12 +2294,13 @@ static noinline struct module *load_module(void __user *umod,
|
|||
/* Get rid of temporary copy */
|
||||
vfree(hdr);
|
||||
|
||||
stop_machine_destroy();
|
||||
/* Done! */
|
||||
return mod;
|
||||
|
||||
unlink:
|
||||
stop_machine(__unlink_module, mod, NULL);
|
||||
/* Unlink carefully: kallsyms could be walking list. */
|
||||
list_del_rcu(&mod->list);
|
||||
synchronize_sched();
|
||||
module_arch_cleanup(mod);
|
||||
cleanup:
|
||||
kobject_del(&mod->mkobj.kobj);
|
||||
|
@ -2317,8 +2308,8 @@ static noinline struct module *load_module(void __user *umod,
|
|||
ftrace_release(mod->module_core, mod->core_size);
|
||||
free_unload:
|
||||
module_unload_free(mod);
|
||||
free_init:
|
||||
#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP)
|
||||
free_init:
|
||||
percpu_modfree(mod->refptr);
|
||||
#endif
|
||||
module_free(mod, mod->module_init);
|
||||
|
@ -2332,7 +2323,6 @@ static noinline struct module *load_module(void __user *umod,
|
|||
kfree(args);
|
||||
free_hdr:
|
||||
vfree(hdr);
|
||||
stop_machine_destroy();
|
||||
return ERR_PTR(err);
|
||||
|
||||
truncated:
|
||||
|
@ -2609,6 +2599,25 @@ unsigned long module_kallsyms_lookup_name(const char *name)
|
|||
preempt_enable();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
|
||||
struct module *, unsigned long),
|
||||
void *data)
|
||||
{
|
||||
struct module *mod;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
list_for_each_entry(mod, &modules, list) {
|
||||
for (i = 0; i < mod->num_symtab; i++) {
|
||||
ret = fn(data, mod->strtab + mod->symtab[i].st_name,
|
||||
mod, mod->symtab[i].st_value);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_KALLSYMS */
|
||||
|
||||
static char *module_flags(struct module *mod, char *buf)
|
||||
|
@ -2744,29 +2753,31 @@ const struct exception_table_entry *search_module_extables(unsigned long addr)
|
|||
}
|
||||
|
||||
/*
|
||||
* Is this a valid module address?
|
||||
* is_module_address - is this address inside a module?
|
||||
* @addr: the address to check.
|
||||
*
|
||||
* See is_module_text_address() if you simply want to see if the address
|
||||
* is code (not data).
|
||||
*/
|
||||
int is_module_address(unsigned long addr)
|
||||
bool is_module_address(unsigned long addr)
|
||||
{
|
||||
struct module *mod;
|
||||
bool ret;
|
||||
|
||||
preempt_disable();
|
||||
|
||||
list_for_each_entry_rcu(mod, &modules, list) {
|
||||
if (within_module_core(addr, mod)) {
|
||||
preempt_enable();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
ret = __module_address(addr) != NULL;
|
||||
preempt_enable();
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Is this a valid kernel address? */
|
||||
__notrace_funcgraph struct module *__module_text_address(unsigned long addr)
|
||||
/*
|
||||
* __module_address - get the module which contains an address.
|
||||
* @addr: the address.
|
||||
*
|
||||
* Must be called with preempt disabled or module mutex held so that
|
||||
* module doesn't get freed during this.
|
||||
*/
|
||||
__notrace_funcgraph struct module *__module_address(unsigned long addr)
|
||||
{
|
||||
struct module *mod;
|
||||
|
||||
|
@ -2774,22 +2785,51 @@ __notrace_funcgraph struct module *__module_text_address(unsigned long addr)
|
|||
return NULL;
|
||||
|
||||
list_for_each_entry_rcu(mod, &modules, list)
|
||||
if (within(addr, mod->module_init, mod->init_text_size)
|
||||
|| within(addr, mod->module_core, mod->core_text_size))
|
||||
if (within_module_core(addr, mod)
|
||||
|| within_module_init(addr, mod))
|
||||
return mod;
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__module_address);
|
||||
|
||||
struct module *module_text_address(unsigned long addr)
|
||||
/*
|
||||
* is_module_text_address - is this address inside module code?
|
||||
* @addr: the address to check.
|
||||
*
|
||||
* See is_module_address() if you simply want to see if the address is
|
||||
* anywhere in a module. See kernel_text_address() for testing if an
|
||||
* address corresponds to kernel or module code.
|
||||
*/
|
||||
bool is_module_text_address(unsigned long addr)
|
||||
{
|
||||
struct module *mod;
|
||||
bool ret;
|
||||
|
||||
preempt_disable();
|
||||
mod = __module_text_address(addr);
|
||||
ret = __module_text_address(addr) != NULL;
|
||||
preempt_enable();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* __module_text_address - get the module whose code contains an address.
|
||||
* @addr: the address.
|
||||
*
|
||||
* Must be called with preempt disabled or module mutex held so that
|
||||
* module doesn't get freed during this.
|
||||
*/
|
||||
struct module *__module_text_address(unsigned long addr)
|
||||
{
|
||||
struct module *mod = __module_address(addr);
|
||||
if (mod) {
|
||||
/* Make sure it's within the text section. */
|
||||
if (!within(addr, mod->module_init, mod->init_text_size)
|
||||
&& !within(addr, mod->module_core, mod->core_text_size))
|
||||
mod = NULL;
|
||||
}
|
||||
return mod;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__module_text_address);
|
||||
|
||||
/* Don't grab lock, we're oopsing. */
|
||||
void print_modules(void)
|
||||
|
@ -2809,9 +2849,17 @@ void print_modules(void)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_MODVERSIONS
|
||||
/* Generate the signature for struct module here, too, for modversions. */
|
||||
void struct_module(struct module *mod) { return; }
|
||||
EXPORT_SYMBOL(struct_module);
|
||||
/* Generate the signature for all relevant module structures here.
|
||||
* If these change, we don't want to try to parse the module. */
|
||||
void module_layout(struct module *mod,
|
||||
struct modversion_info *ver,
|
||||
struct kernel_param *kp,
|
||||
struct kernel_symbol *ks,
|
||||
struct marker *marker,
|
||||
struct tracepoint *tp)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL(module_layout);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MARKERS
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/* We abuse the high bits of "perm" to record whether we kmalloc'ed. */
|
||||
#define KPARAM_KMALLOCED 0x80000000
|
||||
|
||||
#if 0
|
||||
#define DEBUGP printk
|
||||
#else
|
||||
|
@ -217,7 +220,19 @@ int param_set_charp(const char *val, struct kernel_param *kp)
|
|||
return -ENOSPC;
|
||||
}
|
||||
|
||||
*(char **)kp->arg = (char *)val;
|
||||
if (kp->perm & KPARAM_KMALLOCED)
|
||||
kfree(*(char **)kp->arg);
|
||||
|
||||
/* This is a hack. We can't need to strdup in early boot, and we
|
||||
* don't need to; this mangled commandline is preserved. */
|
||||
if (slab_is_available()) {
|
||||
kp->perm |= KPARAM_KMALLOCED;
|
||||
*(char **)kp->arg = kstrdup(val, GFP_KERNEL);
|
||||
if (!kp->arg)
|
||||
return -ENOMEM;
|
||||
} else
|
||||
*(const char **)kp->arg = val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -571,6 +586,15 @@ void module_param_sysfs_remove(struct module *mod)
|
|||
}
|
||||
#endif
|
||||
|
||||
void destroy_params(const struct kernel_param *params, unsigned num)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
if (params[i].perm & KPARAM_KMALLOCED)
|
||||
kfree(*(char **)params[i].arg);
|
||||
}
|
||||
|
||||
static void __init kernel_add_sysfs_param(const char *name,
|
||||
struct kernel_param *kparam,
|
||||
unsigned int name_skip)
|
||||
|
|
|
@ -1607,12 +1607,12 @@ static void read_symbols(char *modname)
|
|||
|
||||
parse_elf_finish(&info);
|
||||
|
||||
/* Our trick to get versioning for struct_module - it's
|
||||
/* Our trick to get versioning for module struct etc. - it's
|
||||
* never passed as an argument to an exported function, so
|
||||
* the automatic versioning doesn't pick it up, but it's really
|
||||
* important anyhow */
|
||||
if (modversions)
|
||||
mod->unres = alloc_symbol("struct_module", 0, mod->unres);
|
||||
mod->unres = alloc_symbol("module_layout", 0, mod->unres);
|
||||
}
|
||||
|
||||
#define SZ 500
|
||||
|
|
Loading…
Reference in a new issue