Commit 3d43321b7015387cfebbe26436d0e9d299162ea1
Committed by
James Morris
1 parent
8a6f83afd0
Exists in
master
and in
7 other branches
modules: sysctl to block module loading
Implement a sysctl file that disables module-loading system-wide since there is no longer a viable way to remove CAP_SYS_MODULE after the system bounding capability set was removed in 2.6.25. Value can only be set to "1", and is tested only if standard capability checks allow CAP_SYS_MODULE. Given existing /dev/mem protections, this should allow administrators a one-way method to block module loading after initial boot-time module loading has finished. Signed-off-by: Kees Cook <kees.cook@canonical.com> Acked-by: Serge Hallyn <serue@us.ibm.com> Signed-off-by: James Morris <jmorris@namei.org>
Showing 3 changed files with 28 additions and 2 deletions Side-by-side Diff
Documentation/sysctl/kernel.txt
... | ... | @@ -30,6 +30,7 @@ |
30 | 30 | - kstack_depth_to_print [ X86 only ] |
31 | 31 | - l2cr [ PPC only ] |
32 | 32 | - modprobe ==> Documentation/debugging-modules.txt |
33 | +- modules_disabled | |
33 | 34 | - msgmax |
34 | 35 | - msgmnb |
35 | 36 | - msgmni |
... | ... | @@ -176,6 +177,16 @@ |
176 | 177 | |
177 | 178 | Controls the number of words to print when dumping the raw |
178 | 179 | kernel stack. |
180 | + | |
181 | +============================================================== | |
182 | + | |
183 | +modules_disabled: | |
184 | + | |
185 | +A toggle value indicating if modules are allowed to be loaded | |
186 | +in an otherwise modular kernel. This toggle defaults to off | |
187 | +(0), but can be set true (1). Once true, modules can be | |
188 | +neither loaded nor unloaded, and the toggle cannot be set back | |
189 | +to false. | |
179 | 190 | |
180 | 191 | ============================================================== |
181 | 192 |
kernel/module.c
... | ... | @@ -778,6 +778,9 @@ |
778 | 778 | mutex_lock(&module_mutex); |
779 | 779 | } |
780 | 780 | |
781 | +/* Block module loading/unloading? */ | |
782 | +int modules_disabled = 0; | |
783 | + | |
781 | 784 | SYSCALL_DEFINE2(delete_module, const char __user *, name_user, |
782 | 785 | unsigned int, flags) |
783 | 786 | { |
... | ... | @@ -785,7 +788,7 @@ |
785 | 788 | char name[MODULE_NAME_LEN]; |
786 | 789 | int ret, forced = 0; |
787 | 790 | |
788 | - if (!capable(CAP_SYS_MODULE)) | |
791 | + if (!capable(CAP_SYS_MODULE) || modules_disabled) | |
789 | 792 | return -EPERM; |
790 | 793 | |
791 | 794 | if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0) |
... | ... | @@ -2349,7 +2352,7 @@ |
2349 | 2352 | int ret = 0; |
2350 | 2353 | |
2351 | 2354 | /* Must have permission */ |
2352 | - if (!capable(CAP_SYS_MODULE)) | |
2355 | + if (!capable(CAP_SYS_MODULE) || modules_disabled) | |
2353 | 2356 | return -EPERM; |
2354 | 2357 | |
2355 | 2358 | /* Only one module load at a time, please */ |
kernel/sysctl.c
... | ... | @@ -113,6 +113,7 @@ |
113 | 113 | |
114 | 114 | #ifdef CONFIG_MODULES |
115 | 115 | extern char modprobe_path[]; |
116 | +extern int modules_disabled; | |
116 | 117 | #endif |
117 | 118 | #ifdef CONFIG_CHR_DEV_SG |
118 | 119 | extern int sg_big_buff; |
... | ... | @@ -532,6 +533,17 @@ |
532 | 533 | .mode = 0644, |
533 | 534 | .proc_handler = &proc_dostring, |
534 | 535 | .strategy = &sysctl_string, |
536 | + }, | |
537 | + { | |
538 | + .ctl_name = CTL_UNNUMBERED, | |
539 | + .procname = "modules_disabled", | |
540 | + .data = &modules_disabled, | |
541 | + .maxlen = sizeof(int), | |
542 | + .mode = 0644, | |
543 | + /* only handle a transition from default "0" to "1" */ | |
544 | + .proc_handler = &proc_dointvec_minmax, | |
545 | + .extra1 = &one, | |
546 | + .extra2 = &one, | |
535 | 547 | }, |
536 | 548 | #endif |
537 | 549 | #if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET) |