From: Matthew Garrett <hidden> Date: 2019-06-22 00:04:03
Minor updates over V33 - security_is_locked_down renamed to
security_locked_down, return value of security_locked_down is returned
in most cases, one unnecessary patch was dropped, couple of minor nits
fixed.
From: Matthew Garrett <hidden> Date: 2019-06-22 00:04:07
The lockdown module is intended to allow for kernels to be locked down
early in boot - sufficiently early that we don't have the ability to
kmalloc() yet. Add support for early initialisation of some LSMs, and
then add them to the list of names when we do full initialisation later.
Early LSMs are initialised in link order and cannot be overridden via
boot parameters, and cannot make use of kmalloc() (since the allocator
isn't initialised yet).
Signed-off-by: Matthew Garrett <redacted>
---
include/asm-generic/vmlinux.lds.h | 8 ++++-
include/linux/lsm_hooks.h | 6 ++++
include/linux/security.h | 1 +
init/main.c | 1 +
security/security.c | 50 ++++++++++++++++++++++++++-----
5 files changed, 57 insertions(+), 9 deletions(-)
@@ -37,6 +37,7 @@/* How many LSMs were built into the kernel? */#define LSM_COUNT (__end_lsm_info - __start_lsm_info)+#define EARLY_LSM_COUNT (__end_early_lsm_info - __start_early_lsm_info)structsecurity_hook_headssecurity_hook_heads__lsm_ro_after_init;staticATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
@@ -426,8 +453,15 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,hooks[i].lsm=lsm;hlist_add_tail_rcu(&hooks[i].list,hooks[i].head);}-if(lsm_append(lsm,&lsm_names)<0)-panic("%s - Cannot get early memory.\n",__func__);++/*+*Don'ttrytoappendduringearly_security_init(),we'llcomeback+*andfixthisupafterwards.+*/+if(slab_is_available()){+if(lsm_append(lsm,&lsm_names)<0)+panic("%s - Cannot get early memory.\n",__func__);+}}intcall_lsm_notifier(enumlsm_eventevent,void*data)
From: Matthew Garrett <hidden> Date: 2019-06-22 00:04:09
Add a mechanism 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.
Signed-off-by: Matthew Garrett <redacted>
---
include/linux/lsm_hooks.h | 2 ++
include/linux/security.h | 11 +++++++++++
security/security.c | 6 ++++++
3 files changed, 19 insertions(+)
@@ -76,6 +76,12 @@ enum lsm_event {LSM_POLICY_CHANGE,};+enumlockdown_reason{+LOCKDOWN_NONE,+LOCKDOWN_INTEGRITY_MAX,+LOCKDOWN_CONFIDENTIALITY_MAX,+};+/* These functions are in security/commoncap.c */externintcap_capable(conststructcred*cred,structuser_namespace*ns,intcap,unsignedintopts);
From: Matthew Garrett <hidden> Date: 2019-06-22 00:04:12
While existing LSMs can be extended to handle lockdown policy,
distributions generally want to be able to apply a straightforward
static policy. This patch adds a simple LSM that can be configured to
reject either integrity or all lockdown queries, and can be configured
at runtime (through securityfs), boot time (via a kernel parameter) or
build time (via a kconfig option). Based on initial code by David
Howells.
Signed-off-by: Matthew Garrett <redacted>
Cc: David Howells <dhowells@redhat.com>
---
.../admin-guide/kernel-parameters.txt | 9 +
include/linux/security.h | 4 +
security/Kconfig | 3 +-
security/Makefile | 2 +
security/lockdown/Kconfig | 47 +++++
security/lockdown/Makefile | 1 +
security/lockdown/lockdown.c | 172 ++++++++++++++++++
7 files changed, 237 insertions(+), 1 deletion(-)
create mode 100644 security/lockdown/Kconfig
create mode 100644 security/lockdown/Makefile
create mode 100644 security/lockdown/lockdown.c
@@ -2239,6 +2239,15 @@ lockd.nlm_udpport=M [NFS] Assign UDP port. Format: <integer>+ lockdown= [SECURITY]+ { 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.+ locktorture.nreaders_stress= [KNL] Set the number of locking read-acquisition kthreads. Defaults to being automatically set based on the
@@ -236,12 +236,13 @@ source "security/apparmor/Kconfig"source"security/loadpin/Kconfig"source"security/yama/Kconfig"source"security/safesetid/Kconfig"+source"security/lockdown/Kconfig"source"security/integrity/Kconfig"configLSMstring"Ordered list of enabled LSMs"-default"yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor"+default"lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor"helpAcomma-separatedlistofLSMs,ininitializationorder.AnyLSMsleftoffthislistwillbeignored.Thiscanbe
@@ -0,0 +1,172 @@+// SPDX-License-Identifier: GPL-2.0+/* Lock down the kernel+*+*Copyright(C)2016RedHat,Inc.AllRightsReserved.+*WrittenbyDavidHowells(dhowells@redhat.com)+*+*Thisprogramisfreesoftware;youcanredistributeitand/or+*modifyitunderthetermsoftheGNUGeneralPublicLicence+*aspublishedbytheFreeSoftwareFoundation;eitherversion+*2oftheLicence,or(atyouroption)anylaterversion.+*/++#include<linux/security.h>+#include<linux/export.h>+#include<linux/lsm_hooks.h>++staticenumlockdown_reasonkernel_locked_down;++staticchar*lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1]={+[LOCKDOWN_NONE]="none",+[LOCKDOWN_INTEGRITY_MAX]="integrity",+[LOCKDOWN_CONFIDENTIALITY_MAX]="confidentiality",+};++staticenumlockdown_reasonlockdown_levels[]={LOCKDOWN_NONE,+LOCKDOWN_INTEGRITY_MAX,+LOCKDOWN_CONFIDENTIALITY_MAX};++/*+*Putthekernelintolock-downmode.+*/+staticintlock_kernel_down(constchar*where,enumlockdown_reasonlevel)+{+if(kernel_locked_down>=level)+return-EPERM;++kernel_locked_down=level;+pr_notice("Kernel is locked down from %s; see man kernel_lockdown.7\n",+where);+return0;+}++staticint__initlockdown_param(char*level)+{+if(!level)+return-EINVAL;++if(strcmp(level,"integrity")==0)+lock_kernel_down("command line",LOCKDOWN_INTEGRITY_MAX);+elseif(strcmp(level,"confidentiality")==0)+lock_kernel_down("command line",LOCKDOWN_CONFIDENTIALITY_MAX);+else+return-EINVAL;++return0;+}++early_param("lockdown",lockdown_param);++/**+*lockdown_is_locked_down-Findoutifthekernelislockeddown+*@what:Tagtouseinnoticegeneratediflockdownisineffect+*/+staticintlockdown_is_locked_down(enumlockdown_reasonwhat)+{+if((kernel_locked_down>=what)){+if(lockdown_reasons[what])+pr_notice("Lockdown: %s is restricted; see man kernel_lockdown.7\n",+lockdown_reasons[what]);+return-EPERM;+}++return0;+}++staticstructsecurity_hook_listlockdown_hooks[]__lsm_ro_after_init={+LSM_HOOK_INIT(locked_down,lockdown_is_locked_down),+};++staticint__initlockdown_lsm_init(void)+{+#if defined(CONFIG_LOCK_DOWN_KERNEL_FORCE_INTEGRITY)+lock_kernel_down("Kernel configuration",LOCKDOWN_INTEGRITY_MAX);+#elif defined(CONFIG_LOCK_DOWN_KERNEL_FORCE_CONFIDENTIALITY)+lock_kernel_down("Kernel configuration",LOCKDOWN_CONFIDENTIALITY_MAX);+#endif+security_add_hooks(lockdown_hooks,ARRAY_SIZE(lockdown_hooks),+"lockdown");+return0;+}++staticssize_tlockdown_read(structfile*filp,char__user*buf,size_tcount,+loff_t*ppos)+{+chartemp[80];+inti,offset=0;++for(i=0;i<ARRAY_SIZE(lockdown_levels);i++){+enumlockdown_reasonlevel=lockdown_levels[i];++if(lockdown_reasons[level]){+constchar*label=lockdown_reasons[level];++if(kernel_locked_down==level)+offset+=sprintf(temp+offset,"[%s] ",label);+else+offset+=sprintf(temp+offset,"%s ",label);+}+}++/* Convert the last space to a newline if needed. */+if(offset>0)+temp[offset-1]='\n';++returnsimple_read_from_buffer(buf,count,ppos,temp,strlen(temp));+}++staticssize_tlockdown_write(structfile*file,constchar__user*buf,+size_tn,loff_t*ppos)+{+char*state;+inti,len,err=-EINVAL;++state=memdup_user_nul(buf,n);+if(IS_ERR(state))+returnPTR_ERR(state);++len=strlen(state);+if(len&&state[len-1]=='\n'){+state[len-1]='\0';+len--;+}++for(i=0;i<ARRAY_SIZE(lockdown_levels);i++){+enumlockdown_reasonlevel=lockdown_levels[i];+constchar*label=lockdown_reasons[level];++if(label&&!strcmp(state,label))+err=lock_kernel_down("securityfs",level);+}++kfree(state);+returnerr?err:n;+}++staticconststructfile_operationslockdown_ops={+.read=lockdown_read,+.write=lockdown_write,+};++staticint__initlockdown_secfs_init(void)+{+structdentry*dentry;++dentry=securityfs_create_file("lockdown",0600,NULL,NULL,+&lockdown_ops);+if(IS_ERR(dentry))+returnPTR_ERR(dentry);++return0;+}++core_initcall(lockdown_secfs_init);++#ifdef CONFIG_SECURITY_LOCKDOWN_LSM_EARLY+DEFINE_EARLY_LSM(lockdown)={+#else+DEFINE_LSM(lockdown)={+#endif+.name="lockdown",+.init=lockdown_lsm_init,+};
From: Matthew Garrett <hidden> Date: 2019-06-22 00:04:15
From: David Howells <dhowells@redhat.com>
If the kernel is locked down, require that all modules have valid
signatures that we can verify.
I have adjusted the errors generated:
(1) If there's no signature (ENODATA) or we can't check it (ENOPKG,
ENOKEY), then:
(a) If signatures are enforced then EKEYREJECTED is returned.
(b) If there's no signature or we can't check it, but the kernel is
locked down then EPERM is returned (this is then consistent with
other lockdown cases).
(2) If the signature is unparseable (EBADMSG, EINVAL), the signature fails
the check (EKEYREJECTED) or a system error occurs (eg. ENOMEM), we
return the error we got.
Note that the X.509 code doesn't check for key expiry as the RTC might not
be valid or might not have been transferred to the kernel's clock yet.
[Modified by Matthew Garrett to remove the IMA integration. This will
be replaced with integration with the IMA architecture policy
patchset.]
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
Cc: Jessica Yu <jeyu@kernel.org>
---
include/linux/security.h | 1 +
kernel/module.c | 38 +++++++++++++++++++++++++++++-------
security/lockdown/lockdown.c | 1 +
3 files changed, 33 insertions(+), 7 deletions(-)
@@ -2779,16 +2780,39 @@ static int module_sig_check(struct load_info *info, int flags)err=mod_verify_sig(mod,info);}-if(!err){+switch(err){+case0:info->sig_ok=true;return0;-}-/* Not having a signature is only an error if we're strict. */-if(err==-ENOKEY&&!is_module_sig_enforced())-err=0;+/* We don't permit modules to be loaded into trusted kernels+*withoutavalidsignatureonthem,butifwe'renot+*enforcing,certainerrorsarenon-fatal.+*/+case-ENODATA:+reason="Loading of unsigned module";+gotodecide;+case-ENOPKG:+reason="Loading of module with unsupported crypto";+gotodecide;+case-ENOKEY:+reason="Loading of module with unavailable key";+decide:+if(is_module_sig_enforced()){+pr_notice("%s is rejected\n",reason);+return-EKEYREJECTED;+}-returnerr;+ret=security_locked_down(LOCKDOWN_MODULE_SIGNATURE);+returnret;++/* All other errors are fatal, including nomem, unparseable+*signaturesandsignaturecheckfailures-evenifsignatures+*aren'trequired.+*/+default:+returnerr;+}}#else /* !CONFIG_MODULE_SIG */staticintmodule_sig_check(structload_info*info,intflags)
From: Matthew Garrett <hidden> Date: 2019-06-22 00:04:18
From: Matthew Garrett <mjg59@srcf.ucam.org>
Allowing users to read and write to core kernel memory makes it possible
for the kernel to be subverted, avoiding module loading restrictions, and
also to steal cryptographic information.
Disallow /dev/mem and /dev/kmem from being opened this when the kernel has
been locked down to prevent this.
Also disallow /dev/port from being opened to prevent raw ioport access and
thus DMA from being used to accomplish the same thing.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
Cc: x86@kernel.org
---
drivers/char/mem.c | 6 +++++-
include/linux/security.h | 1 +
security/lockdown/lockdown.c | 1 +
3 files changed, 7 insertions(+), 1 deletion(-)
From: Matthew Garrett <hidden> Date: 2019-06-22 00:04:21
From: Matthew Garrett <mjg59@srcf.ucam.org>
The kexec_load() syscall permits the loading and execution of arbitrary
code in ring 0, which is something that lock-down is meant to prevent. It
makes sense to disable kexec_load() in this situation.
This does not affect kexec_file_load() syscall which can check for a
signature on the image to be booted.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
Acked-by: Dave Young <redacted>
cc: kexec@lists.infradead.org
---
include/linux/security.h | 1 +
kernel/kexec.c | 8 ++++++++
security/lockdown/lockdown.c | 1 +
3 files changed, 10 insertions(+)
@@ -207,6 +207,14 @@ static inline int kexec_load_check(unsigned long nr_segments,if(result<0)returnresult;+/*+*kexeccanbeusedtocircumventmoduleloadingrestrictions,so+*preventloadinginthatcase+*/+result=security_locked_down(LOCKDOWN_KEXEC);+if(result)+returnresult;+/**Verifywehavealegalsetofflags*Thisleavesusroomforfutureextensions.
From: Matthew Garrett <hidden> Date: 2019-06-22 00:04:24
From: Dave Young <redacted>
Kexec reboot in case secure boot being enabled does not keep the secure
boot mode in new kernel, so later one can load unsigned kernel via legacy
kexec_load. In this state, the system is missing the protections provided
by secure boot.
Adding a patch to fix this by retain the secure_boot flag in original
kernel.
secure_boot flag in boot_params is set in EFI stub, but kexec bypasses the
stub. Fixing this issue by copying secure_boot flag across kexec reboot.
Signed-off-by: Dave Young <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
cc: kexec@lists.infradead.org
---
arch/x86/kernel/kexec-bzimage64.c | 1 +
1 file changed, 1 insertion(+)
From: Matthew Garrett <hidden> Date: 2019-06-22 00:04:28
From: Jiri Bohac <redacted>
This is a preparatory patch for kexec_file_load() lockdown. A locked down
kernel needs to prevent unsigned kernel images from being loaded with
kexec_file_load(). Currently, the only way to force the signature
verification is compiling with KEXEC_VERIFY_SIG. This prevents loading
usigned images even when the kernel is not locked down at runtime.
This patch splits KEXEC_VERIFY_SIG into KEXEC_SIG and KEXEC_SIG_FORCE.
Analogous to the MODULE_SIG and MODULE_SIG_FORCE for modules, KEXEC_SIG
turns on the signature verification but allows unsigned images to be
loaded. KEXEC_SIG_FORCE disallows images without a valid signature.
[Modified by David Howells such that:
(1) verify_pefile_signature() differentiates between no-signature and
sig-didn't-match in its returned errors.
(2) kexec fails with EKEYREJECTED if there is a signature for which we
have a key, but signature doesn't match - even if in non-forcing mode.
(3) kexec fails with EBADMSG or some other error if there is a signature
which cannot be parsed - even if in non-forcing mode.
(4) kexec fails with ELIBBAD if the PE file cannot be parsed to extract
the signature - even if in non-forcing mode.
]
Signed-off-by: Jiri Bohac <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
Reviewed-by: Jiri Bohac <redacted>
cc: kexec@lists.infradead.org
---
arch/x86/Kconfig | 20 ++++++++---
crypto/asymmetric_keys/verify_pefile.c | 4 ++-
include/linux/kexec.h | 4 +--
kernel/kexec_file.c | 47 ++++++++++++++++++++++----
4 files changed, 60 insertions(+), 15 deletions(-)
@@ -100,7 +100,7 @@ static int pefile_parse_binary(const void *pebuf, unsigned int pelen,if(!ddir->certs.virtual_address||!ddir->certs.size){pr_debug("Unsigned PE binary\n");-return-EKEYREJECTED;+return-ENODATA;}chkaddr(ctx->header_size,ddir->certs.virtual_address,
@@ -408,6 +408,8 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen,*(*)0ifatleastonesignaturechainintersectswiththekeysinthetrust*keyring,or:*+*(*)-ENODATAifthereisnosignaturepresent.+**(*)-ENOPKGifasuitablecryptomodulecouldn'tbefoundforacheckona*chain.*
@@ -188,7 +188,8 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,constchar__user*cmdline_ptr,unsignedlongcmdline_len,unsignedflags){-intret=0;+constchar*reason;+intret;void*ldata;loff_tsize;
@@ -207,15 +208,47 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,if(ret)gotoout;-#ifdef CONFIG_KEXEC_VERIFY_SIG+#ifdef CONFIG_KEXEC_SIGret=arch_kexec_kernel_verify_sig(image,image->kernel_buf,image->kernel_buf_len);-if(ret){-pr_debug("kernel signature verification failed.\n");+#else+ret=-ENODATA;+#endif++switch(ret){+case0:+break;++/* Certain verification errors are non-fatal if we're not+*checkingerrors,providedwearen'tmandatingthatthere+*mustbeavalidsignature.+*/+case-ENODATA:+reason="kexec of unsigned image";+gotodecide;+case-ENOPKG:+reason="kexec of image with unsupported crypto";+gotodecide;+case-ENOKEY:+reason="kexec of image with unavailable key";+decide:+if(IS_ENABLED(CONFIG_KEXEC_SIG_FORCE)){+pr_notice("%s rejected\n",reason);+gotoout;+}++ret=0;+break;++/* All other errors are fatal, including nomem, unparseable+*signaturesandsignaturecheckfailures-evenifsignatures+*aren'trequired.+*/+default:+pr_notice("kernel signature verification failed (%d).\n",ret);gotoout;}-pr_debug("kernel signature verification successful.\n");-#endif+/* It is possible that there no initramfs is being loaded */if(!(flags&KEXEC_FILE_NO_INITRAMFS)){ret=kernel_read_file_from_fd(initrd_fd,&image->initrd_buf,
From: Matthew Garrett <hidden> Date: 2019-06-22 00:04:32
From: Josh Boyer <redacted>
There is currently no way to verify the resume image when returning
from hibernate. This might compromise the signed modules trust model,
so until we can work with signed hibernate images we disable it when the
kernel is locked down.
Signed-off-by: Josh Boyer <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
Cc: rjw@rjwysocki.net
Cc: pavel@ucw.cz
cc: linux-pm@vger.kernel.org
---
include/linux/security.h | 1 +
kernel/power/hibernate.c | 3 ++-
security/lockdown/lockdown.c | 1 +
3 files changed, 4 insertions(+), 1 deletion(-)
From: Matthew Garrett <hidden> Date: 2019-06-22 00:04:34
From: Matthew Garrett <mjg59@srcf.ucam.org>
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.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
cc: linux-pci@vger.kernel.org
---
drivers/pci/pci-sysfs.c | 16 ++++++++++++++++
drivers/pci/proc.c | 14 ++++++++++++--
drivers/pci/syscall.c | 4 +++-
include/linux/security.h | 1 +
security/lockdown/lockdown.c | 1 +
5 files changed, 33 insertions(+), 3 deletions(-)
From: Matthew Garrett <hidden> Date: 2019-06-22 00:04:42
From: Matthew Garrett <mjg59@srcf.ucam.org>
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.
Signed-off-by: Matthew Garrett <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
cc: x86@kernel.org
---
arch/x86/kernel/ioport.c | 7 +++++--
include/linux/security.h | 1 +
security/lockdown/lockdown.c | 1 +
3 files changed, 7 insertions(+), 2 deletions(-)
@@ -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)||+security_locked_down(LOCKDOWN_IOPORT)))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)||+security_locked_down(LOCKDOWN_IOPORT))return-EPERM;}regs->flags=(regs->flags&~X86_EFLAGS_IOPL)|
From: Matthew Garrett <hidden> Date: 2019-06-22 00:04:45
From: Josh Boyer <redacted>
This option allows userspace to pass the RSDP address to the kernel, which
makes it possible for a user to modify the workings of hardware . Reject
the option when the kernel is locked down.
Signed-off-by: Josh Boyer <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
cc: Dave Young <redacted>
cc: linux-acpi@vger.kernel.org
---
drivers/acpi/osl.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
From: Matthew Garrett <hidden> Date: 2019-06-22 00:04:53
From: David Howells <dhowells@redhat.com>
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.
Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
cc: Jiri Slaby <redacted>
Cc: linux-serial@vger.kernel.org
---
drivers/tty/serial/serial_core.c | 5 +++++
include/linux/security.h | 1 +
security/lockdown/lockdown.c | 1 +
3 files changed, 7 insertions(+)
From: Matthew Garrett <hidden> Date: 2019-06-22 00:04:57
From: David Howells <dhowells@redhat.com>
The testmmiotrace module shouldn't be permitted when the kernel is locked
down as it can be used to arbitrarily read and write MMIO space. This is
a runtime check rather than buildtime in order to allow configurations
where the same kernel may be run in both locked down or permissive modes
depending on local policy.
Suggested-by: Thomas Gleixner <redacted>
Signed-off-by: David Howells <dhowells@redhat.com
Signed-off-by: Matthew Garrett <redacted>
cc: Thomas Gleixner <redacted>
cc: Steven Rostedt <rostedt@goodmis.org>
cc: Ingo Molnar <mingo@kernel.org>
cc: "H. Peter Anvin" <hpa@zytor.com>
cc: x86@kernel.org
---
arch/x86/mm/testmmiotrace.c | 5 +++++
include/linux/security.h | 1 +
security/lockdown/lockdown.c | 1 +
3 files changed, 7 insertions(+)
@@ -114,6 +115,10 @@ static void do_test_bulk_ioremapping(void)staticint__initinit(void){unsignedlongsize=(read_far)?(8<<20):(16<<10);+intret=security_locked_down(LOCKDOWN_MMIOTRACE);++if(ret)+returnret;if(mmio_address==0){pr_err("you have to use the module argument mmio_address.\n");
From: Matthew Garrett <hidden> Date: 2019-06-22 00:05:01
From: David Howells <dhowells@redhat.com>
Disallow access to /proc/kcore when the kernel is locked down to prevent
access to cryptographic data. This is limited to lockdown
confidentiality mode and is still permitted in integrity mode.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
---
fs/proc/kcore.c | 5 +++++
include/linux/security.h | 1 +
security/lockdown/lockdown.c | 1 +
3 files changed, 7 insertions(+)
@@ -10731,6 +10731,13 @@ SYSCALL_DEFINE5(perf_event_open,return-EINVAL;}+err=security_locked_down(LOCKDOWN_PERF);+if(err&&(attr.sample_type&PERF_SAMPLE_REGS_INTR))+/* REGS_INTR can leak data, lockdown must prevent this */+returnerr;+else+err=0;+/* Only privileged users can get physical addresses */if((attr.sample_type&PERF_SAMPLE_PHYS_ADDR)&&perf_paranoid_kernel()&&!capable(CAP_SYS_ADMIN))
@@ -34,6 +34,7 @@ static char *lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {[LOCKDOWN_KCORE]="/proc/kcore access",[LOCKDOWN_KPROBES]="use of kprobes",[LOCKDOWN_BPF_READ]="use of bpf to read kernel RAM",+[LOCKDOWN_PERF]="unsafe use of perf",[LOCKDOWN_CONFIDENTIALITY_MAX]="confidentiality",};
From: Matthew Garrett <hidden> Date: 2019-06-22 00:05:18
Tracefs may release more information about the kernel than desirable, so
restrict it when the kernel is locked down in confidentiality mode by
preventing open().
Signed-off-by: Matthew Garrett <redacted>
Cc: Steven Rostedt <rostedt@goodmis.org>
---
fs/tracefs/inode.c | 43 +++++++++++++++++++++++++++++++++++-
include/linux/security.h | 1 +
security/lockdown/lockdown.c | 1 +
3 files changed, 44 insertions(+), 1 deletion(-)
@@ -36,6 +36,7 @@ static char *lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {[LOCKDOWN_KPROBES]="use of kprobes",[LOCKDOWN_BPF_READ]="use of bpf to read kernel RAM",[LOCKDOWN_PERF]="unsafe use of perf",+[LOCKDOWN_TRACEFS]="use of tracefs",[LOCKDOWN_CONFIDENTIALITY_MAX]="confidentiality",};
From: Matthew Garrett <hidden> Date: 2019-06-22 00:05:21
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.
Signed-off-by: Matthew Garrett <redacted>
Cc: Ard Biesheuvel <redacted>
Cc: linux-efi@vger.kernel.org
---
drivers/firmware/efi/efi.c | 6 ++++++
1 file changed, 6 insertions(+)
From: Matthew Garrett <hidden> Date: 2019-06-22 00:05:25
Print the content of current->comm in messages generated by lockdown to
indicate a restriction that was hit. This makes it a bit easier to find
out what caused the message.
The message now patterned something like:
Lockdown: <comm>: <what> is restricted; see man kernel_lockdown.7
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
---
security/lockdown/lockdown.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
@@ -83,8 +83,8 @@ static int lockdown_is_locked_down(enum lockdown_reason what){if((kernel_locked_down>=what)){if(lockdown_reasons[what])-pr_notice("Lockdown: %s is restricted; see man kernel_lockdown.7\n",-lockdown_reasons[what]);+pr_notice("Lockdown: %s: %s is restricted; see man kernel_lockdown.7\n",+current->comm,lockdown_reasons[what]);return-EPERM;}
From: Matthew Garrett <hidden> Date: 2019-06-22 00:05:58
From: David Howells <dhowells@redhat.com>
Disallow opening of debugfs files that might be used to muck around when
the kernel is locked down as various drivers give raw access to hardware
through debugfs. Given the effort of auditing all 2000 or so files and
manually fixing each one as necessary, I've chosen to apply a heuristic
instead. The following changes are made:
(1) chmod and chown are disallowed on debugfs objects (though the root dir
can be modified by mount and remount, but I'm not worried about that).
(2) When the kernel is locked down, only files with the following criteria
are permitted to be opened:
- The file must have mode 00444
- The file must not have ioctl methods
- The file must not have mmap
(3) When the kernel is locked down, files may only be opened for reading.
Normal device interaction should be done through configfs, sysfs or a
miscdev, not debugfs.
Note that this makes it unnecessary to specifically lock down show_dsts(),
show_devs() and show_call() in the asus-wmi driver.
I would actually prefer to lock down all files by default and have the
the files unlocked by the creator. This is tricky to manage correctly,
though, as there are 19 creation functions and ~1600 call sites (some of
them in loops scanning tables).
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Andy Shevchenko <redacted>
cc: acpi4asus-user@lists.sourceforge.net
cc: platform-driver-x86@vger.kernel.org
cc: Matthew Garrett <mjg59@srcf.ucam.org>
cc: Thomas Gleixner <redacted>
Signed-off-by: Matthew Garrett <redacted>
---
fs/debugfs/file.c | 30 ++++++++++++++++++++++++++++++
fs/debugfs/inode.c | 32 ++++++++++++++++++++++++++++++--
include/linux/security.h | 1 +
security/lockdown/lockdown.c | 1 +
4 files changed, 62 insertions(+), 2 deletions(-)
@@ -147,6 +167,11 @@ static int open_proxy_open(struct inode *inode, struct file *filp)returnr==-EIO?-ENOENT:r;real_fops=debugfs_real_fops(filp);++r=debugfs_is_locked_down(inode,filp,real_fops);+if(r)+gotoout;+real_fops=fops_get(real_fops);if(!real_fops){/* Huh? Module did not clean up after itself at exit? */
@@ -272,6 +297,11 @@ static int full_proxy_open(struct inode *inode, struct file *filp)returnr==-EIO?-ENOENT:r;real_fops=debugfs_real_fops(filp);++r=debugfs_is_locked_down(inode,filp,real_fops);+if(r)+gotoout;+real_fops=fops_get(real_fops);if(!real_fops){/* Huh? Module did not cleanup after itself at exit? */
@@ -30,6 +30,7 @@ static char *lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {[LOCKDOWN_TIOCSSERIAL]="reconfiguration of serial port IO",[LOCKDOWN_MODULE_PARAMETERS]="unsafe module parameters",[LOCKDOWN_MMIOTRACE]="unsafe mmio",+[LOCKDOWN_DEBUGFS]="debugfs access",[LOCKDOWN_INTEGRITY_MAX]="integrity",[LOCKDOWN_KCORE]="/proc/kcore access",[LOCKDOWN_KPROBES]="use of kprobes",
From: Matthew Garrett <hidden> Date: 2019-06-22 00:06:00
Systems in lockdown mode should block the kexec of untrusted kernels.
For x86 and ARM we can ensure that a kernel is trustworthy by validating
a PE signature, but this isn't possible on other architectures. On those
platforms we can use IMA digital signatures instead. Add a function to
determine whether IMA has or will verify signatures for a given event type,
and if so permit kexec_file() even if the kernel is otherwise locked down.
This is restricted to cases where CONFIG_INTEGRITY_TRUSTED_KEYRING is set
in order to prevent an attacker from loading additional keys at runtime.
Signed-off-by: Matthew Garrett <redacted>
Acked-by: Mimi Zohar <zohar@linux.ibm.com>
Cc: Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
Cc: linux-integrity@vger.kernel.org
---
include/linux/ima.h | 9 ++++++
kernel/kexec_file.c | 11 +++++--
security/integrity/ima/ima.h | 2 ++
security/integrity/ima/ima_main.c | 2 +-
security/integrity/ima/ima_policy.c | 50 +++++++++++++++++++++++++++++
5 files changed, 71 insertions(+), 3 deletions(-)
@@ -237,8 +237,15 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,gotoout;}-ret=security_locked_down(LOCKDOWN_KEXEC);-if(ret)+ret=0;++/* If IMA is guaranteed to appraise a signature on the kexec+*image,permititevenifthekernelisotherwiselocked+*down.+*/+if(!ima_appraise_signature(READING_KEXEC_IMAGE)&&+security_locked_down(LOCKDOWN_KEXEC)){+ret=-EPERM;gotoout;break;
From: Matthew Garrett <hidden> Date: 2019-06-22 00:06:03
From: David Howells <dhowells@redhat.com>
There are some bpf functions can be used to read kernel memory:
bpf_probe_read, bpf_probe_write_user and bpf_trace_printk. These allow
private keys in kernel memory (e.g. the hibernation image signing key) to
be read by an eBPF program and kernel memory to be altered without
restriction. Disable them if the kernel has been locked down in
confidentiality mode.
Suggested-by: Alexei Starovoitov <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
cc: netdev@vger.kernel.org
cc: Chun-Yi Lee <jlee@suse.com>
cc: Alexei Starovoitov <redacted>
Cc: Daniel Borkmann <daniel@iogearbox.net>
---
include/linux/security.h | 1 +
kernel/trace/bpf_trace.c | 20 +++++++++++++++++++-
security/lockdown/lockdown.c | 1 +
3 files changed, 21 insertions(+), 1 deletion(-)
From: Matthew Garrett <hidden> Date: 2019-06-22 00:06:10
From: David Howells <dhowells@redhat.com>
Disallow the creation of perf and ftrace kprobes when the kernel is
locked down in confidentiality mode by preventing their registration.
This prevents kprobes from being used to access kernel memory to steal
crypto data, but continues to allow the use of kprobes from signed
modules.
Reported-by: Alexei Starovoitov <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
Cc: Naveen N. Rao <redacted>
Cc: Anil S Keshavamurthy <redacted>
Cc: davem@davemloft.net
Cc: Masami Hiramatsu <mhiramat@kernel.org>
---
include/linux/security.h | 1 +
kernel/trace/trace_kprobe.c | 5 +++++
security/lockdown/lockdown.c | 1 +
3 files changed, 7 insertions(+)
@@ -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 */
From: Matthew Garrett <hidden> Date: 2019-06-22 00:06:27
From: Linn Crosetto <redacted>
From the kernel documentation (initrd_table_override.txt):
If the ACPI_INITRD_TABLE_OVERRIDE compile option is true, it is possible
to override nearly any ACPI table provided by the BIOS with an
instrumented, modified one.
When lockdown is enabled, the kernel should disallow any unauthenticated
changes to kernel space. ACPI tables contain code invoked by the kernel,
so do not allow ACPI tables to be overridden if the kernel is locked down.
Signed-off-by: Linn Crosetto <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
cc: linux-acpi@vger.kernel.org
---
drivers/acpi/tables.c | 6 ++++++
1 file changed, 6 insertions(+)
From: Matthew Garrett <hidden> Date: 2019-06-22 00:06:31
From: Matthew Garrett <mjg59@srcf.ucam.org>
Writing to MSRs should not be allowed if the kernel is locked down, since
it could lead to execution of arbitrary code in kernel mode. Based on a
patch by Kees Cook.
Signed-off-by: Matthew Garrett <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Kees Cook <redacted>
Reviewed-by: Thomas Gleixner <redacted>
cc: x86@kernel.org
---
arch/x86/kernel/msr.c | 8 ++++++++
include/linux/security.h | 1 +
security/lockdown/lockdown.c | 1 +
3 files changed, 10 insertions(+)
@@ -135,6 +140,9 @@ static long msr_ioctl(struct file *file, unsigned int ioc, unsigned long arg)err=-EFAULT;break;}+err=security_locked_down(LOCKDOWN_MSR);+if(err)+break;err=wrmsr_safe_regs_on_cpu(cpu,regs);if(err)break;
From: Matthew Garrett <hidden> Date: 2019-06-22 00:06:36
From: Matthew Garrett <mjg59@srcf.ucam.org>
custom_method effectively allows arbitrary access to system memory, making
it possible for an attacker to circumvent restrictions on module loading.
Disable it if the kernel is locked down.
Signed-off-by: Matthew Garrett <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
cc: linux-acpi@vger.kernel.org
---
drivers/acpi/custom_method.c | 6 ++++++
include/linux/security.h | 1 +
security/lockdown/lockdown.c | 1 +
3 files changed, 8 insertions(+)
From: Matthew Garrett <hidden> Date: 2019-06-22 00:06:42
From: Jiri Bohac <redacted>
When KEXEC_SIG is not enabled, kernel should not load images through
kexec_file systemcall if the kernel is locked down.
[Modified by David Howells to fit with modifications to the previous patch
and to return -EPERM if the kernel is locked down for consistency with
other lockdowns. Modified by Matthew Garrett to remove the IMA
integration, which will be replaced by integrating with the IMA
architecture policy patches.]
Signed-off-by: Jiri Bohac <redacted>
Signed-off-by: David Howells <redacted>
Signed-off-by: Matthew Garrett <redacted>
Reviewed-by: Jiri Bohac <redacted>
cc: kexec-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
---
kernel/kexec_file.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
@@ -237,7 +237,10 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,gotoout;}-ret=0;+ret=security_locked_down(LOCKDOWN_KEXEC);+if(ret)+gotoout;+break;/* All other errors are fatal, including nomem, unparseable
From: Pavel Machek <hidden> Date: 2019-06-22 17:52:12
On Fri 2019-06-21 17:03:39, Matthew Garrett wrote:
From: Josh Boyer <redacted>
There is currently no way to verify the resume image when returning
from hibernate. This might compromise the signed modules trust model,
so until we can work with signed hibernate images we disable it when the
kernel is locked down.
On Fri, Jun 21, 2019 at 05:03:30PM -0700, Matthew Garrett wrote:
The lockdown module is intended to allow for kernels to be locked down
early in boot - sufficiently early that we don't have the ability to
kmalloc() yet. Add support for early initialisation of some LSMs, and
then add them to the list of names when we do full initialisation later.
Early LSMs are initialised in link order and cannot be overridden via
boot parameters, and cannot make use of kmalloc() (since the allocator
isn't initialised yet).
Signed-off-by: Matthew Garrett <redacted>
@@ -37,6 +37,7 @@/* How many LSMs were built into the kernel? */#define LSM_COUNT (__end_lsm_info - __start_lsm_info)+#define EARLY_LSM_COUNT (__end_early_lsm_info - __start_early_lsm_info)structsecurity_hook_headssecurity_hook_heads__lsm_ro_after_init;staticATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
@@ -426,8 +453,15 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,hooks[i].lsm=lsm;hlist_add_tail_rcu(&hooks[i].list,hooks[i].head);}-if(lsm_append(lsm,&lsm_names)<0)-panic("%s - Cannot get early memory.\n",__func__);++/*+*Don'ttrytoappendduringearly_security_init(),we'llcomeback+*andfixthisupafterwards.+*/+if(slab_is_available()){+if(lsm_append(lsm,&lsm_names)<0)+panic("%s - Cannot get early memory.\n",__func__);+}}intcall_lsm_notifier(enumlsm_eventevent,void*data)
On Fri, Jun 21, 2019 at 05:03:31PM -0700, Matthew Garrett wrote:
Add a mechanism 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.
Signed-off-by: Matthew Garrett <redacted>
@@ -76,6 +76,12 @@ enum lsm_event {LSM_POLICY_CHANGE,};+enumlockdown_reason{+LOCKDOWN_NONE,+LOCKDOWN_INTEGRITY_MAX,+LOCKDOWN_CONFIDENTIALITY_MAX,+};+/* These functions are in security/commoncap.c */externintcap_capable(conststructcred*cred,structuser_namespace*ns,intcap,unsignedintopts);
On Fri, Jun 21, 2019 at 05:03:32PM -0700, Matthew Garrett wrote:
While existing LSMs can be extended to handle lockdown policy,
distributions generally want to be able to apply a straightforward
static policy. This patch adds a simple LSM that can be configured to
reject either integrity or all lockdown queries, and can be configured
at runtime (through securityfs), boot time (via a kernel parameter) or
build time (via a kconfig option). Based on initial code by David
Howells.
Signed-off-by: Matthew Garrett <redacted>
@@ -2239,6 +2239,15 @@ lockd.nlm_udpport=M [NFS] Assign UDP port. Format: <integer>+ lockdown= [SECURITY]+ { 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.+ locktorture.nreaders_stress= [KNL] Set the number of locking read-acquisition kthreads. Defaults to being automatically set based on the
@@ -236,12 +236,13 @@ source "security/apparmor/Kconfig"source"security/loadpin/Kconfig"source"security/yama/Kconfig"source"security/safesetid/Kconfig"+source"security/lockdown/Kconfig"source"security/integrity/Kconfig"configLSMstring"Ordered list of enabled LSMs"-default"yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor"+default"lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor"helpAcomma-separatedlistofLSMs,ininitializationorder.AnyLSMsleftoffthislistwillbeignored.Thiscanbe
@@ -0,0 +1,172 @@+// SPDX-License-Identifier: GPL-2.0+/* Lock down the kernel+*+*Copyright(C)2016RedHat,Inc.AllRightsReserved.+*WrittenbyDavidHowells(dhowells@redhat.com)+*+*Thisprogramisfreesoftware;youcanredistributeitand/or+*modifyitunderthetermsoftheGNUGeneralPublicLicence+*aspublishedbytheFreeSoftwareFoundation;eitherversion+*2oftheLicence,or(atyouroption)anylaterversion.+*/++#include<linux/security.h>+#include<linux/export.h>+#include<linux/lsm_hooks.h>++staticenumlockdown_reasonkernel_locked_down;++staticchar*lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1]={+[LOCKDOWN_NONE]="none",+[LOCKDOWN_INTEGRITY_MAX]="integrity",+[LOCKDOWN_CONFIDENTIALITY_MAX]="confidentiality",+};++staticenumlockdown_reasonlockdown_levels[]={LOCKDOWN_NONE,+LOCKDOWN_INTEGRITY_MAX,+LOCKDOWN_CONFIDENTIALITY_MAX};++/*+*Putthekernelintolock-downmode.+*/+staticintlock_kernel_down(constchar*where,enumlockdown_reasonlevel)+{+if(kernel_locked_down>=level)+return-EPERM;++kernel_locked_down=level;+pr_notice("Kernel is locked down from %s; see man kernel_lockdown.7\n",+where);+return0;+}++staticint__initlockdown_param(char*level)+{+if(!level)+return-EINVAL;++if(strcmp(level,"integrity")==0)+lock_kernel_down("command line",LOCKDOWN_INTEGRITY_MAX);+elseif(strcmp(level,"confidentiality")==0)+lock_kernel_down("command line",LOCKDOWN_CONFIDENTIALITY_MAX);+else+return-EINVAL;++return0;+}++early_param("lockdown",lockdown_param);++/**+*lockdown_is_locked_down-Findoutifthekernelislockeddown+*@what:Tagtouseinnoticegeneratediflockdownisineffect+*/+staticintlockdown_is_locked_down(enumlockdown_reasonwhat)+{+if((kernel_locked_down>=what)){+if(lockdown_reasons[what])+pr_notice("Lockdown: %s is restricted; see man kernel_lockdown.7\n",+lockdown_reasons[what]);+return-EPERM;+}++return0;+}++staticstructsecurity_hook_listlockdown_hooks[]__lsm_ro_after_init={+LSM_HOOK_INIT(locked_down,lockdown_is_locked_down),+};++staticint__initlockdown_lsm_init(void)+{+#if defined(CONFIG_LOCK_DOWN_KERNEL_FORCE_INTEGRITY)+lock_kernel_down("Kernel configuration",LOCKDOWN_INTEGRITY_MAX);+#elif defined(CONFIG_LOCK_DOWN_KERNEL_FORCE_CONFIDENTIALITY)+lock_kernel_down("Kernel configuration",LOCKDOWN_CONFIDENTIALITY_MAX);+#endif+security_add_hooks(lockdown_hooks,ARRAY_SIZE(lockdown_hooks),+"lockdown");+return0;+}++staticssize_tlockdown_read(structfile*filp,char__user*buf,size_tcount,+loff_t*ppos)+{+chartemp[80];+inti,offset=0;++for(i=0;i<ARRAY_SIZE(lockdown_levels);i++){+enumlockdown_reasonlevel=lockdown_levels[i];++if(lockdown_reasons[level]){+constchar*label=lockdown_reasons[level];++if(kernel_locked_down==level)+offset+=sprintf(temp+offset,"[%s] ",label);+else+offset+=sprintf(temp+offset,"%s ",label);+}+}++/* Convert the last space to a newline if needed. */+if(offset>0)+temp[offset-1]='\n';++returnsimple_read_from_buffer(buf,count,ppos,temp,strlen(temp));+}++staticssize_tlockdown_write(structfile*file,constchar__user*buf,+size_tn,loff_t*ppos)+{+char*state;+inti,len,err=-EINVAL;++state=memdup_user_nul(buf,n);+if(IS_ERR(state))+returnPTR_ERR(state);++len=strlen(state);+if(len&&state[len-1]=='\n'){+state[len-1]='\0';+len--;+}++for(i=0;i<ARRAY_SIZE(lockdown_levels);i++){+enumlockdown_reasonlevel=lockdown_levels[i];+constchar*label=lockdown_reasons[level];++if(label&&!strcmp(state,label))+err=lock_kernel_down("securityfs",level);+}++kfree(state);+returnerr?err:n;+}++staticconststructfile_operationslockdown_ops={+.read=lockdown_read,+.write=lockdown_write,+};++staticint__initlockdown_secfs_init(void)+{+structdentry*dentry;++dentry=securityfs_create_file("lockdown",0600,NULL,NULL,+&lockdown_ops);+if(IS_ERR(dentry))+returnPTR_ERR(dentry);++return0;+}++core_initcall(lockdown_secfs_init);++#ifdef CONFIG_SECURITY_LOCKDOWN_LSM_EARLY+DEFINE_EARLY_LSM(lockdown)={+#else+DEFINE_LSM(lockdown)={+#endif+.name="lockdown",+.init=lockdown_lsm_init,+};
On Fri, Jun 21, 2019 at 05:03:33PM -0700, Matthew Garrett wrote:
quoted hunk
From: David Howells <dhowells@redhat.com>
If the kernel is locked down, require that all modules have valid
signatures that we can verify.
I have adjusted the errors generated:
(1) If there's no signature (ENODATA) or we can't check it (ENOPKG,
ENOKEY), then:
(a) If signatures are enforced then EKEYREJECTED is returned.
(b) If there's no signature or we can't check it, but the kernel is
locked down then EPERM is returned (this is then consistent with
other lockdown cases).
(2) If the signature is unparseable (EBADMSG, EINVAL), the signature fails
the check (EKEYREJECTED) or a system error occurs (eg. ENOMEM), we
return the error we got.
Note that the X.509 code doesn't check for key expiry as the RTC might not
be valid or might not have been transferred to the kernel's clock yet.
[Modified by Matthew Garrett to remove the IMA integration. This will
be replaced with integration with the IMA architecture policy
patchset.]
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
Cc: Jessica Yu <jeyu@kernel.org>
---
include/linux/security.h | 1 +
kernel/module.c | 38 +++++++++++++++++++++++++++++-------
security/lockdown/lockdown.c | 1 +
3 files changed, 33 insertions(+), 7 deletions(-)
@@ -2779,16 +2780,39 @@ static int module_sig_check(struct load_info *info, int flags)err=mod_verify_sig(mod,info);}-if(!err){+switch(err){+case0:info->sig_ok=true;return0;-}-/* Not having a signature is only an error if we're strict. */-if(err==-ENOKEY&&!is_module_sig_enforced())-err=0;+/* We don't permit modules to be loaded into trusted kernels+*withoutavalidsignatureonthem,butifwe'renot+*enforcing,certainerrorsarenon-fatal.+*/+case-ENODATA:+reason="Loading of unsigned module";+gotodecide;+case-ENOPKG:+reason="Loading of module with unsupported crypto";+gotodecide;+case-ENOKEY:+reason="Loading of module with unavailable key";+decide:+if(is_module_sig_enforced()){+pr_notice("%s is rejected\n",reason);+return-EKEYREJECTED;+}-returnerr;+ret=security_locked_down(LOCKDOWN_MODULE_SIGNATURE);+returnret;
return security_locked_down(LOCKDOWN_MODULE_SIGNATURE); ? Means no need
to add "ret". Regardless:
Reviewed-by: Kees Cook <redacted>
-Kees
quoted hunk
+
+ /* All other errors are fatal, including nomem, unparseable
+ * signatures and signature check failures - even if signatures
+ * aren't required.
+ */
+ default:
+ return err;
+ }
}
#else /* !CONFIG_MODULE_SIG */
static int module_sig_check(struct load_info *info, int flags)
On Fri, Jun 21, 2019 at 05:03:34PM -0700, Matthew Garrett wrote:
quoted hunk
From: Matthew Garrett <mjg59@srcf.ucam.org>
Allowing users to read and write to core kernel memory makes it possible
for the kernel to be subverted, avoiding module loading restrictions, and
also to steal cryptographic information.
Disallow /dev/mem and /dev/kmem from being opened this when the kernel has
been locked down to prevent this.
Also disallow /dev/port from being opened to prevent raw ioport access and
thus DMA from being used to accomplish the same thing.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
Cc: x86@kernel.org
---
drivers/char/mem.c | 6 +++++-
include/linux/security.h | 1 +
security/lockdown/lockdown.c | 1 +
3 files changed, 7 insertions(+), 1 deletion(-)
Usually the ordering for LSM tests tends to follow capable checks, which
allows for things like audit to generate logs for capability rejections,
etc. I'd expect this to be:
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
return security_locked_down(LOCKDOWN_DEV_MEM)
With that fixed:
Reviewed-by: Kees Cook <redacted>
-Kees
On Fri, Jun 21, 2019 at 05:03:35PM -0700, Matthew Garrett wrote:
From: Matthew Garrett <mjg59@srcf.ucam.org>
The kexec_load() syscall permits the loading and execution of arbitrary
code in ring 0, which is something that lock-down is meant to prevent. It
makes sense to disable kexec_load() in this situation.
This does not affect kexec_file_load() syscall which can check for a
signature on the image to be booted.
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Kees Cook <redacted>
-Kees
quoted hunk
Signed-off-by: Matthew Garrett <redacted>
Acked-by: Dave Young <redacted>
cc: kexec@lists.infradead.org
---
include/linux/security.h | 1 +
kernel/kexec.c | 8 ++++++++
security/lockdown/lockdown.c | 1 +
3 files changed, 10 insertions(+)
@@ -207,6 +207,14 @@ static inline int kexec_load_check(unsigned long nr_segments,if(result<0)returnresult;+/*+*kexeccanbeusedtocircumventmoduleloadingrestrictions,so+*preventloadinginthatcase+*/+result=security_locked_down(LOCKDOWN_KEXEC);+if(result)+returnresult;+/**Verifywehavealegalsetofflags*Thisleavesusroomforfutureextensions.
On Fri, Jun 21, 2019 at 05:03:36PM -0700, Matthew Garrett wrote:
From: Dave Young <redacted>
Kexec reboot in case secure boot being enabled does not keep the secure
boot mode in new kernel, so later one can load unsigned kernel via legacy
kexec_load. In this state, the system is missing the protections provided
by secure boot.
Adding a patch to fix this by retain the secure_boot flag in original
kernel.
secure_boot flag in boot_params is set in EFI stub, but kexec bypasses the
stub. Fixing this issue by copying secure_boot flag across kexec reboot.
Signed-off-by: Dave Young <redacted>
Reviewed-by: Kees Cook <redacted>
-Kees
quoted hunk
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
cc: kexec@lists.infradead.org
---
arch/x86/kernel/kexec-bzimage64.c | 1 +
1 file changed, 1 insertion(+)
On Fri, Jun 21, 2019 at 05:03:38PM -0700, Matthew Garrett wrote:
From: Jiri Bohac <redacted>
When KEXEC_SIG is not enabled, kernel should not load images through
kexec_file systemcall if the kernel is locked down.
[Modified by David Howells to fit with modifications to the previous patch
and to return -EPERM if the kernel is locked down for consistency with
other lockdowns. Modified by Matthew Garrett to remove the IMA
integration, which will be replaced by integrating with the IMA
architecture policy patches.]
Signed-off-by: Jiri Bohac <redacted>
@@ -237,7 +237,10 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,gotoout;}-ret=0;+ret=security_locked_down(LOCKDOWN_KEXEC);+if(ret)+gotoout;+break;/* All other errors are fatal, including nomem, unparseable
On Fri, Jun 21, 2019 at 05:03:39PM -0700, Matthew Garrett wrote:
From: Josh Boyer <redacted>
There is currently no way to verify the resume image when returning
from hibernate. This might compromise the signed modules trust model,
so until we can work with signed hibernate images we disable it when the
kernel is locked down.
Signed-off-by: Josh Boyer <redacted>
On Fri, Jun 21, 2019 at 05:03:40PM -0700, Matthew Garrett wrote:
From: Matthew Garrett <mjg59@srcf.ucam.org>
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.
Signed-off-by: David Howells <dhowells@redhat.com>
On Fri, Jun 21, 2019 at 05:03:41PM -0700, Matthew Garrett wrote:
From: Matthew Garrett <mjg59@srcf.ucam.org>
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.
Signed-off-by: Matthew Garrett <redacted>
@@ -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)||+security_locked_down(LOCKDOWN_IOPORT)))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)||+security_locked_down(LOCKDOWN_IOPORT))return-EPERM;}regs->flags=(regs->flags&~X86_EFLAGS_IOPL)|
On Fri, Jun 21, 2019 at 05:03:43PM -0700, Matthew Garrett wrote:
From: Matthew Garrett <mjg59@srcf.ucam.org>
custom_method effectively allows arbitrary access to system memory, making
it possible for an attacker to circumvent restrictions on module loading.
Disable it if the kernel is locked down.
Signed-off-by: Matthew Garrett <redacted>
On Fri, Jun 21, 2019 at 05:03:44PM -0700, Matthew Garrett wrote:
From: Josh Boyer <redacted>
This option allows userspace to pass the RSDP address to the kernel, which
makes it possible for a user to modify the workings of hardware . Reject
the option when the kernel is locked down.
Signed-off-by: Josh Boyer <redacted>
Reviewed-by: Kees Cook <redacted>
-Kees
quoted hunk
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
cc: Dave Young <redacted>
cc: linux-acpi@vger.kernel.org
---
drivers/acpi/osl.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
On Fri, Jun 21, 2019 at 05:03:45PM -0700, Matthew Garrett wrote:
From: Linn Crosetto <redacted>
From the kernel documentation (initrd_table_override.txt):
If the ACPI_INITRD_TABLE_OVERRIDE compile option is true, it is possible
to override nearly any ACPI table provided by the BIOS with an
instrumented, modified one.
When lockdown is enabled, the kernel should disallow any unauthenticated
changes to kernel space. ACPI tables contain code invoked by the kernel,
so do not allow ACPI tables to be overridden if the kernel is locked down.
Signed-off-by: Linn Crosetto <redacted>
Reviewed-by: Kees Cook <redacted>
-Kees
quoted hunk
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
cc: linux-acpi@vger.kernel.org
---
drivers/acpi/tables.c | 6 ++++++
1 file changed, 6 insertions(+)
On Fri, Jun 21, 2019 at 05:03:46PM -0700, Matthew Garrett wrote:
From: David Howells <dhowells@redhat.com>
Prohibit replacement of the PCMCIA Card Information Structure when the
kernel is locked down.
Suggested-by: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: David Howells <dhowells@redhat.com>
On Fri, Jun 21, 2019 at 05:03:47PM -0700, Matthew Garrett wrote:
quoted hunk
From: David Howells <dhowells@redhat.com>
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.
Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
cc: Jiri Slaby <redacted>
Cc: linux-serial@vger.kernel.org
---
drivers/tty/serial/serial_core.c | 5 +++++
include/linux/security.h | 1 +
security/lockdown/lockdown.c | 1 +
3 files changed, 7 insertions(+)
On Fri, Jun 21, 2019 at 05:03:48PM -0700, Matthew Garrett wrote:
From: David Howells <dhowells@redhat.com>
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).
Suggested-by: Alan Cox <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
@@ -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 */
On Fri, Jun 21, 2019 at 05:03:49PM -0700, Matthew Garrett wrote:
From: David Howells <dhowells@redhat.com>
The testmmiotrace module shouldn't be permitted when the kernel is locked
down as it can be used to arbitrarily read and write MMIO space. This is
a runtime check rather than buildtime in order to allow configurations
where the same kernel may be run in both locked down or permissive modes
depending on local policy.
Suggested-by: Thomas Gleixner <redacted>
Signed-off-by: David Howells <dhowells@redhat.com
@@ -114,6 +115,10 @@ static void do_test_bulk_ioremapping(void)staticint__initinit(void){unsignedlongsize=(read_far)?(8<<20):(16<<10);+intret=security_locked_down(LOCKDOWN_MMIOTRACE);++if(ret)+returnret;if(mmio_address==0){pr_err("you have to use the module argument mmio_address.\n");
On Fri, Jun 21, 2019 at 05:03:50PM -0700, Matthew Garrett wrote:
quoted hunk
From: David Howells <dhowells@redhat.com>
Disallow access to /proc/kcore when the kernel is locked down to prevent
access to cryptographic data. This is limited to lockdown
confidentiality mode and is still permitted in integrity mode.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
---
fs/proc/kcore.c | 5 +++++
include/linux/security.h | 1 +
security/lockdown/lockdown.c | 1 +
3 files changed, 7 insertions(+)
On Fri, Jun 21, 2019 at 05:03:51PM -0700, Matthew Garrett wrote:
From: David Howells <dhowells@redhat.com>
Disallow the creation of perf and ftrace kprobes when the kernel is
locked down in confidentiality mode by preventing their registration.
This prevents kprobes from being used to access kernel memory to steal
crypto data, but continues to allow the use of kprobes from signed
modules.
Reported-by: Alexei Starovoitov <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
Cc: Naveen N. Rao <redacted>
Cc: Anil S Keshavamurthy <redacted>
Cc: davem@davemloft.net
Cc: Masami Hiramatsu <mhiramat@kernel.org>
On Fri, Jun 21, 2019 at 05:03:52PM -0700, Matthew Garrett wrote:
From: David Howells <dhowells@redhat.com>
There are some bpf functions can be used to read kernel memory:
bpf_probe_read, bpf_probe_write_user and bpf_trace_printk. These allow
private keys in kernel memory (e.g. the hibernation image signing key) to
be read by an eBPF program and kernel memory to be altered without
restriction. Disable them if the kernel has been locked down in
confidentiality mode.
Suggested-by: Alexei Starovoitov <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
@@ -10731,6 +10731,13 @@ SYSCALL_DEFINE5(perf_event_open,return-EINVAL;}+err=security_locked_down(LOCKDOWN_PERF);+if(err&&(attr.sample_type&PERF_SAMPLE_REGS_INTR))+/* REGS_INTR can leak data, lockdown must prevent this */+returnerr;+else+err=0;+/* Only privileged users can get physical addresses */if((attr.sample_type&PERF_SAMPLE_PHYS_ADDR)&&perf_paranoid_kernel()&&!capable(CAP_SYS_ADMIN))
With moar capable() ordering fixed...
Reviewed-by: Kees Cook <redacted>
-Kees
@@ -34,6 +34,7 @@ static char *lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {[LOCKDOWN_KCORE]="/proc/kcore access",[LOCKDOWN_KPROBES]="use of kprobes",[LOCKDOWN_BPF_READ]="use of bpf to read kernel RAM",+[LOCKDOWN_PERF]="unsafe use of perf",[LOCKDOWN_CONFIDENTIALITY_MAX]="confidentiality",};
On Fri, Jun 21, 2019 at 05:03:57PM -0700, Matthew Garrett wrote:
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.
Signed-off-by: Matthew Garrett <redacted>
On Fri, Jun 21, 2019 at 05:03:58PM -0700, Matthew Garrett wrote:
quoted hunk
Print the content of current->comm in messages generated by lockdown to
indicate a restriction that was hit. This makes it a bit easier to find
out what caused the message.
The message now patterned something like:
Lockdown: <comm>: <what> is restricted; see man kernel_lockdown.7
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
---
security/lockdown/lockdown.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
@@ -83,8 +83,8 @@ static int lockdown_is_locked_down(enum lockdown_reason what){if((kernel_locked_down>=what)){
To satisfy my paranoia, can you just add here:
if (WARN(what > LOCKDOWN_..._MAX))
return -EPERM;
With that:
Reviewed-by: Kees Cook <redacted>
-Kees
if (lockdown_reasons[what])
- pr_notice("Lockdown: %s is restricted; see man kernel_lockdown.7\n",
- lockdown_reasons[what]);
+ pr_notice("Lockdown: %s: %s is restricted; see man kernel_lockdown.7\n",
+ current->comm, lockdown_reasons[what]);
return -EPERM;
}
--
2.22.0.410.gd8fdbe21b5-goog
On Fri, 21 Jun 2019 17:03:51 -0700
Matthew Garrett [off-list ref] wrote:
From: David Howells <dhowells@redhat.com>
Disallow the creation of perf and ftrace kprobes when the kernel is
locked down in confidentiality mode by preventing their registration.
This prevents kprobes from being used to access kernel memory to steal
crypto data, but continues to allow the use of kprobes from signed
modules.
Looks (and sounds) good to me.
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Thank you,
From: Thomas Gleixner <hidden> Date: 2019-06-23 11:10:21
On Fri, 21 Jun 2019, Matthew Garrett wrote:
From: David Howells <dhowells@redhat.com>
The testmmiotrace module shouldn't be permitted when the kernel is locked
down as it can be used to arbitrarily read and write MMIO space. This is
a runtime check rather than buildtime in order to allow configurations
where the same kernel may be run in both locked down or permissive modes
depending on local policy.
Suggested-by: Thomas Gleixner <redacted>
Signed-off-by: David Howells <dhowells@redhat.com
Signed-off-by: Matthew Garrett <redacted>
cc: Thomas Gleixner <redacted>
cc: Steven Rostedt <rostedt@goodmis.org>
cc: Ingo Molnar <mingo@kernel.org>
cc: "H. Peter Anvin" <hpa@zytor.com>
cc: x86@kernel.org
From: Dave Young <hidden> Date: 2019-06-24 02:01:18
On 06/21/19 at 05:03pm, Matthew Garrett wrote:
From: Jiri Bohac <redacted>
This is a preparatory patch for kexec_file_load() lockdown. A locked down
kernel needs to prevent unsigned kernel images from being loaded with
kexec_file_load(). Currently, the only way to force the signature
verification is compiling with KEXEC_VERIFY_SIG. This prevents loading
usigned images even when the kernel is not locked down at runtime.
This patch splits KEXEC_VERIFY_SIG into KEXEC_SIG and KEXEC_SIG_FORCE.
Analogous to the MODULE_SIG and MODULE_SIG_FORCE for modules, KEXEC_SIG
turns on the signature verification but allows unsigned images to be
loaded. KEXEC_SIG_FORCE disallows images without a valid signature.
[Modified by David Howells such that:
(1) verify_pefile_signature() differentiates between no-signature and
sig-didn't-match in its returned errors.
(2) kexec fails with EKEYREJECTED if there is a signature for which we
have a key, but signature doesn't match - even if in non-forcing mode.
(3) kexec fails with EBADMSG or some other error if there is a signature
which cannot be parsed - even if in non-forcing mode.
(4) kexec fails with ELIBBAD if the PE file cannot be parsed to extract
the signature - even if in non-forcing mode.
]
Seems I do not see EBADMSG and ELIBBAD in this patch, also kexec fails
with proper errno instead of EKEYREJECTED only.
I may missed something? Other than the patch log issue:
Reviewed-by: Dave Young <redacted>
@@ -100,7 +100,7 @@ static int pefile_parse_binary(const void *pebuf, unsigned int pelen,if(!ddir->certs.virtual_address||!ddir->certs.size){pr_debug("Unsigned PE binary\n");-return-EKEYREJECTED;+return-ENODATA;}chkaddr(ctx->header_size,ddir->certs.virtual_address,
@@ -408,6 +408,8 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen,*(*)0ifatleastonesignaturechainintersectswiththekeysinthetrust*keyring,or:*+*(*)-ENODATAifthereisnosignaturepresent.+**(*)-ENOPKGifasuitablecryptomodulecouldn'tbefoundforacheckona*chain.*
@@ -188,7 +188,8 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,constchar__user*cmdline_ptr,unsignedlongcmdline_len,unsignedflags){-intret=0;+constchar*reason;+intret;void*ldata;loff_tsize;
@@ -207,15 +208,47 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,if(ret)gotoout;-#ifdef CONFIG_KEXEC_VERIFY_SIG+#ifdef CONFIG_KEXEC_SIGret=arch_kexec_kernel_verify_sig(image,image->kernel_buf,image->kernel_buf_len);-if(ret){-pr_debug("kernel signature verification failed.\n");+#else+ret=-ENODATA;+#endif++switch(ret){+case0:+break;++/* Certain verification errors are non-fatal if we're not+*checkingerrors,providedwearen'tmandatingthatthere+*mustbeavalidsignature.+*/+case-ENODATA:+reason="kexec of unsigned image";+gotodecide;+case-ENOPKG:+reason="kexec of image with unsupported crypto";+gotodecide;+case-ENOKEY:+reason="kexec of image with unavailable key";+decide:+if(IS_ENABLED(CONFIG_KEXEC_SIG_FORCE)){+pr_notice("%s rejected\n",reason);+gotoout;+}++ret=0;+break;++/* All other errors are fatal, including nomem, unparseable+*signaturesandsignaturecheckfailures-evenifsignatures+*aren'trequired.+*/+default:+pr_notice("kernel signature verification failed (%d).\n",ret);gotoout;}-pr_debug("kernel signature verification successful.\n");-#endif+/* It is possible that there no initramfs is being loaded */if(!(flags&KEXEC_FILE_NO_INITRAMFS)){ret=kernel_read_file_from_fd(initrd_fd,&image->initrd_buf,
There is currently no way to verify the resume image when returning
from hibernate. This might compromise the signed modules trust model,
so until we can work with signed hibernate images we disable it when the
kernel is locked down.
I keep getting these...
IIRC suse has patches to verify the images.
Yeah, Joey Lee is taking care of those. CCing.
--
Jiri Kosina
SUSE Labs
From: Daniel Borkmann <daniel@iogearbox.net> Date: 2019-06-24 15:37:27
On 06/22/2019 02:03 AM, Matthew Garrett wrote:
From: David Howells <dhowells@redhat.com>
There are some bpf functions can be used to read kernel memory:
Nit: that
bpf_probe_read, bpf_probe_write_user and bpf_trace_printk. These allow
Please explain how bpf_probe_write_user reads kernel memory ... ?!
private keys in kernel memory (e.g. the hibernation image signing key) to
be read by an eBPF program and kernel memory to be altered without
... and while we're at it, also how they allow "kernel memory to be
altered without restriction". I've been pointing this false statement
out long ago.
restriction. Disable them if the kernel has been locked down in
confidentiality mode.
Suggested-by: Alexei Starovoitov <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <redacted>
cc: netdev@vger.kernel.org
cc: Chun-Yi Lee <jlee@suse.com>
cc: Alexei Starovoitov <redacted>
Cc: Daniel Borkmann <daniel@iogearbox.net>
This whole thing is still buggy as has been pointed out before by
Jann. For helpers like above and few others below, error conditions
must clear the buffer ...
quoted hunk
ret = probe_kernel_read(dst, unsafe_ptr, size);
if (unlikely(ret < 0))
memset(dst, 0, size);
@@ -156,6 +160,12 @@ static const struct bpf_func_proto bpf_probe_read_proto = { BPF_CALL_3(bpf_probe_write_user, void *, unsafe_ptr, const void *, src, u32, size) {+ int ret;++ ret = security_locked_down(LOCKDOWN_BPF_READ);+ if (ret)+ return ret;+ /* * Ensure we're in user context which is safe for the helper to * run. This helper has no business in a kthread.
@@ -205,7 +215,11 @@ BPF_CALL_5(bpf_trace_printk, char *, fmt, u32, fmt_size, u64, arg1, int fmt_cnt = 0; u64 unsafe_addr; char buf[64];- int i;+ int i, ret;++ ret = security_locked_down(LOCKDOWN_BPF_READ);+ if (ret)+ return ret; /* * bpf_check()->check_func_arg()->check_stack_boundary()
@@ -534,6 +548,10 @@ BPF_CALL_3(bpf_probe_read_str, void *, dst, u32, size, { int ret;+ ret = security_locked_down(LOCKDOWN_BPF_READ);+ if (ret)+ return ret;+ /* * The strncpy_from_unsafe() call will likely not fill the entire * buffer, but that's okay in this circumstance as we're probing
From: Matthew Garrett <hidden> Date: 2019-06-24 19:54:15
On Mon, Jun 24, 2019 at 8:37 AM Daniel Borkmann [off-list ref] wrote:
On 06/22/2019 02:03 AM, Matthew Garrett wrote:
quoted
From: David Howells <dhowells@redhat.com>
There are some bpf functions can be used to read kernel memory:
Nit: that
Fixed.
quoted
bpf_probe_read, bpf_probe_write_user and bpf_trace_printk. These allow
Please explain how bpf_probe_write_user reads kernel memory ... ?!
Ha.
quoted
private keys in kernel memory (e.g. the hibernation image signing key) to
be read by an eBPF program and kernel memory to be altered without
... and while we're at it, also how they allow "kernel memory to be
altered without restriction". I've been pointing this false statement
out long ago.
Yup. How's the following description:
bpf: Restrict bpf when kernel lockdown is in confidentiality mode
There are some bpf functions that can be used to read kernel memory and
exfiltrate it to userland: bpf_probe_read, bpf_probe_write_user and
bpf_trace_printk. These could be abused to (eg) allow private
keys in kernel
memory to be leaked. Disable them if the kernel has been locked
down in confidentiality
mode.
This whole thing is still buggy as has been pointed out before by
Jann. For helpers like above and few others below, error conditions
must clear the buffer ...
From: Andy Lutomirski <luto@kernel.org> Date: 2019-06-24 20:09:01
On Mon, Jun 24, 2019 at 12:54 PM Matthew Garrett [off-list ref] wrote:
On Mon, Jun 24, 2019 at 8:37 AM Daniel Borkmann [off-list ref] wrote:
quoted
On 06/22/2019 02:03 AM, Matthew Garrett wrote:
quoted
From: David Howells <dhowells@redhat.com>
There are some bpf functions can be used to read kernel memory:
Nit: that
Fixed.
quoted
quoted
bpf_probe_read, bpf_probe_write_user and bpf_trace_printk. These allow
Please explain how bpf_probe_write_user reads kernel memory ... ?!
Ha.
quoted
quoted
private keys in kernel memory (e.g. the hibernation image signing key) to
be read by an eBPF program and kernel memory to be altered without
... and while we're at it, also how they allow "kernel memory to be
altered without restriction". I've been pointing this false statement
out long ago.
Yup. How's the following description:
bpf: Restrict bpf when kernel lockdown is in confidentiality mode
There are some bpf functions that can be used to read kernel memory and
exfiltrate it to userland: bpf_probe_read, bpf_probe_write_user and
bpf_trace_printk. These could be abused to (eg) allow private
keys in kernel
memory to be leaked. Disable them if the kernel has been locked
down in confidentiality
mode.
I'm confused. I understand why we're restricting bpf_probe_read().
Why are we restricting bpf_probe_write_user() and bpf_trace_printk(),
though?
--Andy
From: Daniel Borkmann <daniel@iogearbox.net> Date: 2019-06-24 21:22:23
On 06/24/2019 10:08 PM, Andy Lutomirski wrote:
On Mon, Jun 24, 2019 at 12:54 PM Matthew Garrett [off-list ref] wrote:
quoted
On Mon, Jun 24, 2019 at 8:37 AM Daniel Borkmann [off-list ref] wrote:
quoted
On 06/22/2019 02:03 AM, Matthew Garrett wrote:
quoted
From: David Howells <dhowells@redhat.com>
There are some bpf functions can be used to read kernel memory:
Nit: that
Fixed.
quoted
quoted
bpf_probe_read, bpf_probe_write_user and bpf_trace_printk. These allow
Please explain how bpf_probe_write_user reads kernel memory ... ?!
Ha.
quoted
quoted
private keys in kernel memory (e.g. the hibernation image signing key) to
be read by an eBPF program and kernel memory to be altered without
... and while we're at it, also how they allow "kernel memory to be
altered without restriction". I've been pointing this false statement
out long ago.
Yup. How's the following description:
bpf: Restrict bpf when kernel lockdown is in confidentiality mode
There are some bpf functions that can be used to read kernel memory and
exfiltrate it to userland: bpf_probe_read, bpf_probe_write_user and
bpf_trace_printk. These could be abused to (eg) allow private
keys in kernel
memory to be leaked. Disable them if the kernel has been locked
down in confidentiality
mode.
I'm confused. I understand why we're restricting bpf_probe_read().
Why are we restricting bpf_probe_write_user() and bpf_trace_printk(),
though?
Agree, for example, bpf_probe_write_user() can never write into
kernel memory (only user one). Just thinking out loud, wouldn't it
be cleaner and more generic to perform this check at the actual function
which performs the kernel memory without faulting? All three of these
are in mm/maccess.c, and the very few occasions that override the
probe_kernel_read symbol are calling eventually into __probe_kernel_read(),
so this would catch all of them wrt lockdown restrictions. Otherwise
you'd need to keep tracking every bit of new code being merged that
calls into one of these, no? That way you only need to do it once like
below and are guaranteed that the check catches these in future as well.
Thanks,
Daniel
From: Matthew Garrett <hidden> Date: 2019-06-24 21:31:01
On Mon, Jun 24, 2019 at 2:22 PM Daniel Borkmann [off-list ref] wrote:
Agree, for example, bpf_probe_write_user() can never write into
kernel memory (only user one). Just thinking out loud, wouldn't it
be cleaner and more generic to perform this check at the actual function
which performs the kernel memory without faulting? All three of these
are in mm/maccess.c, and the very few occasions that override the
probe_kernel_read symbol are calling eventually into __probe_kernel_read(),
so this would catch all of them wrt lockdown restrictions. Otherwise
you'd need to keep tracking every bit of new code being merged that
calls into one of these, no? That way you only need to do it once like
below and are guaranteed that the check catches these in future as well.
Not all paths into probe_kernel_read/write are from entry points that
need to be locked down (eg, as far as I can tell ftrace can't leak
anything interesting here).
From: James Morris <jmorris@namei.org> Date: 2019-06-24 23:01:56
On Fri, 21 Jun 2019, Matthew Garrett wrote:
Minor updates over V33 - security_is_locked_down renamed to
security_locked_down, return value of security_locked_down is returned
in most cases, one unnecessary patch was dropped, couple of minor nits
fixed.
Thanks for the respin.
We are still not resolved on granularity. Stephen has said he's not sure
if a useful policy can be constructed with just confidentiality and
integrity settings. I'd be interested to know JJ and Casey's thoughts on
lockdown policy flexibility wrt their respective LSMs.
These are also "all or nothing" choices which may prevent deployment due
to a user needing to allow (presumably controlled or mitigated) exceptions
to the policy.
--
James Morris
[off-list ref]
Minor updates over V33 - security_is_locked_down renamed to
security_locked_down, return value of security_locked_down is returned
in most cases, one unnecessary patch was dropped, couple of minor nits
fixed.
Thanks for the respin.
We are still not resolved on granularity. Stephen has said he's not sure
if a useful policy can be constructed with just confidentiality and
integrity settings. I'd be interested to know JJ and Casey's thoughts on
lockdown policy flexibility wrt their respective LSMs.
Smack is a mandatory access control mechanism on named
objects controlled by the system. Issues of administrative
control, like whether hibernation is allowed, are outside
the scope of what Smack controls. There may be some subject/object
implications, but I have not identified any yet.
These are also "all or nothing" choices which may prevent deployment due
to a user needing to allow (presumably controlled or mitigated) exceptions
to the policy.
From: Matthew Garrett <hidden> Date: 2019-06-24 23:56:41
On Mon, Jun 24, 2019 at 4:01 PM James Morris [off-list ref] wrote:
On Fri, 21 Jun 2019, Matthew Garrett wrote:
quoted
Minor updates over V33 - security_is_locked_down renamed to
security_locked_down, return value of security_locked_down is returned
in most cases, one unnecessary patch was dropped, couple of minor nits
fixed.
Thanks for the respin.
We are still not resolved on granularity. Stephen has said he's not sure
if a useful policy can be constructed with just confidentiality and
integrity settings. I'd be interested to know JJ and Casey's thoughts on
lockdown policy flexibility wrt their respective LSMs.
This implementation provides arbitrary granularity at the LSM level,
though the lockdown LSM itself only provides two levels. Other LSMs
can choose an appropriate level of exposure.
These are also "all or nothing" choices which may prevent deployment due
to a user needing to allow (presumably controlled or mitigated) exceptions
to the policy.
Distributions have been deploying the "all or nothing" solution for
several years now, which implies that it's adequate for the common
case. I think it's reasonable to punt finer grained policies over to
other LSMs - people who want that are probably already using custom
LSM policy.
From: Dave Young <hidden> Date: 2019-06-25 02:35:26
On 06/24/19 at 10:01am, Dave Young wrote:
On 06/21/19 at 05:03pm, Matthew Garrett wrote:
quoted
From: Jiri Bohac <redacted>
This is a preparatory patch for kexec_file_load() lockdown. A locked down
kernel needs to prevent unsigned kernel images from being loaded with
kexec_file_load(). Currently, the only way to force the signature
verification is compiling with KEXEC_VERIFY_SIG. This prevents loading
usigned images even when the kernel is not locked down at runtime.
This patch splits KEXEC_VERIFY_SIG into KEXEC_SIG and KEXEC_SIG_FORCE.
Analogous to the MODULE_SIG and MODULE_SIG_FORCE for modules, KEXEC_SIG
turns on the signature verification but allows unsigned images to be
loaded. KEXEC_SIG_FORCE disallows images without a valid signature.
[Modified by David Howells such that:
(1) verify_pefile_signature() differentiates between no-signature and
sig-didn't-match in its returned errors.
(2) kexec fails with EKEYREJECTED if there is a signature for which we
have a key, but signature doesn't match - even if in non-forcing mode.
(3) kexec fails with EBADMSG or some other error if there is a signature
which cannot be parsed - even if in non-forcing mode.
(4) kexec fails with ELIBBAD if the PE file cannot be parsed to extract
the signature - even if in non-forcing mode.
]
Seems I do not see EBADMSG and ELIBBAD in this patch, also kexec fails
with proper errno instead of EKEYREJECTED only.
I may missed something? Other than the patch log issue:
Reviewed-by: Dave Young <redacted>
Hold on :) Noticed another issue, please see comment inline..
@@ -100,7 +100,7 @@ static int pefile_parse_binary(const void *pebuf, unsigned int pelen,if(!ddir->certs.virtual_address||!ddir->certs.size){pr_debug("Unsigned PE binary\n");-return-EKEYREJECTED;+return-ENODATA;}chkaddr(ctx->header_size,ddir->certs.virtual_address,
@@ -408,6 +408,8 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen,*(*)0ifatleastonesignaturechainintersectswiththekeysinthetrust*keyring,or:*+*(*)-ENODATAifthereisnosignaturepresent.+**(*)-ENOPKGifasuitablecryptomodulecouldn'tbefoundforacheckona*chain.*
@@ -188,7 +188,8 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,constchar__user*cmdline_ptr,unsignedlongcmdline_len,unsignedflags){-intret=0;+constchar*reason;+intret;void*ldata;loff_tsize;
@@ -207,15 +208,47 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,if(ret)gotoout;-#ifdef CONFIG_KEXEC_VERIFY_SIG+#ifdef CONFIG_KEXEC_SIGret=arch_kexec_kernel_verify_sig(image,image->kernel_buf,image->kernel_buf_len);-if(ret){-pr_debug("kernel signature verification failed.\n");+#else+ret=-ENODATA;
Use -ENODATA for above case looks not correct, please just remove the #else and
move the #endif to the end of the switch chunk.
quoted
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+
+ /* Certain verification errors are non-fatal if we're not
+ * checking errors, provided we aren't mandating that there
+ * must be a valid signature.
+ */
+ case -ENODATA:
+ reason = "kexec of unsigned image";
+ goto decide;
+ case -ENOPKG:
+ reason = "kexec of image with unsupported crypto";
+ goto decide;
+ case -ENOKEY:
+ reason = "kexec of image with unavailable key";
+ decide:
+ if (IS_ENABLED(CONFIG_KEXEC_SIG_FORCE)) {
+ pr_notice("%s rejected\n", reason);
+ goto out;
+ }
+
+ ret = 0;
+ break;
+
+ /* All other errors are fatal, including nomem, unparseable
+ * signatures and signature check failures - even if signatures
+ * aren't required.
+ */
+ default:
+ pr_notice("kernel signature verification failed (%d).\n", ret);
goto out;
}
- pr_debug("kernel signature verification successful.\n");
-#endif
+
/* It is possible that there no initramfs is being loaded */
if (!(flags & KEXEC_FILE_NO_INITRAMFS)) {
ret = kernel_read_file_from_fd(initrd_fd, &image->initrd_buf,
--
2.22.0.410.gd8fdbe21b5-goog
From: James Morris <jmorris@namei.org> Date: 2019-06-25 06:04:29
On Mon, 24 Jun 2019, Matthew Garrett wrote:
quoted
We are still not resolved on granularity. Stephen has said he's not sure
if a useful policy can be constructed with just confidentiality and
integrity settings. I'd be interested to know JJ and Casey's thoughts on
lockdown policy flexibility wrt their respective LSMs.
This implementation provides arbitrary granularity at the LSM level,
though the lockdown LSM itself only provides two levels. Other LSMs
can choose an appropriate level of exposure.
Ahh, OK, I only looked at the patchset description and had not looked at
V33 yet.
This is looking good.
--
James Morris
[off-list ref]
From: John Johansen <john.johansen@canonical.com> Date: 2019-06-25 08:17:00
On 6/24/19 4:01 PM, James Morris wrote:
On Fri, 21 Jun 2019, Matthew Garrett wrote:
quoted
Minor updates over V33 - security_is_locked_down renamed to
security_locked_down, return value of security_locked_down is returned
in most cases, one unnecessary patch was dropped, couple of minor nits
fixed.
Thanks for the respin.
We are still not resolved on granularity. Stephen has said he's not sure
if a useful policy can be constructed with just confidentiality and
integrity settings. I'd be interested to know JJ and Casey's thoughts on
lockdown policy flexibility wrt their respective LSMs.
These are also "all or nothing" choices which may prevent deployment due
to a user needing to allow (presumably controlled or mitigated) exceptions
to the policy.
I haven't gotten a chance to play with this the way I want to so there is
still a lot of questions regarding its interaction with apparmor and its
policy, but from what I have seen so far it is looking good.
I expect the all or nothing choices may limit its deployments (we really
need to play with this more to say) but we already face similar issues.
There are options we provide at a distro level that we can't turn on by
default, but we do recommend to more security conscious users.
If lockdown was in kernel we would certainly make it available for our
users, we have even had a few people ask about it.
On Sat, 22 Jun 2019 at 02:05, Matthew Garrett [off-list ref] wrote:
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.
Signed-off-by: Matthew Garrett <redacted>
Cc: Ard Biesheuvel <redacted>
Cc: linux-efi@vger.kernel.org
@@ -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 */
From: James Morris <jmorris@namei.org> Date: 2019-06-27 04:59:36
On Fri, 21 Jun 2019, Matthew Garrett wrote:
From: Jiri Bohac <redacted>
When KEXEC_SIG is not enabled, kernel should not load images through
kexec_file systemcall if the kernel is locked down.
This is not a criticism of the patch but a related issue which I haven't
seen discussed (apologies if it has).
If signed code is loaded into ring 0, verified by the kernel, then
executed, you still lose your secure/trusted/verified boot state. If the
currently running kernel has been runtime-compromised, any signature
verification performed by the kernel cannot be trusted.
This problem is out of scope for the lockdown threat model (which
naturally cannot include a compromised kernel), but folk should be aware
that signature-verified kexec does not provide equivalent assurance to a
full reboot on a secure-boot system.
Potential mitigations here include runtime integrity verification of the
kernel via a separate security monitor (hypervisor, SMM, TEE etc.) or some
kind of platform support for kexec verification.
--
James Morris
[off-list ref]
From: Matthew Garrett <hidden> Date: 2019-06-27 15:28:23
On Wed, Jun 26, 2019 at 9:59 PM James Morris [off-list ref] wrote:
This is not a criticism of the patch but a related issue which I haven't
seen discussed (apologies if it has).
If signed code is loaded into ring 0, verified by the kernel, then
executed, you still lose your secure/trusted/verified boot state. If the
currently running kernel has been runtime-compromised, any signature
verification performed by the kernel cannot be trusted.
This problem is out of scope for the lockdown threat model (which
naturally cannot include a compromised kernel), but folk should be aware
that signature-verified kexec does not provide equivalent assurance to a
full reboot on a secure-boot system.
By that metric, on a secure boot system how do we determine that code
running in the firmware environment wasn't compromised before it
launched the initial signed kernel?