| Bugzilla: N/A |
| Upstream-status: Fedora mustard. Replaced by securelevels, but that was nak'd |
| |
| From 0fc411ee00c81b8a18b1417d31f2736fad155d89 Mon Sep 17 00:00:00 2001 |
| From: Matthew Garrett <matthew.garrett@nebula.com> |
| Date: Fri, 9 Aug 2013 17:58:15 -0400 |
| Subject: [PATCH 01/14] Add secure_modules() call |
| |
| Provide a single call to allow kernel code to determine whether the system |
| has been configured to either disable module loading entirely or to load |
| only modules signed with a trusted key. |
| |
| Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com> |
| |
| include/linux/module.h | 7 +++++++ |
| kernel/module.c | 10 ++++++++++ |
| 2 files changed, 17 insertions(+) |
| |
| diff --git a/include/linux/module.h b/include/linux/module.h |
| index 05f2447..de97e77 100644 |
| |
| |
| @@ -515,6 +515,8 @@ int unregister_module_notifier(struct notifier_block * nb); |
| |
| extern void print_modules(void); |
| |
| +extern bool secure_modules(void); |
| + |
| #else /* !CONFIG_MODULES... */ |
| |
| /* Given an address, look for it in the exception tables. */ |
| @@ -625,6 +627,11 @@ static inline int unregister_module_notifier(struct notifier_block * nb) |
| static inline void print_modules(void) |
| { |
| } |
| + |
| +static inline bool secure_modules(void) |
| +{ |
| + return false; |
| +} |
| #endif /* CONFIG_MODULES */ |
| |
| #ifdef CONFIG_SYSFS |
| diff --git a/kernel/module.c b/kernel/module.c |
| index dc58274..81206c1 100644 |
| |
| |
| @@ -3860,3 +3860,13 @@ void module_layout(struct module *mod, |
| } |
| EXPORT_SYMBOL(module_layout); |
| #endif |
| + |
| +bool secure_modules(void) |
| +{ |
| +#ifdef CONFIG_MODULE_SIG |
| + return (sig_enforce || modules_disabled); |
| +#else |
| + return modules_disabled; |
| +#endif |
| +} |
| +EXPORT_SYMBOL(secure_modules); |
| -- |
| 1.8.3.1 |
| |
| |
| From b94942e55b519e70366e970cea3665c464d1b7da Mon Sep 17 00:00:00 2001 |
| From: Matthew Garrett <matthew.garrett@nebula.com> |
| Date: Thu, 8 Mar 2012 10:10:38 -0500 |
| Subject: [PATCH 02/14] PCI: Lock down BAR access when module security is |
| enabled |
| |
| 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 modify |
| kernel code, allowing them to circumvent disabled module loading or module |
| signing. Default to paranoid - in future we can potentially relax this for |
| sufficiently IOMMU-isolated devices. |
| |
| Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com> |
| |
| drivers/pci/pci-sysfs.c | 10 ++++++++++ |
| drivers/pci/proc.c | 8 +++++++- |
| drivers/pci/syscall.c | 3 ++- |
| 3 files changed, 19 insertions(+), 2 deletions(-) |
| |
| diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c |
| index d8eb880..a851ad6 100644 |
| |
| |
| @@ -29,6 +29,7 @@ |
| #include <linux/slab.h> |
| #include <linux/vgaarb.h> |
| #include <linux/pm_runtime.h> |
| +#include <linux/module.h> |
| #include "pci.h" |
| |
| static int sysfs_initialized; /* = 0 */ |
| @@ -644,6 +645,9 @@ pci_write_config(struct file* filp, struct kobject *kobj, |
| loff_t init_off = off; |
| u8 *data = (u8*) buf; |
| |
| + if (secure_modules()) |
| + return -EPERM; |
| + |
| if (off > dev->cfg_size) |
| return 0; |
| if (off + count > dev->cfg_size) { |
| @@ -950,6 +954,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, |
| resource_size_t start, end; |
| int i; |
| |
| + if (secure_modules()) |
| + return -EPERM; |
| + |
| for (i = 0; i < PCI_ROM_RESOURCE; i++) |
| if (res == &pdev->resource[i]) |
| break; |
| @@ -1057,6 +1064,9 @@ pci_write_resource_io(struct file *filp, struct kobject *kobj, |
| struct bin_attribute *attr, char *buf, |
| loff_t off, size_t count) |
| { |
| + if (secure_modules()) |
| + 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 cdc7836..e3d498b 100644 |
| |
| |
| @@ -117,6 +117,9 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof |
| int size = dev->cfg_size; |
| int cnt; |
| |
| + if (secure_modules()) |
| + return -EPERM; |
| + |
| if (pos >= size) |
| return 0; |
| if (nbytes >= size) |
| @@ -196,6 +199,9 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd, |
| #endif /* HAVE_PCI_MMAP */ |
| int ret = 0; |
| |
| + if (secure_modules()) |
| + return -EPERM; |
| + |
| switch (cmd) { |
| case PCIIOC_CONTROLLER: |
| ret = pci_domain_nr(dev->bus); |
| @@ -234,7 +240,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) || secure_modules()) |
| 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..bffbf71 100644 |
| |
| |
| @@ -10,6 +10,7 @@ |
| #include <linux/errno.h> |
| #include <linux/pci.h> |
| #include <linux/syscalls.h> |
| +#include <linux/module.h> |
| #include <asm/uaccess.h> |
| #include "pci.h" |
| |
| @@ -92,7 +93,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) || secure_modules()) |
| return -EPERM; |
| |
| dev = pci_get_bus_and_slot(bus, dfn); |
| -- |
| 1.8.3.1 |
| |
| |
| From 36f34509fe52cc49e1b1f6815a3f235040f64a03 Mon Sep 17 00:00:00 2001 |
| From: Matthew Garrett <matthew.garrett@nebula.com> |
| Date: Thu, 8 Mar 2012 10:35:59 -0500 |
| Subject: [PATCH 03/14] x86: Lock down IO port access when module security is |
| enabled |
| |
| 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 <matthew.garrett@nebula.com> |
| |
| arch/x86/kernel/ioport.c | 5 +++-- |
| drivers/char/mem.c | 4 ++++ |
| 2 files changed, 7 insertions(+), 2 deletions(-) |
| |
| diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c |
| index 4ddaf66..00b4403 100644 |
| |
| |
| @@ -15,6 +15,7 @@ |
| #include <linux/thread_info.h> |
| #include <linux/syscalls.h> |
| #include <linux/bitmap.h> |
| +#include <linux/module.h> |
| #include <asm/syscalls.h> |
| |
| /* |
| @@ -28,7 +29,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) || secure_modules())) |
| return -EPERM; |
| |
| /* |
| @@ -103,7 +104,7 @@ SYSCALL_DEFINE1(iopl, unsigned int, level) |
| return -EINVAL; |
| /* Trying to gain more privileges? */ |
| if (level > old) { |
| - if (!capable(CAP_SYS_RAWIO)) |
| + if (!capable(CAP_SYS_RAWIO) || secure_modules()) |
| return -EPERM; |
| } |
| regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); |
| diff --git a/drivers/char/mem.c b/drivers/char/mem.c |
| index f895a8c..1af8664 100644 |
| |
| |
| @@ -28,6 +28,7 @@ |
| #include <linux/export.h> |
| #include <linux/io.h> |
| #include <linux/aio.h> |
| +#include <linux/module.h> |
| |
| #include <asm/uaccess.h> |
| |
| @@ -563,6 +564,9 @@ static ssize_t write_port(struct file *file, const char __user *buf, |
| unsigned long i = *ppos; |
| const char __user *tmp = buf; |
| |
| + if (secure_modules()) |
| + return -EPERM; |
| + |
| if (!access_ok(VERIFY_READ, buf, count)) |
| return -EFAULT; |
| while (count-- > 0 && i < 65536) { |
| -- |
| 1.8.3.1 |
| |
| |
| From 67d9800dcf60467e076587b0aac67bcdc516cfe2 Mon Sep 17 00:00:00 2001 |
| From: Matthew Garrett <matthew.garrett@nebula.com> |
| Date: Fri, 9 Mar 2012 08:39:37 -0500 |
| Subject: [PATCH 04/14] ACPI: Limit access to custom_method |
| |
| custom_method effectively allows arbitrary access to system memory, making |
| it possible for an attacker to circumvent restrictions on module loading. |
| Disable it if any such restrictions have been enabled. |
| |
| Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com> |
| |
| 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 12b62f2..50647b3 100644 |
| |
| |
| @@ -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 (secure_modules()) |
| + return -EPERM; |
| + |
| if (!(*ppos)) { |
| /* parse the table header to get the table length */ |
| if (count <= sizeof(struct acpi_table_header)) |
| -- |
| 1.8.3.1 |
| |
| |
| From bdf3761573167c20c72b151c1088b24fd24869ac Mon Sep 17 00:00:00 2001 |
| From: Matthew Garrett <matthew.garrett@nebula.com> |
| Date: Fri, 9 Mar 2012 08:46:50 -0500 |
| Subject: [PATCH 05/14] asus-wmi: Restrict debugfs interface when module |
| loading is restricted |
| |
| 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, circumventing module loading restrictions. Prevent that if any of |
| these features are enabled. |
| |
| Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com> |
| |
| 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 19c313b..db18ef66 100644 |
| |
| |
| @@ -1618,6 +1618,9 @@ static int show_dsts(struct seq_file *m, void *data) |
| int err; |
| u32 retval = -1; |
| |
| + if (secure_modules()) |
| + return -EPERM; |
| + |
| err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval); |
| |
| if (err < 0) |
| @@ -1634,6 +1637,9 @@ static int show_devs(struct seq_file *m, void *data) |
| int err; |
| u32 retval = -1; |
| |
| + if (secure_modules()) |
| + return -EPERM; |
| + |
| err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param, |
| &retval); |
| |
| @@ -1658,6 +1664,9 @@ static int show_call(struct seq_file *m, void *data) |
| union acpi_object *obj; |
| acpi_status status; |
| |
| + if (secure_modules()) |
| + return -EPERM; |
| + |
| status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, |
| 1, asus->debug.method_id, |
| &input, &output); |
| -- |
| 1.8.3.1 |
| |
| |
| From 65d88af5a2c6bb6d01da17819d8ba782bd208837 Mon Sep 17 00:00:00 2001 |
| From: Matthew Garrett <matthew.garrett@nebula.com> |
| Date: Fri, 9 Mar 2012 09:28:15 -0500 |
| Subject: [PATCH 06/14] Restrict /dev/mem and /dev/kmem when module loading is |
| restricted |
| |
| Allowing users to write to address space makes it possible for the kernel |
| to be subverted, avoiding module loading restrictions. Prevent this when |
| any restrictions have been imposed on loading modules. |
| |
| Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com> |
| |
| drivers/char/mem.c | 6 ++++++ |
| 1 file changed, 6 insertions(+) |
| |
| diff --git a/drivers/char/mem.c b/drivers/char/mem.c |
| index 1af8664..61406c8 100644 |
| |
| |
| @@ -159,6 +159,9 @@ static ssize_t write_mem(struct file *file, const char __user *buf, |
| unsigned long copied; |
| void *ptr; |
| |
| + if (secure_modules()) |
| + return -EPERM; |
| + |
| if (!valid_phys_addr_range(p, count)) |
| return -EFAULT; |
| |
| @@ -497,6 +500,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 (secure_modules()) |
| + return -EPERM; |
| + |
| if (p < (unsigned long) high_memory) { |
| unsigned long to_write = min_t(unsigned long, count, |
| (unsigned long)high_memory - p); |
| -- |
| 1.8.3.1 |
| |
| |
| From 4aa42b7fa5d7f79eb1d179e728ffa561fd9cf354 Mon Sep 17 00:00:00 2001 |
| From: Josh Boyer <jwboyer@redhat.com> |
| Date: Mon, 25 Jun 2012 19:57:30 -0400 |
| Subject: [PATCH 07/14] acpi: Ignore acpi_rsdp kernel parameter when module |
| loading is restricted |
| |
| This option allows userspace to pass the RSDP address to the kernel, which |
| makes it possible for a user to circumvent any restrictions imposed on |
| loading modules. Disable it in that case. |
| |
| Signed-off-by: Josh Boyer <jwboyer@redhat.com> |
| |
| drivers/acpi/osl.c | 3 ++- |
| 1 file changed, 2 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c |
| index e5f416c..9311c00 100644 |
| |
| |
| @@ -45,6 +45,7 @@ |
| #include <linux/list.h> |
| #include <linux/jiffies.h> |
| #include <linux/semaphore.h> |
| +#include <linux/module.h> |
| |
| #include <asm/io.h> |
| #include <asm/uaccess.h> |
| @@ -249,7 +250,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 && !secure_modules()) |
| return acpi_rsdp; |
| #endif |
| |
| -- |
| 1.8.3.1 |
| |
| |
| From c9e62c2ce588d98a774a3853e56d95e48b9df98c Mon Sep 17 00:00:00 2001 |
| From: Matthew Garrett <matthew.garrett@nebula.com> |
| Date: Fri, 9 Aug 2013 03:33:56 -0400 |
| Subject: [PATCH 08/14] kexec: Disable at runtime if the kernel enforces module |
| loading restrictions |
| |
| kexec permits the loading and execution of arbitrary code in ring 0, which |
| is something that module signing enforcement is meant to prevent. It makes |
| sense to disable kexec in this situation. |
| |
| Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com> |
| |
| kernel/kexec.c | 8 ++++++++ |
| 1 file changed, 8 insertions(+) |
| |
| diff --git a/kernel/kexec.c b/kernel/kexec.c |
| index 2a74f30..13601e3 100644 |
| |
| |
| @@ -32,6 +32,7 @@ |
| #include <linux/vmalloc.h> |
| #include <linux/swap.h> |
| #include <linux/syscore_ops.h> |
| +#include <linux/module.h> |
| |
| #include <asm/page.h> |
| #include <asm/uaccess.h> |
| @@ -943,6 +944,13 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, |
| return -EPERM; |
| |
| /* |
| + * kexec can be used to circumvent module loading restrictions, so |
| + * prevent loading in that case |
| + */ |
| + if (secure_modules()) |
| + return -EPERM; |
| + |
| + /* |
| * Verify we have a legal set of flags |
| * This leaves us room for future extensions. |
| */ |
| -- |
| 1.8.3.1 |
| |
| |
| From d0e3cb2c13dc9634849ddacf75b6f0d94147516a Mon Sep 17 00:00:00 2001 |
| From: Matthew Garrett <matthew.garrett@nebula.com> |
| Date: Tue, 3 Sep 2013 11:23:29 -0400 |
| Subject: [PATCH 09/14] uswsusp: Disable when module loading is restricted |
| |
| uswsusp allows a user process to dump and then restore kernel state, which |
| makes it possible to avoid module loading restrictions. Prevent this when |
| any restrictions have been imposed on loading modules. |
| |
| Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com> |
| |
| kernel/power/user.c | 4 ++++ |
| 1 file changed, 4 insertions(+) |
| |
| diff --git a/kernel/power/user.c b/kernel/power/user.c |
| index 957f061..e570609d 100644 |
| |
| |
| @@ -24,6 +24,7 @@ |
| #include <linux/console.h> |
| #include <linux/cpu.h> |
| #include <linux/freezer.h> |
| +#include <linux/module.h> |
| |
| #include <asm/uaccess.h> |
| |
| @@ -49,6 +50,9 @@ static int snapshot_open(struct inode *inode, struct file *filp) |
| struct snapshot_data *data; |
| int error; |
| |
| + if (secure_modules()) |
| + return -EPERM; |
| + |
| lock_system_sleep(); |
| |
| if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { |
| -- |
| 1.8.3.1 |
| |
| |
| From b238417ed3c5a0b21bbfcac84f6c70011b8977c0 Mon Sep 17 00:00:00 2001 |
| From: Matthew Garrett <matthew.garrett@nebula.com> |
| Date: Fri, 8 Feb 2013 11:12:13 -0800 |
| Subject: [PATCH 10/14] x86: Restrict MSR access when module loading is |
| restricted |
| |
| Writing to MSRs should not be allowed if module loading is restricted, |
| since it could lead to execution of arbitrary code in kernel mode. Based |
| on a patch by Kees Cook. |
| |
| Cc: Kees Cook <keescook@chromium.org> |
| Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com> |
| |
| arch/x86/kernel/msr.c | 7 +++++++ |
| 1 file changed, 7 insertions(+) |
| |
| diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c |
| index 05266b5..e2bd647 100644 |
| |
| |
| @@ -103,6 +103,9 @@ static ssize_t msr_write(struct file *file, const char __user *buf, |
| int err = 0; |
| ssize_t bytes = 0; |
| |
| + if (secure_modules()) |
| + return -EPERM; |
| + |
| if (count % 8) |
| return -EINVAL; /* Invalid chunk size */ |
| |
| @@ -150,6 +153,10 @@ static long msr_ioctl(struct file *file, unsigned int ioc, unsigned long arg) |
| err = -EBADF; |
| break; |
| } |
| + if (secure_modules()) { |
| + err = -EPERM; |
| + break; |
| + } |
| if (copy_from_user(®s, uregs, sizeof regs)) { |
| err = -EFAULT; |
| break; |
| -- |
| 1.8.3.1 |
| |
| |
| From c3a9afb3b580b4f721d245fc5d13e378b99b9cd8 Mon Sep 17 00:00:00 2001 |
| From: Matthew Garrett <matthew.garrett@nebula.com> |
| Date: Fri, 9 Aug 2013 18:36:30 -0400 |
| Subject: [PATCH 11/14] Add option to automatically enforce module signatures |
| when in Secure Boot mode |
| |
| UEFI Secure Boot provides a mechanism for ensuring that the firmware will |
| only load signed bootloaders and kernels. Certain use cases may also |
| require that all kernel modules also be signed. Add a configuration option |
| that enforces this automatically when enabled. |
| |
| Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com> |
| |
| Documentation/x86/zero-page.txt | 2 ++ |
| arch/x86/Kconfig | 10 ++++++++++ |
| arch/x86/boot/compressed/eboot.c | 36 +++++++++++++++++++++++++++++++++++ |
| arch/x86/include/uapi/asm/bootparam.h | 3 ++- |
| arch/x86/kernel/setup.c | 6 ++++++ |
| include/linux/module.h | 6 ++++++ |
| kernel/module.c | 7 +++++++ |
| 7 files changed, 69 insertions(+), 1 deletion(-) |
| |
| diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt |
| index 199f453..ec38acf 100644 |
| |
| |
| @@ -30,6 +30,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 Secure boot is enabled in the firmware |
| 1EF/001 ALL sentinel Used to detect broken bootloaders |
| 290/040 ALL edd_mbr_sig_buffer EDD MBR signatures |
| 2D0/A00 ALL e820_map E820 memory map table |
| diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig |
| index 725e157..fe212ef 100644 |
| |
| |
| @@ -1604,6 +1604,16 @@ config EFI_STUB |
| |
| See Documentation/efi-stub.txt for more information. |
| |
| +config EFI_SECURE_BOOT_SIG_ENFORCE |
| + def_bool n |
| + prompt "Force module signing when UEFI Secure Boot is enabled" |
| + ---help--- |
| + UEFI Secure Boot provides a mechanism for ensuring that the |
| + firmware will only load signed bootloaders and kernels. Certain |
| + use cases may also require that all kernel modules also be signed. |
| + Say Y here to automatically enable module signature enforcement |
| + when a system boots with UEFI Secure Boot enabled. |
| + |
| config SECCOMP |
| def_bool y |
| prompt "Enable seccomp to safely compute untrusted bytecode" |
| diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c |
| index a7677ba..4e172e9 100644 |
| |
| |
| @@ -12,6 +12,7 @@ |
| #include <asm/efi.h> |
| #include <asm/setup.h> |
| #include <asm/desc.h> |
| +#include <asm/bootparam_utils.h> |
| |
| #undef memcpy /* Use memcpy from misc.c */ |
| |
| @@ -741,6 +742,37 @@ free_mem_map: |
| } |
| |
| |
| +static int get_secure_boot(void) |
| +{ |
| + 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; |
| +} |
| + |
| + |
| /* |
| * On success we return a pointer to a boot_params structure, and NULL |
| * on failure. |
| @@ -760,6 +792,10 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, |
| if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) |
| goto fail; |
| |
| + sanitize_boot_params(boot_params); |
| + |
| + boot_params->secure_boot = get_secure_boot(); |
| + |
| setup_graphics(boot_params); |
| |
| setup_efi_pci(boot_params); |
| diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h |
| index 9c3733c..a7ba210 100644 |
| |
| |
| @@ -131,7 +131,8 @@ struct boot_params { |
| __u8 eddbuf_entries; /* 0x1e9 */ |
| __u8 edd_mbr_sig_buf_entries; /* 0x1ea */ |
| __u8 kbd_status; /* 0x1eb */ |
| - __u8 _pad5[3]; /* 0x1ec */ |
| + __u8 secure_boot; /* 0x1ec */ |
| + __u8 _pad5[2]; /* 0x1ed */ |
| /* |
| * The sentinel is set to a nonzero value (0xff) in header.S. |
| * |
| diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c |
| index 918d489..fe429c1 100644 |
| |
| |
| @@ -1127,6 +1127,12 @@ void __init setup_arch(char **cmdline_p) |
| |
| io_delay_init(); |
| |
| +#ifdef CONFIG_EFI_SECURE_BOOT_SIG_ENFORCE |
| + if (boot_params.secure_boot) { |
| + enforce_signed_modules(); |
| + } |
| +#endif |
| + |
| /* |
| * Parse the ACPI tables for possible boot-time SMP configuration. |
| */ |
| diff --git a/include/linux/module.h b/include/linux/module.h |
| index de97e77..d69fe19 100644 |
| |
| |
| @@ -190,6 +190,12 @@ const struct exception_table_entry *search_exception_tables(unsigned long add); |
| |
| struct notifier_block; |
| |
| +#ifdef CONFIG_MODULE_SIG |
| +extern void enforce_signed_modules(void); |
| +#else |
| +static inline void enforce_signed_modules(void) {}; |
| +#endif |
| + |
| #ifdef CONFIG_MODULES |
| |
| extern int modules_disabled; /* for sysctl */ |
| diff --git a/kernel/module.c b/kernel/module.c |
| index 81206c1..e1428f0 100644 |
| |
| |
| @@ -3861,6 +3861,13 @@ void module_layout(struct module *mod, |
| EXPORT_SYMBOL(module_layout); |
| #endif |
| |
| +#ifdef CONFIG_MODULE_SIG |
| +void enforce_signed_modules(void) |
| +{ |
| + sig_enforce = true; |
| +} |
| +#endif |
| + |
| bool secure_modules(void) |
| { |
| #ifdef CONFIG_MODULE_SIG |
| -- |
| 1.8.3.1 |
| |
| |
| From 27a1aa77c7fbaaae8c6a776190a38dcbf3c3d6d2 Mon Sep 17 00:00:00 2001 |
| From: Josh Boyer <jwboyer@redhat.com> |
| Date: Tue, 5 Feb 2013 19:25:05 -0500 |
| Subject: [PATCH 12/14] efi: Disable secure boot if shim is in insecure mode |
| |
| A user can manually tell the shim boot loader to disable validation of |
| images it loads. When a user does this, it creates a UEFI variable called |
| MokSBState that does not have the runtime attribute set. Given that the |
| user explicitly disabled validation, we can honor that and not enable |
| secure boot mode if that variable is set. |
| |
| Signed-off-by: Josh Boyer <jwboyer@redhat.com> |
| |
| arch/x86/boot/compressed/eboot.c | 20 +++++++++++++++++++- |
| 1 file changed, 19 insertions(+), 1 deletion(-) |
| |
| diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c |
| index 4e172e9..4905f4d 100644 |
| |
| |
| @@ -744,8 +744,9 @@ free_mem_map: |
| |
| static int get_secure_boot(void) |
| { |
| - u8 sb, setup; |
| + u8 sb, setup, moksbstate; |
| unsigned long datasize = sizeof(sb); |
| + u32 attr; |
| efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; |
| efi_status_t status; |
| |
| @@ -769,6 +770,23 @@ static int get_secure_boot(void) |
| if (setup == 1) |
| return 0; |
| |
| + /* See if a user has put shim into insecure_mode. If so, and the variable |
| + * doesn't have the runtime attribute set, we might as well honor that. |
| + */ |
| + var_guid = EFI_SHIM_LOCK_GUID; |
| + status = efi_call_phys5(sys_table->runtime->get_variable, |
| + L"MokSBState", &var_guid, &attr, &datasize, |
| + &moksbstate); |
| + |
| + /* If it fails, we don't care why. Default to secure */ |
| + if (status != EFI_SUCCESS) |
| + return 1; |
| + |
| + if (!(attr & EFI_VARIABLE_RUNTIME_ACCESS)) { |
| + if (moksbstate == 1) |
| + return 0; |
| + } |
| + |
| return 1; |
| } |
| |
| -- |
| 1.8.3.1 |
| |
| |
| From 2a445ca2c187da4497ef5f68f111574fd2b0d419 Mon Sep 17 00:00:00 2001 |
| From: Josh Boyer <jwboyer@fedoraproject.org> |
| Date: Tue, 27 Aug 2013 13:28:43 -0400 |
| Subject: [PATCH 13/14] efi: Make EFI_SECURE_BOOT_SIG_ENFORCE depend on EFI |
| |
| The functionality of the config option is dependent upon the platform being |
| UEFI based. Reflect this in the config deps. |
| |
| Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org> |
| |
| arch/x86/Kconfig | 3 ++- |
| 1 file changed, 2 insertions(+), 1 deletion(-) |
| |
| diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig |
| index fe212ef..bf83fd3 100644 |
| |
| |
| @@ -1605,7 +1605,8 @@ config EFI_STUB |
| See Documentation/efi-stub.txt for more information. |
| |
| config EFI_SECURE_BOOT_SIG_ENFORCE |
| - def_bool n |
| + def_bool n |
| + depends on EFI |
| prompt "Force module signing when UEFI Secure Boot is enabled" |
| ---help--- |
| UEFI Secure Boot provides a mechanism for ensuring that the |
| -- |
| 1.8.3.1 |
| |
| |
| From b1c533cc1d1ca7a03497cc4f2e1b029bde95633c Mon Sep 17 00:00:00 2001 |
| From: Josh Boyer <jwboyer@fedoraproject.org> |
| Date: Tue, 27 Aug 2013 13:33:03 -0400 |
| Subject: [PATCH 14/14] efi: Add EFI_SECURE_BOOT bit |
| |
| UEFI machines can be booted in Secure Boot mode. Add a EFI_SECURE_BOOT bit |
| for use with efi_enabled. |
| |
| Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org> |
| |
| arch/x86/kernel/setup.c | 2 ++ |
| include/linux/efi.h | 1 + |
| 2 files changed, 3 insertions(+) |
| |
| diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c |
| index fe429c1..469fbf0 100644 |
| |
| |
| @@ -1129,7 +1129,9 @@ void __init setup_arch(char **cmdline_p) |
| |
| #ifdef CONFIG_EFI_SECURE_BOOT_SIG_ENFORCE |
| if (boot_params.secure_boot) { |
| + set_bit(EFI_SECURE_BOOT, &x86_efi_facility); |
| enforce_signed_modules(); |
| + pr_info("Secure boot enabled\n"); |
| } |
| #endif |
| |
| diff --git a/include/linux/efi.h b/include/linux/efi.h |
| index bc5687d..b010a2e 100644 |
| |
| |
| @@ -653,6 +653,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.3.1 |
| |