Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions usr/share/hardened-kernel/build
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ tar -xf "${source_folder}/linux-${version}.tar.xz" -C "$working_folder"
ls "$extracted_linux_kernel_sources_folder"

cat "${source_folder}/linux-hardened-${version}.a.patch" | patch --silent -p1 -d "$extracted_linux_kernel_sources_folder"
cat "${MYDIR}/patches/lockdown/*.patch" | patch --silent -p1 -d "$extracted_linux_kernel_sources_folder"

cp "${MYDIR}/${kernel_config}" "$extracted_linux_kernel_sources_folder/.config"

Expand Down
1 change: 1 addition & 0 deletions usr/share/hardened-kernel/hardened-host-kernel
Original file line number Diff line number Diff line change
Expand Up @@ -6958,6 +6958,7 @@ CONFIG_FORTIFY_SOURCE=y
CONFIG_PAGE_SANITIZE=y
CONFIG_PAGE_SANITIZE_VERIFY=y
# CONFIG_STATIC_USERMODEHELPER is not set
CONFIG_SECURITY_LOCKDOWN=y
# CONFIG_SECURITY_SELINUX is not set
# CONFIG_SECURITY_SMACK is not set
# CONFIG_SECURITY_TOMOYO is not set
Expand Down
1 change: 1 addition & 0 deletions usr/share/hardened-kernel/hardened-vm-kernel
Original file line number Diff line number Diff line change
Expand Up @@ -4643,6 +4643,7 @@ CONFIG_FORTIFY_SOURCE=y
CONFIG_PAGE_SANITIZE=y
CONFIG_PAGE_SANITIZE_VERIFY=y
# CONFIG_STATIC_USERMODEHELPER is not set
CONFIG_SECURITY_LOCKDOWN=y
# CONFIG_SECURITY_SELINUX is not set
# CONFIG_SECURITY_SMACK is not set
# CONFIG_SECURITY_TOMOYO is not set
Expand Down
81 changes: 81 additions & 0 deletions usr/share/hardened-kernel/patches/lockdown/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
This patchset implements features of the lockdown LSM that we need as
lockdown is not available in LTS kernels.

Features that are already mitigated by our kernel configuration are not
implemented.

# lockdown-kconfig.patch:

Creates the CONFIG_SECURITY_LOCKDOWN kconfig setting and boot parameter
to enable/disable kernel lockdown.

# lockdown-efivar_ssdt_load.patch:

Disables efivar_ssdt_load.

Only useful for the host kernel.

> efivar_ssdt_load allows the kernel to import arbitrary ACPI code from an
EFI variable, which gives arbitrary code execution in ring 0. Prevent
that when the kernel is locked down.

# lockdown-pci-bar-access.patch:

Locks down PCI BAR access.

> Any hardware that can potentially generate DMA has to be locked down in
order to avoid it being possible for an attacker to modify kernel code,
allowing them to circumvent disabled module loading or module signing.
Default to paranoid - in future we can potentially relax this for
sufficiently IOMMU-isolated devices.

# lockdown-perf.patch:

Locks down perf.

The official lockdown patchset only locks down REGS_INTR but this patch
disables perf_event_open entirely to further reduce attack surface.

This will be dropped if perf_event_paranoid=4 support is merged into
linux-hardened.

> Disallow the use of certain perf facilities that might allow userspace to
access kernel data.

# lockdown-tiocsserial.patch

Locks down TIOCSSERIAL.

> Lock down TIOCSSERIAL as that can be used to change the ioport and irq
settings on a serial port. This only appears to be an issue for the serial
drivers that use the core serial code. All other drivers seem to either
ignore attempts to change port/irq or give an error.

# lockdown-ioport.patch:

Locks down IO port access (specifically, the ioperm() and iopl() syscalls).

> IO port access would permit users to gain access to PCI configuration
registers, which in turn (on a lot of hardware) give access to MMIO
register space. This would potentially permit root to trigger arbitrary
DMA, so lock it down by default.
>
> This also implicitly locks down the KDADDIO, KDDELIO, KDENABIO and
KDDISABIO console ioctls.

# lockdown-pcmcia.patch:

Locks down PCMCIA.

Only useful for the host kernel.

> Prohibit replacement of the PCMCIA Card Information Structure when the
kernel is locked down.

# lockdown-module-params.patch:

Locks down module parameters.

> Provided an annotation for module parameters that specify hardware
parameters (such as io ports, iomem addresses, irqs, dma channels, fixed
dma buffers and other types).
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index d54fca9..94b0781 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -31,6 +31,7 @@
#include <linux/acpi.h>
#include <linux/ucs2_string.h>
#include <linux/memblock.h>
+#include <linux/security.h>

#include <asm/early_ioremap.h>

@@ -241,6 +242,9 @@ static void generic_ops_unregister(void)
static char efivar_ssdt[EFIVAR_SSDT_NAME_MAX] __initdata;
static int __init efivar_ssdt_setup(char *str)
{
+ if (kernel_lockdown)
+ return -EPERM;
+
if (strlen(str) < sizeof(efivar_ssdt))
memcpy(efivar_ssdt, str, strlen(str));
else
32 changes: 32 additions & 0 deletions usr/share/hardened-kernel/patches/lockdown/lockdown-ioport.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c
index 0fe1c87..e6a02e7 100644
--- a/arch/x86/kernel/ioport.c
+++ b/arch/x86/kernel/ioport.c
@@ -11,6 +11,7 @@
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/ioport.h>
+#include <linux/security.h>
#include <linux/smp.h>
#include <linux/stddef.h>
#include <linux/slab.h>
@@ -31,7 +32,8 @@ long ksys_ioperm(unsigned long from, unsigned long num, int turn_on)

if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
return -EINVAL;
- if (turn_on && !capable(CAP_SYS_RAWIO))
+ if (turn_on && (!capable(CAP_SYS_RAWIO) ||
+ kernel_lockdown))
return -EPERM;

/*
@@ -126,7 +128,8 @@ SYSCALL_DEFINE1(iopl, unsigned int, level)
return -EINVAL;
/* Trying to gain more privileges? */
if (level > old) {
- if (!capable(CAP_SYS_RAWIO))
+ if (!capable(CAP_SYS_RAWIO) ||
+ kernel_lockdown)
return -EPERM;
}
regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) |
86 changes: 86 additions & 0 deletions usr/share/hardened-kernel/patches/lockdown/lockdown-kconfig.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 9ae9f28..6f31664 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -2186,6 +2186,12 @@
lockd.nlm_udpport=M [NFS] Assign UDP port.
Format: <integer>

+ lockdown= [SECURITY]
+ { on | off }
+ Enable the kernel lockdown feature. If set to on,
+ kernel lockdown will be enabled and features that
+ allow userspace to modify the kernel will be disabled.
+
locktorture.nreaders_stress= [KNL]
Set the number of locking read-acquisition kthreads.
Defaults to being automatically set based on the
diff --git a/include/linux/security.h b/include/linux/security.h
index 75f4156..1a69db0 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -66,6 +66,9 @@ struct audit_krule;
struct user_namespace;
struct timezone;

+/* Kernel lockdown */
+extern int kernel_lockdown;
+
enum lsm_event {
LSM_POLICY_CHANGE,
};
diff --git a/security/Kconfig b/security/Kconfig
index a921713..92b4f43 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -281,6 +281,13 @@ config STATIC_USERMODEHELPER_PATH
If you wish for all usermode helper programs to be disabled,
specify an empty string here (i.e. "").

+config SECURITY_LOCKDOWN
+ bool "Enable kernel lockdown"
+ default y
+ help
+ Enables kernel lockdown which disables any feature that
+ userspace can abuse to compromise the kernel.
+
source security/selinux/Kconfig
source security/smack/Kconfig
source security/tomoyo/Kconfig
diff --git a/security/Makefile b/security/Makefile
index 4d2d378..4b183ad 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -30,3 +30,6 @@ obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
# Object integrity file lists
subdir-$(CONFIG_INTEGRITY) += integrity
obj-$(CONFIG_INTEGRITY) += integrity/
+
+# Kernel lockdown
+obj-y += lockdown.o
diff --git a/security/lockdown.c b/security/lockdown.c
new file mode 100644
index 0000000..f9291b3
--- /dev/null
+++ b/security/lockdown.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/security.h>
+
+int kernel_lockdown __ro_after_init = IS_ENABLED(CONFIG_SECURITY_LOCKDOWN);
+
+static int __init enable_lockdown(char *level)
+{
+ if (!level)
+ return -EINVAL;
+
+ if (strcmp(level, "on") == 0)
+ kernel_lockdown = 1;
+ else if (strcmp(level, "off") == 0)
+ kernel_lockdown = 0;
+ else
+ return -EINVAL;
+
+ return 0;
+}
+early_param("lockdown", enable_lockdown);
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
diff --git a/kernel/params.c b/kernel/params.c
index ce89f75..98221b8 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -24,6 +24,7 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/ctype.h>
+#include <linux/security.h>

#ifdef CONFIG_SYSFS
/* Protects all built-in parameters, modules use their own param_lock */
@@ -108,13 +109,19 @@ bool parameq(const char *a, const char *b)
return parameqn(a, b, strlen(a)+1);
}

-static void param_check_unsafe(const struct kernel_param *kp)
+static bool param_check_unsafe(const struct kernel_param *kp)
{
+ if (kp->flags & KERNEL_PARAM_FL_HWPARAM &&
+ kernel_lockdown)
+ return false;
+
if (kp->flags & KERNEL_PARAM_FL_UNSAFE) {
pr_notice("Setting dangerous option %s - tainting kernel\n",
kp->name);
add_taint(TAINT_USER, LOCKDEP_STILL_OK);
}
+
+ return true;
}

static int parse_one(char *param,
@@ -144,8 +151,10 @@ static int parse_one(char *param,
pr_debug("handling %s with %p\n", param,
params[i].ops->set);
kernel_param_lock(params[i].mod);
- param_check_unsafe(&params[i]);
- err = params[i].ops->set(val, &params[i]);
+ if (param_check_unsafe(&params[i]))
+ err = params[i].ops->set(val, &params[i]);
+ else
+ err = -EPERM;
kernel_param_unlock(params[i].mod);
return err;
}
@@ -565,8 +574,10 @@ static ssize_t param_attr_store(struct module_attribute *mattr,
return -EPERM;

kernel_param_lock(mk->mod);
- param_check_unsafe(attribute->param);
- err = attribute->param->ops->set(buf, attribute->param);
+ if (param_check_unsafe(attribute->param))
+ err = attribute->param->ops->set(buf, attribute->param);
+ else
+ err = -EPERM;
kernel_param_unlock(mk->mod);
if (!err)
return len;
Loading