diff --git a/iwlegacy-fix-IBSS-cleanup.patch b/iwlegacy-fix-IBSS-cleanup.patch deleted file mode 100644 index 5533aed..0000000 --- a/iwlegacy-fix-IBSS-cleanup.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 658f1bd2dd632209df00ec66349e15941ffdd83b Mon Sep 17 00:00:00 2001 -From: Stanislaw Gruszka -Date: Wed, 16 Jan 2013 10:28:09 +0000 -Subject: [PATCH 3.8] iwlegacy: fix IBSS cleanup - -We do not correctly change interface type when switching from -IBSS mode to STA mode, that results in microcode errors. - -Resolves: -https://bugzilla.redhat.com/show_bug.cgi?id=886946 - -Reported-by: Jaroslav Skarvada -Cc: stable@vger.kernel.org -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/iwlegacy/common.c | 35 ++++++++++++++-------------------- - 1 file changed, 14 insertions(+), 21 deletions(-) - -diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c -index 7e16d10..90b8970 100644 ---- a/drivers/net/wireless/iwlegacy/common.c -+++ b/drivers/net/wireless/iwlegacy/common.c -@@ -3958,17 +3958,21 @@ il_connection_init_rx_config(struct il_priv *il) - - memset(&il->staging, 0, sizeof(il->staging)); - -- if (!il->vif) { -+ switch (il->iw_mode) { -+ case NL80211_IFTYPE_UNSPECIFIED: - il->staging.dev_type = RXON_DEV_TYPE_ESS; -- } else if (il->vif->type == NL80211_IFTYPE_STATION) { -+ break; -+ case NL80211_IFTYPE_STATION: - il->staging.dev_type = RXON_DEV_TYPE_ESS; - il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; -- } else if (il->vif->type == NL80211_IFTYPE_ADHOC) { -+ break; -+ case NL80211_IFTYPE_ADHOC: - il->staging.dev_type = RXON_DEV_TYPE_IBSS; - il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; - il->staging.filter_flags = - RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; -- } else { -+ break; -+ default: - IL_ERR("Unsupported interface type %d\n", il->vif->type); - return; - } -@@ -4550,8 +4554,7 @@ out: - EXPORT_SYMBOL(il_mac_add_interface); - - static void --il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, -- bool mode_change) -+il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif) - { - lockdep_assert_held(&il->mutex); - -@@ -4560,9 +4563,7 @@ il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, - il_force_scan_end(il); - } - -- if (!mode_change) -- il_set_mode(il); -- -+ il_set_mode(il); - } - - void -@@ -4575,8 +4576,8 @@ il_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) - - WARN_ON(il->vif != vif); - il->vif = NULL; -- -- il_teardown_interface(il, vif, false); -+ il->iw_mode = NL80211_IFTYPE_UNSPECIFIED; -+ il_teardown_interface(il, vif); - memset(il->bssid, 0, ETH_ALEN); - - D_MAC80211("leave\n"); -@@ -4685,18 +4686,10 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - } - - /* success */ -- il_teardown_interface(il, vif, true); - vif->type = newtype; - vif->p2p = false; -- err = il_set_mode(il); -- WARN_ON(err); -- /* -- * We've switched internally, but submitting to the -- * device may have failed for some reason. Mask this -- * error, because otherwise mac80211 will not switch -- * (and set the interface type back) and we'll be -- * out of sync with it. -- */ -+ il->iw_mode = newtype; -+ il_teardown_interface(il, vif); - err = 0; - - out: --- -1.8.0.2 - diff --git a/kernel.spec b/kernel.spec index e1d177b..0f74ab6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -74,7 +74,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 5 +%define stable_update 6 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -690,7 +690,7 @@ Patch800: linux-2.6-crash-driver.patch Patch901: modsign-post-KS-jwb.patch # secure boot -Patch1000: secure-boot-20121212.patch +Patch1000: secure-boot-3.7-20130204.patch Patch1001: efivarfs-3.7.patch # Improve PCI support on UEFI @@ -773,9 +773,6 @@ Patch21231: 8139cp-revert-set-ring-address-before-enabling-receiver.patch Patch21232: 8139cp-set-ring-address-after-enabling-C-mode.patch Patch21233: 8139cp-re-enable-interrupts-after-tx-timeout.patch -#rhbz 886946 -Patch21234: iwlegacy-fix-IBSS-cleanup.patch - #rhbz 892428 Patch21238: brcmsmac-updates-rhbz892428.patch @@ -1429,7 +1426,7 @@ ApplyPatch modsign-post-KS-jwb.patch # secure boot ApplyPatch efivarfs-3.7.patch -ApplyPatch secure-boot-20121212.patch +ApplyPatch secure-boot-3.7-20130204.patch # Improved PCI support for UEFI ApplyPatch handle-efi-roms.patch @@ -1496,9 +1493,6 @@ ApplyPatch 8139cp-revert-set-ring-address-before-enabling-receiver.patch -R ApplyPatch 8139cp-set-ring-address-after-enabling-C-mode.patch ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch -#rhbz 886948 -ApplyPatch iwlegacy-fix-IBSS-cleanup.patch - #rhbz 892428 ApplyPatch brcmsmac-updates-rhbz892428.patch @@ -2372,6 +2366,10 @@ fi # ||----w | # || || %changelog +* Mon Feb 04 2013 Josh Boyer +- Linux v3.7.6 +- Update secure-boot patchset + * Tue Jan 29 2013 Josh Boyer - Backport driver for Cypress PS/2 trackpad (rhbz 799564) diff --git a/secure-boot-20121212.patch b/secure-boot-20121212.patch deleted file mode 100644 index 61f796e..0000000 --- a/secure-boot-20121212.patch +++ /dev/null @@ -1,1470 +0,0 @@ -From d510ea864f470d96aafb75d0de7f09450407095e Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Thu, 20 Sep 2012 10:40:56 -0400 -Subject: [PATCH 01/20] Secure boot: Add new capability - -Secure boot adds certain policy requirements, including that root must not -be able to do anything that could cause the kernel to execute arbitrary code. -The simplest way to handle this would seem to be to add a new capability -and gate various functionality on that. We'll then strip it from the initial -capability set if required. - -Signed-off-by: Matthew Garrett ---- - include/uapi/linux/capability.h | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/include/uapi/linux/capability.h b/include/uapi/linux/capability.h -index ba478fa..7109e65 100644 ---- a/include/uapi/linux/capability.h -+++ b/include/uapi/linux/capability.h -@@ -343,7 +343,11 @@ struct vfs_cap_data { - - #define CAP_BLOCK_SUSPEND 36 - --#define CAP_LAST_CAP CAP_BLOCK_SUSPEND -+/* Allow things that trivially permit root to modify the running kernel */ -+ -+#define CAP_COMPROMISE_KERNEL 37 -+ -+#define CAP_LAST_CAP CAP_COMPROMISE_KERNEL - - #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP) - --- -1.8.0.1 - - -From a07ae01ac4b304ac7f0e2b5d4193519f1a9eee8d Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Thu, 20 Sep 2012 10:40:57 -0400 -Subject: [PATCH 02/20] PCI: Lock down BAR access in secure boot environments - -Any hardware that can potentially generate DMA has to be locked down from -userspace in order to avoid it being possible for an attacker to cause -arbitrary kernel behaviour. Default to paranoid - in future we can -potentially relax this for sufficiently IOMMU-isolated devices. - -Signed-off-by: Matthew Garrett ---- - drivers/pci/pci-sysfs.c | 9 +++++++++ - drivers/pci/proc.c | 8 +++++++- - drivers/pci/syscall.c | 2 +- - 3 files changed, 17 insertions(+), 2 deletions(-) - -diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c -index f39378d..1db1e74 100644 ---- a/drivers/pci/pci-sysfs.c -+++ b/drivers/pci/pci-sysfs.c -@@ -546,6 +546,9 @@ pci_write_config(struct file* filp, struct kobject *kobj, - loff_t init_off = off; - u8 *data = (u8*) buf; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - if (off > dev->cfg_size) - return 0; - if (off + count > dev->cfg_size) { -@@ -852,6 +855,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, - resource_size_t start, end; - int i; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - for (i = 0; i < PCI_ROM_RESOURCE; i++) - if (res == &pdev->resource[i]) - break; -@@ -959,6 +965,9 @@ pci_write_resource_io(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t off, size_t count) - { -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - return pci_resource_io(filp, kobj, attr, buf, off, count, true); - } - -diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c -index 9b8505c..35580bc 100644 ---- a/drivers/pci/proc.c -+++ b/drivers/pci/proc.c -@@ -139,6 +139,9 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof - int size = dp->size; - int cnt; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - if (pos >= size) - return 0; - if (nbytes >= size) -@@ -219,6 +222,9 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd, - #endif /* HAVE_PCI_MMAP */ - int ret = 0; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - switch (cmd) { - case PCIIOC_CONTROLLER: - ret = pci_domain_nr(dev->bus); -@@ -259,7 +265,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma) - struct pci_filp_private *fpriv = file->private_data; - int i, ret; - -- if (!capable(CAP_SYS_RAWIO)) -+ if (!capable(CAP_SYS_RAWIO) || !capable(CAP_COMPROMISE_KERNEL)) - return -EPERM; - - /* Make sure the caller is mapping a real resource for this device */ -diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c -index e1c1ec5..97e785f 100644 ---- a/drivers/pci/syscall.c -+++ b/drivers/pci/syscall.c -@@ -92,7 +92,7 @@ SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn, - u32 dword; - int err = 0; - -- if (!capable(CAP_SYS_ADMIN)) -+ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_COMPROMISE_KERNEL)) - return -EPERM; - - dev = pci_get_bus_and_slot(bus, dfn); --- -1.8.0.1 - - -From 1b5a1b53577992b32a3f51b18aa07cb9b300a3b1 Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Thu, 20 Sep 2012 10:40:58 -0400 -Subject: [PATCH 03/20] x86: Lock down IO port access in secure boot - environments - -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. - -Signed-off-by: Matthew Garrett ---- - arch/x86/kernel/ioport.c | 4 ++-- - drivers/char/mem.c | 3 +++ - 2 files changed, 5 insertions(+), 2 deletions(-) - -diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c -index 8c96897..a2578c4 100644 ---- a/arch/x86/kernel/ioport.c -+++ b/arch/x86/kernel/ioport.c -@@ -28,7 +28,7 @@ asmlinkage long sys_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) || !capable(CAP_COMPROMISE_KERNEL))) - return -EPERM; - - /* -@@ -102,7 +102,7 @@ long sys_iopl(unsigned int level, struct pt_regs *regs) - return -EINVAL; - /* Trying to gain more privileges? */ - if (level > old) { -- if (!capable(CAP_SYS_RAWIO)) -+ if (!capable(CAP_SYS_RAWIO) || !capable(CAP_COMPROMISE_KERNEL)) - return -EPERM; - } - regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); -diff --git a/drivers/char/mem.c b/drivers/char/mem.c -index 0537903..47501fc 100644 ---- a/drivers/char/mem.c -+++ b/drivers/char/mem.c -@@ -597,6 +597,9 @@ static ssize_t write_port(struct file *file, const char __user *buf, - unsigned long i = *ppos; - const char __user * tmp = buf; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - if (!access_ok(VERIFY_READ, buf, count)) - return -EFAULT; - while (count-- > 0 && i < 65536) { --- -1.8.0.1 - - -From 09c266136915eb1f4a9b36423b7ba65e3d024de4 Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Thu, 20 Sep 2012 10:40:59 -0400 -Subject: [PATCH 04/20] ACPI: Limit access to custom_method - -It must be impossible for even root to get code executed in kernel context -under a secure boot environment. custom_method effectively allows arbitrary -access to system memory, so it needs to have a capability check here. - -Signed-off-by: Matthew Garrett ---- - drivers/acpi/custom_method.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c -index 5d42c24..247d58b 100644 ---- a/drivers/acpi/custom_method.c -+++ b/drivers/acpi/custom_method.c -@@ -29,6 +29,9 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf, - struct acpi_table_header table; - acpi_status status; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - if (!(*ppos)) { - /* parse the table header to get the table length */ - if (count <= sizeof(struct acpi_table_header)) --- -1.8.0.1 - - -From f3e9cb16e5ab3e680ec3ef464682c52371bbbbe3 Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Thu, 20 Sep 2012 10:41:00 -0400 -Subject: [PATCH 05/20] asus-wmi: Restrict debugfs interface - -We have no way of validating what all of the Asus WMI methods do on a -given machine, and there's a risk that some will allow hardware state to -be manipulated in such a way that arbitrary code can be executed in the -kernel. Add a capability check to prevent that. - -Signed-off-by: Matthew Garrett ---- - drivers/platform/x86/asus-wmi.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index c0e9ff4..3c10167 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -1521,6 +1521,9 @@ static int show_dsts(struct seq_file *m, void *data) - int err; - u32 retval = -1; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval); - - if (err < 0) -@@ -1537,6 +1540,9 @@ static int show_devs(struct seq_file *m, void *data) - int err; - u32 retval = -1; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param, - &retval); - -@@ -1561,6 +1567,9 @@ static int show_call(struct seq_file *m, void *data) - union acpi_object *obj; - acpi_status status; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, - 1, asus->debug.method_id, - &input, &output); --- -1.8.0.1 - - -From 23372d2a40135aca7a6d73511bd88790b598b489 Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Thu, 20 Sep 2012 10:41:01 -0400 -Subject: [PATCH 06/20] Restrict /dev/mem and /dev/kmem in secure boot setups - -Allowing users to write to address space makes it possible for the kernel -to be subverted. Restrict this when we need to protect the kernel. - -Signed-off-by: Matthew Garrett ---- - drivers/char/mem.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/drivers/char/mem.c b/drivers/char/mem.c -index 47501fc..8817cdc 100644 ---- a/drivers/char/mem.c -+++ b/drivers/char/mem.c -@@ -158,6 +158,9 @@ static ssize_t write_mem(struct file *file, const char __user *buf, - unsigned long copied; - void *ptr; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - if (!valid_phys_addr_range(p, count)) - return -EFAULT; - -@@ -530,6 +533,9 @@ static ssize_t write_kmem(struct file *file, const char __user *buf, - char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ - int err = 0; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - if (p < (unsigned long) high_memory) { - unsigned long to_write = min_t(unsigned long, count, - (unsigned long)high_memory - p); --- -1.8.0.1 - - -From a0c80b01e80a1f6484a2a2811b4a212322494614 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Thu, 20 Sep 2012 10:41:02 -0400 -Subject: [PATCH 07/20] Secure boot: Add a dummy kernel parameter that will - switch on Secure Boot mode - -This forcibly drops CAP_COMPROMISE_KERNEL from both cap_permitted and cap_bset -in the init_cred struct, which everything else inherits from. This works on -any machine and can be used to develop even if the box doesn't have UEFI. - -Signed-off-by: Josh Boyer ---- - Documentation/kernel-parameters.txt | 7 +++++++ - kernel/cred.c | 17 +++++++++++++++++ - 2 files changed, 24 insertions(+) - -diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index 9776f06..0d6c28d 100644 ---- a/Documentation/kernel-parameters.txt -+++ b/Documentation/kernel-parameters.txt -@@ -2599,6 +2599,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. - Note: increases power consumption, thus should only be - enabled if running jitter sensitive (HPC/RT) workloads. - -+ secureboot_enable= -+ [KNL] Enables an emulated UEFI Secure Boot mode. This -+ locks down various aspects of the kernel guarded by the -+ CAP_COMPROMISE_KERNEL capability. This includes things -+ like /dev/mem, IO port access, and other areas. It can -+ be used on non-UEFI machines for testing purposes. -+ - security= [SECURITY] Choose a security module to enable at boot. - If this boot parameter is not specified, only the first - security module asking for security registration will be -diff --git a/kernel/cred.c b/kernel/cred.c -index 48cea3d..3f5be65 100644 ---- a/kernel/cred.c -+++ b/kernel/cred.c -@@ -623,6 +623,23 @@ void __init cred_init(void) - 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); - } - -+void __init secureboot_enable() -+{ -+ pr_info("Secure boot enabled\n"); -+ cap_lower((&init_cred)->cap_bset, CAP_COMPROMISE_KERNEL); -+ cap_lower((&init_cred)->cap_permitted, CAP_COMPROMISE_KERNEL); -+} -+ -+/* Dummy Secure Boot enable option to fake out UEFI SB=1 */ -+static int __init secureboot_enable_opt(char *str) -+{ -+ int sb_enable = !!simple_strtol(str, NULL, 0); -+ if (sb_enable) -+ secureboot_enable(); -+ return 1; -+} -+__setup("secureboot_enable=", secureboot_enable_opt); -+ - /** - * prepare_kernel_cred - Prepare a set of credentials for a kernel service - * @daemon: A userspace daemon to be used as a reference --- -1.8.0.1 - - -From 640f088c49da87a344417f58d3faa72d63a4f6ed Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Thu, 20 Sep 2012 10:41:03 -0400 -Subject: [PATCH 08/20] efi: Enable secure boot lockdown automatically when - enabled in firmware - -The firmware has a set of flags that indicate whether secure boot is enabled -and enforcing. Use them to indicate whether the kernel should lock itself -down. - -Signed-off-by: Matthew Garrett ---- - Documentation/x86/zero-page.txt | 2 ++ - arch/x86/boot/compressed/eboot.c | 32 ++++++++++++++++++++++++++++++++ - arch/x86/include/asm/bootparam.h | 3 ++- - arch/x86/kernel/setup.c | 3 +++ - include/linux/cred.h | 2 ++ - 5 files changed, 41 insertions(+), 1 deletion(-) - -diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt -index cf5437d..7f9ed48 100644 ---- a/Documentation/x86/zero-page.txt -+++ b/Documentation/x86/zero-page.txt -@@ -27,6 +27,8 @@ Offset Proto Name Meaning - 1E9/001 ALL eddbuf_entries Number of entries in eddbuf (below) - 1EA/001 ALL edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer - (below) -+1EB/001 ALL kbd_status Numlock is enabled -+1EC/001 ALL secure_boot Kernel should enable secure boot lockdowns - 290/040 ALL edd_mbr_sig_buffer EDD MBR signatures - 2D0/A00 ALL e820_map E820 memory map table - (array of struct e820entry) -diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c -index e87b0ca..260cace 100644 ---- a/arch/x86/boot/compressed/eboot.c -+++ b/arch/x86/boot/compressed/eboot.c -@@ -732,6 +732,36 @@ fail: - return status; - } - -+static int get_secure_boot(efi_system_table_t *_table) -+{ -+ u8 sb, setup; -+ unsigned long datasize = sizeof(sb); -+ efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; -+ efi_status_t status; -+ -+ status = efi_call_phys5(sys_table->runtime->get_variable, -+ L"SecureBoot", &var_guid, NULL, &datasize, &sb); -+ -+ if (status != EFI_SUCCESS) -+ return 0; -+ -+ if (sb == 0) -+ return 0; -+ -+ -+ status = efi_call_phys5(sys_table->runtime->get_variable, -+ L"SetupMode", &var_guid, NULL, &datasize, -+ &setup); -+ -+ if (status != EFI_SUCCESS) -+ return 0; -+ -+ if (setup == 1) -+ return 0; -+ -+ return 1; -+} -+ - /* - * Because the x86 boot code expects to be passed a boot_params we - * need to create one ourselves (usually the bootloader would create -@@ -1026,6 +1056,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, - if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) - goto fail; - -+ boot_params->secure_boot = get_secure_boot(sys_table); -+ - setup_graphics(boot_params); - - status = efi_call_phys3(sys_table->boottime->allocate_pool, -diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h -index 2ad874c..c7338e0 100644 ---- a/arch/x86/include/asm/bootparam.h -+++ b/arch/x86/include/asm/bootparam.h -@@ -114,7 +114,8 @@ struct boot_params { - __u8 eddbuf_entries; /* 0x1e9 */ - __u8 edd_mbr_sig_buf_entries; /* 0x1ea */ - __u8 kbd_status; /* 0x1eb */ -- __u8 _pad6[5]; /* 0x1ec */ -+ __u8 secure_boot; /* 0x1ec */ -+ __u8 _pad6[4]; /* 0x1ed */ - struct setup_header hdr; /* setup header */ /* 0x1f1 */ - __u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)]; - __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */ -diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index ca45696..800673d 100644 ---- a/arch/x86/kernel/setup.c -+++ b/arch/x86/kernel/setup.c -@@ -962,6 +962,9 @@ void __init setup_arch(char **cmdline_p) - - io_delay_init(); - -+ if (boot_params.secure_boot) -+ secureboot_enable(); -+ - /* - * Parse the ACPI tables for possible boot-time SMP configuration. - */ -diff --git a/include/linux/cred.h b/include/linux/cred.h -index ebbed2c..a24faf1 100644 ---- a/include/linux/cred.h -+++ b/include/linux/cred.h -@@ -170,6 +170,8 @@ extern int set_security_override_from_ctx(struct cred *, const char *); - extern int set_create_files_as(struct cred *, struct inode *); - extern void __init cred_init(void); - -+extern void secureboot_enable(void); -+ - /* - * check for validity of credentials - */ --- -1.8.0.1 - - -From 994d895b5b684fc53c3b43dda9aee460c1f526f2 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Thu, 20 Sep 2012 10:41:04 -0400 -Subject: [PATCH 09/20] acpi: Ignore acpi_rsdp kernel parameter in a secure - boot environment - -This option allows userspace to pass the RSDP address to the kernel. This -could potentially be used to circumvent the secure boot trust model. -We ignore the setting if we don't have the CAP_COMPROMISE_KERNEL capability. - -Signed-off-by: Josh Boyer ---- - drivers/acpi/osl.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c -index 9eaf708..f94341b 100644 ---- a/drivers/acpi/osl.c -+++ b/drivers/acpi/osl.c -@@ -246,7 +246,7 @@ early_param("acpi_rsdp", setup_acpi_rsdp); - acpi_physical_address __init acpi_os_get_root_pointer(void) - { - #ifdef CONFIG_KEXEC -- if (acpi_rsdp) -+ if (acpi_rsdp && capable(CAP_COMPROMISE_KERNEL)) - return acpi_rsdp; - #endif - --- -1.8.0.1 - - -From c80aaf3eee3cb6b0d1a051e418ee99cd238c868c Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Thu, 20 Sep 2012 10:41:05 -0400 -Subject: [PATCH 10/20] SELinux: define mapping for new Secure Boot capability - -Add the name of the new Secure Boot capability. This allows SELinux -policies to properly map CAP_COMPROMISE_KERNEL to the appropriate -capability class. - -Signed-off-by: Josh Boyer ---- - security/selinux/include/classmap.h | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h -index df2de54..70e2834 100644 ---- a/security/selinux/include/classmap.h -+++ b/security/selinux/include/classmap.h -@@ -146,8 +146,8 @@ struct security_class_mapping secclass_map[] = { - { "memprotect", { "mmap_zero", NULL } }, - { "peer", { "recv", NULL } }, - { "capability2", -- { "mac_override", "mac_admin", "syslog", "wake_alarm", "block_suspend", -- NULL } }, -+ { "mac_override", "mac_admin", "syslog", "wake_alarm", -+ "block_suspend", "compromise_kernel", NULL } }, - { "kernel_service", { "use_as_override", "create_files_as", NULL } }, - { "tun_socket", - { COMMON_SOCK_PERMS, NULL } }, --- -1.8.0.1 - - -From 26352bcb92468233dd960b5d02ba1db344df72b9 Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Tue, 4 Sep 2012 11:55:13 -0400 -Subject: [PATCH 11/20] kexec: Disable in a secure boot environment - -kexec could be used as a vector for a malicious user to use a signed kernel -to circumvent the secure boot trust model. In the long run we'll want to -support signed kexec payloads, but for the moment we should just disable -loading entirely in that situation. - -Signed-off-by: Matthew Garrett ---- - kernel/kexec.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/kernel/kexec.c b/kernel/kexec.c -index 5e4bd78..dd464e0 100644 ---- a/kernel/kexec.c -+++ b/kernel/kexec.c -@@ -943,7 +943,7 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, - int result; - - /* We only trust the superuser with rebooting the system. */ -- if (!capable(CAP_SYS_BOOT)) -+ if (!capable(CAP_SYS_BOOT) || !capable(CAP_COMPROMISE_KERNEL)) - return -EPERM; - - /* --- -1.8.0.1 - - -From c03c68adceaec9656c55c47190fb4243bf903b40 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Mon, 25 Jun 2012 21:29:46 -0400 -Subject: [PATCH 12/20] Documentation: kernel-parameters.txt remove - capability.disable - -Remove the documentation for capability.disable. The code supporting this -parameter was removed with: - - commit 5915eb53861c5776cfec33ca4fcc1fd20d66dd27 - Author: Miklos Szeredi - Date: Thu Jul 3 20:56:05 2008 +0200 - - security: remove dummy module - -Signed-off-by: Josh Boyer ---- - Documentation/kernel-parameters.txt | 6 ------ - 1 file changed, 6 deletions(-) - -diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index 0d6c28d..d9af501 100644 ---- a/Documentation/kernel-parameters.txt -+++ b/Documentation/kernel-parameters.txt -@@ -446,12 +446,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. - possible to determine what the correct size should be. - This option provides an override for these situations. - -- capability.disable= -- [SECURITY] Disable capabilities. This would normally -- be used only if an alternative security model is to be -- configured. Potentially dangerous and should only be -- used if you are entirely sure of the consequences. -- - ccw_timeout_log [S390] - See Documentation/s390/CommonIO for details. - --- -1.8.0.1 - - -From 3f1bda64d2c7b369e2833bd32cd1f3ba6c90348f Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Fri, 5 Oct 2012 10:12:48 -0400 -Subject: [PATCH 13/20] modsign: Always enforce module signing in a Secure Boot - environment - -If a machine is booted into a Secure Boot environment, we need to -protect the trust model. This requires that all modules be signed -with a key that is in the kernel's _modsign keyring. The checks for -this are already done via the 'sig_enforce' module parameter. Make -this visible within the kernel and force it to be true. - -Signed-off-by: Josh Boyer ---- - kernel/cred.c | 8 ++++++++ - kernel/module.c | 4 ++-- - 2 files changed, 10 insertions(+), 2 deletions(-) - -diff --git a/kernel/cred.c b/kernel/cred.c -index 3f5be65..a381e27 100644 ---- a/kernel/cred.c -+++ b/kernel/cred.c -@@ -623,11 +623,19 @@ void __init cred_init(void) - 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); - } - -+#ifdef CONFIG_MODULE_SIG -+extern bool sig_enforce; -+#endif -+ - void __init secureboot_enable() - { - pr_info("Secure boot enabled\n"); - cap_lower((&init_cred)->cap_bset, CAP_COMPROMISE_KERNEL); - cap_lower((&init_cred)->cap_permitted, CAP_COMPROMISE_KERNEL); -+#ifdef CONFIG_MODULE_SIG -+ /* Enable module signature enforcing */ -+ sig_enforce = true; -+#endif - } - - /* Dummy Secure Boot enable option to fake out UEFI SB=1 */ -diff --git a/kernel/module.c b/kernel/module.c -index 6e48c3a..6d5d2aa 100644 ---- a/kernel/module.c -+++ b/kernel/module.c -@@ -106,9 +106,9 @@ struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ - - #ifdef CONFIG_MODULE_SIG - #ifdef CONFIG_MODULE_SIG_FORCE --static bool sig_enforce = true; -+bool sig_enforce = true; - #else --static bool sig_enforce = false; -+bool sig_enforce = false; - - static int param_set_bool_enable_only(const char *val, - const struct kernel_param *kp) --- -1.8.0.1 - - -From e6e3ec77b2fa037b32829e7f5ee468ad8a62dd05 Mon Sep 17 00:00:00 2001 -From: Dave Howells -Date: Tue, 23 Oct 2012 09:30:54 -0400 -Subject: [PATCH 14/20] Add EFI signature data types, such as are used for - containing hashes, keys and certificates for cryptographic verification. - -Signed-off-by: David Howells ---- - include/linux/efi.h | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/include/linux/efi.h b/include/linux/efi.h -index 337aefb..a01f8a7 100644 ---- a/include/linux/efi.h -+++ b/include/linux/efi.h -@@ -317,6 +317,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, - #define EFI_FILE_SYSTEM_GUID \ - EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) - -+#define EFI_CERT_SHA256_GUID \ -+ EFI_GUID( 0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 ) -+ -+#define EFI_CERT_X509_GUID \ -+ EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 ) -+ - typedef struct { - efi_guid_t guid; - u64 table; -@@ -452,6 +458,20 @@ typedef struct { - - #define EFI_INVALID_TABLE_ADDR (~0UL) - -+typedef struct { -+ efi_guid_t signature_owner; -+ u8 signature_data[]; -+} efi_signature_data_t; -+ -+typedef struct { -+ efi_guid_t signature_type; -+ u32 signature_list_size; -+ u32 signature_header_size; -+ u32 signature_size; -+ u8 signature_header[]; -+ /* efi_signature_data_t signatures[][] */ -+} efi_signature_list_t; -+ - /* - * All runtime access to EFI goes through this structure: - */ --- -1.8.0.1 - - -From c2542256f632a22232cf02d5fd64568a5afa4516 Mon Sep 17 00:00:00 2001 -From: Dave Howells -Date: Tue, 23 Oct 2012 09:36:28 -0400 -Subject: [PATCH 15/20] Add an EFI signature blob parser and key loader. X.509 - certificates are loaded into the specified keyring as asymmetric type keys. - -Signed-off-by: David Howells ---- - crypto/asymmetric_keys/Kconfig | 7 +++ - crypto/asymmetric_keys/Makefile | 1 + - crypto/asymmetric_keys/efi_parser.c | 107 ++++++++++++++++++++++++++++++++++++ - include/linux/efi.h | 4 ++ - 4 files changed, 119 insertions(+) - create mode 100644 crypto/asymmetric_keys/efi_parser.c - -diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig -index 6d2c2ea..eb53fc3 100644 ---- a/crypto/asymmetric_keys/Kconfig -+++ b/crypto/asymmetric_keys/Kconfig -@@ -35,4 +35,11 @@ config X509_CERTIFICATE_PARSER - data and provides the ability to instantiate a crypto key from a - public key packet found inside the certificate. - -+config EFI_SIGNATURE_LIST_PARSER -+ bool "EFI signature list parser" -+ select X509_CERTIFICATE_PARSER -+ help -+ This option provides support for parsing EFI signature lists for -+ X.509 certificates and turning them into keys. -+ - endif # ASYMMETRIC_KEY_TYPE -diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile -index 0727204..cd8388e 100644 ---- a/crypto/asymmetric_keys/Makefile -+++ b/crypto/asymmetric_keys/Makefile -@@ -8,6 +8,7 @@ asymmetric_keys-y := asymmetric_type.o signature.o - - obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o - obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o -+obj-$(CONFIG_EFI_SIGNATURE_LIST_PARSER) += efi_parser.o - - # - # X.509 Certificate handling -diff --git a/crypto/asymmetric_keys/efi_parser.c b/crypto/asymmetric_keys/efi_parser.c -new file mode 100644 -index 0000000..59b859a ---- /dev/null -+++ b/crypto/asymmetric_keys/efi_parser.c -@@ -0,0 +1,107 @@ -+/* EFI signature/key/certificate list parser -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#define pr_fmt(fmt) "EFI: "fmt -+#include -+#include -+#include -+#include -+#include -+ -+static __initdata efi_guid_t efi_cert_x509_guid = EFI_CERT_X509_GUID; -+ -+/** -+ * parse_efi_signature_list - Parse an EFI signature list for certificates -+ * @data: The data blob to parse -+ * @size: The size of the data blob -+ * @keyring: The keyring to add extracted keys to -+ */ -+int __init parse_efi_signature_list(const void *data, size_t size, struct key *keyring) -+{ -+ unsigned offs = 0; -+ size_t lsize, esize, hsize, elsize; -+ -+ pr_devel("-->%s(,%zu)\n", __func__, size); -+ -+ while (size > 0) { -+ efi_signature_list_t list; -+ const efi_signature_data_t *elem; -+ key_ref_t key; -+ -+ if (size < sizeof(list)) -+ return -EBADMSG; -+ -+ memcpy(&list, data, sizeof(list)); -+ pr_devel("LIST[%04x] guid=%pUl ls=%x hs=%x ss=%x\n", -+ offs, -+ list.signature_type.b, list.signature_list_size, -+ list.signature_header_size, list.signature_size); -+ -+ lsize = list.signature_list_size; -+ hsize = list.signature_header_size; -+ esize = list.signature_size; -+ elsize = lsize - sizeof(list) - hsize; -+ -+ if (lsize > size) { -+ pr_devel("<--%s() = -EBADMSG [overrun @%x]\n", -+ __func__, offs); -+ return -EBADMSG; -+ } -+ if (lsize < sizeof(list) || -+ lsize - sizeof(list) < hsize || -+ esize < sizeof(*elem) || -+ elsize < esize || -+ elsize % esize != 0) { -+ pr_devel("- bad size combo @%x\n", offs); -+ continue; -+ } -+ -+ if (efi_guidcmp(list.signature_type, efi_cert_x509_guid) != 0) { -+ data += lsize; -+ size -= lsize; -+ offs += lsize; -+ continue; -+ } -+ -+ data += sizeof(list) + hsize; -+ size -= sizeof(list) + hsize; -+ offs += sizeof(list) + hsize; -+ -+ for (; elsize > 0; elsize -= esize) { -+ elem = data; -+ -+ pr_devel("ELEM[%04x]\n", offs); -+ -+ key = key_create_or_update( -+ make_key_ref(keyring, 1), -+ "asymmetric", -+ NULL, -+ &elem->signature_data, -+ esize - sizeof(*elem), -+ (KEY_POS_ALL & ~KEY_POS_SETATTR) | -+ KEY_USR_VIEW, -+ KEY_ALLOC_NOT_IN_QUOTA); -+ -+ if (IS_ERR(key)) -+ pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", -+ PTR_ERR(key)); -+ else -+ pr_notice("Loaded cert '%s'\n", -+ key_ref_to_ptr(key)->description); -+ -+ data += esize; -+ size -= esize; -+ offs += esize; -+ } -+ } -+ -+ return 0; -+} -diff --git a/include/linux/efi.h b/include/linux/efi.h -index a01f8a7..44a7faa 100644 ---- a/include/linux/efi.h -+++ b/include/linux/efi.h -@@ -541,6 +541,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime); - extern void efi_reserve_boot_services(void); - extern struct efi_memory_map memmap; - -+struct key; -+extern int __init parse_efi_signature_list(const void *data, size_t size, -+ struct key *keyring); -+ - /** - * efi_range_is_wc - check the WC bit on an address range - * @start: starting kvirt address --- -1.8.0.1 - - -From a418e6fdd2aa946a30cf1bee5c9540d03d626981 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Fri, 26 Oct 2012 12:29:49 -0400 -Subject: [PATCH 16/20] EFI: Add in-kernel variable to determine if Secure Boot - is enabled - -There are a few cases where in-kernel functions may need to know if -Secure Boot is enabled. The added capability check cannot be used as the -kernel can't drop it's own capabilites, so we add a global variable -similar to efi_enabled so they can determine if Secure Boot is enabled. - -Signed-off-by: Josh Boyer ---- - arch/x86/kernel/setup.c | 6 +++++- - arch/x86/platform/efi/efi.c | 2 ++ - include/linux/efi.h | 3 +++ - 3 files changed, 10 insertions(+), 1 deletion(-) - -diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index 800673d..cf8823b 100644 ---- a/arch/x86/kernel/setup.c -+++ b/arch/x86/kernel/setup.c -@@ -962,8 +962,12 @@ void __init setup_arch(char **cmdline_p) - - io_delay_init(); - -- if (boot_params.secure_boot) -+ if (boot_params.secure_boot) { - secureboot_enable(); -+#ifdef CONFIG_EFI -+ secure_boot_enabled = 1; -+#endif -+ } - - /* - * Parse the ACPI tables for possible boot-time SMP configuration. -diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c -index ad44391..d22bfeb 100644 ---- a/arch/x86/platform/efi/efi.c -+++ b/arch/x86/platform/efi/efi.c -@@ -54,6 +54,8 @@ - int efi_enabled; - EXPORT_SYMBOL(efi_enabled); - -+int secure_boot_enabled; -+ - struct efi __read_mostly efi = { - .mps = EFI_INVALID_TABLE_ADDR, - .acpi = EFI_INVALID_TABLE_ADDR, -diff --git a/include/linux/efi.h b/include/linux/efi.h -index 44a7faa..b5403ae 100644 ---- a/include/linux/efi.h -+++ b/include/linux/efi.h -@@ -578,11 +578,14 @@ extern int __init efi_setup_pcdp_console(char *); - # ifdef CONFIG_X86 - extern int efi_enabled; - extern bool efi_64bit; -+ extern int secure_boot_enabled; - # else - # define efi_enabled 1 -+# define secure_boot_enabled 0 - # endif - #else - # define efi_enabled 0 -+# define secure_boot_enabled 0 - #endif - - /* --- -1.8.0.1 - - -From f6d05f0974f6a7667ebbbf91624678bcf32169ae Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Fri, 26 Oct 2012 12:36:24 -0400 -Subject: [PATCH 17/20] MODSIGN: Add module certificate blacklist keyring - -This adds an additional keyring that is used to store certificates that -are blacklisted. This keyring is searched first when loading signed modules -and if the module's certificate is found, it will refuse to load. This is -useful in cases where third party certificates are used for module signing. - -Signed-off-by: Josh Boyer ---- - init/Kconfig | 8 ++++++++ - kernel/modsign_pubkey.c | 17 +++++++++++++++++ - kernel/module-internal.h | 3 +++ - kernel/module_signing.c | 14 +++++++++++++- - 4 files changed, 41 insertions(+), 1 deletion(-) - -diff --git a/init/Kconfig b/init/Kconfig -index 6fdd6e3..7a9bf00 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1602,6 +1602,14 @@ config MODULE_SIG_FORCE - Reject unsigned modules or signed modules for which we don't have a - key. Without this, such modules will simply taint the kernel. - -+config MODULE_SIG_BLACKLIST -+ bool "Support for blacklisting module signature certificates" -+ depends on MODULE_SIG -+ help -+ This adds support for keeping a blacklist of certificates that -+ should not pass module signature verification. If a module is -+ signed with something in this keyring, the load will be rejected. -+ - choice - prompt "Which hash algorithm should modules be signed with?" - depends on MODULE_SIG -diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c -index 767e559..3bfb7ed 100644 ---- a/kernel/modsign_pubkey.c -+++ b/kernel/modsign_pubkey.c -@@ -17,6 +17,9 @@ - #include "module-internal.h" - - struct key *modsign_keyring; -+#ifdef CONFIG_MODULE_SIG_BLACKLIST -+struct key *modsign_blacklist; -+#endif - - extern __initdata const u8 modsign_certificate_list[]; - extern __initdata const u8 modsign_certificate_list_end[]; -@@ -52,6 +55,20 @@ static __init int module_verify_init(void) - if (key_instantiate_and_link(modsign_keyring, NULL, 0, NULL, NULL) < 0) - panic("Can't instantiate module signing keyring\n"); - -+#ifdef CONFIG_MODULE_SIG_BLACKLIST -+ modsign_blacklist = key_alloc(&key_type_keyring, ".modsign_blacklist", -+ KUIDT_INIT(0), KGIDT_INIT(0), -+ current_cred(), -+ (KEY_POS_ALL & ~KEY_POS_SETATTR) | -+ KEY_USR_VIEW | KEY_USR_READ, -+ KEY_ALLOC_NOT_IN_QUOTA); -+ if (IS_ERR(modsign_blacklist)) -+ panic("Can't allocate module signing blacklist keyring\n"); -+ -+ if (key_instantiate_and_link(modsign_blacklist, NULL, 0, NULL, NULL) < 0) -+ panic("Can't instantiate module signing blacklist keyring\n"); -+#endif -+ - return 0; - } - -diff --git a/kernel/module-internal.h b/kernel/module-internal.h -index 24f9247..51a8380 100644 ---- a/kernel/module-internal.h -+++ b/kernel/module-internal.h -@@ -10,5 +10,8 @@ - */ - - extern struct key *modsign_keyring; -+#ifdef CONFIG_MODULE_SIG_BLACKLIST -+extern struct key *modsign_blacklist; -+#endif - - extern int mod_verify_sig(const void *mod, unsigned long *_modlen); -diff --git a/kernel/module_signing.c b/kernel/module_signing.c -index f2970bd..8ab83a6 100644 ---- a/kernel/module_signing.c -+++ b/kernel/module_signing.c -@@ -132,7 +132,7 @@ static int mod_extract_mpi_array(struct public_key_signature *pks, - static struct key *request_asymmetric_key(const char *signer, size_t signer_len, - const u8 *key_id, size_t key_id_len) - { -- key_ref_t key; -+ key_ref_t key, blacklist; - size_t i; - char *id, *q; - -@@ -157,6 +157,18 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len, - - pr_debug("Look up: \"%s\"\n", id); - -+#ifdef CONFIG_MODULE_SIG_BLACKLIST -+ blacklist = keyring_search(make_key_ref(modsign_blacklist, 1), -+ &key_type_asymmetric, id); -+ if (!IS_ERR(blacklist)) { -+ /* module is signed with a cert in the blacklist. reject */ -+ pr_err("Module key '%s' is in blacklist\n", id); -+ key_ref_put(blacklist); -+ kfree(id); -+ return ERR_PTR(-EKEYREJECTED); -+ } -+#endif -+ - key = keyring_search(make_key_ref(modsign_keyring, 1), - &key_type_asymmetric, id); - if (IS_ERR(key)) --- -1.8.0.1 - - -From ff0ed221fe8d5a46a9bc36323ca8fb6f75c22a83 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Fri, 26 Oct 2012 12:42:16 -0400 -Subject: [PATCH 18/20] MODSIGN: Import certificates from UEFI Secure Boot - -Secure Boot stores a list of allowed certificates in the 'db' variable. -This imports those certificates into the module signing keyring. This -allows for a third party signing certificate to be used in conjunction -with signed modules. By importing the public certificate into the 'db' -variable, a user can allow a module signed with that certificate to -load. The shim UEFI bootloader has a similar certificate list stored -in the 'MokListRT' variable. We import those as well. - -In the opposite case, Secure Boot maintains a list of disallowed -certificates in the 'dbx' variable. We load those certificates into -the newly introduced module blacklist keyring and forbid any module -signed with those from loading. - -Signed-off-by: Josh Boyer ---- - include/linux/efi.h | 6 ++++ - init/Kconfig | 9 ++++++ - kernel/Makefile | 3 ++ - kernel/modsign_uefi.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 108 insertions(+) - create mode 100644 kernel/modsign_uefi.c - -diff --git a/include/linux/efi.h b/include/linux/efi.h -index b5403ae..bba53e3 100644 ---- a/include/linux/efi.h -+++ b/include/linux/efi.h -@@ -323,6 +323,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, - #define EFI_CERT_X509_GUID \ - EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 ) - -+#define EFI_IMAGE_SECURITY_DATABASE_GUID \ -+ EFI_GUID( 0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f ) -+ -+#define EFI_SHIM_LOCK_GUID \ -+ EFI_GUID( 0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 ) -+ - typedef struct { - efi_guid_t guid; - u64 table; -diff --git a/init/Kconfig b/init/Kconfig -index 7a9bf00..51aa170 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1610,6 +1610,15 @@ config MODULE_SIG_BLACKLIST - should not pass module signature verification. If a module is - signed with something in this keyring, the load will be rejected. - -+config MODULE_SIG_UEFI -+ bool "Allow modules signed with certs stored in UEFI" -+ depends on MODULE_SIG && MODULE_SIG_BLACKLIST && EFI -+ select EFI_SIGNATURE_LIST_PARSER -+ help -+ This will import certificates stored in UEFI and allow modules -+ signed with those to be loaded. It will also disallow loading -+ of modules stored in the UEFI dbx variable. -+ - choice - prompt "Which hash algorithm should modules be signed with?" - depends on MODULE_SIG -diff --git a/kernel/Makefile b/kernel/Makefile -index 86e3285..12e17ab 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -55,6 +55,7 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o - obj-$(CONFIG_UID16) += uid16.o - obj-$(CONFIG_MODULES) += module.o - obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o -+obj-$(CONFIG_MODULE_SIG_UEFI) += modsign_uefi.o - obj-$(CONFIG_KALLSYMS) += kallsyms.o - obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o - obj-$(CONFIG_KEXEC) += kexec.o -@@ -113,6 +114,8 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o - - $(obj)/configs.o: $(obj)/config_data.h - -+$(obj)/modsign_uefi.o: KBUILD_CFLAGS += -fshort-wchar -+ - # config_data.h contains the same information as ikconfig.h but gzipped. - # Info from config_data can be extracted from /proc/config* - targets += config_data.gz -diff --git a/kernel/modsign_uefi.c b/kernel/modsign_uefi.c -new file mode 100644 -index 0000000..76a5a34 ---- /dev/null -+++ b/kernel/modsign_uefi.c -@@ -0,0 +1,90 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "module-internal.h" -+ -+static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid, unsigned long *size) -+{ -+ efi_status_t status; -+ unsigned long lsize = 4; -+ unsigned long tmpdb[4]; -+ void *db = NULL; -+ -+ status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb); -+ if (status != EFI_BUFFER_TOO_SMALL) { -+ pr_err("Couldn't get size: 0x%lx\n", status); -+ return NULL; -+ } -+ -+ db = kmalloc(lsize, GFP_KERNEL); -+ if (!db) { -+ pr_err("Couldn't allocate memory for uefi cert list\n"); -+ goto out; -+ } -+ -+ status = efi.get_variable(name, guid, NULL, &lsize, db); -+ if (status != EFI_SUCCESS) { -+ kfree(db); -+ db = NULL; -+ pr_err("Error reading db var: 0x%lx\n", status); -+ } -+out: -+ *size = lsize; -+ return db; -+} -+ -+/* -+ * * Load the certs contained in the UEFI databases -+ * */ -+static int __init load_uefi_certs(void) -+{ -+ efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID; -+ efi_guid_t mok_var = EFI_SHIM_LOCK_GUID; -+ void *db = NULL, *dbx = NULL, *mok = NULL; -+ unsigned long dbsize = 0, dbxsize = 0, moksize = 0; -+ int rc = 0; -+ -+ /* Check if SB is enabled and just return if not */ -+ if (!secure_boot_enabled) -+ return 0; -+ -+ /* Get db, MokListRT, and dbx. They might not exist, so it isn't -+ * an error if we can't get them. -+ */ -+ db = get_cert_list(L"db", &secure_var, &dbsize); -+ if (!db) { -+ pr_err("MODSIGN: Couldn't get UEFI db list\n"); -+ } else { -+ rc = parse_efi_signature_list(db, dbsize, modsign_keyring); -+ if (rc) -+ pr_err("Couldn't parse db signatures: %d\n", rc); -+ kfree(db); -+ } -+ -+ mok = get_cert_list(L"MokListRT", &mok_var, &moksize); -+ if (!mok) { -+ pr_info("MODSIGN: Couldn't get UEFI MokListRT\n"); -+ } else { -+ rc = parse_efi_signature_list(mok, moksize, modsign_keyring); -+ if (rc) -+ pr_err("Couldn't parse MokListRT signatures: %d\n", rc); -+ kfree(mok); -+ } -+ -+ dbx = get_cert_list(L"dbx", &secure_var, &dbxsize); -+ if (!dbx) { -+ pr_info("MODSIGN: Couldn't get UEFI dbx list\n"); -+ } else { -+ rc = parse_efi_signature_list(dbx, dbxsize, -+ modsign_blacklist); -+ if (rc) -+ pr_err("Couldn't parse dbx signatures: %d\n", rc); -+ kfree(dbx); -+ } -+ -+ return rc; -+} -+late_initcall(load_uefi_certs); --- -1.8.0.1 - - -From e45330362517d08579cdaddc718febe68e2cae06 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Fri, 26 Oct 2012 14:02:09 -0400 -Subject: [PATCH] hibernate: Disable in a Secure Boot environment - -There is currently no way to verify the resume image when returning -from hibernate. This might compromise the secure boot trust model, -so until we can work with signed hibernate images we disable it in -a Secure Boot environment. - -Signed-off-by: Josh Boyer ---- - kernel/power/hibernate.c | 15 ++++++++++++++- - kernel/power/main.c | 7 ++++++- - kernel/power/user.c | 3 +++ - 3 files changed, 23 insertions(+), 2 deletions(-) - -diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c -index b26f5f1..26bdfa8 100644 ---- a/kernel/power/hibernate.c -+++ b/kernel/power/hibernate.c -@@ -28,6 +28,7 @@ - #include - #include - #include -+#include - - #include "power.h" - -@@ -632,6 +633,10 @@ int hibernate(void) - { - int error; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) { -+ return -EPERM; -+ } -+ - lock_system_sleep(); - /* The snapshot device should not be opened while we're running */ - if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { -@@ -723,7 +728,7 @@ static int software_resume(void) - /* - * If the user said "noresume".. bail out early. - */ -- if (noresume) -+ if (noresume || !capable(CAP_COMPROMISE_KERNEL)) - return 0; - - /* -@@ -889,6 +894,11 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr, - int i; - char *start = buf; - -+ if (secure_boot_enabled) { -+ buf += sprintf(buf, "[%s]\n", "disabled"); -+ return buf-start; -+ } -+ - for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) { - if (!hibernation_modes[i]) - continue; -@@ -923,6 +933,9 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr, - char *p; - int mode = HIBERNATION_INVALID; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - p = memchr(buf, '\n', n); - len = p ? p - buf : n; - -diff --git a/kernel/power/main.c b/kernel/power/main.c -index 1c16f91..8e3456d 100644 ---- a/kernel/power/main.c -+++ b/kernel/power/main.c -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - - #include "power.h" - -@@ -301,7 +302,11 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, - } - #endif - #ifdef CONFIG_HIBERNATION -- s += sprintf(s, "%s\n", "disk"); -+ if (!secure_boot_enabled) { -+ s += sprintf(s, "%s\n", "disk"); -+ } else { -+ s += sprintf(s, "\n"); -+ } - #else - if (s != buf) - /* convert the last space to a newline */ -diff --git a/kernel/power/user.c b/kernel/power/user.c -index 4ed81e7..b11a0f4 100644 ---- a/kernel/power/user.c -+++ b/kernel/power/user.c -@@ -48,6 +48,9 @@ static int snapshot_open(struct inode *inode, struct file *filp) - struct snapshot_data *data; - int error; - -+ if (!capable(CAP_COMPROMISE_KERNEL)) -+ return -EPERM; -+ - lock_system_sleep(); - - if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { --- -1.8.0.2 - - -From 81adc779dba0f45f10b5ff307bd55832305f1112 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Wed, 12 Dec 2012 11:48:49 -0500 -Subject: [PATCH 20/20] Don't soft lockup on bad EFI signature lists - -If a signature list is read from an UEFI variable and that contains bogus -data, we can go into an infinite loop in efi_parse_signature_list. Notably, -if one of the entries in the list has a signature_size that is larger than -the actual signature size, it will fail the elsize < esize test. Simply -continuing in the loop without modifying the data or size variables just -leads to the same list entry being parsed repeatedly. - -Since the data is bogus, but we can't tell which value is actually -incorrect, we need to stop parsing the list. Just return -EBADMSG instead. - -Signed-off-by: Josh Boyer ---- - crypto/asymmetric_keys/efi_parser.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/crypto/asymmetric_keys/efi_parser.c b/crypto/asymmetric_keys/efi_parser.c -index 59b859a..a0b8a3a 100644 ---- a/crypto/asymmetric_keys/efi_parser.c -+++ b/crypto/asymmetric_keys/efi_parser.c -@@ -61,7 +61,7 @@ int __init parse_efi_signature_list(const void *data, size_t size, struct key *k - elsize < esize || - elsize % esize != 0) { - pr_devel("- bad size combo @%x\n", offs); -- continue; -+ return -EBADMSG; - } - - if (efi_guidcmp(list.signature_type, efi_cert_x509_guid) != 0) { --- -1.8.0.1 - diff --git a/secure-boot-3.7-20130204.patch b/secure-boot-3.7-20130204.patch new file mode 100644 index 0000000..653ac67 --- /dev/null +++ b/secure-boot-3.7-20130204.patch @@ -0,0 +1,1334 @@ +From 428db98d65770561ec5b8e9fc1931acf2210c5dd Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Thu, 20 Sep 2012 10:40:56 -0400 +Subject: [PATCH 01/17] Secure boot: Add new capability + +Secure boot adds certain policy requirements, including that root must not +be able to do anything that could cause the kernel to execute arbitrary code. +The simplest way to handle this would seem to be to add a new capability +and gate various functionality on that. We'll then strip it from the initial +capability set if required. + +Signed-off-by: Matthew Garrett +--- + include/uapi/linux/capability.h | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/include/uapi/linux/capability.h b/include/uapi/linux/capability.h +index ba478fa..7109e65 100644 +--- a/include/uapi/linux/capability.h ++++ b/include/uapi/linux/capability.h +@@ -343,7 +343,11 @@ struct vfs_cap_data { + + #define CAP_BLOCK_SUSPEND 36 + +-#define CAP_LAST_CAP CAP_BLOCK_SUSPEND ++/* Allow things that trivially permit root to modify the running kernel */ ++ ++#define CAP_COMPROMISE_KERNEL 37 ++ ++#define CAP_LAST_CAP CAP_COMPROMISE_KERNEL + + #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP) + +-- +1.8.1 + + +From 57902a5335b6f1f0aad56c669c874b45e9dd4ee8 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Thu, 20 Sep 2012 10:41:05 -0400 +Subject: [PATCH 02/17] SELinux: define mapping for new Secure Boot capability + +Add the name of the new Secure Boot capability. This allows SELinux +policies to properly map CAP_COMPROMISE_KERNEL to the appropriate +capability class. + +Signed-off-by: Josh Boyer +--- + security/selinux/include/classmap.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h +index df2de54..70e2834 100644 +--- a/security/selinux/include/classmap.h ++++ b/security/selinux/include/classmap.h +@@ -146,8 +146,8 @@ struct security_class_mapping secclass_map[] = { + { "memprotect", { "mmap_zero", NULL } }, + { "peer", { "recv", NULL } }, + { "capability2", +- { "mac_override", "mac_admin", "syslog", "wake_alarm", "block_suspend", +- NULL } }, ++ { "mac_override", "mac_admin", "syslog", "wake_alarm", ++ "block_suspend", "compromise_kernel", NULL } }, + { "kernel_service", { "use_as_override", "create_files_as", NULL } }, + { "tun_socket", + { COMMON_SOCK_PERMS, NULL } }, +-- +1.8.1 + + +From 7e2d1d442399258426c0724e7fd6adc6fd8a8590 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Thu, 20 Sep 2012 10:41:02 -0400 +Subject: [PATCH 03/17] Secure boot: Add a dummy kernel parameter that will + switch on Secure Boot mode + +This forcibly drops CAP_COMPROMISE_KERNEL from both cap_permitted and cap_bset +in the init_cred struct, which everything else inherits from. This works on +any machine and can be used to develop even if the box doesn't have UEFI. + +Signed-off-by: Josh Boyer +--- + Documentation/kernel-parameters.txt | 7 +++++++ + kernel/cred.c | 17 +++++++++++++++++ + 2 files changed, 24 insertions(+) + +diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt +index 9776f06..0d6c28d 100644 +--- a/Documentation/kernel-parameters.txt ++++ b/Documentation/kernel-parameters.txt +@@ -2599,6 +2599,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + Note: increases power consumption, thus should only be + enabled if running jitter sensitive (HPC/RT) workloads. + ++ secureboot_enable= ++ [KNL] Enables an emulated UEFI Secure Boot mode. This ++ locks down various aspects of the kernel guarded by the ++ CAP_COMPROMISE_KERNEL capability. This includes things ++ like /dev/mem, IO port access, and other areas. It can ++ be used on non-UEFI machines for testing purposes. ++ + security= [SECURITY] Choose a security module to enable at boot. + If this boot parameter is not specified, only the first + security module asking for security registration will be +diff --git a/kernel/cred.c b/kernel/cred.c +index 48cea3d..3f5be65 100644 +--- a/kernel/cred.c ++++ b/kernel/cred.c +@@ -623,6 +623,23 @@ void __init cred_init(void) + 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); + } + ++void __init secureboot_enable() ++{ ++ pr_info("Secure boot enabled\n"); ++ cap_lower((&init_cred)->cap_bset, CAP_COMPROMISE_KERNEL); ++ cap_lower((&init_cred)->cap_permitted, CAP_COMPROMISE_KERNEL); ++} ++ ++/* Dummy Secure Boot enable option to fake out UEFI SB=1 */ ++static int __init secureboot_enable_opt(char *str) ++{ ++ int sb_enable = !!simple_strtol(str, NULL, 0); ++ if (sb_enable) ++ secureboot_enable(); ++ return 1; ++} ++__setup("secureboot_enable=", secureboot_enable_opt); ++ + /** + * prepare_kernel_cred - Prepare a set of credentials for a kernel service + * @daemon: A userspace daemon to be used as a reference +-- +1.8.1 + + +From 6be9cea6bf2cf06898efa300644ea9e6ad9c5a18 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Thu, 20 Sep 2012 10:41:03 -0400 +Subject: [PATCH 04/17] efi: Enable secure boot lockdown automatically when + enabled in firmware + +The firmware has a set of flags that indicate whether secure boot is enabled +and enforcing. Use them to indicate whether the kernel should lock itself +down. We also indicate the machine is in secure boot mode by adding the +EFI_SECURE_BOOT bit for use with efi_enabled. + +Signed-off-by: Matthew Garrett +Signed-off-by: Josh Boyer +--- + Documentation/x86/zero-page.txt | 2 ++ + arch/x86/boot/compressed/eboot.c | 32 ++++++++++++++++++++++++++++++++ + arch/x86/include/asm/bootparam.h | 3 ++- + arch/x86/kernel/setup.c | 5 +++++ + include/linux/cred.h | 2 ++ + include/linux/efi.h | 1 + + 6 files changed, 44 insertions(+), 1 deletion(-) + +diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt +index cf5437d..7f9ed48 100644 +--- a/Documentation/x86/zero-page.txt ++++ b/Documentation/x86/zero-page.txt +@@ -27,6 +27,8 @@ Offset Proto Name Meaning + 1E9/001 ALL eddbuf_entries Number of entries in eddbuf (below) + 1EA/001 ALL edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer + (below) ++1EB/001 ALL kbd_status Numlock is enabled ++1EC/001 ALL secure_boot Kernel should enable secure boot lockdowns + 290/040 ALL edd_mbr_sig_buffer EDD MBR signatures + 2D0/A00 ALL e820_map E820 memory map table + (array of struct e820entry) +diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c +index ccae7e2..4983e43 100644 +--- a/arch/x86/boot/compressed/eboot.c ++++ b/arch/x86/boot/compressed/eboot.c +@@ -731,6 +731,36 @@ fail: + return status; + } + ++static int get_secure_boot(efi_system_table_t *_table) ++{ ++ u8 sb, setup; ++ unsigned long datasize = sizeof(sb); ++ efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; ++ efi_status_t status; ++ ++ status = efi_call_phys5(sys_table->runtime->get_variable, ++ L"SecureBoot", &var_guid, NULL, &datasize, &sb); ++ ++ if (status != EFI_SUCCESS) ++ return 0; ++ ++ if (sb == 0) ++ return 0; ++ ++ ++ status = efi_call_phys5(sys_table->runtime->get_variable, ++ L"SetupMode", &var_guid, NULL, &datasize, ++ &setup); ++ ++ if (status != EFI_SUCCESS) ++ return 0; ++ ++ if (setup == 1) ++ return 0; ++ ++ return 1; ++} ++ + /* + * Because the x86 boot code expects to be passed a boot_params we + * need to create one ourselves (usually the bootloader would create +@@ -1025,6 +1055,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, + if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) + goto fail; + ++ boot_params->secure_boot = get_secure_boot(sys_table); ++ + setup_graphics(boot_params); + + status = efi_call_phys3(sys_table->boottime->allocate_pool, +diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h +index 2ad874c..c7338e0 100644 +--- a/arch/x86/include/asm/bootparam.h ++++ b/arch/x86/include/asm/bootparam.h +@@ -114,7 +114,8 @@ struct boot_params { + __u8 eddbuf_entries; /* 0x1e9 */ + __u8 edd_mbr_sig_buf_entries; /* 0x1ea */ + __u8 kbd_status; /* 0x1eb */ +- __u8 _pad6[5]; /* 0x1ec */ ++ __u8 secure_boot; /* 0x1ec */ ++ __u8 _pad6[4]; /* 0x1ed */ + struct setup_header hdr; /* setup header */ /* 0x1f1 */ + __u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)]; + __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */ +diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c +index aeacb0e..a196a7e 100644 +--- a/arch/x86/kernel/setup.c ++++ b/arch/x86/kernel/setup.c +@@ -1042,6 +1042,11 @@ void __init setup_arch(char **cmdline_p) + + io_delay_init(); + ++ if (boot_params.secure_boot) { ++ set_bit(EFI_SECURE_BOOT, &x86_efi_facility); ++ secureboot_enable(); ++ } ++ + /* + * Parse the ACPI tables for possible boot-time SMP configuration. + */ +diff --git a/include/linux/cred.h b/include/linux/cred.h +index ebbed2c..a24faf1 100644 +--- a/include/linux/cred.h ++++ b/include/linux/cred.h +@@ -170,6 +170,8 @@ extern int set_security_override_from_ctx(struct cred *, const char *); + extern int set_create_files_as(struct cred *, struct inode *); + extern void __init cred_init(void); + ++extern void secureboot_enable(void); ++ + /* + * check for validity of credentials + */ +diff --git a/include/linux/efi.h b/include/linux/efi.h +index b424f64..fef4ca6 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -551,6 +551,7 @@ extern int __init efi_setup_pcdp_console(char *); + #define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */ + #define EFI_MEMMAP 4 /* Can we use EFI memory map? */ + #define EFI_64BIT 5 /* Is the firmware 64-bit? */ ++#define EFI_SECURE_BOOT 6 /* Are we in Secure Boot mode? */ + + #ifdef CONFIG_EFI + # ifdef CONFIG_X86 +-- +1.8.1 + + +From 2d03e24bded4e30a14656795eb8e052bbaa5ee27 Mon Sep 17 00:00:00 2001 +From: Dave Howells +Date: Tue, 23 Oct 2012 09:30:54 -0400 +Subject: [PATCH 05/17] Add EFI signature data types + +Add the data types that are used for containing hashes, keys and certificates +for cryptographic verification. + +Signed-off-by: David Howells +--- + include/linux/efi.h | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/include/linux/efi.h b/include/linux/efi.h +index fef4ca6..a5dab3c 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -312,6 +312,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, + #define EFI_FILE_SYSTEM_GUID \ + EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) + ++#define EFI_CERT_SHA256_GUID \ ++ EFI_GUID( 0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 ) ++ ++#define EFI_CERT_X509_GUID \ ++ EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 ) ++ + typedef struct { + efi_guid_t guid; + u64 table; +@@ -447,6 +453,20 @@ typedef struct { + + #define EFI_INVALID_TABLE_ADDR (~0UL) + ++typedef struct { ++ efi_guid_t signature_owner; ++ u8 signature_data[]; ++} efi_signature_data_t; ++ ++typedef struct { ++ efi_guid_t signature_type; ++ u32 signature_list_size; ++ u32 signature_header_size; ++ u32 signature_size; ++ u8 signature_header[]; ++ /* efi_signature_data_t signatures[][] */ ++} efi_signature_list_t; ++ + /* + * All runtime access to EFI goes through this structure: + */ +-- +1.8.1 + + +From 2152dae45a6f98592ed5a6da8416a4a799bda3dd Mon Sep 17 00:00:00 2001 +From: Dave Howells +Date: Tue, 23 Oct 2012 09:36:28 -0400 +Subject: [PATCH 06/17] Add an EFI signature blob parser and key loader. + +X.509 certificates are loaded into the specified keyring as asymmetric type +keys. + +Signed-off-by: David Howells +--- + crypto/asymmetric_keys/Kconfig | 8 +++ + crypto/asymmetric_keys/Makefile | 1 + + crypto/asymmetric_keys/efi_parser.c | 108 ++++++++++++++++++++++++++++++++++++ + include/linux/efi.h | 4 ++ + 4 files changed, 121 insertions(+) + create mode 100644 crypto/asymmetric_keys/efi_parser.c + +diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig +index 6d2c2ea..ace9c30 100644 +--- a/crypto/asymmetric_keys/Kconfig ++++ b/crypto/asymmetric_keys/Kconfig +@@ -35,4 +35,12 @@ config X509_CERTIFICATE_PARSER + data and provides the ability to instantiate a crypto key from a + public key packet found inside the certificate. + ++config EFI_SIGNATURE_LIST_PARSER ++ bool "EFI signature list parser" ++ depends on EFI ++ select X509_CERTIFICATE_PARSER ++ help ++ This option provides support for parsing EFI signature lists for ++ X.509 certificates and turning them into keys. ++ + endif # ASYMMETRIC_KEY_TYPE +diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile +index 0727204..cd8388e 100644 +--- a/crypto/asymmetric_keys/Makefile ++++ b/crypto/asymmetric_keys/Makefile +@@ -8,6 +8,7 @@ asymmetric_keys-y := asymmetric_type.o signature.o + + obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o + obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o ++obj-$(CONFIG_EFI_SIGNATURE_LIST_PARSER) += efi_parser.o + + # + # X.509 Certificate handling +diff --git a/crypto/asymmetric_keys/efi_parser.c b/crypto/asymmetric_keys/efi_parser.c +new file mode 100644 +index 0000000..636feb1 +--- /dev/null ++++ b/crypto/asymmetric_keys/efi_parser.c +@@ -0,0 +1,108 @@ ++/* EFI signature/key/certificate list parser ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#define pr_fmt(fmt) "EFI: "fmt ++#include ++#include ++#include ++#include ++#include ++ ++static __initdata efi_guid_t efi_cert_x509_guid = EFI_CERT_X509_GUID; ++ ++/** ++ * parse_efi_signature_list - Parse an EFI signature list for certificates ++ * @data: The data blob to parse ++ * @size: The size of the data blob ++ * @keyring: The keyring to add extracted keys to ++ */ ++int __init parse_efi_signature_list(const void *data, size_t size, struct key *keyring) ++{ ++ unsigned offs = 0; ++ size_t lsize, esize, hsize, elsize; ++ ++ pr_devel("-->%s(,%zu)\n", __func__, size); ++ ++ while (size > 0) { ++ efi_signature_list_t list; ++ const efi_signature_data_t *elem; ++ key_ref_t key; ++ ++ if (size < sizeof(list)) ++ return -EBADMSG; ++ ++ memcpy(&list, data, sizeof(list)); ++ pr_devel("LIST[%04x] guid=%pUl ls=%x hs=%x ss=%x\n", ++ offs, ++ list.signature_type.b, list.signature_list_size, ++ list.signature_header_size, list.signature_size); ++ ++ lsize = list.signature_list_size; ++ hsize = list.signature_header_size; ++ esize = list.signature_size; ++ elsize = lsize - sizeof(list) - hsize; ++ ++ if (lsize > size) { ++ pr_devel("<--%s() = -EBADMSG [overrun @%x]\n", ++ __func__, offs); ++ return -EBADMSG; ++ } ++ if (lsize < sizeof(list) || ++ lsize - sizeof(list) < hsize || ++ esize < sizeof(*elem) || ++ elsize < esize || ++ elsize % esize != 0) { ++ pr_devel("- bad size combo @%x\n", offs); ++ return -EBADMSG; ++ } ++ ++ if (efi_guidcmp(list.signature_type, efi_cert_x509_guid) != 0) { ++ data += lsize; ++ size -= lsize; ++ offs += lsize; ++ continue; ++ } ++ ++ data += sizeof(list) + hsize; ++ size -= sizeof(list) + hsize; ++ offs += sizeof(list) + hsize; ++ ++ for (; elsize > 0; elsize -= esize) { ++ elem = data; ++ ++ pr_devel("ELEM[%04x]\n", offs); ++ ++ key = key_create_or_update( ++ make_key_ref(keyring, 1), ++ "asymmetric", ++ NULL, ++ &elem->signature_data, ++ esize - sizeof(*elem), ++ (KEY_POS_ALL & ~KEY_POS_SETATTR) | ++ KEY_USR_VIEW, ++ KEY_ALLOC_NOT_IN_QUOTA); ++ ++ if (IS_ERR(key)) ++ pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", ++ PTR_ERR(key)); ++ else ++ pr_notice("Loaded cert '%s' linked to '%s'\n", ++ key_ref_to_ptr(key)->description, ++ keyring->description); ++ ++ data += esize; ++ size -= esize; ++ offs += esize; ++ } ++ } ++ ++ return 0; ++} +diff --git a/include/linux/efi.h b/include/linux/efi.h +index a5dab3c..7bfc4f2 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -536,6 +536,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime); + extern void efi_reserve_boot_services(void); + extern struct efi_memory_map memmap; + ++struct key; ++extern int __init parse_efi_signature_list(const void *data, size_t size, ++ struct key *keyring); ++ + /** + * efi_range_is_wc - check the WC bit on an address range + * @start: starting kvirt address +-- +1.8.1 + + +From bb1024f03b0a4cb05bac6503b933279a905bc5fb Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Fri, 26 Oct 2012 12:36:24 -0400 +Subject: [PATCH 07/17] MODSIGN: Add module certificate blacklist keyring + +This adds an additional keyring that is used to store certificates that +are blacklisted. This keyring is searched first when loading signed modules +and if the module's certificate is found, it will refuse to load. This is +useful in cases where third party certificates are used for module signing. + +Signed-off-by: Josh Boyer +--- + init/Kconfig | 8 ++++++++ + kernel/modsign_pubkey.c | 17 +++++++++++++++++ + kernel/module-internal.h | 3 +++ + kernel/module_signing.c | 12 ++++++++++++ + 4 files changed, 40 insertions(+) + +diff --git a/init/Kconfig b/init/Kconfig +index 6fdd6e3..7a9bf00 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1602,6 +1602,14 @@ config MODULE_SIG_FORCE + Reject unsigned modules or signed modules for which we don't have a + key. Without this, such modules will simply taint the kernel. + ++config MODULE_SIG_BLACKLIST ++ bool "Support for blacklisting module signature certificates" ++ depends on MODULE_SIG ++ help ++ This adds support for keeping a blacklist of certificates that ++ should not pass module signature verification. If a module is ++ signed with something in this keyring, the load will be rejected. ++ + choice + prompt "Which hash algorithm should modules be signed with?" + depends on MODULE_SIG +diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c +index 767e559..d99cd51 100644 +--- a/kernel/modsign_pubkey.c ++++ b/kernel/modsign_pubkey.c +@@ -17,6 +17,9 @@ + #include "module-internal.h" + + struct key *modsign_keyring; ++#ifdef CONFIG_MODULE_SIG_BLACKLIST ++struct key *modsign_blacklist; ++#endif + + extern __initdata const u8 modsign_certificate_list[]; + extern __initdata const u8 modsign_certificate_list_end[]; +@@ -52,6 +55,20 @@ static __init int module_verify_init(void) + if (key_instantiate_and_link(modsign_keyring, NULL, 0, NULL, NULL) < 0) + panic("Can't instantiate module signing keyring\n"); + ++#ifdef CONFIG_MODULE_SIG_BLACKLIST ++ modsign_blacklist = key_alloc(&key_type_keyring, ".modsign_blacklist", ++ KUIDT_INIT(0), KGIDT_INIT(0), ++ current_cred(), ++ (KEY_POS_ALL & ~KEY_POS_SETATTR) | ++ KEY_USR_VIEW | KEY_USR_READ, ++ KEY_ALLOC_NOT_IN_QUOTA); ++ if (IS_ERR(modsign_blacklist)) ++ panic("Can't allocate module signing blacklist keyring\n"); ++ ++ if (key_instantiate_and_link(modsign_blacklist, NULL, 0, NULL, NULL) < 0) ++ panic("Can't instantiate module blacklist keyring\n"); ++#endif ++ + return 0; + } + +diff --git a/kernel/module-internal.h b/kernel/module-internal.h +index 24f9247..51a8380 100644 +--- a/kernel/module-internal.h ++++ b/kernel/module-internal.h +@@ -10,5 +10,8 @@ + */ + + extern struct key *modsign_keyring; ++#ifdef CONFIG_MODULE_SIG_BLACKLIST ++extern struct key *modsign_blacklist; ++#endif + + extern int mod_verify_sig(const void *mod, unsigned long *_modlen); +diff --git a/kernel/module_signing.c b/kernel/module_signing.c +index f2970bd..5423195 100644 +--- a/kernel/module_signing.c ++++ b/kernel/module_signing.c +@@ -157,6 +157,18 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len, + + pr_debug("Look up: \"%s\"\n", id); + ++#ifdef CONFIG_MODULE_SIG_BLACKLIST ++ key = keyring_search(make_key_ref(modsign_blacklist, 1), ++ &key_type_asymmetric, id); ++ if (!IS_ERR(key)) { ++ /* module is signed with a cert in the blacklist. reject */ ++ pr_err("Module key '%s' is in blacklist\n", id); ++ key_ref_put(key); ++ kfree(id); ++ return ERR_PTR(-EKEYREJECTED); ++ } ++#endif ++ + key = keyring_search(make_key_ref(modsign_keyring, 1), + &key_type_asymmetric, id); + if (IS_ERR(key)) +-- +1.8.1 + + +From 10f89ba8724e88046cd05aef20e80a935d3968f6 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Fri, 26 Oct 2012 12:42:16 -0400 +Subject: [PATCH 08/17] MODSIGN: Import certificates from UEFI Secure Boot + +Secure Boot stores a list of allowed certificates in the 'db' variable. +This imports those certificates into the module signing keyring. This +allows for a third party signing certificate to be used in conjunction +with signed modules. By importing the public certificate into the 'db' +variable, a user can allow a module signed with that certificate to +load. The shim UEFI bootloader has a similar certificate list stored +in the 'MokListRT' variable. We import those as well. + +In the opposite case, Secure Boot maintains a list of disallowed +certificates in the 'dbx' variable. We load those certificates into +the newly introduced module blacklist keyring and forbid any module +signed with those from loading. + +Signed-off-by: Josh Boyer +--- + include/linux/efi.h | 6 ++++ + init/Kconfig | 9 ++++++ + kernel/Makefile | 3 ++ + kernel/modsign_uefi.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 108 insertions(+) + create mode 100644 kernel/modsign_uefi.c + +diff --git a/include/linux/efi.h b/include/linux/efi.h +index 7bfc4f2..014a013 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -318,6 +318,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, + #define EFI_CERT_X509_GUID \ + EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 ) + ++#define EFI_IMAGE_SECURITY_DATABASE_GUID \ ++ EFI_GUID( 0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f ) ++ ++#define EFI_SHIM_LOCK_GUID \ ++ EFI_GUID( 0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 ) ++ + typedef struct { + efi_guid_t guid; + u64 table; +diff --git a/init/Kconfig b/init/Kconfig +index 7a9bf00..51aa170 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1610,6 +1610,15 @@ config MODULE_SIG_BLACKLIST + should not pass module signature verification. If a module is + signed with something in this keyring, the load will be rejected. + ++config MODULE_SIG_UEFI ++ bool "Allow modules signed with certs stored in UEFI" ++ depends on MODULE_SIG && MODULE_SIG_BLACKLIST && EFI ++ select EFI_SIGNATURE_LIST_PARSER ++ help ++ This will import certificates stored in UEFI and allow modules ++ signed with those to be loaded. It will also disallow loading ++ of modules stored in the UEFI dbx variable. ++ + choice + prompt "Which hash algorithm should modules be signed with?" + depends on MODULE_SIG +diff --git a/kernel/Makefile b/kernel/Makefile +index 86e3285..12e17ab 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -55,6 +55,7 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o + obj-$(CONFIG_UID16) += uid16.o + obj-$(CONFIG_MODULES) += module.o + obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o ++obj-$(CONFIG_MODULE_SIG_UEFI) += modsign_uefi.o + obj-$(CONFIG_KALLSYMS) += kallsyms.o + obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o + obj-$(CONFIG_KEXEC) += kexec.o +@@ -113,6 +114,8 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o + + $(obj)/configs.o: $(obj)/config_data.h + ++$(obj)/modsign_uefi.o: KBUILD_CFLAGS += -fshort-wchar ++ + # config_data.h contains the same information as ikconfig.h but gzipped. + # Info from config_data can be extracted from /proc/config* + targets += config_data.gz +diff --git a/kernel/modsign_uefi.c b/kernel/modsign_uefi.c +new file mode 100644 +index 0000000..b9237d7 +--- /dev/null ++++ b/kernel/modsign_uefi.c +@@ -0,0 +1,90 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "module-internal.h" ++ ++static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid, unsigned long *size) ++{ ++ efi_status_t status; ++ unsigned long lsize = 4; ++ unsigned long tmpdb[4]; ++ void *db = NULL; ++ ++ status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb); ++ if (status != EFI_BUFFER_TOO_SMALL) { ++ pr_err("Couldn't get size: 0x%lx\n", status); ++ return NULL; ++ } ++ ++ db = kmalloc(lsize, GFP_KERNEL); ++ if (!db) { ++ pr_err("Couldn't allocate memory for uefi cert list\n"); ++ goto out; ++ } ++ ++ status = efi.get_variable(name, guid, NULL, &lsize, db); ++ if (status != EFI_SUCCESS) { ++ kfree(db); ++ db = NULL; ++ pr_err("Error reading db var: 0x%lx\n", status); ++ } ++out: ++ *size = lsize; ++ return db; ++} ++ ++/* ++ * * Load the certs contained in the UEFI databases ++ * */ ++static int __init load_uefi_certs(void) ++{ ++ efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID; ++ efi_guid_t mok_var = EFI_SHIM_LOCK_GUID; ++ void *db = NULL, *dbx = NULL, *mok = NULL; ++ unsigned long dbsize = 0, dbxsize = 0, moksize = 0; ++ int rc = 0; ++ ++ /* Check if SB is enabled and just return if not */ ++ if (!efi_enabled(EFI_SECURE_BOOT)) ++ return 0; ++ ++ /* Get db, MokListRT, and dbx. They might not exist, so it isn't ++ * an error if we can't get them. ++ */ ++ db = get_cert_list(L"db", &secure_var, &dbsize); ++ if (!db) { ++ pr_err("MODSIGN: Couldn't get UEFI db list\n"); ++ } else { ++ rc = parse_efi_signature_list(db, dbsize, modsign_keyring); ++ if (rc) ++ pr_err("Couldn't parse db signatures: %d\n", rc); ++ kfree(db); ++ } ++ ++ mok = get_cert_list(L"MokListRT", &mok_var, &moksize); ++ if (!mok) { ++ pr_info("MODSIGN: Couldn't get UEFI MokListRT\n"); ++ } else { ++ rc = parse_efi_signature_list(mok, moksize, modsign_keyring); ++ if (rc) ++ pr_err("Couldn't parse MokListRT signatures: %d\n", rc); ++ kfree(mok); ++ } ++ ++ dbx = get_cert_list(L"dbx", &secure_var, &dbxsize); ++ if (!dbx) { ++ pr_info("MODSIGN: Couldn't get UEFI dbx list\n"); ++ } else { ++ rc = parse_efi_signature_list(dbx, dbxsize, ++ modsign_blacklist); ++ if (rc) ++ pr_err("Couldn't parse dbx signatures: %d\n", rc); ++ kfree(dbx); ++ } ++ ++ return rc; ++} ++late_initcall(load_uefi_certs); +-- +1.8.1 + + +From db76f49f8ded0df6aaff8ae2531ff1aaeff04440 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Thu, 20 Sep 2012 10:40:57 -0400 +Subject: [PATCH 09/17] PCI: Lock down BAR access in secure boot environments + +Any hardware that can potentially generate DMA has to be locked down from +userspace in order to avoid it being possible for an attacker to cause +arbitrary kernel behaviour. Default to paranoid - in future we can +potentially relax this for sufficiently IOMMU-isolated devices. + +Signed-off-by: Matthew Garrett +--- + drivers/pci/pci-sysfs.c | 9 +++++++++ + drivers/pci/proc.c | 8 +++++++- + drivers/pci/syscall.c | 2 +- + 3 files changed, 17 insertions(+), 2 deletions(-) + +diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c +index f39378d..1db1e74 100644 +--- a/drivers/pci/pci-sysfs.c ++++ b/drivers/pci/pci-sysfs.c +@@ -546,6 +546,9 @@ pci_write_config(struct file* filp, struct kobject *kobj, + loff_t init_off = off; + u8 *data = (u8*) buf; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + if (off > dev->cfg_size) + return 0; + if (off + count > dev->cfg_size) { +@@ -852,6 +855,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, + resource_size_t start, end; + int i; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + for (i = 0; i < PCI_ROM_RESOURCE; i++) + if (res == &pdev->resource[i]) + break; +@@ -959,6 +965,9 @@ pci_write_resource_io(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t off, size_t count) + { ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + return pci_resource_io(filp, kobj, attr, buf, off, count, true); + } + +diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c +index 9b8505c..35580bc 100644 +--- a/drivers/pci/proc.c ++++ b/drivers/pci/proc.c +@@ -139,6 +139,9 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof + int size = dp->size; + int cnt; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + if (pos >= size) + return 0; + if (nbytes >= size) +@@ -219,6 +222,9 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd, + #endif /* HAVE_PCI_MMAP */ + int ret = 0; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + switch (cmd) { + case PCIIOC_CONTROLLER: + ret = pci_domain_nr(dev->bus); +@@ -259,7 +265,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma) + struct pci_filp_private *fpriv = file->private_data; + int i, ret; + +- if (!capable(CAP_SYS_RAWIO)) ++ if (!capable(CAP_SYS_RAWIO) || !capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + + /* Make sure the caller is mapping a real resource for this device */ +diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c +index e1c1ec5..97e785f 100644 +--- a/drivers/pci/syscall.c ++++ b/drivers/pci/syscall.c +@@ -92,7 +92,7 @@ SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn, + u32 dword; + int err = 0; + +- if (!capable(CAP_SYS_ADMIN)) ++ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + + dev = pci_get_bus_and_slot(bus, dfn); +-- +1.8.1 + + +From 0d71d1586db8d8f6f2f362953fc747528f0dbb2a Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Thu, 20 Sep 2012 10:40:58 -0400 +Subject: [PATCH 10/17] x86: Lock down IO port access in secure boot + environments + +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. + +Signed-off-by: Matthew Garrett +--- + arch/x86/kernel/ioport.c | 4 ++-- + drivers/char/mem.c | 3 +++ + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c +index 8c96897..a2578c4 100644 +--- a/arch/x86/kernel/ioport.c ++++ b/arch/x86/kernel/ioport.c +@@ -28,7 +28,7 @@ asmlinkage long sys_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) || !capable(CAP_COMPROMISE_KERNEL))) + return -EPERM; + + /* +@@ -102,7 +102,7 @@ long sys_iopl(unsigned int level, struct pt_regs *regs) + return -EINVAL; + /* Trying to gain more privileges? */ + if (level > old) { +- if (!capable(CAP_SYS_RAWIO)) ++ if (!capable(CAP_SYS_RAWIO) || !capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + } + regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); +diff --git a/drivers/char/mem.c b/drivers/char/mem.c +index 0537903..47501fc 100644 +--- a/drivers/char/mem.c ++++ b/drivers/char/mem.c +@@ -597,6 +597,9 @@ static ssize_t write_port(struct file *file, const char __user *buf, + unsigned long i = *ppos; + const char __user * tmp = buf; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + if (!access_ok(VERIFY_READ, buf, count)) + return -EFAULT; + while (count-- > 0 && i < 65536) { +-- +1.8.1 + + +From cbe40e9c220c6c49774e04d6e4df437a2f450aba Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Thu, 20 Sep 2012 10:40:59 -0400 +Subject: [PATCH 11/17] ACPI: Limit access to custom_method + +It must be impossible for even root to get code executed in kernel context +under a secure boot environment. custom_method effectively allows arbitrary +access to system memory, so it needs to have a capability check here. + +Signed-off-by: Matthew Garrett +--- + drivers/acpi/custom_method.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c +index 5d42c24..247d58b 100644 +--- a/drivers/acpi/custom_method.c ++++ b/drivers/acpi/custom_method.c +@@ -29,6 +29,9 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf, + struct acpi_table_header table; + acpi_status status; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + if (!(*ppos)) { + /* parse the table header to get the table length */ + if (count <= sizeof(struct acpi_table_header)) +-- +1.8.1 + + +From 48da61f5b2a04df0a7df6d9e443a6705e2bc6ef9 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Thu, 20 Sep 2012 10:41:00 -0400 +Subject: [PATCH 12/17] asus-wmi: Restrict debugfs interface + +We have no way of validating what all of the Asus WMI methods do on a +given machine, and there's a risk that some will allow hardware state to +be manipulated in such a way that arbitrary code can be executed in the +kernel. Add a capability check to prevent that. + +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/asus-wmi.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index c0e9ff4..3c10167 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -1521,6 +1521,9 @@ static int show_dsts(struct seq_file *m, void *data) + int err; + u32 retval = -1; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval); + + if (err < 0) +@@ -1537,6 +1540,9 @@ static int show_devs(struct seq_file *m, void *data) + int err; + u32 retval = -1; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param, + &retval); + +@@ -1561,6 +1567,9 @@ static int show_call(struct seq_file *m, void *data) + union acpi_object *obj; + acpi_status status; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, + 1, asus->debug.method_id, + &input, &output); +-- +1.8.1 + + +From 293d2f88602d7d951c23e379c66d0adc440de47c Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Thu, 20 Sep 2012 10:41:01 -0400 +Subject: [PATCH 13/17] Restrict /dev/mem and /dev/kmem in secure boot setups + +Allowing users to write to address space makes it possible for the kernel +to be subverted. Restrict this when we need to protect the kernel. + +Signed-off-by: Matthew Garrett +--- + drivers/char/mem.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/char/mem.c b/drivers/char/mem.c +index 47501fc..8817cdc 100644 +--- a/drivers/char/mem.c ++++ b/drivers/char/mem.c +@@ -158,6 +158,9 @@ static ssize_t write_mem(struct file *file, const char __user *buf, + unsigned long copied; + void *ptr; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + if (!valid_phys_addr_range(p, count)) + return -EFAULT; + +@@ -530,6 +533,9 @@ static ssize_t write_kmem(struct file *file, const char __user *buf, + char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ + int err = 0; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + if (p < (unsigned long) high_memory) { + unsigned long to_write = min_t(unsigned long, count, + (unsigned long)high_memory - p); +-- +1.8.1 + + +From ca1c6f1c294f4ca76599603b801e84945d6f0277 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Thu, 20 Sep 2012 10:41:04 -0400 +Subject: [PATCH 14/17] acpi: Ignore acpi_rsdp kernel parameter in a secure + boot environment + +This option allows userspace to pass the RSDP address to the kernel. This +could potentially be used to circumvent the secure boot trust model. +We ignore the setting if we don't have the CAP_COMPROMISE_KERNEL capability. + +Signed-off-by: Josh Boyer +--- + drivers/acpi/osl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c +index 251435a..b67cf29 100644 +--- a/drivers/acpi/osl.c ++++ b/drivers/acpi/osl.c +@@ -246,7 +246,7 @@ early_param("acpi_rsdp", setup_acpi_rsdp); + acpi_physical_address __init acpi_os_get_root_pointer(void) + { + #ifdef CONFIG_KEXEC +- if (acpi_rsdp) ++ if (acpi_rsdp && capable(CAP_COMPROMISE_KERNEL)) + return acpi_rsdp; + #endif + +-- +1.8.1 + + +From 1e5b3f2c3ea547cd281bf5754fbc7717431db5fe Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Tue, 4 Sep 2012 11:55:13 -0400 +Subject: [PATCH 15/17] kexec: Disable in a secure boot environment + +kexec could be used as a vector for a malicious user to use a signed kernel +to circumvent the secure boot trust model. In the long run we'll want to +support signed kexec payloads, but for the moment we should just disable +loading entirely in that situation. + +Signed-off-by: Matthew Garrett +--- + kernel/kexec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/kexec.c b/kernel/kexec.c +index 5e4bd78..dd464e0 100644 +--- a/kernel/kexec.c ++++ b/kernel/kexec.c +@@ -943,7 +943,7 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, + int result; + + /* We only trust the superuser with rebooting the system. */ +- if (!capable(CAP_SYS_BOOT)) ++ if (!capable(CAP_SYS_BOOT) || !capable(CAP_COMPROMISE_KERNEL)) + return -EPERM; + + /* +-- +1.8.1 + + +From c399cdb725681eba45239b3ae9218f0fc813e678 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Fri, 5 Oct 2012 10:12:48 -0400 +Subject: [PATCH 16/17] MODSIGN: Always enforce module signing in a Secure Boot + environment + +If a machine is booted into a Secure Boot environment, we need to +protect the trust model. This requires that all modules be signed +with a key that is in the kernel's _modsign keyring. The checks for +this are already done via the 'sig_enforce' module parameter. Make +this visible within the kernel and force it to be true. + +Signed-off-by: Josh Boyer +--- + kernel/cred.c | 8 ++++++++ + kernel/module.c | 4 ++-- + 2 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/kernel/cred.c b/kernel/cred.c +index 3f5be65..a381e27 100644 +--- a/kernel/cred.c ++++ b/kernel/cred.c +@@ -623,11 +623,19 @@ void __init cred_init(void) + 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); + } + ++#ifdef CONFIG_MODULE_SIG ++extern bool sig_enforce; ++#endif ++ + void __init secureboot_enable() + { + pr_info("Secure boot enabled\n"); + cap_lower((&init_cred)->cap_bset, CAP_COMPROMISE_KERNEL); + cap_lower((&init_cred)->cap_permitted, CAP_COMPROMISE_KERNEL); ++#ifdef CONFIG_MODULE_SIG ++ /* Enable module signature enforcing */ ++ sig_enforce = true; ++#endif + } + + /* Dummy Secure Boot enable option to fake out UEFI SB=1 */ +diff --git a/kernel/module.c b/kernel/module.c +index 3e544f4..7a9a802 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -106,9 +106,9 @@ struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ + + #ifdef CONFIG_MODULE_SIG + #ifdef CONFIG_MODULE_SIG_FORCE +-static bool sig_enforce = true; ++bool sig_enforce = true; + #else +-static bool sig_enforce = false; ++bool sig_enforce = false; + + static int param_set_bool_enable_only(const char *val, + const struct kernel_param *kp) +-- +1.8.1 + + +From 8e236de2ec08dceb9ce1e8ab07926e85440deb6b Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Fri, 26 Oct 2012 14:02:09 -0400 +Subject: [PATCH 17/17] hibernate: Disable in a Secure Boot environment + +There is currently no way to verify the resume image when returning +from hibernate. This might compromise the secure boot trust model, +so until we can work with signed hibernate images we disable it in +a Secure Boot environment. + +Signed-off-by: Josh Boyer +--- + kernel/power/hibernate.c | 15 ++++++++++++++- + kernel/power/main.c | 7 ++++++- + kernel/power/user.c | 3 +++ + 3 files changed, 23 insertions(+), 2 deletions(-) + +diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c +index b26f5f1..7f63cb4 100644 +--- a/kernel/power/hibernate.c ++++ b/kernel/power/hibernate.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include "power.h" + +@@ -632,6 +633,10 @@ int hibernate(void) + { + int error; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) { ++ return -EPERM; ++ } ++ + lock_system_sleep(); + /* The snapshot device should not be opened while we're running */ + if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { +@@ -723,7 +728,7 @@ static int software_resume(void) + /* + * If the user said "noresume".. bail out early. + */ +- if (noresume) ++ if (noresume || !capable(CAP_COMPROMISE_KERNEL)) + return 0; + + /* +@@ -889,6 +894,11 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr, + int i; + char *start = buf; + ++ if (efi_enabled(EFI_SECURE_BOOT)) { ++ buf += sprintf(buf, "[%s]\n", "disabled"); ++ return buf-start; ++ } ++ + for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) { + if (!hibernation_modes[i]) + continue; +@@ -923,6 +933,9 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr, + char *p; + int mode = HIBERNATION_INVALID; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + p = memchr(buf, '\n', n); + len = p ? p - buf : n; + +diff --git a/kernel/power/main.c b/kernel/power/main.c +index f458238..734bc26 100644 +--- a/kernel/power/main.c ++++ b/kernel/power/main.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #include "power.h" + +@@ -301,7 +302,11 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, + } + #endif + #ifdef CONFIG_HIBERNATION +- s += sprintf(s, "%s\n", "disk"); ++ if (!efi_enabled(EFI_SECURE_BOOT)) { ++ s += sprintf(s, "%s\n", "disk"); ++ } else { ++ s += sprintf(s, "\n"); ++ } + #else + if (s != buf) + /* convert the last space to a newline */ +diff --git a/kernel/power/user.c b/kernel/power/user.c +index 4ed81e7..b11a0f4 100644 +--- a/kernel/power/user.c ++++ b/kernel/power/user.c +@@ -48,6 +48,9 @@ static int snapshot_open(struct inode *inode, struct file *filp) + struct snapshot_data *data; + int error; + ++ if (!capable(CAP_COMPROMISE_KERNEL)) ++ return -EPERM; ++ + lock_system_sleep(); + + if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { +-- +1.8.1 + diff --git a/sources b/sources index 17024d9..d3b6270 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 21223369d682bcf44bcdfe1521095983 linux-3.7.tar.xz -c100b62e571bfb80e8c290e811c0963c patch-3.7.5.xz +ec61c44f37585a768d41c0439101ef9c patch-3.7.6.xz