Skip to content

Commit

Permalink
Merge tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/li…
Browse files Browse the repository at this point in the history
…nux/kernel/git/rusty/linux

Pull module updates from Rusty Russell:
 "Nothing interesting.  Except the most embarrassing bugfix ever.  But
  let's ignore that"

* tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux:
  module: cleanup call chain.
  module: do percpu allocation after uniqueness check.  No, really!
  modules: don't fail to load on unknown parameters.
  ABI: Clarify when /sys/module/MODULENAME is created
  There is no /sys/parameters
  module: don't modify argument of module_kallsyms_lookup_name()
  • Loading branch information
Linus Torvalds committed Jul 10, 2013
2 parents 5f12972 + 9eb76d7 commit 8133633
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 39 deletions.
10 changes: 7 additions & 3 deletions Documentation/ABI/stable/sysfs-module
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ Description:

/sys/module/MODULENAME
The name of the module that is in the kernel. This
module name will show up either if the module is built
directly into the kernel, or if it is loaded as a
dynamic module.
module name will always show up if the module is loaded as a
dynamic module. If it is built directly into the kernel, it
will only show up if it has a version or at least one
parameter.

Note: The conditions of creation in the built-in case are not
by design and may be removed in the future.

/sys/module/MODULENAME/parameters
This directory contains individual files that are each
Expand Down
2 changes: 1 addition & 1 deletion include/linux/moduleparam.h
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ extern struct kernel_param_ops param_ops_string;
extern int param_set_copystring(const char *val, const struct kernel_param *);
extern int param_get_string(char *buffer, const struct kernel_param *kp);

/* for exporting parameters in /sys/parameters */
/* for exporting parameters in /sys/module/.../parameters */

struct module;

Expand Down
77 changes: 43 additions & 34 deletions kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,23 +455,23 @@ const struct kernel_symbol *find_symbol(const char *name,
EXPORT_SYMBOL_GPL(find_symbol);

/* Search for module by name: must hold module_mutex. */
static struct module *find_module_all(const char *name,
static struct module *find_module_all(const char *name, size_t len,
bool even_unformed)
{
struct module *mod;

list_for_each_entry(mod, &modules, list) {
if (!even_unformed && mod->state == MODULE_STATE_UNFORMED)
continue;
if (strcmp(mod->name, name) == 0)
if (strlen(mod->name) == len && !memcmp(mod->name, name, len))
return mod;
}
return NULL;
}

struct module *find_module(const char *name)
{
return find_module_all(name, false);
return find_module_all(name, strlen(name), false);
}
EXPORT_SYMBOL_GPL(find_module);

Expand All @@ -482,23 +482,28 @@ static inline void __percpu *mod_percpu(struct module *mod)
return mod->percpu;
}

static int percpu_modalloc(struct module *mod,
unsigned long size, unsigned long align)
static int percpu_modalloc(struct module *mod, struct load_info *info)
{
Elf_Shdr *pcpusec = &info->sechdrs[info->index.pcpu];
unsigned long align = pcpusec->sh_addralign;

if (!pcpusec->sh_size)
return 0;

if (align > PAGE_SIZE) {
printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n",
mod->name, align, PAGE_SIZE);
align = PAGE_SIZE;
}

mod->percpu = __alloc_reserved_percpu(size, align);
mod->percpu = __alloc_reserved_percpu(pcpusec->sh_size, align);
if (!mod->percpu) {
printk(KERN_WARNING
"%s: Could not allocate %lu bytes percpu data\n",
mod->name, size);
mod->name, (unsigned long)pcpusec->sh_size);
return -ENOMEM;
}
mod->percpu_size = size;
mod->percpu_size = pcpusec->sh_size;
return 0;
}

Expand Down Expand Up @@ -563,10 +568,12 @@ static inline void __percpu *mod_percpu(struct module *mod)
{
return NULL;
}
static inline int percpu_modalloc(struct module *mod,
unsigned long size, unsigned long align)
static int percpu_modalloc(struct module *mod, struct load_info *info)
{
return -ENOMEM;
/* UP modules shouldn't have this section: ENOMEM isn't quite right */
if (info->sechdrs[info->index.pcpu].sh_size != 0)
return -ENOMEM;
return 0;
}
static inline void percpu_modfree(struct module *mod)
{
Expand Down Expand Up @@ -2927,7 +2934,6 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
{
/* Module within temporary copy. */
struct module *mod;
Elf_Shdr *pcpusec;
int err;

mod = setup_load_info(info, flags);
Expand All @@ -2942,17 +2948,10 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
err = module_frob_arch_sections(info->hdr, info->sechdrs,
info->secstrings, mod);
if (err < 0)
goto out;
return ERR_PTR(err);

pcpusec = &info->sechdrs[info->index.pcpu];
if (pcpusec->sh_size) {
/* We have a special allocation for this section. */
err = percpu_modalloc(mod,
pcpusec->sh_size, pcpusec->sh_addralign);
if (err)
goto out;
pcpusec->sh_flags &= ~(unsigned long)SHF_ALLOC;
}
/* We will do a special allocation for per-cpu sections later. */
info->sechdrs[info->index.pcpu].sh_flags &= ~(unsigned long)SHF_ALLOC;

/* Determine total sizes, and put offsets in sh_entsize. For now
this is done generically; there doesn't appear to be any
Expand All @@ -2963,17 +2962,12 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
/* Allocate and move to the final place */
err = move_module(mod, info);
if (err)
goto free_percpu;
return ERR_PTR(err);

/* Module has been copied to its final place now: return it. */
mod = (void *)info->sechdrs[info->index.mod].sh_addr;
kmemleak_load_module(mod, info);
return mod;

free_percpu:
percpu_modfree(mod);
out:
return ERR_PTR(err);
}

/* mod is no longer valid after this! */
Expand Down Expand Up @@ -3014,7 +3008,7 @@ static bool finished_loading(const char *name)
bool ret;

mutex_lock(&module_mutex);
mod = find_module_all(name, true);
mod = find_module_all(name, strlen(name), true);
ret = !mod || mod->state == MODULE_STATE_LIVE
|| mod->state == MODULE_STATE_GOING;
mutex_unlock(&module_mutex);
Expand Down Expand Up @@ -3152,7 +3146,8 @@ static int add_unformed_module(struct module *mod)

again:
mutex_lock(&module_mutex);
if ((old = find_module_all(mod->name, true)) != NULL) {
old = find_module_all(mod->name, strlen(mod->name), true);
if (old != NULL) {
if (old->state == MODULE_STATE_COMING
|| old->state == MODULE_STATE_UNFORMED) {
/* Wait in case it fails to load. */
Expand Down Expand Up @@ -3198,6 +3193,17 @@ static int complete_formation(struct module *mod, struct load_info *info)
return err;
}

static int unknown_module_param_cb(char *param, char *val, const char *modname)
{
/* Check for magic 'dyndbg' arg */
int ret = ddebug_dyndbg_module_param_cb(param, val, modname);
if (ret != 0) {
printk(KERN_WARNING "%s: unknown parameter '%s' ignored\n",
modname, param);
}
return 0;
}

/* Allocate and load the module: note that size of section 0 is always
zero, and we rely on this for optional sections. */
static int load_module(struct load_info *info, const char __user *uargs,
Expand Down Expand Up @@ -3237,6 +3243,11 @@ static int load_module(struct load_info *info, const char __user *uargs,
}
#endif

/* To avoid stressing percpu allocator, do this once we're unique. */
err = percpu_modalloc(mod, info);
if (err)
goto unlink_mod;

/* Now module is in final location, initialize linked lists, etc. */
err = module_unload_init(mod);
if (err)
Expand Down Expand Up @@ -3284,7 +3295,7 @@ static int load_module(struct load_info *info, const char __user *uargs,

/* Module is ready to execute: parsing args may do that. */
err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,
-32768, 32767, &ddebug_dyndbg_module_param_cb);
-32768, 32767, unknown_module_param_cb);
if (err < 0)
goto bug_cleanup;

Expand Down Expand Up @@ -3563,10 +3574,8 @@ unsigned long module_kallsyms_lookup_name(const char *name)
/* Don't lock: we're in enough trouble already. */
preempt_disable();
if ((colon = strchr(name, ':')) != NULL) {
*colon = '\0';
if ((mod = find_module(name)) != NULL)
if ((mod = find_module_all(name, colon - name, false)) != NULL)
ret = mod_find_symname(mod, colon+1);
*colon = ':';
} else {
list_for_each_entry_rcu(mod, &modules, list) {
if (mod->state == MODULE_STATE_UNFORMED)
Expand Down
2 changes: 1 addition & 1 deletion kernel/params.c
Original file line number Diff line number Diff line change
Expand Up @@ -787,7 +787,7 @@ static void __init kernel_add_sysfs_param(const char *name,
}

/*
* param_sysfs_builtin - add contents in /sys/parameters for built-in modules
* param_sysfs_builtin - add sysfs parameters for built-in modules
*
* Add module_parameters to sysfs for "modules" built into the kernel.
*
Expand Down

0 comments on commit 8133633

Please sign in to comment.