Commit 3398d252 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux

Pull module updates from Rusty Russell:
 "Minor fixes mainly, including a potential use-after-free on remove
  found by CONFIG_DEBUG_KOBJECT_RELEASE which may be theoretical"

* tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux:
  module: Fix mod->mkobj.kobj potentially freed too early
  kernel/params.c: use scnprintf() instead of sprintf()
  kernel/module.c: use scnprintf() instead of sprintf()
  module/lsm: Have apparmor module parameters work with no args
  module: Add NOARG flag for ops with param_set_bool_enable_only() set function
  module: Add flag to allow mod params to have no arguments
  modules: add support for soft module dependencies
  scripts/mod/modpost.c: permit '.cranges' secton for sh64 architecture.
  module: fix sprintf format specifier in param_get_byte()
parents 27703bb4 942e4431
...@@ -42,6 +42,7 @@ struct module_kobject { ...@@ -42,6 +42,7 @@ struct module_kobject {
struct module *mod; struct module *mod;
struct kobject *drivers_dir; struct kobject *drivers_dir;
struct module_param_attrs *mp; struct module_param_attrs *mp;
struct completion *kobj_completion;
}; };
struct module_attribute { struct module_attribute {
...@@ -97,6 +98,11 @@ extern const struct gtype##_id __mod_##gtype##_table \ ...@@ -97,6 +98,11 @@ extern const struct gtype##_id __mod_##gtype##_table \
/* For userspace: you can also call me... */ /* For userspace: you can also call me... */
#define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias) #define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias)
/* Soft module dependencies. See man modprobe.d for details.
* Example: MODULE_SOFTDEP("pre: module-foo module-bar post: module-baz")
*/
#define MODULE_SOFTDEP(_softdep) MODULE_INFO(softdep, _softdep)
/* /*
* The following license idents are currently accepted as indicating free * The following license idents are currently accepted as indicating free
* software modules * software modules
......
...@@ -36,7 +36,18 @@ static const char __UNIQUE_ID(name)[] \ ...@@ -36,7 +36,18 @@ static const char __UNIQUE_ID(name)[] \
struct kernel_param; struct kernel_param;
/*
* Flags available for kernel_param_ops
*
* NOARG - the parameter allows for no argument (foo instead of foo=1)
*/
enum {
KERNEL_PARAM_FL_NOARG = (1 << 0)
};
struct kernel_param_ops { struct kernel_param_ops {
/* How the ops should behave */
unsigned int flags;
/* Returns 0, or -errno. arg is in kp->arg. */ /* Returns 0, or -errno. arg is in kp->arg. */
int (*set)(const char *val, const struct kernel_param *kp); int (*set)(const char *val, const struct kernel_param *kp);
/* Returns length written or -errno. Buffer is 4k (ie. be short!) */ /* Returns length written or -errno. Buffer is 4k (ie. be short!) */
...@@ -187,7 +198,7 @@ struct kparam_array ...@@ -187,7 +198,7 @@ struct kparam_array
/* Obsolete - use module_param_cb() */ /* Obsolete - use module_param_cb() */
#define module_param_call(name, set, get, arg, perm) \ #define module_param_call(name, set, get, arg, perm) \
static struct kernel_param_ops __param_ops_##name = \ static struct kernel_param_ops __param_ops_##name = \
{ (void *)set, (void *)get }; \ { 0, (void *)set, (void *)get }; \
__module_param_call(MODULE_PARAM_PREFIX, \ __module_param_call(MODULE_PARAM_PREFIX, \
name, &__param_ops_##name, arg, \ name, &__param_ops_##name, arg, \
(perm) + sizeof(__check_old_set_param(set))*0, -1) (perm) + sizeof(__check_old_set_param(set))*0, -1)
......
...@@ -136,6 +136,7 @@ static int param_set_bool_enable_only(const char *val, ...@@ -136,6 +136,7 @@ static int param_set_bool_enable_only(const char *val,
} }
static const struct kernel_param_ops param_ops_bool_enable_only = { static const struct kernel_param_ops param_ops_bool_enable_only = {
.flags = KERNEL_PARAM_FL_NOARG,
.set = param_set_bool_enable_only, .set = param_set_bool_enable_only,
.get = param_get_bool, .get = param_get_bool,
}; };
...@@ -603,7 +604,7 @@ static void setup_modinfo_##field(struct module *mod, const char *s) \ ...@@ -603,7 +604,7 @@ static void setup_modinfo_##field(struct module *mod, const char *s) \
static ssize_t show_modinfo_##field(struct module_attribute *mattr, \ static ssize_t show_modinfo_##field(struct module_attribute *mattr, \
struct module_kobject *mk, char *buffer) \ struct module_kobject *mk, char *buffer) \
{ \ { \
return sprintf(buffer, "%s\n", mk->mod->field); \ return scnprintf(buffer, PAGE_SIZE, "%s\n", mk->mod->field); \
} \ } \
static int modinfo_##field##_exists(struct module *mod) \ static int modinfo_##field##_exists(struct module *mod) \
{ \ { \
...@@ -1611,6 +1612,14 @@ static void module_remove_modinfo_attrs(struct module *mod) ...@@ -1611,6 +1612,14 @@ static void module_remove_modinfo_attrs(struct module *mod)
kfree(mod->modinfo_attrs); kfree(mod->modinfo_attrs);
} }
static void mod_kobject_put(struct module *mod)
{
DECLARE_COMPLETION_ONSTACK(c);
mod->mkobj.kobj_completion = &c;
kobject_put(&mod->mkobj.kobj);
wait_for_completion(&c);
}
static int mod_sysfs_init(struct module *mod) static int mod_sysfs_init(struct module *mod)
{ {
int err; int err;
...@@ -1638,7 +1647,7 @@ static int mod_sysfs_init(struct module *mod) ...@@ -1638,7 +1647,7 @@ static int mod_sysfs_init(struct module *mod)
err = kobject_init_and_add(&mod->mkobj.kobj, &module_ktype, NULL, err = kobject_init_and_add(&mod->mkobj.kobj, &module_ktype, NULL,
"%s", mod->name); "%s", mod->name);
if (err) if (err)
kobject_put(&mod->mkobj.kobj); mod_kobject_put(mod);
/* delay uevent until full sysfs population */ /* delay uevent until full sysfs population */
out: out:
...@@ -1682,7 +1691,7 @@ static int mod_sysfs_setup(struct module *mod, ...@@ -1682,7 +1691,7 @@ static int mod_sysfs_setup(struct module *mod,
out_unreg_holders: out_unreg_holders:
kobject_put(mod->holders_dir); kobject_put(mod->holders_dir);
out_unreg: out_unreg:
kobject_put(&mod->mkobj.kobj); mod_kobject_put(mod);
out: out:
return err; return err;
} }
...@@ -1691,7 +1700,7 @@ static void mod_sysfs_fini(struct module *mod) ...@@ -1691,7 +1700,7 @@ static void mod_sysfs_fini(struct module *mod)
{ {
remove_notes_attrs(mod); remove_notes_attrs(mod);
remove_sect_attrs(mod); remove_sect_attrs(mod);
kobject_put(&mod->mkobj.kobj); mod_kobject_put(mod);
} }
#else /* !CONFIG_SYSFS */ #else /* !CONFIG_SYSFS */
......
...@@ -103,8 +103,8 @@ static int parse_one(char *param, ...@@ -103,8 +103,8 @@ static int parse_one(char *param,
|| params[i].level > max_level) || params[i].level > max_level)
return 0; return 0;
/* No one handled NULL, so do it here. */ /* No one handled NULL, so do it here. */
if (!val && params[i].ops->set != param_set_bool if (!val &&
&& params[i].ops->set != param_set_bint) !(params[i].ops->flags & KERNEL_PARAM_FL_NOARG))
return -EINVAL; return -EINVAL;
pr_debug("handling %s with %p\n", param, pr_debug("handling %s with %p\n", param,
params[i].ops->set); params[i].ops->set);
...@@ -241,7 +241,8 @@ int parse_args(const char *doing, ...@@ -241,7 +241,8 @@ int parse_args(const char *doing,
} \ } \
int param_get_##name(char *buffer, const struct kernel_param *kp) \ int param_get_##name(char *buffer, const struct kernel_param *kp) \
{ \ { \
return sprintf(buffer, format, *((type *)kp->arg)); \ return scnprintf(buffer, PAGE_SIZE, format, \
*((type *)kp->arg)); \
} \ } \
struct kernel_param_ops param_ops_##name = { \ struct kernel_param_ops param_ops_##name = { \
.set = param_set_##name, \ .set = param_set_##name, \
...@@ -252,7 +253,7 @@ int parse_args(const char *doing, ...@@ -252,7 +253,7 @@ int parse_args(const char *doing,
EXPORT_SYMBOL(param_ops_##name) EXPORT_SYMBOL(param_ops_##name)
STANDARD_PARAM_DEF(byte, unsigned char, "%c", unsigned long, strict_strtoul); STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", unsigned long, strict_strtoul);
STANDARD_PARAM_DEF(short, short, "%hi", long, strict_strtol); STANDARD_PARAM_DEF(short, short, "%hi", long, strict_strtol);
STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", unsigned long, strict_strtoul); STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", unsigned long, strict_strtoul);
STANDARD_PARAM_DEF(int, int, "%i", long, strict_strtol); STANDARD_PARAM_DEF(int, int, "%i", long, strict_strtol);
...@@ -285,7 +286,7 @@ EXPORT_SYMBOL(param_set_charp); ...@@ -285,7 +286,7 @@ EXPORT_SYMBOL(param_set_charp);
int param_get_charp(char *buffer, const struct kernel_param *kp) int param_get_charp(char *buffer, const struct kernel_param *kp)
{ {
return sprintf(buffer, "%s", *((char **)kp->arg)); return scnprintf(buffer, PAGE_SIZE, "%s", *((char **)kp->arg));
} }
EXPORT_SYMBOL(param_get_charp); EXPORT_SYMBOL(param_get_charp);
...@@ -320,6 +321,7 @@ int param_get_bool(char *buffer, const struct kernel_param *kp) ...@@ -320,6 +321,7 @@ int param_get_bool(char *buffer, const struct kernel_param *kp)
EXPORT_SYMBOL(param_get_bool); EXPORT_SYMBOL(param_get_bool);
struct kernel_param_ops param_ops_bool = { struct kernel_param_ops param_ops_bool = {
.flags = KERNEL_PARAM_FL_NOARG,
.set = param_set_bool, .set = param_set_bool,
.get = param_get_bool, .get = param_get_bool,
}; };
...@@ -370,6 +372,7 @@ int param_set_bint(const char *val, const struct kernel_param *kp) ...@@ -370,6 +372,7 @@ int param_set_bint(const char *val, const struct kernel_param *kp)
EXPORT_SYMBOL(param_set_bint); EXPORT_SYMBOL(param_set_bint);
struct kernel_param_ops param_ops_bint = { struct kernel_param_ops param_ops_bint = {
.flags = KERNEL_PARAM_FL_NOARG,
.set = param_set_bint, .set = param_set_bint,
.get = param_get_int, .get = param_get_int,
}; };
...@@ -827,7 +830,7 @@ ssize_t __modver_version_show(struct module_attribute *mattr, ...@@ -827,7 +830,7 @@ ssize_t __modver_version_show(struct module_attribute *mattr,
struct module_version_attribute *vattr = struct module_version_attribute *vattr =
container_of(mattr, struct module_version_attribute, mattr); container_of(mattr, struct module_version_attribute, mattr);
return sprintf(buf, "%s\n", vattr->version); return scnprintf(buf, PAGE_SIZE, "%s\n", vattr->version);
} }
extern const struct module_version_attribute *__start___modver[]; extern const struct module_version_attribute *__start___modver[];
...@@ -912,7 +915,14 @@ static const struct kset_uevent_ops module_uevent_ops = { ...@@ -912,7 +915,14 @@ static const struct kset_uevent_ops module_uevent_ops = {
struct kset *module_kset; struct kset *module_kset;
int module_sysfs_initialized; int module_sysfs_initialized;
static void module_kobj_release(struct kobject *kobj)
{
struct module_kobject *mk = to_module_kobject(kobj);
complete(mk->kobj_completion);
}
struct kobj_type module_ktype = { struct kobj_type module_ktype = {
.release = module_kobj_release,
.sysfs_ops = &module_sysfs_ops, .sysfs_ops = &module_sysfs_ops,
}; };
......
...@@ -821,6 +821,7 @@ static const char *section_white_list[] = ...@@ -821,6 +821,7 @@ static const char *section_white_list[] =
{ {
".comment*", ".comment*",
".debug*", ".debug*",
".cranges", /* sh64 */
".zdebug*", /* Compressed debug sections. */ ".zdebug*", /* Compressed debug sections. */
".GCC-command-line", /* mn10300 */ ".GCC-command-line", /* mn10300 */
".GCC.command.line", /* record-gcc-switches, non mn10300 */ ".GCC.command.line", /* record-gcc-switches, non mn10300 */
......
...@@ -666,6 +666,7 @@ static int param_set_aabool(const char *val, const struct kernel_param *kp); ...@@ -666,6 +666,7 @@ static int param_set_aabool(const char *val, const struct kernel_param *kp);
static int param_get_aabool(char *buffer, const struct kernel_param *kp); static int param_get_aabool(char *buffer, const struct kernel_param *kp);
#define param_check_aabool param_check_bool #define param_check_aabool param_check_bool
static struct kernel_param_ops param_ops_aabool = { static struct kernel_param_ops param_ops_aabool = {
.flags = KERNEL_PARAM_FL_NOARG,
.set = param_set_aabool, .set = param_set_aabool,
.get = param_get_aabool .get = param_get_aabool
}; };
...@@ -682,6 +683,7 @@ static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp ...@@ -682,6 +683,7 @@ static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp
static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp); static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp);
#define param_check_aalockpolicy param_check_bool #define param_check_aalockpolicy param_check_bool
static struct kernel_param_ops param_ops_aalockpolicy = { static struct kernel_param_ops param_ops_aalockpolicy = {
.flags = KERNEL_PARAM_FL_NOARG,
.set = param_set_aalockpolicy, .set = param_set_aalockpolicy,
.get = param_get_aalockpolicy .get = param_get_aalockpolicy
}; };
......
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