Commit ddaefe89 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'modules-for-v5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux

Pull module updates from Jessica Yu:
 "Summary of modules changes for the 5.6 merge window:

   - Add "MS" (SHF_MERGE|SHF_STRINGS) section flags to __ksymtab_strings
     to indicate to the linker that it can perform string deduplication
     (i.e., duplicate strings are reduced to a single copy in the string
     table). This means any repeated namespace string would be merged to
     just one entry in __ksymtab_strings.

   - Various code cleanups and small fixes (fix small memleak in error
     path, improve moduleparam docs, silence rcu warnings, improve error
     logging)"

* tag 'modules-for-v5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux:
  module.h: Annotate mod_kallsyms with __rcu
  module: avoid setting info->name early in case we can fall back to info->mod->name
  modsign: print module name along with error message
  kernel/module: Fix memleak in module_add_modinfo_attrs()
  export.h: reduce __ksymtab_strings string duplication by using "MS" section flags
  moduleparam: fix kerneldoc
  modules: lockdep: Suppress suspicious RCU usage warning
parents c5951e7c 6080d608
...@@ -27,9 +27,11 @@ ...@@ -27,9 +27,11 @@
.endm .endm
/* /*
* note on .section use: @progbits vs %progbits nastiness doesn't matter, * note on .section use: we specify progbits since usage of the "M" (SHF_MERGE)
* since we immediately emit into those sections anyway. * section flag requires it. Use '%progbits' instead of '@progbits' since the
* former apparently works on all arches according to the binutils source.
*/ */
.macro ___EXPORT_SYMBOL name,val,sec .macro ___EXPORT_SYMBOL name,val,sec
#ifdef CONFIG_MODULES #ifdef CONFIG_MODULES
.section ___ksymtab\sec+\name,"a" .section ___ksymtab\sec+\name,"a"
...@@ -37,7 +39,7 @@ ...@@ -37,7 +39,7 @@
__ksymtab_\name: __ksymtab_\name:
__put \val, __kstrtab_\name __put \val, __kstrtab_\name
.previous .previous
.section __ksymtab_strings,"a" .section __ksymtab_strings,"aMS",%progbits,1
__kstrtab_\name: __kstrtab_\name:
.asciz "\name" .asciz "\name"
.previous .previous
......
...@@ -82,16 +82,29 @@ struct kernel_symbol { ...@@ -82,16 +82,29 @@ struct kernel_symbol {
#else #else
/* For every exported symbol, place a struct in the __ksymtab section */ /*
* For every exported symbol, do the following:
*
* - If applicable, place a CRC entry in the __kcrctab section.
* - Put the name of the symbol and namespace (empty string "" for none) in
* __ksymtab_strings.
* - Place a struct kernel_symbol entry in the __ksymtab section.
*
* note on .section use: we specify progbits since usage of the "M" (SHF_MERGE)
* section flag requires it. Use '%progbits' instead of '@progbits' since the
* former apparently works on all arches according to the binutils source.
*/
#define ___EXPORT_SYMBOL(sym, sec, ns) \ #define ___EXPORT_SYMBOL(sym, sec, ns) \
extern typeof(sym) sym; \ extern typeof(sym) sym; \
extern const char __kstrtab_##sym[]; \
extern const char __kstrtabns_##sym[]; \
__CRC_SYMBOL(sym, sec); \ __CRC_SYMBOL(sym, sec); \
static const char __kstrtab_##sym[] \ asm(" .section \"__ksymtab_strings\",\"aMS\",%progbits,1 \n" \
__attribute__((section("__ksymtab_strings"), used, aligned(1))) \ "__kstrtab_" #sym ": \n" \
= #sym; \ " .asciz \"" #sym "\" \n" \
static const char __kstrtabns_##sym[] \ "__kstrtabns_" #sym ": \n" \
__attribute__((section("__ksymtab_strings"), used, aligned(1))) \ " .asciz \"" ns "\" \n" \
= ns; \ " .previous \n"); \
__KSYMTAB_ENTRY(sym, sec) __KSYMTAB_ENTRY(sym, sec)
#endif #endif
......
...@@ -429,7 +429,7 @@ struct module { ...@@ -429,7 +429,7 @@ struct module {
#ifdef CONFIG_KALLSYMS #ifdef CONFIG_KALLSYMS
/* Protected by RCU and/or module_mutex: use rcu_dereference() */ /* Protected by RCU and/or module_mutex: use rcu_dereference() */
struct mod_kallsyms *kallsyms; struct mod_kallsyms __rcu *kallsyms;
struct mod_kallsyms core_kallsyms; struct mod_kallsyms core_kallsyms;
/* Section attributes */ /* Section attributes */
......
...@@ -128,6 +128,9 @@ struct kparam_array ...@@ -128,6 +128,9 @@ struct kparam_array
/** /**
* module_param_unsafe - same as module_param but taints kernel * module_param_unsafe - same as module_param but taints kernel
* @name: the variable to alter, and exposed parameter name.
* @type: the type of the parameter
* @perm: visibility in sysfs.
*/ */
#define module_param_unsafe(name, type, perm) \ #define module_param_unsafe(name, type, perm) \
module_param_named_unsafe(name, name, type, perm) module_param_named_unsafe(name, name, type, perm)
...@@ -150,6 +153,10 @@ struct kparam_array ...@@ -150,6 +153,10 @@ struct kparam_array
/** /**
* module_param_named_unsafe - same as module_param_named but taints kernel * module_param_named_unsafe - same as module_param_named but taints kernel
* @name: a valid C identifier which is the parameter name.
* @value: the actual lvalue to alter.
* @type: the type of the parameter
* @perm: visibility in sysfs.
*/ */
#define module_param_named_unsafe(name, value, type, perm) \ #define module_param_named_unsafe(name, value, type, perm) \
param_check_##type(name, &(value)); \ param_check_##type(name, &(value)); \
...@@ -160,6 +167,7 @@ struct kparam_array ...@@ -160,6 +167,7 @@ struct kparam_array
* module_param_cb - general callback for a module/cmdline parameter * module_param_cb - general callback for a module/cmdline parameter
* @name: a valid C identifier which is the parameter name. * @name: a valid C identifier which is the parameter name.
* @ops: the set & get operations for this parameter. * @ops: the set & get operations for this parameter.
* @arg: args for @ops
* @perm: visibility in sysfs. * @perm: visibility in sysfs.
* *
* The ops can have NULL set or get functions. * The ops can have NULL set or get functions.
...@@ -171,36 +179,96 @@ struct kparam_array ...@@ -171,36 +179,96 @@ struct kparam_array
__module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, -1, \ __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, -1, \
KERNEL_PARAM_FL_UNSAFE) KERNEL_PARAM_FL_UNSAFE)
#define __level_param_cb(name, ops, arg, perm, level) \
__module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, level, 0)
/** /**
* <level>_param_cb - general callback for a module/cmdline parameter * core_param_cb - general callback for a module/cmdline parameter
* to be evaluated before certain initcall level * to be evaluated before core initcall level
* @name: a valid C identifier which is the parameter name. * @name: a valid C identifier which is the parameter name.
* @ops: the set & get operations for this parameter. * @ops: the set & get operations for this parameter.
* @arg: args for @ops
* @perm: visibility in sysfs. * @perm: visibility in sysfs.
* *
* The ops can have NULL set or get functions. * The ops can have NULL set or get functions.
*/ */
#define __level_param_cb(name, ops, arg, perm, level) \
__module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, level, 0)
#define core_param_cb(name, ops, arg, perm) \ #define core_param_cb(name, ops, arg, perm) \
__level_param_cb(name, ops, arg, perm, 1) __level_param_cb(name, ops, arg, perm, 1)
/**
* postcore_param_cb - general callback for a module/cmdline parameter
* to be evaluated before postcore initcall level
* @name: a valid C identifier which is the parameter name.
* @ops: the set & get operations for this parameter.
* @arg: args for @ops
* @perm: visibility in sysfs.
*
* The ops can have NULL set or get functions.
*/
#define postcore_param_cb(name, ops, arg, perm) \ #define postcore_param_cb(name, ops, arg, perm) \
__level_param_cb(name, ops, arg, perm, 2) __level_param_cb(name, ops, arg, perm, 2)
/**
* arch_param_cb - general callback for a module/cmdline parameter
* to be evaluated before arch initcall level
* @name: a valid C identifier which is the parameter name.
* @ops: the set & get operations for this parameter.
* @arg: args for @ops
* @perm: visibility in sysfs.
*
* The ops can have NULL set or get functions.
*/
#define arch_param_cb(name, ops, arg, perm) \ #define arch_param_cb(name, ops, arg, perm) \
__level_param_cb(name, ops, arg, perm, 3) __level_param_cb(name, ops, arg, perm, 3)
/**
* subsys_param_cb - general callback for a module/cmdline parameter
* to be evaluated before subsys initcall level
* @name: a valid C identifier which is the parameter name.
* @ops: the set & get operations for this parameter.
* @arg: args for @ops
* @perm: visibility in sysfs.
*
* The ops can have NULL set or get functions.
*/
#define subsys_param_cb(name, ops, arg, perm) \ #define subsys_param_cb(name, ops, arg, perm) \
__level_param_cb(name, ops, arg, perm, 4) __level_param_cb(name, ops, arg, perm, 4)
/**
* fs_param_cb - general callback for a module/cmdline parameter
* to be evaluated before fs initcall level
* @name: a valid C identifier which is the parameter name.
* @ops: the set & get operations for this parameter.
* @arg: args for @ops
* @perm: visibility in sysfs.
*
* The ops can have NULL set or get functions.
*/
#define fs_param_cb(name, ops, arg, perm) \ #define fs_param_cb(name, ops, arg, perm) \
__level_param_cb(name, ops, arg, perm, 5) __level_param_cb(name, ops, arg, perm, 5)
/**
* device_param_cb - general callback for a module/cmdline parameter
* to be evaluated before device initcall level
* @name: a valid C identifier which is the parameter name.
* @ops: the set & get operations for this parameter.
* @arg: args for @ops
* @perm: visibility in sysfs.
*
* The ops can have NULL set or get functions.
*/
#define device_param_cb(name, ops, arg, perm) \ #define device_param_cb(name, ops, arg, perm) \
__level_param_cb(name, ops, arg, perm, 6) __level_param_cb(name, ops, arg, perm, 6)
/**
* late_param_cb - general callback for a module/cmdline parameter
* to be evaluated before late initcall level
* @name: a valid C identifier which is the parameter name.
* @ops: the set & get operations for this parameter.
* @arg: args for @ops
* @perm: visibility in sysfs.
*
* The ops can have NULL set or get functions.
*/
#define late_param_cb(name, ops, arg, perm) \ #define late_param_cb(name, ops, arg, perm) \
__level_param_cb(name, ops, arg, perm, 7) __level_param_cb(name, ops, arg, perm, 7)
...@@ -263,6 +331,10 @@ static inline void kernel_param_unlock(struct module *mod) ...@@ -263,6 +331,10 @@ static inline void kernel_param_unlock(struct module *mod)
/** /**
* core_param_unsafe - same as core_param but taints kernel * core_param_unsafe - same as core_param but taints kernel
* @name: the name of the cmdline and sysfs parameter (often the same as var)
* @var: the variable
* @type: the type of the parameter
* @perm: visibility in sysfs
*/ */
#define core_param_unsafe(name, var, type, perm) \ #define core_param_unsafe(name, var, type, perm) \
param_check_##type(name, &(var)); \ param_check_##type(name, &(var)); \
......
...@@ -214,7 +214,8 @@ static struct module *mod_find(unsigned long addr) ...@@ -214,7 +214,8 @@ static struct module *mod_find(unsigned long addr)
{ {
struct module *mod; struct module *mod;
list_for_each_entry_rcu(mod, &modules, list) { list_for_each_entry_rcu(mod, &modules, list,
lockdep_is_held(&module_mutex)) {
if (within_module(addr, mod)) if (within_module(addr, mod))
return mod; return mod;
} }
...@@ -448,7 +449,8 @@ bool each_symbol_section(bool (*fn)(const struct symsearch *arr, ...@@ -448,7 +449,8 @@ bool each_symbol_section(bool (*fn)(const struct symsearch *arr,
if (each_symbol_in_section(arr, ARRAY_SIZE(arr), NULL, fn, data)) if (each_symbol_in_section(arr, ARRAY_SIZE(arr), NULL, fn, data))
return true; return true;
list_for_each_entry_rcu(mod, &modules, list) { list_for_each_entry_rcu(mod, &modules, list,
lockdep_is_held(&module_mutex)) {
struct symsearch arr[] = { struct symsearch arr[] = {
{ mod->syms, mod->syms + mod->num_syms, mod->crcs, { mod->syms, mod->syms + mod->num_syms, mod->crcs,
NOT_GPL_ONLY, false }, NOT_GPL_ONLY, false },
...@@ -616,7 +618,8 @@ static struct module *find_module_all(const char *name, size_t len, ...@@ -616,7 +618,8 @@ static struct module *find_module_all(const char *name, size_t len,
module_assert_mutex_or_preempt(); module_assert_mutex_or_preempt();
list_for_each_entry_rcu(mod, &modules, list) { list_for_each_entry_rcu(mod, &modules, list,
lockdep_is_held(&module_mutex)) {
if (!even_unformed && mod->state == MODULE_STATE_UNFORMED) if (!even_unformed && mod->state == MODULE_STATE_UNFORMED)
continue; continue;
if (strlen(mod->name) == len && !memcmp(mod->name, name, len)) if (strlen(mod->name) == len && !memcmp(mod->name, name, len))
...@@ -1781,6 +1784,8 @@ static int module_add_modinfo_attrs(struct module *mod) ...@@ -1781,6 +1784,8 @@ static int module_add_modinfo_attrs(struct module *mod)
error_out: error_out:
if (i > 0) if (i > 0)
module_remove_modinfo_attrs(mod, --i); module_remove_modinfo_attrs(mod, --i);
else
kfree(mod->modinfo_attrs);
return error; return error;
} }
...@@ -2834,7 +2839,7 @@ static int module_sig_check(struct load_info *info, int flags) ...@@ -2834,7 +2839,7 @@ static int module_sig_check(struct load_info *info, int flags)
reason = "Loading of module with unavailable key"; reason = "Loading of module with unavailable key";
decide: decide:
if (is_module_sig_enforced()) { if (is_module_sig_enforced()) {
pr_notice("%s is rejected\n", reason); pr_notice("%s: %s is rejected\n", info->name, reason);
return -EKEYREJECTED; return -EKEYREJECTED;
} }
...@@ -3011,9 +3016,7 @@ static int setup_load_info(struct load_info *info, int flags) ...@@ -3011,9 +3016,7 @@ static int setup_load_info(struct load_info *info, int flags)
/* Try to find a name early so we can log errors with a module name */ /* Try to find a name early so we can log errors with a module name */
info->index.info = find_sec(info, ".modinfo"); info->index.info = find_sec(info, ".modinfo");
if (!info->index.info) if (info->index.info)
info->name = "(missing .modinfo section)";
else
info->name = get_modinfo(info, "name"); info->name = get_modinfo(info, "name");
/* Find internal symbols and strings. */ /* Find internal symbols and strings. */
...@@ -3028,14 +3031,15 @@ static int setup_load_info(struct load_info *info, int flags) ...@@ -3028,14 +3031,15 @@ static int setup_load_info(struct load_info *info, int flags)
} }
if (info->index.sym == 0) { if (info->index.sym == 0) {
pr_warn("%s: module has no symbols (stripped?)\n", info->name); pr_warn("%s: module has no symbols (stripped?)\n",
info->name ?: "(missing .modinfo section or name field)");
return -ENOEXEC; return -ENOEXEC;
} }
info->index.mod = find_sec(info, ".gnu.linkonce.this_module"); info->index.mod = find_sec(info, ".gnu.linkonce.this_module");
if (!info->index.mod) { if (!info->index.mod) {
pr_warn("%s: No module found in object\n", pr_warn("%s: No module found in object\n",
info->name ?: "(missing .modinfo name field)"); info->name ?: "(missing .modinfo section or name field)");
return -ENOEXEC; return -ENOEXEC;
} }
/* This is temporary: point mod into copy of data. */ /* This is temporary: point mod into copy of data. */
......
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