summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Boyer <jwboyer@redhat.com>2019-08-19 20:17:51 -0400
committerJames Morris <jmorris@namei.org>2019-08-20 00:54:16 -0400
commit41fa1ee9c6d687afb05760dd349f361855f1d7f5 (patch)
tree301d02e3063b577dc6fb09c8f7153116bb1ff591
parentf474e1486b78ac15322f8a1cda48a32a1deff9d3 (diff)
acpi: Ignore acpi_rsdp kernel param when the kernel has been locked down
This option allows userspace to pass the RSDP address to the kernel, which makes it possible for a user to modify the workings of hardware. Reject the option when the kernel is locked down. This requires some reworking of the existing RSDP command line logic, since the early boot code also makes use of a command-line passed RSDP when locating the SRAT table before the lockdown code has been initialised. This is achieved by separating the command line RSDP path in the early boot code from the generic RSDP path, and then copying the command line RSDP into boot params in the kernel proper if lockdown is not enabled. If lockdown is enabled and an RSDP is provided on the command line, this will only be used when parsing SRAT (which shouldn't permit kernel code execution) and will be ignored in the rest of the kernel. (Modified by Matthew Garrett in order to handle the early boot RSDP environment) Signed-off-by: Josh Boyer <jwboyer@redhat.com> Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Matthew Garrett <mjg59@google.com> Reviewed-by: Kees Cook <keescook@chromium.org> cc: Dave Young <dyoung@redhat.com> cc: linux-acpi@vger.kernel.org Signed-off-by: James Morris <jmorris@namei.org>
-rw-r--r--arch/x86/boot/compressed/acpi.c19
-rw-r--r--arch/x86/include/asm/acpi.h9
-rw-r--r--arch/x86/include/asm/x86_init.h2
-rw-r--r--arch/x86/kernel/acpi/boot.c5
-rw-r--r--arch/x86/kernel/x86_init.c1
-rw-r--r--drivers/acpi/osl.c14
-rw-r--r--include/linux/acpi.h6
7 files changed, 49 insertions, 7 deletions
diff --git a/arch/x86/boot/compressed/acpi.c b/arch/x86/boot/compressed/acpi.c
index ad84239e595e..e726e9b44bb1 100644
--- a/arch/x86/boot/compressed/acpi.c
+++ b/arch/x86/boot/compressed/acpi.c
@@ -26,7 +26,7 @@ struct mem_vector immovable_mem[MAX_NUMNODES*2];
26 */ 26 */
27#define MAX_ADDR_LEN 19 27#define MAX_ADDR_LEN 19
28 28
29static acpi_physical_address get_acpi_rsdp(void) 29static acpi_physical_address get_cmdline_acpi_rsdp(void)
30{ 30{
31 acpi_physical_address addr = 0; 31 acpi_physical_address addr = 0;
32 32
@@ -215,10 +215,7 @@ acpi_physical_address get_rsdp_addr(void)
215{ 215{
216 acpi_physical_address pa; 216 acpi_physical_address pa;
217 217
218 pa = get_acpi_rsdp(); 218 pa = boot_params->acpi_rsdp_addr;
219
220 if (!pa)
221 pa = boot_params->acpi_rsdp_addr;
222 219
223 if (!pa) 220 if (!pa)
224 pa = efi_get_rsdp_addr(); 221 pa = efi_get_rsdp_addr();
@@ -240,7 +237,17 @@ static unsigned long get_acpi_srat_table(void)
240 char arg[10]; 237 char arg[10];
241 u8 *entry; 238 u8 *entry;
242 239
243 rsdp = (struct acpi_table_rsdp *)(long)boot_params->acpi_rsdp_addr; 240 /*
241 * Check whether we were given an RSDP on the command line. We don't
242 * stash this in boot params because the kernel itself may have
243 * different ideas about whether to trust a command-line parameter.
244 */
245 rsdp = (struct acpi_table_rsdp *)get_cmdline_acpi_rsdp();
246
247 if (!rsdp)
248 rsdp = (struct acpi_table_rsdp *)(long)
249 boot_params->acpi_rsdp_addr;
250
244 if (!rsdp) 251 if (!rsdp)
245 return 0; 252 return 0;
246 253
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index aac686e1e005..bc9693c9107e 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -117,6 +117,12 @@ static inline bool acpi_has_cpu_in_madt(void)
117 return !!acpi_lapic; 117 return !!acpi_lapic;
118} 118}
119 119
120#define ACPI_HAVE_ARCH_SET_ROOT_POINTER
121static inline void acpi_arch_set_root_pointer(u64 addr)
122{
123 x86_init.acpi.set_root_pointer(addr);
124}
125
120#define ACPI_HAVE_ARCH_GET_ROOT_POINTER 126#define ACPI_HAVE_ARCH_GET_ROOT_POINTER
121static inline u64 acpi_arch_get_root_pointer(void) 127static inline u64 acpi_arch_get_root_pointer(void)
122{ 128{
@@ -125,6 +131,7 @@ static inline u64 acpi_arch_get_root_pointer(void)
125 131
126void acpi_generic_reduced_hw_init(void); 132void acpi_generic_reduced_hw_init(void);
127 133
134void x86_default_set_root_pointer(u64 addr);
128u64 x86_default_get_root_pointer(void); 135u64 x86_default_get_root_pointer(void);
129 136
130#else /* !CONFIG_ACPI */ 137#else /* !CONFIG_ACPI */
@@ -138,6 +145,8 @@ static inline void disable_acpi(void) { }
138 145
139static inline void acpi_generic_reduced_hw_init(void) { } 146static inline void acpi_generic_reduced_hw_init(void) { }
140 147
148static inline void x86_default_set_root_pointer(u64 addr) { }
149
141static inline u64 x86_default_get_root_pointer(void) 150static inline u64 x86_default_get_root_pointer(void)
142{ 151{
143 return 0; 152 return 0;
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index b85a7c54c6a1..d584128435cb 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -134,10 +134,12 @@ struct x86_hyper_init {
134 134
135/** 135/**
136 * struct x86_init_acpi - x86 ACPI init functions 136 * struct x86_init_acpi - x86 ACPI init functions
137 * @set_root_poitner: set RSDP address
137 * @get_root_pointer: get RSDP address 138 * @get_root_pointer: get RSDP address
138 * @reduced_hw_early_init: hardware reduced platform early init 139 * @reduced_hw_early_init: hardware reduced platform early init
139 */ 140 */
140struct x86_init_acpi { 141struct x86_init_acpi {
142 void (*set_root_pointer)(u64 addr);
141 u64 (*get_root_pointer)(void); 143 u64 (*get_root_pointer)(void);
142 void (*reduced_hw_early_init)(void); 144 void (*reduced_hw_early_init)(void);
143}; 145};
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 17b33ef604f3..04205ce127a1 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -1760,6 +1760,11 @@ void __init arch_reserve_mem_area(acpi_physical_address addr, size_t size)
1760 e820__update_table_print(); 1760 e820__update_table_print();
1761} 1761}
1762 1762
1763void x86_default_set_root_pointer(u64 addr)
1764{
1765 boot_params.acpi_rsdp_addr = addr;
1766}
1767
1763u64 x86_default_get_root_pointer(void) 1768u64 x86_default_get_root_pointer(void)
1764{ 1769{
1765 return boot_params.acpi_rsdp_addr; 1770 return boot_params.acpi_rsdp_addr;
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index 50a2b492fdd6..d0b8f5585a73 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -95,6 +95,7 @@ struct x86_init_ops x86_init __initdata = {
95 }, 95 },
96 96
97 .acpi = { 97 .acpi = {
98 .set_root_pointer = x86_default_set_root_pointer,
98 .get_root_pointer = x86_default_get_root_pointer, 99 .get_root_pointer = x86_default_get_root_pointer,
99 .reduced_hw_early_init = acpi_generic_reduced_hw_init, 100 .reduced_hw_early_init = acpi_generic_reduced_hw_init,
100 }, 101 },
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index cc7507091dec..b7c3aeb175dd 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -26,6 +26,7 @@
26#include <linux/list.h> 26#include <linux/list.h>
27#include <linux/jiffies.h> 27#include <linux/jiffies.h>
28#include <linux/semaphore.h> 28#include <linux/semaphore.h>
29#include <linux/security.h>
29 30
30#include <asm/io.h> 31#include <asm/io.h>
31#include <linux/uaccess.h> 32#include <linux/uaccess.h>
@@ -180,8 +181,19 @@ acpi_physical_address __init acpi_os_get_root_pointer(void)
180 acpi_physical_address pa; 181 acpi_physical_address pa;
181 182
182#ifdef CONFIG_KEXEC 183#ifdef CONFIG_KEXEC
183 if (acpi_rsdp) 184 /*
185 * We may have been provided with an RSDP on the command line,
186 * but if a malicious user has done so they may be pointing us
187 * at modified ACPI tables that could alter kernel behaviour -
188 * so, we check the lockdown status before making use of
189 * it. If we trust it then also stash it in an architecture
190 * specific location (if appropriate) so it can be carried
191 * over further kexec()s.
192 */
193 if (acpi_rsdp && !security_locked_down(LOCKDOWN_ACPI_TABLES)) {
194 acpi_arch_set_root_pointer(acpi_rsdp);
184 return acpi_rsdp; 195 return acpi_rsdp;
196 }
185#endif 197#endif
186 pa = acpi_arch_get_root_pointer(); 198 pa = acpi_arch_get_root_pointer();
187 if (pa) 199 if (pa)
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index d315d86844e4..268a4d91f54c 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -632,6 +632,12 @@ bool acpi_gtdt_c3stop(int type);
632int acpi_arch_timer_mem_init(struct arch_timer_mem *timer_mem, int *timer_count); 632int acpi_arch_timer_mem_init(struct arch_timer_mem *timer_mem, int *timer_count);
633#endif 633#endif
634 634
635#ifndef ACPI_HAVE_ARCH_SET_ROOT_POINTER
636static inline void acpi_arch_set_root_pointer(u64 addr)
637{
638}
639#endif
640
635#ifndef ACPI_HAVE_ARCH_GET_ROOT_POINTER 641#ifndef ACPI_HAVE_ARCH_GET_ROOT_POINTER
636static inline u64 acpi_arch_get_root_pointer(void) 642static inline u64 acpi_arch_get_root_pointer(void)
637{ 643{