Skip to content

Commit

Permalink
kexec: add sysctl to disable kexec_load
Browse files Browse the repository at this point in the history
For general-purpose (i.e.  distro) kernel builds it makes sense to build
with CONFIG_KEXEC to allow end users to choose what kind of things they
want to do with kexec.  However, in the face of trying to lock down a
system with such a kernel, there needs to be a way to disable kexec_load
(much like module loading can be disabled).  Without this, it is too easy
for the root user to modify kernel memory even when CONFIG_STRICT_DEVMEM
and modules_disabled are set.  With this change, it is still possible to
load an image for use later, then disable kexec_load so the image (or lack
of image) can't be altered.

The intention is for using this in environments where "perfect"
enforcement is hard.  Without a verified boot, along with verified
modules, and along with verified kexec, this is trying to give a system a
better chance to defend itself (or at least grow the window of
discoverability) against attack in the face of a privilege escalation.

In my mind, I consider several boot scenarios:

1) Verified boot of read-only verified root fs loading fd-based
   verification of kexec images.
2) Secure boot of writable root fs loading signed kexec images.
3) Regular boot loading kexec (e.g. kcrash) image early and locking it.
4) Regular boot with no control of kexec image at all.

1 and 2 don't exist yet, but will soon once the verified kexec series has
landed.  4 is the state of things now.  The gap between 2 and 4 is too
large, so this change creates scenario 3, a middle-ground above 4 when 2
and 1 are not possible for a system.

Signed-off-by: Kees Cook <[email protected]>
Acked-by: Rik van Riel <[email protected]>
Cc: Vivek Goyal <[email protected]>
Cc: Eric Biederman <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
kees authored and torvalds committed Jan 24, 2014
1 parent 3b96d7d commit 7984754
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 2 deletions.
15 changes: 14 additions & 1 deletion Documentation/sysctl/kernel.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ show up in /proc/sys/kernel:
- domainname
- hostname
- hotplug
- kexec_load_disabled
- kptr_restrict
- kstack_depth_to_print [ X86 only ]
- l2cr [ PPC only ]
Expand Down Expand Up @@ -287,6 +288,18 @@ Default value is "/sbin/hotplug".

==============================================================

kexec_load_disabled:

A toggle indicating if the kexec_load syscall has been disabled. This
value defaults to 0 (false: kexec_load enabled), but can be set to 1
(true: kexec_load disabled). Once true, kexec can no longer be used, and
the toggle cannot be set back to false. This allows a kexec image to be
loaded before disabling the syscall, allowing a system to set up (and
later use) an image without it being altered. Generally used together
with the "modules_disabled" sysctl.

==============================================================

kptr_restrict:

This toggle indicates whether restrictions are placed on
Expand Down Expand Up @@ -331,7 +344,7 @@ A toggle value indicating if modules are allowed to be loaded
in an otherwise modular kernel. This toggle defaults to off
(0), but can be set true (1). Once true, modules can be
neither loaded nor unloaded, and the toggle cannot be set back
to false.
to false. Generally used with the "kexec_load_disabled" toggle.

==============================================================

Expand Down
1 change: 1 addition & 0 deletions include/linux/kexec.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ unsigned long paddr_vmcoreinfo_note(void);

extern struct kimage *kexec_image;
extern struct kimage *kexec_crash_image;
extern int kexec_load_disabled;

#ifndef kexec_flush_icache_page
#define kexec_flush_icache_page(page)
Expand Down
3 changes: 2 additions & 1 deletion kernel/kexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,7 @@ static int kimage_load_segment(struct kimage *image,
*/
struct kimage *kexec_image;
struct kimage *kexec_crash_image;
int kexec_load_disabled;

static DEFINE_MUTEX(kexec_mutex);

Expand All @@ -942,7 +943,7 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
int result;

/* We only trust the superuser with rebooting the system. */
if (!capable(CAP_SYS_BOOT))
if (!capable(CAP_SYS_BOOT) || kexec_load_disabled)
return -EPERM;

/*
Expand Down
13 changes: 13 additions & 0 deletions kernel/sysctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
#include <linux/capability.h>
#include <linux/binfmts.h>
#include <linux/sched/sysctl.h>
#include <linux/kexec.h>

#include <asm/uaccess.h>
#include <asm/processor.h>
Expand Down Expand Up @@ -614,6 +615,18 @@ static struct ctl_table kern_table[] = {
.proc_handler = proc_dointvec,
},
#endif
#ifdef CONFIG_KEXEC
{
.procname = "kexec_load_disabled",
.data = &kexec_load_disabled,
.maxlen = sizeof(int),
.mode = 0644,
/* only handle a transition from default "0" to "1" */
.proc_handler = proc_dointvec_minmax,
.extra1 = &one,
.extra2 = &one,
},
#endif
#ifdef CONFIG_MODULES
{
.procname = "modprobe",
Expand Down

0 comments on commit 7984754

Please sign in to comment.