c9d9c5a
From 17832506ee9b52bc8e00c2ec89b49257998171ed Mon Sep 17 00:00:00 2001
c9d9c5a
From: Matthew Garrett <matthew.garrett@nebula.com>
c9d9c5a
Date: Mon, 19 Aug 2013 13:26:02 -0400
c9d9c5a
Subject: [PATCH 01/13] Add secure_modules() call
c9d9c5a
c9d9c5a
Provide a single call to allow kernel code to determine whether the system
c9d9c5a
has been configured to either disable module loading entirely or to load
c9d9c5a
only modules signed with a trusted key.
c9d9c5a
c9d9c5a
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
c9d9c5a
---
c9d9c5a
 include/linux/module.h |  7 +++++++
c9d9c5a
 kernel/module.c        | 10 ++++++++++
c9d9c5a
 2 files changed, 17 insertions(+)
c9d9c5a
c9d9c5a
diff --git a/include/linux/module.h b/include/linux/module.h
c9d9c5a
index 46f1ea0..0c266b2 100644
c9d9c5a
--- a/include/linux/module.h
c9d9c5a
+++ b/include/linux/module.h
c9d9c5a
@@ -509,6 +509,8 @@ int unregister_module_notifier(struct notifier_block * nb);
c9d9c5a
 
c9d9c5a
 extern void print_modules(void);
c9d9c5a
 
c9d9c5a
+extern bool secure_modules(void);
c9d9c5a
+
c9d9c5a
 #else /* !CONFIG_MODULES... */
c9d9c5a
 
c9d9c5a
 /* Given an address, look for it in the exception tables. */
c9d9c5a
@@ -619,6 +621,11 @@ static inline int unregister_module_notifier(struct notifier_block * nb)
c9d9c5a
 static inline void print_modules(void)
c9d9c5a
 {
c9d9c5a
 }
c9d9c5a
+
c9d9c5a
+static inline bool secure_modules(void)
c9d9c5a
+{
c9d9c5a
+	return false;
c9d9c5a
+}
c9d9c5a
 #endif /* CONFIG_MODULES */
c9d9c5a
 
c9d9c5a
 #ifdef CONFIG_SYSFS
c9d9c5a
diff --git a/kernel/module.c b/kernel/module.c
c9d9c5a
index 2069158..499ee57 100644
c9d9c5a
--- a/kernel/module.c
c9d9c5a
+++ b/kernel/module.c
c9d9c5a
@@ -3852,3 +3852,13 @@ void module_layout(struct module *mod,
c9d9c5a
 }
c9d9c5a
 EXPORT_SYMBOL(module_layout);
c9d9c5a
 #endif
c9d9c5a
+
c9d9c5a
+bool secure_modules(void)
c9d9c5a
+{
c9d9c5a
+#ifdef CONFIG_MODULE_SIG
c9d9c5a
+	return (sig_enforce || modules_disabled);
c9d9c5a
+#else
c9d9c5a
+	return modules_disabled;
c9d9c5a
+#endif
c9d9c5a
+}
c9d9c5a
+EXPORT_SYMBOL_GPL(secure_modules);
c9d9c5a
-- 
c9d9c5a
1.8.3.1
c9d9c5a
c9d9c5a
c9d9c5a
From e347503648ace6a4b71dfb566365f1aa19657746 Mon Sep 17 00:00:00 2001
c9d9c5a
From: Matthew Garrett <matthew.garrett@nebula.com>
c9d9c5a
Date: Mon, 19 Aug 2013 13:26:03 -0400
c9d9c5a
Subject: [PATCH 02/13] PCI: Lock down BAR access when module security is
c9d9c5a
 enabled
c9d9c5a
c9d9c5a
Any hardware that can potentially generate DMA has to be locked down from
c9d9c5a
userspace in order to avoid it being possible for an attacker to modify
c9d9c5a
kernel code, allowing them to circumvent disabled module loading or module
c9d9c5a
signing. Default to paranoid - in future we can potentially relax this for
c9d9c5a
sufficiently IOMMU-isolated devices.
c9d9c5a
c9d9c5a
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
c9d9c5a
---
c9d9c5a
 drivers/pci/pci-sysfs.c | 10 ++++++++++
c9d9c5a
 drivers/pci/proc.c      |  8 +++++++-
c9d9c5a
 drivers/pci/syscall.c   |  3 ++-
c9d9c5a
 3 files changed, 19 insertions(+), 2 deletions(-)
c9d9c5a
c9d9c5a
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
c9d9c5a
index c0dbe1f..cd4e35f 100644
c9d9c5a
--- a/drivers/pci/pci-sysfs.c
c9d9c5a
+++ b/drivers/pci/pci-sysfs.c
c9d9c5a
@@ -29,6 +29,7 @@
c9d9c5a
 #include <linux/slab.h>
c9d9c5a
 #include <linux/vgaarb.h>
c9d9c5a
 #include <linux/pm_runtime.h>
c9d9c5a
+#include <linux/module.h>
c9d9c5a
 #include "pci.h"
c9d9c5a
 
c9d9c5a
 static int sysfs_initialized;	/* = 0 */
c9d9c5a
@@ -624,6 +625,9 @@ pci_write_config(struct file* filp, struct kobject *kobj,
c9d9c5a
 	loff_t init_off = off;
c9d9c5a
 	u8 *data = (u8*) buf;
c9d9c5a
 
c9d9c5a
+	if (secure_modules())
c9d9c5a
+		return -EPERM;
c9d9c5a
+
c9d9c5a
 	if (off > dev->cfg_size)
c9d9c5a
 		return 0;
c9d9c5a
 	if (off + count > dev->cfg_size) {
c9d9c5a
@@ -930,6 +934,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
c9d9c5a
 	resource_size_t start, end;
c9d9c5a
 	int i;
c9d9c5a
 
c9d9c5a
+	if (secure_modules())
c9d9c5a
+		return -EPERM;
c9d9c5a
+
c9d9c5a
 	for (i = 0; i < PCI_ROM_RESOURCE; i++)
c9d9c5a
 		if (res == &pdev->resource[i])
c9d9c5a
 			break;
c9d9c5a
@@ -1037,6 +1044,9 @@ pci_write_resource_io(struct file *filp, struct kobject *kobj,
c9d9c5a
 		      struct bin_attribute *attr, char *buf,
c9d9c5a
 		      loff_t off, size_t count)
c9d9c5a
 {
c9d9c5a
+	if (secure_modules())
c9d9c5a
+		return -EPERM;
c9d9c5a
+
c9d9c5a
 	return pci_resource_io(filp, kobj, attr, buf, off, count, true);
c9d9c5a
 }
c9d9c5a
 
c9d9c5a
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
c9d9c5a
index cdc7836..e3d498b 100644
c9d9c5a
--- a/drivers/pci/proc.c
c9d9c5a
+++ b/drivers/pci/proc.c
c9d9c5a
@@ -117,6 +117,9 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
c9d9c5a
 	int size = dev->cfg_size;
c9d9c5a
 	int cnt;
c9d9c5a
 
c9d9c5a
+	if (secure_modules())
c9d9c5a
+		return -EPERM;
c9d9c5a
+
c9d9c5a
 	if (pos >= size)
c9d9c5a
 		return 0;
c9d9c5a
 	if (nbytes >= size)
c9d9c5a
@@ -196,6 +199,9 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
c9d9c5a
 #endif /* HAVE_PCI_MMAP */
c9d9c5a
 	int ret = 0;
c9d9c5a
 
c9d9c5a
+	if (secure_modules())
c9d9c5a
+		return -EPERM;
c9d9c5a
+
c9d9c5a
 	switch (cmd) {
c9d9c5a
 	case PCIIOC_CONTROLLER:
c9d9c5a
 		ret = pci_domain_nr(dev->bus);
c9d9c5a
@@ -234,7 +240,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
c9d9c5a
 	struct pci_filp_private *fpriv = file->private_data;
c9d9c5a
 	int i, ret;
c9d9c5a
 
c9d9c5a
-	if (!capable(CAP_SYS_RAWIO))
c9d9c5a
+	if (!capable(CAP_SYS_RAWIO) || secure_modules())
c9d9c5a
 		return -EPERM;
c9d9c5a
 
c9d9c5a
 	/* Make sure the caller is mapping a real resource for this device */
c9d9c5a
diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c
c9d9c5a
index e1c1ec5..bffbf71 100644
c9d9c5a
--- a/drivers/pci/syscall.c
c9d9c5a
+++ b/drivers/pci/syscall.c
c9d9c5a
@@ -10,6 +10,7 @@
c9d9c5a
 #include <linux/errno.h>
c9d9c5a
 #include <linux/pci.h>
c9d9c5a
 #include <linux/syscalls.h>
c9d9c5a
+#include <linux/module.h>
c9d9c5a
 #include <asm/uaccess.h>
c9d9c5a
 #include "pci.h"
c9d9c5a
 
c9d9c5a
@@ -92,7 +93,7 @@ SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn,
c9d9c5a
 	u32 dword;
c9d9c5a
 	int err = 0;
c9d9c5a
 
c9d9c5a
-	if (!capable(CAP_SYS_ADMIN))
c9d9c5a
+	if (!capable(CAP_SYS_ADMIN) || secure_modules())
c9d9c5a
 		return -EPERM;
c9d9c5a
 
c9d9c5a
 	dev = pci_get_bus_and_slot(bus, dfn);
c9d9c5a
-- 
c9d9c5a
1.8.3.1
c9d9c5a
c9d9c5a
c9d9c5a
From b846e3958d3f4ff875ec958efba8b681ccbae04e Mon Sep 17 00:00:00 2001
c9d9c5a
From: Matthew Garrett <matthew.garrett@nebula.com>
c9d9c5a
Date: Mon, 19 Aug 2013 13:26:04 -0400
c9d9c5a
Subject: [PATCH 03/13] x86: Lock down IO port access when module security is
c9d9c5a
 enabled
c9d9c5a
c9d9c5a
IO port access would permit users to gain access to PCI configuration
c9d9c5a
registers, which in turn (on a lot of hardware) give access to MMIO register
c9d9c5a
space. This would potentially permit root to trigger arbitrary DMA, so lock
c9d9c5a
it down by default.
c9d9c5a
c9d9c5a
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
c9d9c5a
---
c9d9c5a
 arch/x86/kernel/ioport.c | 5 +++--
c9d9c5a
 drivers/char/mem.c       | 4 ++++
c9d9c5a
 2 files changed, 7 insertions(+), 2 deletions(-)
c9d9c5a
c9d9c5a
diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c
c9d9c5a
index 4ddaf66..00b4403 100644
c9d9c5a
--- a/arch/x86/kernel/ioport.c
c9d9c5a
+++ b/arch/x86/kernel/ioport.c
c9d9c5a
@@ -15,6 +15,7 @@
c9d9c5a
 #include <linux/thread_info.h>
c9d9c5a
 #include <linux/syscalls.h>
c9d9c5a
 #include <linux/bitmap.h>
c9d9c5a
+#include <linux/module.h>
c9d9c5a
 #include <asm/syscalls.h>
c9d9c5a
 
c9d9c5a
 /*
c9d9c5a
@@ -28,7 +29,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
c9d9c5a
 
c9d9c5a
 	if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
c9d9c5a
 		return -EINVAL;
c9d9c5a
-	if (turn_on && !capable(CAP_SYS_RAWIO))
c9d9c5a
+	if (turn_on && (!capable(CAP_SYS_RAWIO) || secure_modules()))
c9d9c5a
 		return -EPERM;
c9d9c5a
 
c9d9c5a
 	/*
c9d9c5a
@@ -103,7 +104,7 @@ SYSCALL_DEFINE1(iopl, unsigned int, level)
c9d9c5a
 		return -EINVAL;
c9d9c5a
 	/* Trying to gain more privileges? */
c9d9c5a
 	if (level > old) {
c9d9c5a
-		if (!capable(CAP_SYS_RAWIO))
c9d9c5a
+		if (!capable(CAP_SYS_RAWIO) || secure_modules())
c9d9c5a
 			return -EPERM;
c9d9c5a
 	}
c9d9c5a
 	regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12);
c9d9c5a
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
c9d9c5a
index f895a8c..1af8664 100644
c9d9c5a
--- a/drivers/char/mem.c
c9d9c5a
+++ b/drivers/char/mem.c
c9d9c5a
@@ -28,6 +28,7 @@
c9d9c5a
 #include <linux/export.h>
c9d9c5a
 #include <linux/io.h>
c9d9c5a
 #include <linux/aio.h>
c9d9c5a
+#include <linux/module.h>
c9d9c5a
 
c9d9c5a
 #include <asm/uaccess.h>
c9d9c5a
 
c9d9c5a
@@ -563,6 +564,9 @@ static ssize_t write_port(struct file *file, const char __user *buf,
c9d9c5a
 	unsigned long i = *ppos;
c9d9c5a
 	const char __user *tmp = buf;
c9d9c5a
 
c9d9c5a
+	if (secure_modules())
c9d9c5a
+		return -EPERM;
c9d9c5a
+
c9d9c5a
 	if (!access_ok(VERIFY_READ, buf, count))
c9d9c5a
 		return -EFAULT;
c9d9c5a
 	while (count-- > 0 && i < 65536) {
c9d9c5a
-- 
c9d9c5a
1.8.3.1
c9d9c5a
c9d9c5a
c9d9c5a
From 8c11e2cc989eece2d4978cfbc83f9b898f3cd1aa Mon Sep 17 00:00:00 2001
c9d9c5a
From: Matthew Garrett <matthew.garrett@nebula.com>
c9d9c5a
Date: Mon, 19 Aug 2013 13:26:05 -0400
c9d9c5a
Subject: [PATCH 04/13] ACPI: Limit access to custom_method
c9d9c5a
c9d9c5a
custom_method effectively allows arbitrary access to system memory, making
c9d9c5a
it possible for an attacker to circumvent restrictions on module loading.
c9d9c5a
Disable it if any such restrictions have been enabled.
c9d9c5a
c9d9c5a
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
c9d9c5a
---
c9d9c5a
 drivers/acpi/custom_method.c | 4 ++++
c9d9c5a
 1 file changed, 4 insertions(+)
c9d9c5a
c9d9c5a
diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c
c9d9c5a
index 12b62f2..55a013f 100644
c9d9c5a
--- a/drivers/acpi/custom_method.c
c9d9c5a
+++ b/drivers/acpi/custom_method.c
c9d9c5a
@@ -7,6 +7,7 @@
c9d9c5a
 #include <linux/kernel.h>
c9d9c5a
 #include <linux/uaccess.h>
c9d9c5a
 #include <linux/debugfs.h>
c9d9c5a
+#include <linux/module.h>
c9d9c5a
 #include <acpi/acpi_drivers.h>
c9d9c5a
 
c9d9c5a
 #include "internal.h"
c9d9c5a
@@ -29,6 +30,9 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf,
c9d9c5a
 	struct acpi_table_header table;
c9d9c5a
 	acpi_status status;
c9d9c5a
 
c9d9c5a
+	if (secure_modules())
c9d9c5a
+		return -EPERM;
c9d9c5a
+
c9d9c5a
 	if (!(*ppos)) {
c9d9c5a
 		/* parse the table header to get the table length */
c9d9c5a
 		if (count <= sizeof(struct acpi_table_header))
c9d9c5a
-- 
c9d9c5a
1.8.3.1
c9d9c5a
c9d9c5a
c9d9c5a
From 968ccfb32df5d5c9673c57641ebf90b25c0df880 Mon Sep 17 00:00:00 2001
c9d9c5a
From: Matthew Garrett <matthew.garrett@nebula.com>
c9d9c5a
Date: Mon, 19 Aug 2013 13:26:06 -0400
c9d9c5a
Subject: [PATCH 05/13] asus-wmi: Restrict debugfs interface when module
c9d9c5a
 loading is restricted
c9d9c5a
c9d9c5a
We have no way of validating what all of the Asus WMI methods do on a
c9d9c5a
given machine, and there's a risk that some will allow hardware state to
c9d9c5a
be manipulated in such a way that arbitrary code can be executed in the
c9d9c5a
kernel, circumventing module loading restrictions. Prevent that if any of
c9d9c5a
these features are enabled.
c9d9c5a
c9d9c5a
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
c9d9c5a
---
c9d9c5a
 drivers/platform/x86/asus-wmi.c | 9 +++++++++
c9d9c5a
 1 file changed, 9 insertions(+)
c9d9c5a
c9d9c5a
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
c9d9c5a
index 19c313b..db18ef66 100644
c9d9c5a
--- a/drivers/platform/x86/asus-wmi.c
c9d9c5a
+++ b/drivers/platform/x86/asus-wmi.c
c9d9c5a
@@ -1618,6 +1618,9 @@ static int show_dsts(struct seq_file *m, void *data)
c9d9c5a
 	int err;
c9d9c5a
 	u32 retval = -1;
c9d9c5a
 
c9d9c5a
+	if (secure_modules())
c9d9c5a
+		return -EPERM;
c9d9c5a
+
c9d9c5a
 	err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval);
c9d9c5a
 
c9d9c5a
 	if (err < 0)
c9d9c5a
@@ -1634,6 +1637,9 @@ static int show_devs(struct seq_file *m, void *data)
c9d9c5a
 	int err;
c9d9c5a
 	u32 retval = -1;
c9d9c5a
 
c9d9c5a
+	if (secure_modules())
c9d9c5a
+		return -EPERM;
c9d9c5a
+
c9d9c5a
 	err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param,
c9d9c5a
 				    &retval);
c9d9c5a
 
c9d9c5a
@@ -1658,6 +1664,9 @@ static int show_call(struct seq_file *m, void *data)
c9d9c5a
 	union acpi_object *obj;
c9d9c5a
 	acpi_status status;
c9d9c5a
 
c9d9c5a
+	if (secure_modules())
c9d9c5a
+		return -EPERM;
c9d9c5a
+
c9d9c5a
 	status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID,
c9d9c5a
 				     1, asus->debug.method_id,
c9d9c5a
 				     &input, &output);
c9d9c5a
-- 
c9d9c5a
1.8.3.1
c9d9c5a
c9d9c5a
c9d9c5a
From e492d0a80bb591c34391757f97fc5aa8eb198e4f Mon Sep 17 00:00:00 2001
c9d9c5a
From: Matthew Garrett <matthew.garrett@nebula.com>
c9d9c5a
Date: Mon, 19 Aug 2013 13:26:07 -0400
c9d9c5a
Subject: [PATCH 06/13] Restrict /dev/mem and /dev/kmem when module loading is
c9d9c5a
 restricted
c9d9c5a
c9d9c5a
Allowing users to write to address space makes it possible for the kernel
c9d9c5a
to be subverted, avoiding module loading restrictions. Prevent this when
c9d9c5a
any restrictions have been imposed on loading modules.
c9d9c5a
c9d9c5a
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
c9d9c5a
---
c9d9c5a
 drivers/char/mem.c | 6 ++++++
c9d9c5a
 1 file changed, 6 insertions(+)
c9d9c5a
c9d9c5a
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
c9d9c5a
index 1af8664..61406c8 100644
c9d9c5a
--- a/drivers/char/mem.c
c9d9c5a
+++ b/drivers/char/mem.c
c9d9c5a
@@ -159,6 +159,9 @@ static ssize_t write_mem(struct file *file, const char __user *buf,
c9d9c5a
 	unsigned long copied;
c9d9c5a
 	void *ptr;
c9d9c5a
 
c9d9c5a
+	if (secure_modules())
c9d9c5a
+		return -EPERM;
c9d9c5a
+
c9d9c5a
 	if (!valid_phys_addr_range(p, count))
c9d9c5a
 		return -EFAULT;
c9d9c5a
 
c9d9c5a
@@ -497,6 +500,9 @@ static ssize_t write_kmem(struct file *file, const char __user *buf,
c9d9c5a
 	char *kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
c9d9c5a
 	int err = 0;
c9d9c5a
 
c9d9c5a
+	if (secure_modules())
c9d9c5a
+		return -EPERM;
c9d9c5a
+
c9d9c5a
 	if (p < (unsigned long) high_memory) {
c9d9c5a
 		unsigned long to_write = min_t(unsigned long, count,
c9d9c5a
 					       (unsigned long)high_memory - p);
c9d9c5a
-- 
c9d9c5a
1.8.3.1
c9d9c5a
c9d9c5a
c9d9c5a
From 145913d656bfe8216032b38a576ac150699521e5 Mon Sep 17 00:00:00 2001
c9d9c5a
From: Josh Boyer <jwboyer@redhat.com>
c9d9c5a
Date: Mon, 19 Aug 2013 13:26:08 -0400
c9d9c5a
Subject: [PATCH 07/13] acpi: Ignore acpi_rsdp kernel parameter when module
c9d9c5a
 loading is restricted
c9d9c5a
c9d9c5a
This option allows userspace to pass the RSDP address to the kernel, which
c9d9c5a
makes it possible for a user to circumvent any restrictions imposed on
c9d9c5a
loading modules. Disable it in that case.
c9d9c5a
c9d9c5a
Signed-off-by: Josh Boyer <jwboyer@redhat.com>
c9d9c5a
---
c9d9c5a
 drivers/acpi/osl.c | 3 ++-
c9d9c5a
 1 file changed, 2 insertions(+), 1 deletion(-)
c9d9c5a
c9d9c5a
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
c9d9c5a
index 6ab2c35..e4c4410 100644
c9d9c5a
--- a/drivers/acpi/osl.c
c9d9c5a
+++ b/drivers/acpi/osl.c
c9d9c5a
@@ -45,6 +45,7 @@
c9d9c5a
 #include <linux/list.h>
c9d9c5a
 #include <linux/jiffies.h>
c9d9c5a
 #include <linux/semaphore.h>
c9d9c5a
+#include <linux/module.h>
c9d9c5a
 
c9d9c5a
 #include <asm/io.h>
c9d9c5a
 #include <asm/uaccess.h>
c9d9c5a
@@ -245,7 +246,7 @@ early_param("acpi_rsdp", setup_acpi_rsdp);
c9d9c5a
 acpi_physical_address __init acpi_os_get_root_pointer(void)
c9d9c5a
 {
c9d9c5a
 #ifdef CONFIG_KEXEC
c9d9c5a
-	if (acpi_rsdp)
c9d9c5a
+	if (acpi_rsdp && !secure_modules())
c9d9c5a
 		return acpi_rsdp;
c9d9c5a
 #endif
c9d9c5a
 
c9d9c5a
-- 
c9d9c5a
1.8.3.1
c9d9c5a
c9d9c5a
c9d9c5a
From 012ac79f54ab746114d8276d8858a3df18b10e22 Mon Sep 17 00:00:00 2001
c9d9c5a
From: Matthew Garrett <matthew.garrett@nebula.com>
c9d9c5a
Date: Mon, 19 Aug 2013 13:26:10 -0400
c9d9c5a
Subject: [PATCH 08/13] x86: Restrict MSR access when module loading is
c9d9c5a
 restricted
c9d9c5a
c9d9c5a
Writing to MSRs should not be allowed if module loading is restricted,
c9d9c5a
since it could lead to execution of arbitrary code in kernel mode. Based
c9d9c5a
on a patch by Kees Cook.
c9d9c5a
c9d9c5a
Cc: Kees Cook <keescook@chromium.org>
c9d9c5a
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
c9d9c5a
---
c9d9c5a
 arch/x86/kernel/msr.c | 7 +++++++
c9d9c5a
 1 file changed, 7 insertions(+)
c9d9c5a
c9d9c5a
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
c9d9c5a
index 88458fa..d08f7e3 100644
c9d9c5a
--- a/arch/x86/kernel/msr.c
c9d9c5a
+++ b/arch/x86/kernel/msr.c
c9d9c5a
@@ -103,6 +103,9 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
c9d9c5a
 	int err = 0;
c9d9c5a
 	ssize_t bytes = 0;
c9d9c5a
 
c9d9c5a
+	if (secure_modules())
c9d9c5a
+		return -EPERM;
c9d9c5a
+
c9d9c5a
 	if (count % 8)
c9d9c5a
 		return -EINVAL;	/* Invalid chunk size */
c9d9c5a
 
c9d9c5a
@@ -150,6 +153,10 @@ static long msr_ioctl(struct file *file, unsigned int ioc, unsigned long arg)
c9d9c5a
 			err = -EBADF;
c9d9c5a
 			break;
c9d9c5a
 		}
c9d9c5a
+		if (secure_modules()) {
c9d9c5a
+			err = -EPERM;
c9d9c5a
+			break;
c9d9c5a
+		}
c9d9c5a
 		if (copy_from_user(&regs, uregs, sizeof regs)) {
c9d9c5a
 			err = -EFAULT;
c9d9c5a
 			break;
c9d9c5a
-- 
c9d9c5a
1.8.3.1
c9d9c5a
c9d9c5a
c9d9c5a
From a44d2968968fd667c8cbeba7c043f674d17e7ce7 Mon Sep 17 00:00:00 2001
c9d9c5a
From: Matthew Garrett <matthew.garrett@nebula.com>
c9d9c5a
Date: Mon, 19 Aug 2013 13:26:09 -0400
c9d9c5a
Subject: [PATCH 09/13] kexec: Disable at runtime if the kernel enforces module
c9d9c5a
 loading restrictions
c9d9c5a
c9d9c5a
kexec permits the loading and execution of arbitrary code in ring 0, which
c9d9c5a
is something that module signing enforcement is meant to prevent. It makes
c9d9c5a
sense to disable kexec in this situation.
c9d9c5a
c9d9c5a
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
c9d9c5a
---
c9d9c5a
 kernel/kexec.c | 4 ++++
c9d9c5a
 1 file changed, 4 insertions(+)
c9d9c5a
c9d9c5a
diff --git a/kernel/kexec.c b/kernel/kexec.c
c9d9c5a
index 59f7b55..1a7690f 100644
c9d9c5a
--- a/kernel/kexec.c
c9d9c5a
+++ b/kernel/kexec.c
c9d9c5a
@@ -32,6 +32,7 @@
c9d9c5a
 #include <linux/vmalloc.h>
c9d9c5a
 #include <linux/swap.h>
c9d9c5a
 #include <linux/syscore_ops.h>
c9d9c5a
+#include <linux/module.h>
c9d9c5a
 
c9d9c5a
 #include <asm/page.h>
c9d9c5a
 #include <asm/uaccess.h>
c9d9c5a
@@ -1645,6 +1646,9 @@ int kernel_kexec(void)
c9d9c5a
 		goto Unlock;
c9d9c5a
 	}
c9d9c5a
 
c9d9c5a
+	if (secure_modules())
c9d9c5a
+		return -EPERM;
c9d9c5a
+
c9d9c5a
 #ifdef CONFIG_KEXEC_JUMP
c9d9c5a
 	if (kexec_image->preserve_context) {
c9d9c5a
 		lock_system_sleep();
c9d9c5a
-- 
c9d9c5a
1.8.3.1
c9d9c5a
c9d9c5a
c9d9c5a
From f8f879da5dcc060a990a3b660aa5f340429cc4ed Mon Sep 17 00:00:00 2001
c9d9c5a
From: Matthew Garrett <matthew.garrett@nebula.com>
c9d9c5a
Date: Mon, 19 Aug 2013 13:26:11 -0400
c9d9c5a
Subject: [PATCH 10/13] Add option to automatically enforce module signatures
c9d9c5a
 when in Secure Boot mode
c9d9c5a
c9d9c5a
UEFI Secure Boot provides a mechanism for ensuring that the firmware will
c9d9c5a
only load signed bootloaders and kernels. Certain use cases may also
c9d9c5a
require that all kernel modules also be signed. Add a configuration option
c9d9c5a
that enforces this automatically when enabled.
c9d9c5a
c9d9c5a
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
c9d9c5a
Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org>
c9d9c5a
---
c9d9c5a
 Documentation/x86/zero-page.txt        |  2 ++
c9d9c5a
 arch/x86/Kconfig                       | 10 ++++++++++
c9d9c5a
 arch/x86/boot/compressed/eboot.c       | 33 +++++++++++++++++++++++++++++++++
c9d9c5a
 arch/x86/include/asm/bootparam_utils.h |  8 ++++++--
c9d9c5a
 arch/x86/include/uapi/asm/bootparam.h  |  3 ++-
c9d9c5a
 arch/x86/kernel/setup.c                |  6 ++++++
c9d9c5a
 include/linux/module.h                 |  6 ++++++
c9d9c5a
 kernel/module.c                        |  7 +++++++
c9d9c5a
 8 files changed, 72 insertions(+), 3 deletions(-)
c9d9c5a
c9d9c5a
diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt
c9d9c5a
index 199f453..ec38acf 100644
c9d9c5a
--- a/Documentation/x86/zero-page.txt
c9d9c5a
+++ b/Documentation/x86/zero-page.txt
c9d9c5a
@@ -30,6 +30,8 @@ Offset	Proto	Name		Meaning
c9d9c5a
 1E9/001	ALL	eddbuf_entries	Number of entries in eddbuf (below)
c9d9c5a
 1EA/001	ALL	edd_mbr_sig_buf_entries	Number of entries in edd_mbr_sig_buffer
c9d9c5a
 				(below)
c9d9c5a
+1EB/001	ALL     kbd_status      Numlock is enabled
c9d9c5a
+1EC/001	ALL     secure_boot	Secure boot is enabled in the firmware
c9d9c5a
 1EF/001	ALL	sentinel	Used to detect broken bootloaders
c9d9c5a
 290/040	ALL	edd_mbr_sig_buffer EDD MBR signatures
c9d9c5a
 2D0/A00	ALL	e820_map	E820 memory map table
c9d9c5a
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
c9d9c5a
index b32ebf9..6a6c19b 100644
c9d9c5a
--- a/arch/x86/Kconfig
c9d9c5a
+++ b/arch/x86/Kconfig
c9d9c5a
@@ -1581,6 +1581,16 @@ config EFI_STUB
c9d9c5a
 
c9d9c5a
 	  See Documentation/x86/efi-stub.txt for more information.
c9d9c5a
 
c9d9c5a
+config EFI_SECURE_BOOT_SIG_ENFORCE
c9d9c5a
+        def_bool n
c9d9c5a
+	prompt "Force module signing when UEFI Secure Boot is enabled"
c9d9c5a
+	---help---
c9d9c5a
+	  UEFI Secure Boot provides a mechanism for ensuring that the
c9d9c5a
+	  firmware will only load signed bootloaders and kernels. Certain
c9d9c5a
+	  use cases may also require that all kernel modules also be signed.
c9d9c5a
+	  Say Y here to automatically enable module signature enforcement
c9d9c5a
+	  when a system boots with UEFI Secure Boot enabled.
c9d9c5a
+
c9d9c5a
 config SECCOMP
c9d9c5a
 	def_bool y
c9d9c5a
 	prompt "Enable seccomp to safely compute untrusted bytecode"
c9d9c5a
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
c9d9c5a
index b7388a4..145294d 100644
c9d9c5a
--- a/arch/x86/boot/compressed/eboot.c
c9d9c5a
+++ b/arch/x86/boot/compressed/eboot.c
c9d9c5a
@@ -861,6 +861,37 @@ fail:
c9d9c5a
 	return status;
c9d9c5a
 }
c9d9c5a
 
c9d9c5a
+static int get_secure_boot(efi_system_table_t *_table)
c9d9c5a
+{
c9d9c5a
+	u8 sb, setup;
c9d9c5a
+	unsigned long datasize = sizeof(sb);
c9d9c5a
+	efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID;
c9d9c5a
+	efi_status_t status;
c9d9c5a
+
c9d9c5a
+	status = efi_call_phys5(sys_table->runtime->get_variable,
c9d9c5a
+				L"SecureBoot", &var_guid, NULL, &datasize, &sb);
c9d9c5a
+
c9d9c5a
+	if (status != EFI_SUCCESS)
c9d9c5a
+		return 0;
c9d9c5a
+
c9d9c5a
+	if (sb == 0)
c9d9c5a
+		return 0;
c9d9c5a
+
c9d9c5a
+
c9d9c5a
+	status = efi_call_phys5(sys_table->runtime->get_variable,
c9d9c5a
+				L"SetupMode", &var_guid, NULL, &datasize,
c9d9c5a
+				&setup);
c9d9c5a
+
c9d9c5a
+	if (status != EFI_SUCCESS)
c9d9c5a
+		return 0;
c9d9c5a
+
c9d9c5a
+	if (setup == 1)
c9d9c5a
+		return 0;
c9d9c5a
+
c9d9c5a
+	return 1;
c9d9c5a
+}
c9d9c5a
+
c9d9c5a
+
c9d9c5a
 /*
c9d9c5a
  * Because the x86 boot code expects to be passed a boot_params we
c9d9c5a
  * need to create one ourselves (usually the bootloader would create
c9d9c5a
@@ -1169,6 +1200,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
c9d9c5a
 	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
c9d9c5a
 		goto fail;
c9d9c5a
 
c9d9c5a
+	boot_params->secure_boot = get_secure_boot(sys_table);
c9d9c5a
+
c9d9c5a
 	setup_graphics(boot_params);
c9d9c5a
 
c9d9c5a
 	setup_efi_pci(boot_params);
c9d9c5a
diff --git a/arch/x86/include/asm/bootparam_utils.h b/arch/x86/include/asm/bootparam_utils.h
c9d9c5a
index 4a8cb8d..25f9cf1 100644
c9d9c5a
--- a/arch/x86/include/asm/bootparam_utils.h
c9d9c5a
+++ b/arch/x86/include/asm/bootparam_utils.h
c9d9c5a
@@ -38,9 +38,13 @@ static void sanitize_boot_params(struct boot_params *boot_params)
c9d9c5a
 		memset(&boot_params->ext_ramdisk_image, 0,
c9d9c5a
 		       (char *)&boot_params->efi_info -
c9d9c5a
 			(char *)&boot_params->ext_ramdisk_image);
c9d9c5a
-		memset(&boot_params->kbd_status, 0,
c9d9c5a
+		memset(&boot_params->kbd_status, 0, sizeof(boot_params->kbd_status));
c9d9c5a
+		/* don't clear boot_params->secure_boot.  we set that ourselves
c9d9c5a
+		 * earlier.
c9d9c5a
+		 */
c9d9c5a
+		memset(&boot_params->_pad5[0], 0,
c9d9c5a
 		       (char *)&boot_params->hdr -
c9d9c5a
-		       (char *)&boot_params->kbd_status);
c9d9c5a
+		       (char *)&boot_params->_pad5[0]);
c9d9c5a
 		memset(&boot_params->_pad7[0], 0,
c9d9c5a
 		       (char *)&boot_params->edd_mbr_sig_buffer[0] -
c9d9c5a
 			(char *)&boot_params->_pad7[0]);
c9d9c5a
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
c9d9c5a
index c15ddaf..d35da96 100644
c9d9c5a
--- a/arch/x86/include/uapi/asm/bootparam.h
c9d9c5a
+++ b/arch/x86/include/uapi/asm/bootparam.h
c9d9c5a
@@ -131,7 +131,8 @@ struct boot_params {
c9d9c5a
 	__u8  eddbuf_entries;				/* 0x1e9 */
c9d9c5a
 	__u8  edd_mbr_sig_buf_entries;			/* 0x1ea */
c9d9c5a
 	__u8  kbd_status;				/* 0x1eb */
c9d9c5a
-	__u8  _pad5[3];					/* 0x1ec */
c9d9c5a
+	__u8  secure_boot;				/* 0x1ec */
c9d9c5a
+	__u8  _pad5[2];					/* 0x1ec */
c9d9c5a
 	/*
c9d9c5a
 	 * The sentinel is set to a nonzero value (0xff) in header.S.
c9d9c5a
 	 *
c9d9c5a
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
c9d9c5a
index f8ec578..deeb7bc 100644
c9d9c5a
--- a/arch/x86/kernel/setup.c
c9d9c5a
+++ b/arch/x86/kernel/setup.c
c9d9c5a
@@ -1129,6 +1129,12 @@ void __init setup_arch(char **cmdline_p)
c9d9c5a
 
c9d9c5a
 	io_delay_init();
c9d9c5a
 
c9d9c5a
+#ifdef CONFIG_EFI_SECURE_BOOT_SIG_ENFORCE
c9d9c5a
+	if (boot_params.secure_boot) {
c9d9c5a
+		enforce_signed_modules();
c9d9c5a
+	}
c9d9c5a
+#endif
c9d9c5a
+
c9d9c5a
 	/*
c9d9c5a
 	 * Parse the ACPI tables for possible boot-time SMP configuration.
c9d9c5a
 	 */
c9d9c5a
diff --git a/include/linux/module.h b/include/linux/module.h
c9d9c5a
index 0c266b2..5a6374a 100644
c9d9c5a
--- a/include/linux/module.h
c9d9c5a
+++ b/include/linux/module.h
c9d9c5a
@@ -184,6 +184,12 @@ const struct exception_table_entry *search_exception_tables(unsigned long add);
c9d9c5a
 
c9d9c5a
 struct notifier_block;
c9d9c5a
 
c9d9c5a
+#ifdef CONFIG_MODULE_SIG
c9d9c5a
+extern void enforce_signed_modules(void);
c9d9c5a
+#else
c9d9c5a
+static inline void enforce_signed_modules(void) {};
c9d9c5a
+#endif
c9d9c5a
+
c9d9c5a
 #ifdef CONFIG_MODULES
c9d9c5a
 
c9d9c5a
 extern int modules_disabled; /* for sysctl */
c9d9c5a
diff --git a/kernel/module.c b/kernel/module.c
c9d9c5a
index 499ee57..bc7c987 100644
c9d9c5a
--- a/kernel/module.c
c9d9c5a
+++ b/kernel/module.c
c9d9c5a
@@ -3853,6 +3853,13 @@ void module_layout(struct module *mod,
c9d9c5a
 EXPORT_SYMBOL(module_layout);
c9d9c5a
 #endif
c9d9c5a
 
c9d9c5a
+#ifdef CONFIG_MODULE_SIG
c9d9c5a
+void enforce_signed_modules(void)
c9d9c5a
+{
c9d9c5a
+	sig_enforce = true;
c9d9c5a
+}
c9d9c5a
+#endif
c9d9c5a
+
c9d9c5a
 bool secure_modules(void)
c9d9c5a
 {
c9d9c5a
 #ifdef CONFIG_MODULE_SIG
c9d9c5a
-- 
c9d9c5a
1.8.3.1
c9d9c5a
c9d9c5a
c9d9c5a
From b1604407fff69b17b598af03888a9efda0d58f2b Mon Sep 17 00:00:00 2001
c9d9c5a
From: Josh Boyer <jwboyer@redhat.com>
c9d9c5a
Date: Tue, 5 Feb 2013 19:25:05 -0500
c9d9c5a
Subject: [PATCH 11/13] efi: Disable secure boot if shim is in insecure mode
c9d9c5a
c9d9c5a
A user can manually tell the shim boot loader to disable validation of
c9d9c5a
images it loads.  When a user does this, it creates a UEFI variable called
c9d9c5a
MokSBState that does not have the runtime attribute set.  Given that the
c9d9c5a
user explicitly disabled validation, we can honor that and not enable
c9d9c5a
secure boot mode if that variable is set.
c9d9c5a
c9d9c5a
Signed-off-by: Josh Boyer <jwboyer@redhat.com>
c9d9c5a
---
c9d9c5a
 arch/x86/boot/compressed/eboot.c | 20 +++++++++++++++++++-
c9d9c5a
 1 file changed, 19 insertions(+), 1 deletion(-)
c9d9c5a
c9d9c5a
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
c9d9c5a
index 145294d..545d4a6 100644
c9d9c5a
--- a/arch/x86/boot/compressed/eboot.c
c9d9c5a
+++ b/arch/x86/boot/compressed/eboot.c
c9d9c5a
@@ -863,8 +863,9 @@ fail:
c9d9c5a
 
c9d9c5a
 static int get_secure_boot(efi_system_table_t *_table)
c9d9c5a
 {
c9d9c5a
-	u8 sb, setup;
c9d9c5a
+	u8 sb, setup, moksbstate;
c9d9c5a
 	unsigned long datasize = sizeof(sb);
c9d9c5a
+	u32 attr;
c9d9c5a
 	efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID;
c9d9c5a
 	efi_status_t status;
c9d9c5a
 
c9d9c5a
@@ -888,6 +889,23 @@ static int get_secure_boot(efi_system_table_t *_table)
c9d9c5a
 	if (setup == 1)
c9d9c5a
 		return 0;
c9d9c5a
 
c9d9c5a
+	/* See if a user has put shim into insecure_mode.  If so, and the variable
c9d9c5a
+	 * doesn't have the runtime attribute set, we might as well honor that.
c9d9c5a
+	 */
c9d9c5a
+	var_guid = EFI_SHIM_LOCK_GUID;
c9d9c5a
+	status = efi_call_phys5(sys_table->runtime->get_variable,
c9d9c5a
+				L"MokSBState", &var_guid, &attr, &datasize,
c9d9c5a
+				&moksbstate);
c9d9c5a
+
c9d9c5a
+	/* If it fails, we don't care why.  Default to secure */
c9d9c5a
+	if (status != EFI_SUCCESS)
c9d9c5a
+		return 1;
c9d9c5a
+
c9d9c5a
+	if (!(attr & EFI_VARIABLE_RUNTIME_ACCESS)) {
c9d9c5a
+		if (moksbstate == 1)
c9d9c5a
+			return 0;
c9d9c5a
+	}
c9d9c5a
+
c9d9c5a
 	return 1;
c9d9c5a
 }
c9d9c5a
 
c9d9c5a
-- 
c9d9c5a
1.8.3.1
c9d9c5a
c9d9c5a
c9d9c5a
From 4d8b5cab923a2df15e1f33b3f0511366f9f98756 Mon Sep 17 00:00:00 2001
c9d9c5a
From: Josh Boyer <jwboyer@fedoraproject.org>
c9d9c5a
Date: Tue, 27 Aug 2013 13:28:43 -0400
c9d9c5a
Subject: [PATCH 12/13] efi: Make EFI_SECURE_BOOT_SIG_ENFORCE depend on EFI
c9d9c5a
c9d9c5a
The functionality of the config option is dependent upon the platform being
c9d9c5a
UEFI based.  Reflect this in the config deps.
c9d9c5a
c9d9c5a
Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org>
c9d9c5a
---
c9d9c5a
 arch/x86/Kconfig | 3 ++-
c9d9c5a
 1 file changed, 2 insertions(+), 1 deletion(-)
c9d9c5a
c9d9c5a
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
c9d9c5a
index 6a6c19b..10498ec 100644
c9d9c5a
--- a/arch/x86/Kconfig
c9d9c5a
+++ b/arch/x86/Kconfig
c9d9c5a
@@ -1582,7 +1582,8 @@ config EFI_STUB
c9d9c5a
 	  See Documentation/x86/efi-stub.txt for more information.
c9d9c5a
 
c9d9c5a
 config EFI_SECURE_BOOT_SIG_ENFORCE
c9d9c5a
-        def_bool n
c9d9c5a
+	def_bool n
c9d9c5a
+	depends on EFI
c9d9c5a
 	prompt "Force module signing when UEFI Secure Boot is enabled"
c9d9c5a
 	---help---
c9d9c5a
 	  UEFI Secure Boot provides a mechanism for ensuring that the
c9d9c5a
-- 
c9d9c5a
1.8.3.1
c9d9c5a
c9d9c5a
c9d9c5a
From a87ca6498b8a9f8e3c1d7e6ef7ef4e233ec8639d Mon Sep 17 00:00:00 2001
c9d9c5a
From: Josh Boyer <jwboyer@fedoraproject.org>
c9d9c5a
Date: Tue, 27 Aug 2013 13:33:03 -0400
c9d9c5a
Subject: [PATCH 13/13] efi: Add EFI_SECURE_BOOT bit
c9d9c5a
c9d9c5a
UEFI machines can be booted in Secure Boot mode.  Add a EFI_SECURE_BOOT bit
c9d9c5a
for use with efi_enabled.
c9d9c5a
c9d9c5a
Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org>
c9d9c5a
---
c9d9c5a
 arch/x86/kernel/setup.c | 2 ++
c9d9c5a
 include/linux/efi.h     | 1 +
c9d9c5a
 2 files changed, 3 insertions(+)
c9d9c5a
c9d9c5a
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
c9d9c5a
index deeb7bc..08dc16e 100644
c9d9c5a
--- a/arch/x86/kernel/setup.c
c9d9c5a
+++ b/arch/x86/kernel/setup.c
c9d9c5a
@@ -1131,7 +1131,9 @@ void __init setup_arch(char **cmdline_p)
c9d9c5a
 
c9d9c5a
 #ifdef CONFIG_EFI_SECURE_BOOT_SIG_ENFORCE
c9d9c5a
 	if (boot_params.secure_boot) {
c9d9c5a
+		set_bit(EFI_SECURE_BOOT, &x86_efi_facility);
c9d9c5a
 		enforce_signed_modules();
c9d9c5a
+		pr_info("Secure boot enabled\n");
c9d9c5a
 	}
c9d9c5a
 #endif
c9d9c5a
 
c9d9c5a
diff --git a/include/linux/efi.h b/include/linux/efi.h
c9d9c5a
index 5f8f176..eed2202 100644
c9d9c5a
--- a/include/linux/efi.h
c9d9c5a
+++ b/include/linux/efi.h
c9d9c5a
@@ -634,6 +634,7 @@ extern int __init efi_setup_pcdp_console(char *);
c9d9c5a
 #define EFI_RUNTIME_SERVICES	3	/* Can we use runtime services? */
c9d9c5a
 #define EFI_MEMMAP		4	/* Can we use EFI memory map? */
c9d9c5a
 #define EFI_64BIT		5	/* Is the firmware 64-bit? */
c9d9c5a
+#define EFI_SECURE_BOOT		6 /* Are we in Secure Boot mode? */
c9d9c5a
 
c9d9c5a
 #ifdef CONFIG_EFI
c9d9c5a
 # ifdef CONFIG_X86
c9d9c5a
-- 
c9d9c5a
1.8.3.1
c9d9c5a