Skip to content

Commit aefcf2f

Browse files
committed
Merge branch 'next-lockdown' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull kernel lockdown mode from James Morris: "This is the latest iteration of the kernel lockdown patchset, from Matthew Garrett, David Howells and others. From the original description: This patchset introduces an optional kernel lockdown feature, intended to strengthen the boundary between UID 0 and the kernel. When enabled, various pieces of kernel functionality are restricted. Applications that rely on low-level access to either hardware or the kernel may cease working as a result - therefore this should not be enabled without appropriate evaluation beforehand. The majority of mainstream distributions have been carrying variants of this patchset for many years now, so there's value in providing a doesn't meet every distribution requirement, but gets us much closer to not requiring external patches. There are two major changes since this was last proposed for mainline: - Separating lockdown from EFI secure boot. Background discussion is covered here: https://lwn.net/Articles/751061/ - Implementation as an LSM, with a default stackable lockdown LSM module. This allows the lockdown feature to be policy-driven, rather than encoding an implicit policy within the mechanism. The new locked_down LSM hook is provided to allow LSMs to make a policy decision around whether kernel functionality that would allow tampering with or examining the runtime state of the kernel should be permitted. The included lockdown LSM provides an implementation with a simple policy intended for general purpose use. This policy provides a coarse level of granularity, controllable via the kernel command line: lockdown={integrity|confidentiality} Enable the kernel lockdown feature. If set to integrity, kernel features that allow userland to modify the running kernel are disabled. If set to confidentiality, kernel features that allow userland to extract confidential information from the kernel are also disabled. This may also be controlled via /sys/kernel/security/lockdown and overriden by kernel configuration. New or existing LSMs may implement finer-grained controls of the lockdown features. Refer to the lockdown_reason documentation in include/linux/security.h for details. The lockdown feature has had signficant design feedback and review across many subsystems. This code has been in linux-next for some weeks, with a few fixes applied along the way. Stephen Rothwell noted that commit 9d1f8be ("bpf: Restrict bpf when kernel lockdown is in confidentiality mode") is missing a Signed-off-by from its author. Matthew responded that he is providing this under category (c) of the DCO" * 'next-lockdown' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (31 commits) kexec: Fix file verification on S390 security: constify some arrays in lockdown LSM lockdown: Print current->comm in restriction messages efi: Restrict efivar_ssdt_load when the kernel is locked down tracefs: Restrict tracefs when the kernel is locked down debugfs: Restrict debugfs when the kernel is locked down kexec: Allow kexec_file() with appropriate IMA policy when locked down lockdown: Lock down perf when in confidentiality mode bpf: Restrict bpf when kernel lockdown is in confidentiality mode lockdown: Lock down tracing and perf kprobes when in confidentiality mode lockdown: Lock down /proc/kcore x86/mmiotrace: Lock down the testmmiotrace module lockdown: Lock down module params that specify hardware parameters (eg. ioport) lockdown: Lock down TIOCSSERIAL lockdown: Prohibit PCMCIA CIS storage when the kernel is locked down acpi: Disable ACPI table override if the kernel is locked down acpi: Ignore acpi_rsdp kernel param when the kernel has been locked down ACPI: Limit access to custom_method when the kernel is locked down x86/msr: Restrict MSR access when the kernel is locked down x86: Lock down IO port access when the kernel is locked down ...
2 parents f1f2f61 + 45893a0 commit aefcf2f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+861
-76
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2276,6 +2276,15 @@
22762276
lockd.nlm_udpport=M [NFS] Assign UDP port.
22772277
Format: <integer>
22782278

2279+
lockdown= [SECURITY]
2280+
{ integrity | confidentiality }
2281+
Enable the kernel lockdown feature. If set to
2282+
integrity, kernel features that allow userland to
2283+
modify the running kernel are disabled. If set to
2284+
confidentiality, kernel features that allow userland
2285+
to extract confidential information from the kernel
2286+
are also disabled.
2287+
22792288
locktorture.nreaders_stress= [KNL]
22802289
Set the number of locking read-acquisition kthreads.
22812290
Defaults to being automatically set based on the

arch/arm64/Kconfig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,7 @@ config KEXEC_FILE
982982
for kernel and initramfs as opposed to list of segments as
983983
accepted by previous system call.
984984

985-
config KEXEC_VERIFY_SIG
985+
config KEXEC_SIG
986986
bool "Verify kernel signature during kexec_file_load() syscall"
987987
depends on KEXEC_FILE
988988
help
@@ -997,13 +997,13 @@ config KEXEC_VERIFY_SIG
997997
config KEXEC_IMAGE_VERIFY_SIG
998998
bool "Enable Image signature verification support"
999999
default y
1000-
depends on KEXEC_VERIFY_SIG
1000+
depends on KEXEC_SIG
10011001
depends on EFI && SIGNED_PE_FILE_VERIFICATION
10021002
help
10031003
Enable Image signature verification support.
10041004

10051005
comment "Support for PE file signature verification disabled"
1006-
depends on KEXEC_VERIFY_SIG
1006+
depends on KEXEC_SIG
10071007
depends on !EFI || !SIGNED_PE_FILE_VERIFICATION
10081008

10091009
config CRASH_DUMP

arch/s390/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ config ARCH_HAS_KEXEC_PURGATORY
554554
def_bool y
555555
depends on KEXEC_FILE
556556

557-
config KEXEC_VERIFY_SIG
557+
config KEXEC_SIG
558558
bool "Verify kernel signature during kexec_file_load() syscall"
559559
depends on KEXEC_FILE && MODULE_SIG_FORMAT
560560
help

arch/s390/kernel/kexec_elf.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ static int s390_elf_probe(const char *buf, unsigned long len)
130130
const struct kexec_file_ops s390_kexec_elf_ops = {
131131
.probe = s390_elf_probe,
132132
.load = s390_elf_load,
133-
#ifdef CONFIG_KEXEC_VERIFY_SIG
133+
#ifdef CONFIG_KEXEC_SIG
134134
.verify_sig = s390_verify_sig,
135-
#endif /* CONFIG_KEXEC_VERIFY_SIG */
135+
#endif /* CONFIG_KEXEC_SIG */
136136
};

arch/s390/kernel/kexec_image.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ static int s390_image_probe(const char *buf, unsigned long len)
5959
const struct kexec_file_ops s390_kexec_image_ops = {
6060
.probe = s390_image_probe,
6161
.load = s390_image_load,
62-
#ifdef CONFIG_KEXEC_VERIFY_SIG
62+
#ifdef CONFIG_KEXEC_SIG
6363
.verify_sig = s390_verify_sig,
64-
#endif /* CONFIG_KEXEC_VERIFY_SIG */
64+
#endif /* CONFIG_KEXEC_SIG */
6565
};

arch/s390/kernel/machine_kexec_file.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const struct kexec_file_ops * const kexec_file_loaders[] = {
2222
NULL,
2323
};
2424

25-
#ifdef CONFIG_KEXEC_VERIFY_SIG
25+
#ifdef CONFIG_KEXEC_SIG
2626
int s390_verify_sig(const char *kernel, unsigned long kernel_len)
2727
{
2828
const unsigned long marker_len = sizeof(MODULE_SIG_STRING) - 1;
@@ -68,7 +68,7 @@ int s390_verify_sig(const char *kernel, unsigned long kernel_len)
6868
VERIFYING_MODULE_SIGNATURE,
6969
NULL, NULL);
7070
}
71-
#endif /* CONFIG_KEXEC_VERIFY_SIG */
71+
#endif /* CONFIG_KEXEC_SIG */
7272

7373
static int kexec_file_update_purgatory(struct kimage *image,
7474
struct s390_load_data *data)

arch/x86/Kconfig

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2031,20 +2031,30 @@ config KEXEC_FILE
20312031
config ARCH_HAS_KEXEC_PURGATORY
20322032
def_bool KEXEC_FILE
20332033

2034-
config KEXEC_VERIFY_SIG
2034+
config KEXEC_SIG
20352035
bool "Verify kernel signature during kexec_file_load() syscall"
20362036
depends on KEXEC_FILE
20372037
---help---
2038-
This option makes kernel signature verification mandatory for
2039-
the kexec_file_load() syscall.
20402038

2041-
In addition to that option, you need to enable signature
2039+
This option makes the kexec_file_load() syscall check for a valid
2040+
signature of the kernel image. The image can still be loaded without
2041+
a valid signature unless you also enable KEXEC_SIG_FORCE, though if
2042+
there's a signature that we can check, then it must be valid.
2043+
2044+
In addition to this option, you need to enable signature
20422045
verification for the corresponding kernel image type being
20432046
loaded in order for this to work.
20442047

2048+
config KEXEC_SIG_FORCE
2049+
bool "Require a valid signature in kexec_file_load() syscall"
2050+
depends on KEXEC_SIG
2051+
---help---
2052+
This option makes kernel signature verification mandatory for
2053+
the kexec_file_load() syscall.
2054+
20452055
config KEXEC_BZIMAGE_VERIFY_SIG
20462056
bool "Enable bzImage signature verification support"
2047-
depends on KEXEC_VERIFY_SIG
2057+
depends on KEXEC_SIG
20482058
depends on SIGNED_PE_FILE_VERIFICATION
20492059
select SYSTEM_TRUSTED_KEYRING
20502060
---help---

arch/x86/boot/compressed/acpi.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ struct mem_vector immovable_mem[MAX_NUMNODES*2];
2626
*/
2727
#define MAX_ADDR_LEN 19
2828

29-
static acpi_physical_address get_acpi_rsdp(void)
29+
static acpi_physical_address get_cmdline_acpi_rsdp(void)
3030
{
3131
acpi_physical_address addr = 0;
3232

@@ -278,10 +278,7 @@ acpi_physical_address get_rsdp_addr(void)
278278
{
279279
acpi_physical_address pa;
280280

281-
pa = get_acpi_rsdp();
282-
283-
if (!pa)
284-
pa = boot_params->acpi_rsdp_addr;
281+
pa = boot_params->acpi_rsdp_addr;
285282

286283
/*
287284
* Try to get EFI data from setup_data. This can happen when we're a
@@ -311,7 +308,17 @@ static unsigned long get_acpi_srat_table(void)
311308
char arg[10];
312309
u8 *entry;
313310

314-
rsdp = (struct acpi_table_rsdp *)(long)boot_params->acpi_rsdp_addr;
311+
/*
312+
* Check whether we were given an RSDP on the command line. We don't
313+
* stash this in boot params because the kernel itself may have
314+
* different ideas about whether to trust a command-line parameter.
315+
*/
316+
rsdp = (struct acpi_table_rsdp *)get_cmdline_acpi_rsdp();
317+
318+
if (!rsdp)
319+
rsdp = (struct acpi_table_rsdp *)(long)
320+
boot_params->acpi_rsdp_addr;
321+
315322
if (!rsdp)
316323
return 0;
317324

arch/x86/include/asm/acpi.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@ static inline bool acpi_has_cpu_in_madt(void)
117117
return !!acpi_lapic;
118118
}
119119

120+
#define ACPI_HAVE_ARCH_SET_ROOT_POINTER
121+
static inline void acpi_arch_set_root_pointer(u64 addr)
122+
{
123+
x86_init.acpi.set_root_pointer(addr);
124+
}
125+
120126
#define ACPI_HAVE_ARCH_GET_ROOT_POINTER
121127
static inline u64 acpi_arch_get_root_pointer(void)
122128
{
@@ -125,6 +131,7 @@ static inline u64 acpi_arch_get_root_pointer(void)
125131

126132
void acpi_generic_reduced_hw_init(void);
127133

134+
void x86_default_set_root_pointer(u64 addr);
128135
u64 x86_default_get_root_pointer(void);
129136

130137
#else /* !CONFIG_ACPI */
@@ -138,6 +145,8 @@ static inline void disable_acpi(void) { }
138145

139146
static inline void acpi_generic_reduced_hw_init(void) { }
140147

148+
static inline void x86_default_set_root_pointer(u64 addr) { }
149+
141150
static inline u64 x86_default_get_root_pointer(void)
142151
{
143152
return 0;

arch/x86/include/asm/x86_init.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,12 @@ struct x86_hyper_init {
134134

135135
/**
136136
* struct x86_init_acpi - x86 ACPI init functions
137+
* @set_root_poitner: set RSDP address
137138
* @get_root_pointer: get RSDP address
138139
* @reduced_hw_early_init: hardware reduced platform early init
139140
*/
140141
struct x86_init_acpi {
142+
void (*set_root_pointer)(u64 addr);
141143
u64 (*get_root_pointer)(void);
142144
void (*reduced_hw_early_init)(void);
143145
};

arch/x86/kernel/acpi/boot.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1760,6 +1760,11 @@ void __init arch_reserve_mem_area(acpi_physical_address addr, size_t size)
17601760
e820__update_table_print();
17611761
}
17621762

1763+
void x86_default_set_root_pointer(u64 addr)
1764+
{
1765+
boot_params.acpi_rsdp_addr = addr;
1766+
}
1767+
17631768
u64 x86_default_get_root_pointer(void)
17641769
{
17651770
return boot_params.acpi_rsdp_addr;

arch/x86/kernel/ima_arch.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ bool arch_ima_get_secureboot(void)
7474

7575
/* secureboot arch rules */
7676
static const char * const sb_arch_rules[] = {
77-
#if !IS_ENABLED(CONFIG_KEXEC_VERIFY_SIG)
77+
#if !IS_ENABLED(CONFIG_KEXEC_SIG)
7878
"appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig",
79-
#endif /* CONFIG_KEXEC_VERIFY_SIG */
79+
#endif /* CONFIG_KEXEC_SIG */
8080
"measure func=KEXEC_KERNEL_CHECK",
8181
#if !IS_ENABLED(CONFIG_MODULE_SIG)
8282
"appraise func=MODULE_CHECK appraise_type=imasig",

arch/x86/kernel/ioport.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/errno.h>
1212
#include <linux/types.h>
1313
#include <linux/ioport.h>
14+
#include <linux/security.h>
1415
#include <linux/smp.h>
1516
#include <linux/stddef.h>
1617
#include <linux/slab.h>
@@ -31,7 +32,8 @@ long ksys_ioperm(unsigned long from, unsigned long num, int turn_on)
3132

3233
if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
3334
return -EINVAL;
34-
if (turn_on && !capable(CAP_SYS_RAWIO))
35+
if (turn_on && (!capable(CAP_SYS_RAWIO) ||
36+
security_locked_down(LOCKDOWN_IOPORT)))
3537
return -EPERM;
3638

3739
/*
@@ -126,7 +128,8 @@ SYSCALL_DEFINE1(iopl, unsigned int, level)
126128
return -EINVAL;
127129
/* Trying to gain more privileges? */
128130
if (level > old) {
129-
if (!capable(CAP_SYS_RAWIO))
131+
if (!capable(CAP_SYS_RAWIO) ||
132+
security_locked_down(LOCKDOWN_IOPORT))
130133
return -EPERM;
131134
}
132135
regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) |

arch/x86/kernel/kexec-bzimage64.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ setup_efi_state(struct boot_params *params, unsigned long params_load_addr,
180180
if (efi_enabled(EFI_OLD_MEMMAP))
181181
return 0;
182182

183+
params->secure_boot = boot_params.secure_boot;
183184
ei->efi_loader_signature = current_ei->efi_loader_signature;
184185
ei->efi_systab = current_ei->efi_systab;
185186
ei->efi_systab_hi = current_ei->efi_systab_hi;

arch/x86/kernel/msr.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <linux/notifier.h>
3535
#include <linux/uaccess.h>
3636
#include <linux/gfp.h>
37+
#include <linux/security.h>
3738

3839
#include <asm/cpufeature.h>
3940
#include <asm/msr.h>
@@ -79,6 +80,10 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
7980
int err = 0;
8081
ssize_t bytes = 0;
8182

83+
err = security_locked_down(LOCKDOWN_MSR);
84+
if (err)
85+
return err;
86+
8287
if (count % 8)
8388
return -EINVAL; /* Invalid chunk size */
8489

@@ -130,6 +135,9 @@ static long msr_ioctl(struct file *file, unsigned int ioc, unsigned long arg)
130135
err = -EFAULT;
131136
break;
132137
}
138+
err = security_locked_down(LOCKDOWN_MSR);
139+
if (err)
140+
break;
133141
err = wrmsr_safe_regs_on_cpu(cpu, regs);
134142
if (err)
135143
break;

arch/x86/kernel/x86_init.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ struct x86_init_ops x86_init __initdata = {
9595
},
9696

9797
.acpi = {
98+
.set_root_pointer = x86_default_set_root_pointer,
9899
.get_root_pointer = x86_default_get_root_pointer,
99100
.reduced_hw_early_init = acpi_generic_reduced_hw_init,
100101
},

arch/x86/mm/testmmiotrace.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/module.h>
99
#include <linux/io.h>
1010
#include <linux/mmiotrace.h>
11+
#include <linux/security.h>
1112

1213
static unsigned long mmio_address;
1314
module_param_hw(mmio_address, ulong, iomem, 0);
@@ -115,6 +116,10 @@ static void do_test_bulk_ioremapping(void)
115116
static int __init init(void)
116117
{
117118
unsigned long size = (read_far) ? (8 << 20) : (16 << 10);
119+
int ret = security_locked_down(LOCKDOWN_MMIOTRACE);
120+
121+
if (ret)
122+
return ret;
118123

119124
if (mmio_address == 0) {
120125
pr_err("you have to use the module argument mmio_address.\n");

crypto/asymmetric_keys/verify_pefile.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ static int pefile_parse_binary(const void *pebuf, unsigned int pelen,
9696

9797
if (!ddir->certs.virtual_address || !ddir->certs.size) {
9898
pr_debug("Unsigned PE binary\n");
99-
return -EKEYREJECTED;
99+
return -ENODATA;
100100
}
101101

102102
chkaddr(ctx->header_size, ddir->certs.virtual_address,
@@ -403,6 +403,8 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen,
403403
* (*) 0 if at least one signature chain intersects with the keys in the trust
404404
* keyring, or:
405405
*
406+
* (*) -ENODATA if there is no signature present.
407+
*
406408
* (*) -ENOPKG if a suitable crypto module couldn't be found for a check on a
407409
* chain.
408410
*

drivers/acpi/custom_method.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/uaccess.h>
1010
#include <linux/debugfs.h>
1111
#include <linux/acpi.h>
12+
#include <linux/security.h>
1213

1314
#include "internal.h"
1415

@@ -29,6 +30,11 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf,
2930

3031
struct acpi_table_header table;
3132
acpi_status status;
33+
int ret;
34+
35+
ret = security_locked_down(LOCKDOWN_ACPI_TABLES);
36+
if (ret)
37+
return ret;
3238

3339
if (!(*ppos)) {
3440
/* parse the table header to get the table length */

drivers/acpi/osl.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <linux/list.h>
2828
#include <linux/jiffies.h>
2929
#include <linux/semaphore.h>
30+
#include <linux/security.h>
3031

3132
#include <asm/io.h>
3233
#include <linux/uaccess.h>
@@ -182,8 +183,19 @@ acpi_physical_address __init acpi_os_get_root_pointer(void)
182183
acpi_physical_address pa;
183184

184185
#ifdef CONFIG_KEXEC
185-
if (acpi_rsdp)
186+
/*
187+
* We may have been provided with an RSDP on the command line,
188+
* but if a malicious user has done so they may be pointing us
189+
* at modified ACPI tables that could alter kernel behaviour -
190+
* so, we check the lockdown status before making use of
191+
* it. If we trust it then also stash it in an architecture
192+
* specific location (if appropriate) so it can be carried
193+
* over further kexec()s.
194+
*/
195+
if (acpi_rsdp && !security_locked_down(LOCKDOWN_ACPI_TABLES)) {
196+
acpi_arch_set_root_pointer(acpi_rsdp);
186197
return acpi_rsdp;
198+
}
187199
#endif
188200
pa = acpi_arch_get_root_pointer();
189201
if (pa)

0 commit comments

Comments
 (0)