summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-04 20:34:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-04 20:34:29 -0400
commit3398d252a4da80c47fe9b802184fa0a792387732 (patch)
tree3def3b476b597487193718508f5644a6075a736f
parent27703bb4a66df49ff16b44b864d307d2eb71774c (diff)
parent942e443127e928a5631c3d5102aca8c8b3c2dd98 (diff)
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()
-rw-r--r--include/linux/module.h6
-rw-r--r--include/linux/moduleparam.h13
-rw-r--r--kernel/module.c17
-rw-r--r--kernel/params.c22
-rw-r--r--scripts/mod/modpost.c1
-rw-r--r--security/apparmor/lsm.c2
6 files changed, 50 insertions, 11 deletions
diff --git a/include/linux/module.h b/include/linux/module.h
index 46f1ea01e6f6..05f2447f8c15 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -42,6 +42,7 @@ struct module_kobject {
42 struct module *mod; 42 struct module *mod;
43 struct kobject *drivers_dir; 43 struct kobject *drivers_dir;
44 struct module_param_attrs *mp; 44 struct module_param_attrs *mp;
45 struct completion *kobj_completion;
45}; 46};
46 47
47struct module_attribute { 48struct module_attribute {
@@ -97,6 +98,11 @@ extern const struct gtype##_id __mod_##gtype##_table \
97/* For userspace: you can also call me... */ 98/* For userspace: you can also call me... */
98#define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias) 99#define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias)
99 100
101/* Soft module dependencies. See man modprobe.d for details.
102 * Example: MODULE_SOFTDEP("pre: module-foo module-bar post: module-baz")
103 */
104#define MODULE_SOFTDEP(_softdep) MODULE_INFO(softdep, _softdep)
105
100/* 106/*
101 * The following license idents are currently accepted as indicating free 107 * The following license idents are currently accepted as indicating free
102 * software modules 108 * software modules
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index 27d9da3f86ff..c3eb102a9cc8 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -36,7 +36,18 @@ static const char __UNIQUE_ID(name)[] \
36 36
37struct kernel_param; 37struct kernel_param;
38 38
39/*
40 * Flags available for kernel_param_ops
41 *
42 * NOARG - the parameter allows for no argument (foo instead of foo=1)
43 */
44enum {
45 KERNEL_PARAM_FL_NOARG = (1 << 0)
46};
47
39struct kernel_param_ops { 48struct kernel_param_ops {
49 /* How the ops should behave */
50 unsigned int flags;
40 /* Returns 0, or -errno. arg is in kp->arg. */ 51 /* Returns 0, or -errno. arg is in kp->arg. */
41 int (*set)(const char *val, const struct kernel_param *kp); 52 int (*set)(const char *val, const struct kernel_param *kp);
42 /* Returns length written or -errno. Buffer is 4k (ie. be short!) */ 53 /* Returns length written or -errno. Buffer is 4k (ie. be short!) */
@@ -187,7 +198,7 @@ struct kparam_array
187/* Obsolete - use module_param_cb() */ 198/* Obsolete - use module_param_cb() */
188#define module_param_call(name, set, get, arg, perm) \ 199#define module_param_call(name, set, get, arg, perm) \
189 static struct kernel_param_ops __param_ops_##name = \ 200 static struct kernel_param_ops __param_ops_##name = \
190 { (void *)set, (void *)get }; \ 201 { 0, (void *)set, (void *)get }; \
191 __module_param_call(MODULE_PARAM_PREFIX, \ 202 __module_param_call(MODULE_PARAM_PREFIX, \
192 name, &__param_ops_##name, arg, \ 203 name, &__param_ops_##name, arg, \
193 (perm) + sizeof(__check_old_set_param(set))*0, -1) 204 (perm) + sizeof(__check_old_set_param(set))*0, -1)
diff --git a/kernel/module.c b/kernel/module.c
index 206915830d29..9f5ddae72f44 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -136,6 +136,7 @@ static int param_set_bool_enable_only(const char *val,
136} 136}
137 137
138static const struct kernel_param_ops param_ops_bool_enable_only = { 138static const struct kernel_param_ops param_ops_bool_enable_only = {
139 .flags = KERNEL_PARAM_FL_NOARG,
139 .set = param_set_bool_enable_only, 140 .set = param_set_bool_enable_only,
140 .get = param_get_bool, 141 .get = param_get_bool,
141}; 142};
@@ -603,7 +604,7 @@ static void setup_modinfo_##field(struct module *mod, const char *s) \
603static ssize_t show_modinfo_##field(struct module_attribute *mattr, \ 604static ssize_t show_modinfo_##field(struct module_attribute *mattr, \
604 struct module_kobject *mk, char *buffer) \ 605 struct module_kobject *mk, char *buffer) \
605{ \ 606{ \
606 return sprintf(buffer, "%s\n", mk->mod->field); \ 607 return scnprintf(buffer, PAGE_SIZE, "%s\n", mk->mod->field); \
607} \ 608} \
608static int modinfo_##field##_exists(struct module *mod) \ 609static int modinfo_##field##_exists(struct module *mod) \
609{ \ 610{ \
@@ -1611,6 +1612,14 @@ static void module_remove_modinfo_attrs(struct module *mod)
1611 kfree(mod->modinfo_attrs); 1612 kfree(mod->modinfo_attrs);
1612} 1613}
1613 1614
1615static void mod_kobject_put(struct module *mod)
1616{
1617 DECLARE_COMPLETION_ONSTACK(c);
1618 mod->mkobj.kobj_completion = &c;
1619 kobject_put(&mod->mkobj.kobj);
1620 wait_for_completion(&c);
1621}
1622
1614static int mod_sysfs_init(struct module *mod) 1623static int mod_sysfs_init(struct module *mod)
1615{ 1624{
1616 int err; 1625 int err;
@@ -1638,7 +1647,7 @@ static int mod_sysfs_init(struct module *mod)
1638 err = kobject_init_and_add(&mod->mkobj.kobj, &module_ktype, NULL, 1647 err = kobject_init_and_add(&mod->mkobj.kobj, &module_ktype, NULL,
1639 "%s", mod->name); 1648 "%s", mod->name);
1640 if (err) 1649 if (err)
1641 kobject_put(&mod->mkobj.kobj); 1650 mod_kobject_put(mod);
1642 1651
1643 /* delay uevent until full sysfs population */ 1652 /* delay uevent until full sysfs population */
1644out: 1653out:
@@ -1682,7 +1691,7 @@ out_unreg_param:
1682out_unreg_holders: 1691out_unreg_holders:
1683 kobject_put(mod->holders_dir); 1692 kobject_put(mod->holders_dir);
1684out_unreg: 1693out_unreg:
1685 kobject_put(&mod->mkobj.kobj); 1694 mod_kobject_put(mod);
1686out: 1695out:
1687 return err; 1696 return err;
1688} 1697}
@@ -1691,7 +1700,7 @@ static void mod_sysfs_fini(struct module *mod)
1691{ 1700{
1692 remove_notes_attrs(mod); 1701 remove_notes_attrs(mod);
1693 remove_sect_attrs(mod); 1702 remove_sect_attrs(mod);
1694 kobject_put(&mod->mkobj.kobj); 1703 mod_kobject_put(mod);
1695} 1704}
1696 1705
1697#else /* !CONFIG_SYSFS */ 1706#else /* !CONFIG_SYSFS */
diff --git a/kernel/params.c b/kernel/params.c
index 440e65d1a544..501bde4f3bee 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -103,8 +103,8 @@ static int parse_one(char *param,
103 || params[i].level > max_level) 103 || params[i].level > max_level)
104 return 0; 104 return 0;
105 /* No one handled NULL, so do it here. */ 105 /* No one handled NULL, so do it here. */
106 if (!val && params[i].ops->set != param_set_bool 106 if (!val &&
107 && params[i].ops->set != param_set_bint) 107 !(params[i].ops->flags & KERNEL_PARAM_FL_NOARG))
108 return -EINVAL; 108 return -EINVAL;
109 pr_debug("handling %s with %p\n", param, 109 pr_debug("handling %s with %p\n", param,
110 params[i].ops->set); 110 params[i].ops->set);
@@ -241,7 +241,8 @@ int parse_args(const char *doing,
241 } \ 241 } \
242 int param_get_##name(char *buffer, const struct kernel_param *kp) \ 242 int param_get_##name(char *buffer, const struct kernel_param *kp) \
243 { \ 243 { \
244 return sprintf(buffer, format, *((type *)kp->arg)); \ 244 return scnprintf(buffer, PAGE_SIZE, format, \
245 *((type *)kp->arg)); \
245 } \ 246 } \
246 struct kernel_param_ops param_ops_##name = { \ 247 struct kernel_param_ops param_ops_##name = { \
247 .set = param_set_##name, \ 248 .set = param_set_##name, \
@@ -252,7 +253,7 @@ int parse_args(const char *doing,
252 EXPORT_SYMBOL(param_ops_##name) 253 EXPORT_SYMBOL(param_ops_##name)
253 254
254 255
255STANDARD_PARAM_DEF(byte, unsigned char, "%c", unsigned long, strict_strtoul); 256STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", unsigned long, strict_strtoul);
256STANDARD_PARAM_DEF(short, short, "%hi", long, strict_strtol); 257STANDARD_PARAM_DEF(short, short, "%hi", long, strict_strtol);
257STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", unsigned long, strict_strtoul); 258STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", unsigned long, strict_strtoul);
258STANDARD_PARAM_DEF(int, int, "%i", long, strict_strtol); 259STANDARD_PARAM_DEF(int, int, "%i", long, strict_strtol);
@@ -285,7 +286,7 @@ EXPORT_SYMBOL(param_set_charp);
285 286
286int param_get_charp(char *buffer, const struct kernel_param *kp) 287int param_get_charp(char *buffer, const struct kernel_param *kp)
287{ 288{
288 return sprintf(buffer, "%s", *((char **)kp->arg)); 289 return scnprintf(buffer, PAGE_SIZE, "%s", *((char **)kp->arg));
289} 290}
290EXPORT_SYMBOL(param_get_charp); 291EXPORT_SYMBOL(param_get_charp);
291 292
@@ -320,6 +321,7 @@ int param_get_bool(char *buffer, const struct kernel_param *kp)
320EXPORT_SYMBOL(param_get_bool); 321EXPORT_SYMBOL(param_get_bool);
321 322
322struct kernel_param_ops param_ops_bool = { 323struct kernel_param_ops param_ops_bool = {
324 .flags = KERNEL_PARAM_FL_NOARG,
323 .set = param_set_bool, 325 .set = param_set_bool,
324 .get = param_get_bool, 326 .get = param_get_bool,
325}; 327};
@@ -370,6 +372,7 @@ int param_set_bint(const char *val, const struct kernel_param *kp)
370EXPORT_SYMBOL(param_set_bint); 372EXPORT_SYMBOL(param_set_bint);
371 373
372struct kernel_param_ops param_ops_bint = { 374struct kernel_param_ops param_ops_bint = {
375 .flags = KERNEL_PARAM_FL_NOARG,
373 .set = param_set_bint, 376 .set = param_set_bint,
374 .get = param_get_int, 377 .get = param_get_int,
375}; 378};
@@ -827,7 +830,7 @@ ssize_t __modver_version_show(struct module_attribute *mattr,
827 struct module_version_attribute *vattr = 830 struct module_version_attribute *vattr =
828 container_of(mattr, struct module_version_attribute, mattr); 831 container_of(mattr, struct module_version_attribute, mattr);
829 832
830 return sprintf(buf, "%s\n", vattr->version); 833 return scnprintf(buf, PAGE_SIZE, "%s\n", vattr->version);
831} 834}
832 835
833extern const struct module_version_attribute *__start___modver[]; 836extern const struct module_version_attribute *__start___modver[];
@@ -912,7 +915,14 @@ static const struct kset_uevent_ops module_uevent_ops = {
912struct kset *module_kset; 915struct kset *module_kset;
913int module_sysfs_initialized; 916int module_sysfs_initialized;
914 917
918static void module_kobj_release(struct kobject *kobj)
919{
920 struct module_kobject *mk = to_module_kobject(kobj);
921 complete(mk->kobj_completion);
922}
923
915struct kobj_type module_ktype = { 924struct kobj_type module_ktype = {
925 .release = module_kobj_release,
916 .sysfs_ops = &module_sysfs_ops, 926 .sysfs_ops = &module_sysfs_ops,
917}; 927};
918 928
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 62164348ecf7..8247979e8f64 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -821,6 +821,7 @@ static const char *section_white_list[] =
821{ 821{
822 ".comment*", 822 ".comment*",
823 ".debug*", 823 ".debug*",
824 ".cranges", /* sh64 */
824 ".zdebug*", /* Compressed debug sections. */ 825 ".zdebug*", /* Compressed debug sections. */
825 ".GCC-command-line", /* mn10300 */ 826 ".GCC-command-line", /* mn10300 */
826 ".GCC.command.line", /* record-gcc-switches, non mn10300 */ 827 ".GCC.command.line", /* record-gcc-switches, non mn10300 */
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 2e2a0dd4a73f..e3a704c75ef6 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -666,6 +666,7 @@ static int param_set_aabool(const char *val, const struct kernel_param *kp);
666static int param_get_aabool(char *buffer, const struct kernel_param *kp); 666static int param_get_aabool(char *buffer, const struct kernel_param *kp);
667#define param_check_aabool param_check_bool 667#define param_check_aabool param_check_bool
668static struct kernel_param_ops param_ops_aabool = { 668static struct kernel_param_ops param_ops_aabool = {
669 .flags = KERNEL_PARAM_FL_NOARG,
669 .set = param_set_aabool, 670 .set = param_set_aabool,
670 .get = param_get_aabool 671 .get = param_get_aabool
671}; 672};
@@ -682,6 +683,7 @@ static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp
682static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp); 683static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp);
683#define param_check_aalockpolicy param_check_bool 684#define param_check_aalockpolicy param_check_bool
684static struct kernel_param_ops param_ops_aalockpolicy = { 685static struct kernel_param_ops param_ops_aalockpolicy = {
686 .flags = KERNEL_PARAM_FL_NOARG,
685 .set = param_set_aalockpolicy, 687 .set = param_set_aalockpolicy,
686 .get = param_get_aalockpolicy 688 .get = param_get_aalockpolicy
687}; 689};