blob: 4745278e0f3bbb7bb9624e6e29b8f668692e1d61 [file] [edit]
/* Lock down the kernel
*
* Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/
#include <linux/security.h>
#include <linux/export.h>
#include <linux/sysrq.h>
#include <linux/efi.h>
#include <asm/setup.h>
#ifdef CONFIG_ALLOW_LOCKDOWN_LIFT_BY_SYSRQ
static __read_mostly bool kernel_locked_down;
#else
static __ro_after_init bool kernel_locked_down;
#endif
/*
* Put the kernel into lock-down mode.
*/
static void __init lock_kernel_down(const char *where)
{
if (!kernel_locked_down) {
kernel_locked_down = true;
pr_notice("Kernel is locked down from %s; see man kernel_lockdown.7\n",
where);
}
}
static int __init lockdown_param(char *ignored)
{
lock_kernel_down("command line");
return 0;
}
early_param("lockdown", lockdown_param);
/*
* Lock the kernel down from very early in the arch setup. This must happen
* prior to things like ACPI being initialised.
*/
void __init init_lockdown(void)
{
#ifdef CONFIG_LOCK_DOWN_IN_EFI_SECURE_BOOT
if (efi_enabled(EFI_SECURE_BOOT))
lock_kernel_down("EFI secure boot");
#endif
}
/**
* kernel_is_locked_down - Find out if the kernel is locked down
* @what: Tag to use in notice generated if lockdown is in effect
*/
bool __kernel_is_locked_down(const char *what, bool first)
{
if (what && first && kernel_locked_down)
pr_notice("Lockdown: %s: %s is restricted; see man kernel_lockdown.7\n",
current->comm, what);
return kernel_locked_down;
}
EXPORT_SYMBOL(__kernel_is_locked_down);
#ifdef CONFIG_ALLOW_LOCKDOWN_LIFT_BY_SYSRQ
/*
* Take the kernel out of lockdown mode.
*/
static void lift_kernel_lockdown(void)
{
pr_notice("Lifting lockdown\n");
kernel_locked_down = false;
}
/*
* Allow lockdown to be lifted by pressing something like SysRq+x (and not by
* echoing the appropriate letter into the sysrq-trigger file).
*/
static void sysrq_handle_lockdown_lift(int key)
{
if (kernel_locked_down)
lift_kernel_lockdown();
}
static struct sysrq_key_op lockdown_lift_sysrq_op = {
.handler = sysrq_handle_lockdown_lift,
.help_msg = "unSB(x)",
.action_msg = "Disabling Secure Boot restrictions",
.enable_mask = SYSRQ_DISABLE_USERSPACE,
};
static int __init lockdown_lift_sysrq(void)
{
if (kernel_locked_down) {
lockdown_lift_sysrq_op.help_msg[5] = LOCKDOWN_LIFT_KEY;
register_sysrq_key(LOCKDOWN_LIFT_KEY, &lockdown_lift_sysrq_op);
}
return 0;
}
late_initcall(lockdown_lift_sysrq);
#endif /* CONFIG_ALLOW_LOCKDOWN_LIFT_BY_SYSRQ */