Commit 3398d252a4da80c47fe9b802184fa0a792387732
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
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()
Showing 6 changed files Side-by-side Diff
include/linux/module.h
... | ... | @@ -42,6 +42,7 @@ |
42 | 42 | struct module *mod; |
43 | 43 | struct kobject *drivers_dir; |
44 | 44 | struct module_param_attrs *mp; |
45 | + struct completion *kobj_completion; | |
45 | 46 | }; |
46 | 47 | |
47 | 48 | struct module_attribute { |
... | ... | @@ -96,6 +97,11 @@ |
96 | 97 | |
97 | 98 | /* For userspace: you can also call me... */ |
98 | 99 | #define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias) |
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) | |
99 | 105 | |
100 | 106 | /* |
101 | 107 | * The following license idents are currently accepted as indicating free |
include/linux/moduleparam.h
... | ... | @@ -36,7 +36,18 @@ |
36 | 36 | |
37 | 37 | struct 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 | + */ | |
44 | +enum { | |
45 | + KERNEL_PARAM_FL_NOARG = (1 << 0) | |
46 | +}; | |
47 | + | |
39 | 48 | struct kernel_param_ops { |
49 | + /* How the ops should behave */ | |
50 | + unsigned int flags; | |
40 | 51 | /* Returns 0, or -errno. arg is in kp->arg. */ |
41 | 52 | int (*set)(const char *val, const struct kernel_param *kp); |
42 | 53 | /* Returns length written or -errno. Buffer is 4k (ie. be short!) */ |
... | ... | @@ -187,7 +198,7 @@ |
187 | 198 | /* Obsolete - use module_param_cb() */ |
188 | 199 | #define module_param_call(name, set, get, arg, perm) \ |
189 | 200 | static struct kernel_param_ops __param_ops_##name = \ |
190 | - { (void *)set, (void *)get }; \ | |
201 | + { 0, (void *)set, (void *)get }; \ | |
191 | 202 | __module_param_call(MODULE_PARAM_PREFIX, \ |
192 | 203 | name, &__param_ops_##name, arg, \ |
193 | 204 | (perm) + sizeof(__check_old_set_param(set))*0, -1) |
kernel/module.c
... | ... | @@ -136,6 +136,7 @@ |
136 | 136 | } |
137 | 137 | |
138 | 138 | static const struct kernel_param_ops param_ops_bool_enable_only = { |
139 | + .flags = KERNEL_PARAM_FL_NOARG, | |
139 | 140 | .set = param_set_bool_enable_only, |
140 | 141 | .get = param_get_bool, |
141 | 142 | }; |
... | ... | @@ -603,7 +604,7 @@ |
603 | 604 | static ssize_t show_modinfo_##field(struct module_attribute *mattr, \ |
604 | 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 | } \ |
608 | 609 | static int modinfo_##field##_exists(struct module *mod) \ |
609 | 610 | { \ |
... | ... | @@ -1611,6 +1612,14 @@ |
1611 | 1612 | kfree(mod->modinfo_attrs); |
1612 | 1613 | } |
1613 | 1614 | |
1615 | +static 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 | + | |
1614 | 1623 | static int mod_sysfs_init(struct module *mod) |
1615 | 1624 | { |
1616 | 1625 | int err; |
... | ... | @@ -1638,7 +1647,7 @@ |
1638 | 1647 | err = kobject_init_and_add(&mod->mkobj.kobj, &module_ktype, NULL, |
1639 | 1648 | "%s", mod->name); |
1640 | 1649 | if (err) |
1641 | - kobject_put(&mod->mkobj.kobj); | |
1650 | + mod_kobject_put(mod); | |
1642 | 1651 | |
1643 | 1652 | /* delay uevent until full sysfs population */ |
1644 | 1653 | out: |
... | ... | @@ -1682,7 +1691,7 @@ |
1682 | 1691 | out_unreg_holders: |
1683 | 1692 | kobject_put(mod->holders_dir); |
1684 | 1693 | out_unreg: |
1685 | - kobject_put(&mod->mkobj.kobj); | |
1694 | + mod_kobject_put(mod); | |
1686 | 1695 | out: |
1687 | 1696 | return err; |
1688 | 1697 | } |
... | ... | @@ -1691,7 +1700,7 @@ |
1691 | 1700 | { |
1692 | 1701 | remove_notes_attrs(mod); |
1693 | 1702 | remove_sect_attrs(mod); |
1694 | - kobject_put(&mod->mkobj.kobj); | |
1703 | + mod_kobject_put(mod); | |
1695 | 1704 | } |
1696 | 1705 | |
1697 | 1706 | #else /* !CONFIG_SYSFS */ |
kernel/params.c
... | ... | @@ -103,8 +103,8 @@ |
103 | 103 | || params[i].level > max_level) |
104 | 104 | return 0; |
105 | 105 | /* No one handled NULL, so do it here. */ |
106 | - if (!val && params[i].ops->set != param_set_bool | |
107 | - && params[i].ops->set != param_set_bint) | |
106 | + if (!val && | |
107 | + !(params[i].ops->flags & KERNEL_PARAM_FL_NOARG)) | |
108 | 108 | return -EINVAL; |
109 | 109 | pr_debug("handling %s with %p\n", param, |
110 | 110 | params[i].ops->set); |
... | ... | @@ -241,7 +241,8 @@ |
241 | 241 | } \ |
242 | 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 | 247 | struct kernel_param_ops param_ops_##name = { \ |
247 | 248 | .set = param_set_##name, \ |
... | ... | @@ -252,7 +253,7 @@ |
252 | 253 | EXPORT_SYMBOL(param_ops_##name) |
253 | 254 | |
254 | 255 | |
255 | -STANDARD_PARAM_DEF(byte, unsigned char, "%c", unsigned long, strict_strtoul); | |
256 | +STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", unsigned long, strict_strtoul); | |
256 | 257 | STANDARD_PARAM_DEF(short, short, "%hi", long, strict_strtol); |
257 | 258 | STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", unsigned long, strict_strtoul); |
258 | 259 | STANDARD_PARAM_DEF(int, int, "%i", long, strict_strtol); |
... | ... | @@ -285,7 +286,7 @@ |
285 | 286 | |
286 | 287 | int 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 | } |
290 | 291 | EXPORT_SYMBOL(param_get_charp); |
291 | 292 | |
... | ... | @@ -320,6 +321,7 @@ |
320 | 321 | EXPORT_SYMBOL(param_get_bool); |
321 | 322 | |
322 | 323 | struct kernel_param_ops param_ops_bool = { |
324 | + .flags = KERNEL_PARAM_FL_NOARG, | |
323 | 325 | .set = param_set_bool, |
324 | 326 | .get = param_get_bool, |
325 | 327 | }; |
... | ... | @@ -370,6 +372,7 @@ |
370 | 372 | EXPORT_SYMBOL(param_set_bint); |
371 | 373 | |
372 | 374 | struct kernel_param_ops param_ops_bint = { |
375 | + .flags = KERNEL_PARAM_FL_NOARG, | |
373 | 376 | .set = param_set_bint, |
374 | 377 | .get = param_get_int, |
375 | 378 | }; |
... | ... | @@ -827,7 +830,7 @@ |
827 | 830 | struct module_version_attribute *vattr = |
828 | 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 | |
833 | 836 | extern const struct module_version_attribute *__start___modver[]; |
834 | 837 | |
... | ... | @@ -912,7 +915,14 @@ |
912 | 915 | struct kset *module_kset; |
913 | 916 | int module_sysfs_initialized; |
914 | 917 | |
918 | +static void module_kobj_release(struct kobject *kobj) | |
919 | +{ | |
920 | + struct module_kobject *mk = to_module_kobject(kobj); | |
921 | + complete(mk->kobj_completion); | |
922 | +} | |
923 | + | |
915 | 924 | struct kobj_type module_ktype = { |
925 | + .release = module_kobj_release, | |
916 | 926 | .sysfs_ops = &module_sysfs_ops, |
917 | 927 | }; |
918 | 928 |
scripts/mod/modpost.c
security/apparmor/lsm.c
... | ... | @@ -666,6 +666,7 @@ |
666 | 666 | static int param_get_aabool(char *buffer, const struct kernel_param *kp); |
667 | 667 | #define param_check_aabool param_check_bool |
668 | 668 | static struct kernel_param_ops param_ops_aabool = { |
669 | + .flags = KERNEL_PARAM_FL_NOARG, | |
669 | 670 | .set = param_set_aabool, |
670 | 671 | .get = param_get_aabool |
671 | 672 | }; |
... | ... | @@ -682,6 +683,7 @@ |
682 | 683 | static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp); |
683 | 684 | #define param_check_aalockpolicy param_check_bool |
684 | 685 | static struct kernel_param_ops param_ops_aalockpolicy = { |
686 | + .flags = KERNEL_PARAM_FL_NOARG, | |
685 | 687 | .set = param_set_aalockpolicy, |
686 | 688 | .get = param_get_aalockpolicy |
687 | 689 | }; |