Commit cab4e4c4 authored by Linus Torvalds's avatar Linus Torvalds

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.
parents 5412b539 49502677
...@@ -18,7 +18,10 @@ ...@@ -18,7 +18,10 @@
unsigned int __machine_arch_type; 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 #ifdef STANDALONE_DEBUG
#define putstr printf #define putstr printf
......
...@@ -2720,14 +2720,14 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -2720,14 +2720,14 @@ int nand_scan_tail(struct mtd_info *mtd)
return chip->scan_bbt(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 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. */ to call us from in-kernel code if the core NAND support is modular. */
#ifdef MODULE #ifdef MODULE
#define caller_is_module() (1) #define caller_is_module() (1)
#else #else
#define caller_is_module() \ #define caller_is_module() \
module_text_address((unsigned long)__builtin_return_address(0)) is_module_text_address((unsigned long)__builtin_return_address(0))
#endif #endif
/** /**
......
...@@ -13,10 +13,17 @@ ...@@ -13,10 +13,17 @@
#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \ #define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \
2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1) 2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1)
struct module;
#ifdef CONFIG_KALLSYMS #ifdef CONFIG_KALLSYMS
/* Lookup the address for a symbol. Returns 0 if not found. */ /* Lookup the address for a symbol. Returns 0 if not found. */
unsigned long kallsyms_lookup_name(const char *name); 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, extern int kallsyms_lookup_size_offset(unsigned long addr,
unsigned long *symbolsize, unsigned long *symbolsize,
unsigned long *offset); unsigned long *offset);
...@@ -43,6 +50,14 @@ static inline unsigned long kallsyms_lookup_name(const char *name) ...@@ -43,6 +50,14 @@ static inline unsigned long kallsyms_lookup_name(const char *name)
return 0; 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, static inline int kallsyms_lookup_size_offset(unsigned long addr,
unsigned long *symbolsize, unsigned long *symbolsize,
unsigned long *offset) unsigned long *offset)
......
...@@ -29,10 +29,15 @@ ...@@ -29,10 +29,15 @@
#ifdef CONFIG_MODULES #ifdef CONFIG_MODULES
/* modprobe exit status on success, -ve on error. Return value /* modprobe exit status on success, -ve on error. Return value
* usually useless though. */ * usually useless though. */
extern int request_module(const char * name, ...) __attribute__ ((format (printf, 1, 2))); extern int __request_module(bool wait, const char *name, ...) \
#define try_then_request_module(x, mod...) ((x) ?: (request_module(mod), (x))) __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 #else
static inline int request_module(const char * name, ...) { return -ENOSYS; } 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) #define try_then_request_module(x, mod...) (x)
#endif #endif
......
...@@ -248,6 +248,10 @@ struct module ...@@ -248,6 +248,10 @@ struct module
const unsigned long *crcs; const unsigned long *crcs;
unsigned int num_syms; unsigned int num_syms;
/* Kernel parameters. */
struct kernel_param *kp;
unsigned int num_kp;
/* GPL-only exported symbols. */ /* GPL-only exported symbols. */
unsigned int num_gpl_syms; unsigned int num_gpl_syms;
const struct kernel_symbol *gpl_syms; const struct kernel_symbol *gpl_syms;
...@@ -350,6 +354,8 @@ struct module ...@@ -350,6 +354,8 @@ struct module
#define MODULE_ARCH_INIT {} #define MODULE_ARCH_INIT {}
#endif #endif
extern struct mutex module_mutex;
/* FIXME: It'd be nice to isolate modules during init, too, so they /* 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 aren't used before they (may) fail. But presently too much code
(IDE & SCSI) require entry into the module during init.*/ (IDE & SCSI) require entry into the module during init.*/
...@@ -358,10 +364,10 @@ static inline int module_is_live(struct module *mod) ...@@ -358,10 +364,10 @@ 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? (second is with no locks, for oops) */
struct module *module_text_address(unsigned long addr);
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) 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) ...@@ -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; 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 /* Returns 0 and fills in value, defined and namebuf, or -ERANGE if
symnum out of range. */ symnum out of range. */
int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, 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, ...@@ -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. */ /* Look for this name: can be of form module:name. */
unsigned long module_kallsyms_lookup_name(const char *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) extern void __module_put_and_exit(struct module *mod, long code)
__attribute__((noreturn)); __attribute__((noreturn));
#define module_put_and_exit(code) __module_put_and_exit(THIS_MODULE, code); #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) ...@@ -444,6 +479,7 @@ static inline void __module_get(struct module *module)
#define symbol_put_addr(p) do { } while(0) #define symbol_put_addr(p) do { } while(0)
#endif /* CONFIG_MODULE_UNLOAD */ #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 */ /* This is a #define so the string doesn't get put in every .o file */
#define module_name(mod) \ #define module_name(mod) \
...@@ -490,21 +526,24 @@ search_module_extables(unsigned long addr) ...@@ -490,21 +526,24 @@ search_module_extables(unsigned long addr)
return NULL; return NULL;
} }
/* Is this address in a module? */ static inline struct module *__module_address(unsigned long addr)
static inline struct module *module_text_address(unsigned long addr)
{ {
return NULL; 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) static inline struct module *__module_text_address(unsigned long addr)
{ {
return NULL; 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) */ /* Get/put a kernel symbol (calls should be symmetric) */
...@@ -559,6 +598,14 @@ static inline unsigned long module_kallsyms_lookup_name(const char *name) ...@@ -559,6 +598,14 @@ static inline unsigned long module_kallsyms_lookup_name(const char *name)
return 0; 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) static inline int register_module_notifier(struct notifier_block * nb)
{ {
/* no events will happen anyway, so this can always succeed */ /* no events will happen anyway, so this can always succeed */
......
...@@ -138,6 +138,16 @@ extern int parse_args(const char *name, ...@@ -138,6 +138,16 @@ extern int parse_args(const char *name,
unsigned num, unsigned num,
int (*unknown)(char *param, char *val)); 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 */ /* All the helper functions */
/* The macros to do compile-time type checking stolen from Jakub /* 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. */ 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); ...@@ -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, extern ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos,
const void *from, size_t available); 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
#endif /* _LINUX_STRING_H_ */ #endif /* _LINUX_STRING_H_ */
...@@ -65,7 +65,7 @@ __notrace_funcgraph int __kernel_text_address(unsigned long addr) ...@@ -65,7 +65,7 @@ __notrace_funcgraph int __kernel_text_address(unsigned long addr)
{ {
if (core_kernel_text(addr)) if (core_kernel_text(addr))
return 1; return 1;
if (__module_text_address(addr)) if (is_module_text_address(addr))
return 1; return 1;
/* /*
* There might be init symbols in saved stacktraces. * There might be init symbols in saved stacktraces.
...@@ -84,7 +84,7 @@ int kernel_text_address(unsigned long addr) ...@@ -84,7 +84,7 @@ int kernel_text_address(unsigned long addr)
{ {
if (core_kernel_text(addr)) if (core_kernel_text(addr))
return 1; 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) ...@@ -100,5 +100,5 @@ int func_ptr_is_kernel_text(void *ptr)
addr = (unsigned long) dereference_function_descriptor(ptr); addr = (unsigned long) dereference_function_descriptor(ptr);
if (core_kernel_text(addr)) if (core_kernel_text(addr))
return 1; 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) ...@@ -161,6 +161,25 @@ unsigned long kallsyms_lookup_name(const char *name)
return module_kallsyms_lookup_name(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, static unsigned long get_symbol_pos(unsigned long addr,
unsigned long *symbolsize, unsigned long *symbolsize,
unsigned long *offset) unsigned long *offset)
......
...@@ -50,7 +50,8 @@ static struct workqueue_struct *khelper_wq; ...@@ -50,7 +50,8 @@ static struct workqueue_struct *khelper_wq;
char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe"; 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 * @fmt: printf style format string for the name of the module
* @...: arguments as specified in the format string * @...: arguments as specified in the format string
* *
...@@ -63,7 +64,7 @@ char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe"; ...@@ -63,7 +64,7 @@ char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe";
* If module auto-loading support is disabled then this function * If module auto-loading support is disabled then this function
* becomes a no-operation. * becomes a no-operation.
*/ */
int request_module(const char *fmt, ...) int __request_module(bool wait, const char *fmt, ...)
{ {
va_list args; va_list args;
char module_name[MODULE_NAME_LEN]; char module_name[MODULE_NAME_LEN];
...@@ -108,11 +109,12 @@ int request_module(const char *fmt, ...) ...@@ -108,11 +109,12 @@ int request_module(const char *fmt, ...)
return -ENOMEM; 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); atomic_dec(&kmod_concurrent);
return ret; return ret;
} }
EXPORT_SYMBOL(request_module); EXPORT_SYMBOL(__request_module);
#endif /* CONFIG_MODULES */ #endif /* CONFIG_MODULES */
struct subprocess_info { struct subprocess_info {
......
This diff is collapsed.
...@@ -24,6 +24,9 @@ ...@@ -24,6 +24,9 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/slab.h> #include <linux/slab.h>
/* We abuse the high bits of "perm" to record whether we kmalloc'ed. */
#define KPARAM_KMALLOCED 0x80000000
#if 0 #if 0
#define DEBUGP printk #define DEBUGP printk
#else #else
...@@ -217,7 +220,19 @@ int param_set_charp(const char *val, struct kernel_param *kp) ...@@ -217,7 +220,19 @@ int param_set_charp(const char *val, struct kernel_param *kp)
return -ENOSPC; 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; return 0;
} }
...@@ -571,6 +586,15 @@ void module_param_sysfs_remove(struct module *mod) ...@@ -571,6 +586,15 @@ void module_param_sysfs_remove(struct module *mod)
} }
#endif #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, static void __init kernel_add_sysfs_param(const char *name,
struct kernel_param *kparam, struct kernel_param *kparam,
unsigned int name_skip) unsigned int name_skip)
......
...@@ -1607,12 +1607,12 @@ static void read_symbols(char *modname) ...@@ -1607,12 +1607,12 @@ static void read_symbols(char *modname)
parse_elf_finish(&info); 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 * never passed as an argument to an exported function, so
* the automatic versioning doesn't pick it up, but it's really * the automatic versioning doesn't pick it up, but it's really
* important anyhow */ * important anyhow */
if (modversions) if (modversions)
mod->unres = alloc_symbol("struct_module", 0, mod->unres); mod->unres = alloc_symbol("module_layout", 0, mod->unres);
} }
#define SZ 500 #define SZ 500
......
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