diff options
-rw-r--r-- | Documentation/kernel-parameters.txt | 2 | ||||
-rw-r--r-- | arch/powerpc/mm/hugetlbpage.c | 3 | ||||
-rw-r--r-- | include/asm-generic/vmlinux.lds.h | 35 | ||||
-rw-r--r-- | include/linux/module.h | 32 | ||||
-rw-r--r-- | include/linux/moduleparam.h | 58 | ||||
-rw-r--r-- | init/main.c | 65 | ||||
-rw-r--r-- | kernel/module.c | 37 | ||||
-rw-r--r-- | kernel/params.c | 39 |
8 files changed, 172 insertions, 99 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 58eac231fe6..e2f8c297a8a 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1869,6 +1869,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
1869 | shutdown the other cpus. Instead use the REBOOT_VECTOR | 1869 | shutdown the other cpus. Instead use the REBOOT_VECTOR |
1870 | irq. | 1870 | irq. |
1871 | 1871 | ||
1872 | nomodule Disable module load | ||
1873 | |||
1872 | nopat [X86] Disable PAT (page attribute table extension of | 1874 | nopat [X86] Disable PAT (page attribute table extension of |
1873 | pagetables) support. | 1875 | pagetables) support. |
1874 | 1876 | ||
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 57c7465e656..a3e62872769 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c | |||
@@ -310,7 +310,8 @@ void __init reserve_hugetlb_gpages(void) | |||
310 | int i; | 310 | int i; |
311 | 311 | ||
312 | strlcpy(cmdline, boot_command_line, COMMAND_LINE_SIZE); | 312 | strlcpy(cmdline, boot_command_line, COMMAND_LINE_SIZE); |
313 | parse_args("hugetlb gpages", cmdline, NULL, 0, &do_gpage_early_setup); | 313 | parse_args("hugetlb gpages", cmdline, NULL, 0, 0, 0, |
314 | &do_gpage_early_setup); | ||
314 | 315 | ||
315 | /* | 316 | /* |
316 | * Walk gpage list in reverse, allocating larger page sizes first. | 317 | * Walk gpage list in reverse, allocating larger page sizes first. |
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 798603e8ec3..8aeadf6b553 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h | |||
@@ -616,30 +616,23 @@ | |||
616 | *(.init.setup) \ | 616 | *(.init.setup) \ |
617 | VMLINUX_SYMBOL(__setup_end) = .; | 617 | VMLINUX_SYMBOL(__setup_end) = .; |
618 | 618 | ||
619 | #define INITCALLS \ | 619 | #define INIT_CALLS_LEVEL(level) \ |
620 | *(.initcallearly.init) \ | 620 | VMLINUX_SYMBOL(__initcall##level##_start) = .; \ |
621 | VMLINUX_SYMBOL(__early_initcall_end) = .; \ | 621 | *(.initcall##level##.init) \ |
622 | *(.initcall0.init) \ | 622 | *(.initcall##level##s.init) \ |
623 | *(.initcall0s.init) \ | ||
624 | *(.initcall1.init) \ | ||
625 | *(.initcall1s.init) \ | ||
626 | *(.initcall2.init) \ | ||
627 | *(.initcall2s.init) \ | ||
628 | *(.initcall3.init) \ | ||
629 | *(.initcall3s.init) \ | ||
630 | *(.initcall4.init) \ | ||
631 | *(.initcall4s.init) \ | ||
632 | *(.initcall5.init) \ | ||
633 | *(.initcall5s.init) \ | ||
634 | *(.initcallrootfs.init) \ | ||
635 | *(.initcall6.init) \ | ||
636 | *(.initcall6s.init) \ | ||
637 | *(.initcall7.init) \ | ||
638 | *(.initcall7s.init) | ||
639 | 623 | ||
640 | #define INIT_CALLS \ | 624 | #define INIT_CALLS \ |
641 | VMLINUX_SYMBOL(__initcall_start) = .; \ | 625 | VMLINUX_SYMBOL(__initcall_start) = .; \ |
642 | INITCALLS \ | 626 | *(.initcallearly.init) \ |
627 | INIT_CALLS_LEVEL(0) \ | ||
628 | INIT_CALLS_LEVEL(1) \ | ||
629 | INIT_CALLS_LEVEL(2) \ | ||
630 | INIT_CALLS_LEVEL(3) \ | ||
631 | INIT_CALLS_LEVEL(4) \ | ||
632 | INIT_CALLS_LEVEL(5) \ | ||
633 | INIT_CALLS_LEVEL(rootfs) \ | ||
634 | INIT_CALLS_LEVEL(6) \ | ||
635 | INIT_CALLS_LEVEL(7) \ | ||
643 | VMLINUX_SYMBOL(__initcall_end) = .; | 636 | VMLINUX_SYMBOL(__initcall_end) = .; |
644 | 637 | ||
645 | #define CON_INITCALL \ | 638 | #define CON_INITCALL \ |
diff --git a/include/linux/module.h b/include/linux/module.h index 4598bf03e98..fbcafe2ee13 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
@@ -21,8 +21,6 @@ | |||
21 | #include <linux/percpu.h> | 21 | #include <linux/percpu.h> |
22 | #include <asm/module.h> | 22 | #include <asm/module.h> |
23 | 23 | ||
24 | #include <trace/events/module.h> | ||
25 | |||
26 | /* Not Yet Implemented */ | 24 | /* Not Yet Implemented */ |
27 | #define MODULE_SUPPORTED_DEVICE(name) | 25 | #define MODULE_SUPPORTED_DEVICE(name) |
28 | 26 | ||
@@ -452,33 +450,11 @@ void symbol_put_addr(void *addr); | |||
452 | 450 | ||
453 | /* Sometimes we know we already have a refcount, and it's easier not | 451 | /* Sometimes we know we already have a refcount, and it's easier not |
454 | to handle the error case (which only happens with rmmod --wait). */ | 452 | to handle the error case (which only happens with rmmod --wait). */ |
455 | static inline void __module_get(struct module *module) | 453 | extern void __module_get(struct module *module); |
456 | { | ||
457 | if (module) { | ||
458 | preempt_disable(); | ||
459 | __this_cpu_inc(module->refptr->incs); | ||
460 | trace_module_get(module, _THIS_IP_); | ||
461 | preempt_enable(); | ||
462 | } | ||
463 | } | ||
464 | |||
465 | static inline int try_module_get(struct module *module) | ||
466 | { | ||
467 | int ret = 1; | ||
468 | |||
469 | if (module) { | ||
470 | preempt_disable(); | ||
471 | 454 | ||
472 | if (likely(module_is_live(module))) { | 455 | /* This is the Right Way to get a module: if it fails, it's being removed, |
473 | __this_cpu_inc(module->refptr->incs); | 456 | * so pretend it's not there. */ |
474 | trace_module_get(module, _THIS_IP_); | 457 | extern bool try_module_get(struct module *module); |
475 | } else | ||
476 | ret = 0; | ||
477 | |||
478 | preempt_enable(); | ||
479 | } | ||
480 | return ret; | ||
481 | } | ||
482 | 458 | ||
483 | extern void module_put(struct module *module); | 459 | extern void module_put(struct module *module); |
484 | 460 | ||
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index c47f4d60db0..ea36486378d 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h | |||
@@ -47,14 +47,11 @@ struct kernel_param_ops { | |||
47 | void (*free)(void *arg); | 47 | void (*free)(void *arg); |
48 | }; | 48 | }; |
49 | 49 | ||
50 | /* Flag bits for kernel_param.flags */ | ||
51 | #define KPARAM_ISBOOL 2 | ||
52 | |||
53 | struct kernel_param { | 50 | struct kernel_param { |
54 | const char *name; | 51 | const char *name; |
55 | const struct kernel_param_ops *ops; | 52 | const struct kernel_param_ops *ops; |
56 | u16 perm; | 53 | u16 perm; |
57 | u16 flags; | 54 | s16 level; |
58 | union { | 55 | union { |
59 | void *arg; | 56 | void *arg; |
60 | const struct kparam_string *str; | 57 | const struct kparam_string *str; |
@@ -131,8 +128,40 @@ struct kparam_array | |||
131 | * The ops can have NULL set or get functions. | 128 | * The ops can have NULL set or get functions. |
132 | */ | 129 | */ |
133 | #define module_param_cb(name, ops, arg, perm) \ | 130 | #define module_param_cb(name, ops, arg, perm) \ |
134 | __module_param_call(MODULE_PARAM_PREFIX, \ | 131 | __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, 0) |
135 | name, ops, arg, __same_type((arg), bool *), perm) | 132 | |
133 | /** | ||
134 | * <level>_param_cb - general callback for a module/cmdline parameter | ||
135 | * to be evaluated before certain initcall level | ||
136 | * @name: a valid C identifier which is the parameter name. | ||
137 | * @ops: the set & get operations for this parameter. | ||
138 | * @perm: visibility in sysfs. | ||
139 | * | ||
140 | * The ops can have NULL set or get functions. | ||
141 | */ | ||
142 | #define __level_param_cb(name, ops, arg, perm, level) \ | ||
143 | __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, level) | ||
144 | |||
145 | #define core_param_cb(name, ops, arg, perm) \ | ||
146 | __level_param_cb(name, ops, arg, perm, 1) | ||
147 | |||
148 | #define postcore_param_cb(name, ops, arg, perm) \ | ||
149 | __level_param_cb(name, ops, arg, perm, 2) | ||
150 | |||
151 | #define arch_param_cb(name, ops, arg, perm) \ | ||
152 | __level_param_cb(name, ops, arg, perm, 3) | ||
153 | |||
154 | #define subsys_param_cb(name, ops, arg, perm) \ | ||
155 | __level_param_cb(name, ops, arg, perm, 4) | ||
156 | |||
157 | #define fs_param_cb(name, ops, arg, perm) \ | ||
158 | __level_param_cb(name, ops, arg, perm, 5) | ||
159 | |||
160 | #define device_param_cb(name, ops, arg, perm) \ | ||
161 | __level_param_cb(name, ops, arg, perm, 6) | ||
162 | |||
163 | #define late_param_cb(name, ops, arg, perm) \ | ||
164 | __level_param_cb(name, ops, arg, perm, 7) | ||
136 | 165 | ||
137 | /* On alpha, ia64 and ppc64 relocations to global data cannot go into | 166 | /* On alpha, ia64 and ppc64 relocations to global data cannot go into |
138 | read-only sections (which is part of respective UNIX ABI on these | 167 | read-only sections (which is part of respective UNIX ABI on these |
@@ -146,7 +175,7 @@ struct kparam_array | |||
146 | 175 | ||
147 | /* This is the fundamental function for registering boot/module | 176 | /* This is the fundamental function for registering boot/module |
148 | parameters. */ | 177 | parameters. */ |
149 | #define __module_param_call(prefix, name, ops, arg, isbool, perm) \ | 178 | #define __module_param_call(prefix, name, ops, arg, perm, level) \ |
150 | /* Default value instead of permissions? */ \ | 179 | /* Default value instead of permissions? */ \ |
151 | static int __param_perm_check_##name __attribute__((unused)) = \ | 180 | static int __param_perm_check_##name __attribute__((unused)) = \ |
152 | BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)) \ | 181 | BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)) \ |
@@ -155,8 +184,7 @@ struct kparam_array | |||
155 | static struct kernel_param __moduleparam_const __param_##name \ | 184 | static struct kernel_param __moduleparam_const __param_##name \ |
156 | __used \ | 185 | __used \ |
157 | __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ | 186 | __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ |
158 | = { __param_str_##name, ops, perm, isbool ? KPARAM_ISBOOL : 0, \ | 187 | = { __param_str_##name, ops, perm, level, { arg } } |
159 | { arg } } | ||
160 | 188 | ||
161 | /* Obsolete - use module_param_cb() */ | 189 | /* Obsolete - use module_param_cb() */ |
162 | #define module_param_call(name, set, get, arg, perm) \ | 190 | #define module_param_call(name, set, get, arg, perm) \ |
@@ -164,8 +192,7 @@ struct kparam_array | |||
164 | { (void *)set, (void *)get }; \ | 192 | { (void *)set, (void *)get }; \ |
165 | __module_param_call(MODULE_PARAM_PREFIX, \ | 193 | __module_param_call(MODULE_PARAM_PREFIX, \ |
166 | name, &__param_ops_##name, arg, \ | 194 | name, &__param_ops_##name, arg, \ |
167 | __same_type(arg, bool *), \ | 195 | (perm) + sizeof(__check_old_set_param(set))*0, 0) |
168 | (perm) + sizeof(__check_old_set_param(set))*0) | ||
169 | 196 | ||
170 | /* We don't get oldget: it's often a new-style param_get_uint, etc. */ | 197 | /* We don't get oldget: it's often a new-style param_get_uint, etc. */ |
171 | static inline int | 198 | static inline int |
@@ -245,8 +272,7 @@ static inline void __kernel_param_unlock(void) | |||
245 | */ | 272 | */ |
246 | #define core_param(name, var, type, perm) \ | 273 | #define core_param(name, var, type, perm) \ |
247 | param_check_##type(name, &(var)); \ | 274 | param_check_##type(name, &(var)); \ |
248 | __module_param_call("", name, ¶m_ops_##type, \ | 275 | __module_param_call("", name, ¶m_ops_##type, &var, perm, 0) |
249 | &var, __same_type(var, bool), perm) | ||
250 | #endif /* !MODULE */ | 276 | #endif /* !MODULE */ |
251 | 277 | ||
252 | /** | 278 | /** |
@@ -264,7 +290,7 @@ static inline void __kernel_param_unlock(void) | |||
264 | = { len, string }; \ | 290 | = { len, string }; \ |
265 | __module_param_call(MODULE_PARAM_PREFIX, name, \ | 291 | __module_param_call(MODULE_PARAM_PREFIX, name, \ |
266 | ¶m_ops_string, \ | 292 | ¶m_ops_string, \ |
267 | .str = &__param_string_##name, 0, perm); \ | 293 | .str = &__param_string_##name, perm, 0); \ |
268 | __MODULE_PARM_TYPE(name, "string") | 294 | __MODULE_PARM_TYPE(name, "string") |
269 | 295 | ||
270 | /** | 296 | /** |
@@ -292,6 +318,8 @@ extern int parse_args(const char *name, | |||
292 | char *args, | 318 | char *args, |
293 | const struct kernel_param *params, | 319 | const struct kernel_param *params, |
294 | unsigned num, | 320 | unsigned num, |
321 | s16 level_min, | ||
322 | s16 level_max, | ||
295 | int (*unknown)(char *param, char *val)); | 323 | int (*unknown)(char *param, char *val)); |
296 | 324 | ||
297 | /* Called by module remove. */ | 325 | /* Called by module remove. */ |
@@ -403,7 +431,7 @@ extern int param_set_bint(const char *val, const struct kernel_param *kp); | |||
403 | __module_param_call(MODULE_PARAM_PREFIX, name, \ | 431 | __module_param_call(MODULE_PARAM_PREFIX, name, \ |
404 | ¶m_array_ops, \ | 432 | ¶m_array_ops, \ |
405 | .arr = &__param_arr_##name, \ | 433 | .arr = &__param_arr_##name, \ |
406 | __same_type(array[0], bool), perm); \ | 434 | perm, 0); \ |
407 | __MODULE_PARM_TYPE(name, "array of " #type) | 435 | __MODULE_PARM_TYPE(name, "array of " #type) |
408 | 436 | ||
409 | extern struct kernel_param_ops param_array_ops; | 437 | extern struct kernel_param_ops param_array_ops; |
diff --git a/init/main.c b/init/main.c index c24805c824b..439715858ba 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -400,7 +400,7 @@ static int __init do_early_param(char *param, char *val) | |||
400 | 400 | ||
401 | void __init parse_early_options(char *cmdline) | 401 | void __init parse_early_options(char *cmdline) |
402 | { | 402 | { |
403 | parse_args("early options", cmdline, NULL, 0, do_early_param); | 403 | parse_args("early options", cmdline, NULL, 0, 0, 0, do_early_param); |
404 | } | 404 | } |
405 | 405 | ||
406 | /* Arch code calls this early on, or if not, just before other parsing. */ | 406 | /* Arch code calls this early on, or if not, just before other parsing. */ |
@@ -503,7 +503,7 @@ asmlinkage void __init start_kernel(void) | |||
503 | parse_early_param(); | 503 | parse_early_param(); |
504 | parse_args("Booting kernel", static_command_line, __start___param, | 504 | parse_args("Booting kernel", static_command_line, __start___param, |
505 | __stop___param - __start___param, | 505 | __stop___param - __start___param, |
506 | &unknown_bootoption); | 506 | 0, 0, &unknown_bootoption); |
507 | 507 | ||
508 | jump_label_init(); | 508 | jump_label_init(); |
509 | 509 | ||
@@ -699,16 +699,69 @@ int __init_or_module do_one_initcall(initcall_t fn) | |||
699 | } | 699 | } |
700 | 700 | ||
701 | 701 | ||
702 | extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[]; | 702 | extern initcall_t __initcall_start[]; |
703 | extern initcall_t __initcall0_start[]; | ||
704 | extern initcall_t __initcall1_start[]; | ||
705 | extern initcall_t __initcall2_start[]; | ||
706 | extern initcall_t __initcall3_start[]; | ||
707 | extern initcall_t __initcall4_start[]; | ||
708 | extern initcall_t __initcall5_start[]; | ||
709 | extern initcall_t __initcall6_start[]; | ||
710 | extern initcall_t __initcall7_start[]; | ||
711 | extern initcall_t __initcall_end[]; | ||
712 | |||
713 | static initcall_t *initcall_levels[] __initdata = { | ||
714 | __initcall0_start, | ||
715 | __initcall1_start, | ||
716 | __initcall2_start, | ||
717 | __initcall3_start, | ||
718 | __initcall4_start, | ||
719 | __initcall5_start, | ||
720 | __initcall6_start, | ||
721 | __initcall7_start, | ||
722 | __initcall_end, | ||
723 | }; | ||
724 | |||
725 | static char *initcall_level_names[] __initdata = { | ||
726 | "early parameters", | ||
727 | "core parameters", | ||
728 | "postcore parameters", | ||
729 | "arch parameters", | ||
730 | "subsys parameters", | ||
731 | "fs parameters", | ||
732 | "device parameters", | ||
733 | "late parameters", | ||
734 | }; | ||
735 | |||
736 | static int __init ignore_unknown_bootoption(char *param, char *val) | ||
737 | { | ||
738 | return 0; | ||
739 | } | ||
703 | 740 | ||
704 | static void __init do_initcalls(void) | 741 | static void __init do_initcall_level(int level) |
705 | { | 742 | { |
743 | extern const struct kernel_param __start___param[], __stop___param[]; | ||
706 | initcall_t *fn; | 744 | initcall_t *fn; |
707 | 745 | ||
708 | for (fn = __early_initcall_end; fn < __initcall_end; fn++) | 746 | strcpy(static_command_line, saved_command_line); |
747 | parse_args(initcall_level_names[level], | ||
748 | static_command_line, __start___param, | ||
749 | __stop___param - __start___param, | ||
750 | level, level, | ||
751 | ignore_unknown_bootoption); | ||
752 | |||
753 | for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++) | ||
709 | do_one_initcall(*fn); | 754 | do_one_initcall(*fn); |
710 | } | 755 | } |
711 | 756 | ||
757 | static void __init do_initcalls(void) | ||
758 | { | ||
759 | int level; | ||
760 | |||
761 | for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++) | ||
762 | do_initcall_level(level); | ||
763 | } | ||
764 | |||
712 | /* | 765 | /* |
713 | * Ok, the machine is now initialized. None of the devices | 766 | * Ok, the machine is now initialized. None of the devices |
714 | * have been touched yet, but the CPU subsystem is up and | 767 | * have been touched yet, but the CPU subsystem is up and |
@@ -732,7 +785,7 @@ static void __init do_pre_smp_initcalls(void) | |||
732 | { | 785 | { |
733 | initcall_t *fn; | 786 | initcall_t *fn; |
734 | 787 | ||
735 | for (fn = __initcall_start; fn < __early_initcall_end; fn++) | 788 | for (fn = __initcall_start; fn < __initcall0_start; fn++) |
736 | do_one_initcall(*fn); | 789 | do_one_initcall(*fn); |
737 | } | 790 | } |
738 | 791 | ||
diff --git a/kernel/module.c b/kernel/module.c index 2c932760fd3..78ac6ec1e42 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -105,6 +105,7 @@ struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ | |||
105 | 105 | ||
106 | /* Block module loading/unloading? */ | 106 | /* Block module loading/unloading? */ |
107 | int modules_disabled = 0; | 107 | int modules_disabled = 0; |
108 | core_param(nomodule, modules_disabled, bint, 0); | ||
108 | 109 | ||
109 | /* Waiting for a module to finish initializing? */ | 110 | /* Waiting for a module to finish initializing? */ |
110 | static DECLARE_WAIT_QUEUE_HEAD(module_wq); | 111 | static DECLARE_WAIT_QUEUE_HEAD(module_wq); |
@@ -903,6 +904,36 @@ static ssize_t show_refcnt(struct module_attribute *mattr, | |||
903 | static struct module_attribute modinfo_refcnt = | 904 | static struct module_attribute modinfo_refcnt = |
904 | __ATTR(refcnt, 0444, show_refcnt, NULL); | 905 | __ATTR(refcnt, 0444, show_refcnt, NULL); |
905 | 906 | ||
907 | void __module_get(struct module *module) | ||
908 | { | ||
909 | if (module) { | ||
910 | preempt_disable(); | ||
911 | __this_cpu_inc(module->refptr->incs); | ||
912 | trace_module_get(module, _RET_IP_); | ||
913 | preempt_enable(); | ||
914 | } | ||
915 | } | ||
916 | EXPORT_SYMBOL(__module_get); | ||
917 | |||
918 | bool try_module_get(struct module *module) | ||
919 | { | ||
920 | bool ret = true; | ||
921 | |||
922 | if (module) { | ||
923 | preempt_disable(); | ||
924 | |||
925 | if (likely(module_is_live(module))) { | ||
926 | __this_cpu_inc(module->refptr->incs); | ||
927 | trace_module_get(module, _RET_IP_); | ||
928 | } else | ||
929 | ret = false; | ||
930 | |||
931 | preempt_enable(); | ||
932 | } | ||
933 | return ret; | ||
934 | } | ||
935 | EXPORT_SYMBOL(try_module_get); | ||
936 | |||
906 | void module_put(struct module *module) | 937 | void module_put(struct module *module) |
907 | { | 938 | { |
908 | if (module) { | 939 | if (module) { |
@@ -2380,8 +2411,7 @@ static int copy_and_check(struct load_info *info, | |||
2380 | return -ENOEXEC; | 2411 | return -ENOEXEC; |
2381 | 2412 | ||
2382 | /* Suck in entire file: we'll want most of it. */ | 2413 | /* Suck in entire file: we'll want most of it. */ |
2383 | /* vmalloc barfs on "unusual" numbers. Check here */ | 2414 | if ((hdr = vmalloc(len)) == NULL) |
2384 | if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL) | ||
2385 | return -ENOMEM; | 2415 | return -ENOMEM; |
2386 | 2416 | ||
2387 | if (copy_from_user(hdr, umod, len) != 0) { | 2417 | if (copy_from_user(hdr, umod, len) != 0) { |
@@ -2922,7 +2952,8 @@ static struct module *load_module(void __user *umod, | |||
2922 | mutex_unlock(&module_mutex); | 2952 | mutex_unlock(&module_mutex); |
2923 | 2953 | ||
2924 | /* Module is ready to execute: parsing args may do that. */ | 2954 | /* Module is ready to execute: parsing args may do that. */ |
2925 | err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, NULL); | 2955 | err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, |
2956 | -32768, 32767, NULL); | ||
2926 | if (err < 0) | 2957 | if (err < 0) |
2927 | goto unlink; | 2958 | goto unlink; |
2928 | 2959 | ||
diff --git a/kernel/params.c b/kernel/params.c index 47f5bf12434..f37d8263134 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
@@ -87,6 +87,8 @@ static int parse_one(char *param, | |||
87 | char *val, | 87 | char *val, |
88 | const struct kernel_param *params, | 88 | const struct kernel_param *params, |
89 | unsigned num_params, | 89 | unsigned num_params, |
90 | s16 min_level, | ||
91 | s16 max_level, | ||
90 | int (*handle_unknown)(char *param, char *val)) | 92 | int (*handle_unknown)(char *param, char *val)) |
91 | { | 93 | { |
92 | unsigned int i; | 94 | unsigned int i; |
@@ -95,6 +97,9 @@ static int parse_one(char *param, | |||
95 | /* Find parameter */ | 97 | /* Find parameter */ |
96 | for (i = 0; i < num_params; i++) { | 98 | for (i = 0; i < num_params; i++) { |
97 | if (parameq(param, params[i].name)) { | 99 | if (parameq(param, params[i].name)) { |
100 | if (params[i].level < min_level | ||
101 | || params[i].level > max_level) | ||
102 | return 0; | ||
98 | /* No one handled NULL, so do it here. */ | 103 | /* No one handled NULL, so do it here. */ |
99 | if (!val && params[i].ops->set != param_set_bool | 104 | if (!val && params[i].ops->set != param_set_bool |
100 | && params[i].ops->set != param_set_bint) | 105 | && params[i].ops->set != param_set_bint) |
@@ -174,6 +179,8 @@ int parse_args(const char *name, | |||
174 | char *args, | 179 | char *args, |
175 | const struct kernel_param *params, | 180 | const struct kernel_param *params, |
176 | unsigned num, | 181 | unsigned num, |
182 | s16 min_level, | ||
183 | s16 max_level, | ||
177 | int (*unknown)(char *param, char *val)) | 184 | int (*unknown)(char *param, char *val)) |
178 | { | 185 | { |
179 | char *param, *val; | 186 | char *param, *val; |
@@ -189,7 +196,8 @@ int parse_args(const char *name, | |||
189 | 196 | ||
190 | args = next_arg(args, ¶m, &val); | 197 | args = next_arg(args, ¶m, &val); |
191 | irq_was_disabled = irqs_disabled(); | 198 | irq_was_disabled = irqs_disabled(); |
192 | ret = parse_one(param, val, params, num, unknown); | 199 | ret = parse_one(param, val, params, num, |
200 | min_level, max_level, unknown); | ||
193 | if (irq_was_disabled && !irqs_disabled()) { | 201 | if (irq_was_disabled && !irqs_disabled()) { |
194 | printk(KERN_WARNING "parse_args(): option '%s' enabled " | 202 | printk(KERN_WARNING "parse_args(): option '%s' enabled " |
195 | "irq's!\n", param); | 203 | "irq's!\n", param); |
@@ -297,35 +305,18 @@ EXPORT_SYMBOL(param_ops_charp); | |||
297 | /* Actually could be a bool or an int, for historical reasons. */ | 305 | /* Actually could be a bool or an int, for historical reasons. */ |
298 | int param_set_bool(const char *val, const struct kernel_param *kp) | 306 | int param_set_bool(const char *val, const struct kernel_param *kp) |
299 | { | 307 | { |
300 | bool v; | ||
301 | int ret; | ||
302 | |||
303 | /* No equals means "set"... */ | 308 | /* No equals means "set"... */ |
304 | if (!val) val = "1"; | 309 | if (!val) val = "1"; |
305 | 310 | ||
306 | /* One of =[yYnN01] */ | 311 | /* One of =[yYnN01] */ |
307 | ret = strtobool(val, &v); | 312 | return strtobool(val, kp->arg); |
308 | if (ret) | ||
309 | return ret; | ||
310 | |||
311 | if (kp->flags & KPARAM_ISBOOL) | ||
312 | *(bool *)kp->arg = v; | ||
313 | else | ||
314 | *(int *)kp->arg = v; | ||
315 | return 0; | ||
316 | } | 313 | } |
317 | EXPORT_SYMBOL(param_set_bool); | 314 | EXPORT_SYMBOL(param_set_bool); |
318 | 315 | ||
319 | int param_get_bool(char *buffer, const struct kernel_param *kp) | 316 | int param_get_bool(char *buffer, const struct kernel_param *kp) |
320 | { | 317 | { |
321 | bool val; | ||
322 | if (kp->flags & KPARAM_ISBOOL) | ||
323 | val = *(bool *)kp->arg; | ||
324 | else | ||
325 | val = *(int *)kp->arg; | ||
326 | |||
327 | /* Y and N chosen as being relatively non-coder friendly */ | 318 | /* Y and N chosen as being relatively non-coder friendly */ |
328 | return sprintf(buffer, "%c", val ? 'Y' : 'N'); | 319 | return sprintf(buffer, "%c", *(bool *)kp->arg ? 'Y' : 'N'); |
329 | } | 320 | } |
330 | EXPORT_SYMBOL(param_get_bool); | 321 | EXPORT_SYMBOL(param_get_bool); |
331 | 322 | ||
@@ -343,7 +334,6 @@ int param_set_invbool(const char *val, const struct kernel_param *kp) | |||
343 | struct kernel_param dummy; | 334 | struct kernel_param dummy; |
344 | 335 | ||
345 | dummy.arg = &boolval; | 336 | dummy.arg = &boolval; |
346 | dummy.flags = KPARAM_ISBOOL; | ||
347 | ret = param_set_bool(val, &dummy); | 337 | ret = param_set_bool(val, &dummy); |
348 | if (ret == 0) | 338 | if (ret == 0) |
349 | *(bool *)kp->arg = !boolval; | 339 | *(bool *)kp->arg = !boolval; |
@@ -372,7 +362,6 @@ int param_set_bint(const char *val, const struct kernel_param *kp) | |||
372 | /* Match bool exactly, by re-using it. */ | 362 | /* Match bool exactly, by re-using it. */ |
373 | boolkp = *kp; | 363 | boolkp = *kp; |
374 | boolkp.arg = &v; | 364 | boolkp.arg = &v; |
375 | boolkp.flags |= KPARAM_ISBOOL; | ||
376 | 365 | ||
377 | ret = param_set_bool(val, &boolkp); | 366 | ret = param_set_bool(val, &boolkp); |
378 | if (ret == 0) | 367 | if (ret == 0) |
@@ -393,7 +382,7 @@ static int param_array(const char *name, | |||
393 | unsigned int min, unsigned int max, | 382 | unsigned int min, unsigned int max, |
394 | void *elem, int elemsize, | 383 | void *elem, int elemsize, |
395 | int (*set)(const char *, const struct kernel_param *kp), | 384 | int (*set)(const char *, const struct kernel_param *kp), |
396 | u16 flags, | 385 | s16 level, |
397 | unsigned int *num) | 386 | unsigned int *num) |
398 | { | 387 | { |
399 | int ret; | 388 | int ret; |
@@ -403,7 +392,7 @@ static int param_array(const char *name, | |||
403 | /* Get the name right for errors. */ | 392 | /* Get the name right for errors. */ |
404 | kp.name = name; | 393 | kp.name = name; |
405 | kp.arg = elem; | 394 | kp.arg = elem; |
406 | kp.flags = flags; | 395 | kp.level = level; |
407 | 396 | ||
408 | *num = 0; | 397 | *num = 0; |
409 | /* We expect a comma-separated list of values. */ | 398 | /* We expect a comma-separated list of values. */ |
@@ -444,7 +433,7 @@ static int param_array_set(const char *val, const struct kernel_param *kp) | |||
444 | unsigned int temp_num; | 433 | unsigned int temp_num; |
445 | 434 | ||
446 | return param_array(kp->name, val, 1, arr->max, arr->elem, | 435 | return param_array(kp->name, val, 1, arr->max, arr->elem, |
447 | arr->elemsize, arr->ops->set, kp->flags, | 436 | arr->elemsize, arr->ops->set, kp->level, |
448 | arr->num ?: &temp_num); | 437 | arr->num ?: &temp_num); |
449 | } | 438 | } |
450 | 439 | ||