Commit 4a1106af authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'efi_updates_for_v5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull EFI updates from Borislav Petkov:
 "These got delayed due to a last minute ia64 build issue which got
  fixed in the meantime.

  EFI updates collected by Ard Biesheuvel:

   - Don't move BSS section around pointlessly in the x86 decompressor

   - Refactor helper for discovering the EFI secure boot mode

   - Wire up EFI secure boot to IMA for arm64

   - Some fixes for the capsule loader

   - Expose the RT_PROP table via the EFI test module

   - Relax DT and kernel placement restrictions on ARM

  with a few followup fixes:

   - fix the build breakage on IA64 caused by recent capsule loader
     changes

   - suppress a type mismatch build warning in the expansion of
     EFI_PHYS_ALIGN on ARM"

* tag 'efi_updates_for_v5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  efi: arm: force use of unsigned type for EFI_PHYS_ALIGN
  efi: ia64: disable the capsule loader
  efi: stub: get rid of efi_get_max_fdt_addr()
  efi/efi_test: read RuntimeServicesSupported
  efi: arm: reduce minimum alignment of uncompressed kernel
  efi: capsule: clean scatter-gather entries from the D-cache
  efi: capsule: use atomic kmap for transient sglist mappings
  efi: x86/xen: switch to efi_get_secureboot_mode helper
  arm64/ima: add ima_arch support
  ima: generalize x86/EFI arch glue for other EFI architectures
  efi: generalize efi_get_secureboot
  efi/libstub: EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER should not default to yes
  efi/x86: Only copy the compressed kernel image in efi_relocate_kernel()
  efi/libstub/x86: simplify efi_is_native()
parents 60e8edd2 3dcb8b53
......@@ -66,24 +66,17 @@ static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt)
#define MAX_UNCOMP_KERNEL_SIZE SZ_32M
/*
* phys-to-virt patching requires that the physical to virtual offset fits
* into the immediate field of an add/sub instruction, which comes down to the
* 24 least significant bits being zero, and so the offset should be a multiple
* of 16 MB. Since PAGE_OFFSET itself is a multiple of 16 MB, the physical
* base should be aligned to 16 MB as well.
* phys-to-virt patching requires that the physical to virtual offset is a
* multiple of 2 MiB. However, using an alignment smaller than TEXT_OFFSET
* here throws off the memory allocation logic, so let's use the lowest power
* of two greater than 2 MiB and greater than TEXT_OFFSET.
*/
#define EFI_PHYS_ALIGN SZ_16M
/* on ARM, the FDT should be located in a lowmem region */
static inline unsigned long efi_get_max_fdt_addr(unsigned long image_addr)
{
return round_down(image_addr, EFI_PHYS_ALIGN) + SZ_512M;
}
#define EFI_PHYS_ALIGN max(UL(SZ_2M), roundup_pow_of_two(TEXT_OFFSET))
/* on ARM, the initrd should be loaded in a lowmem region */
static inline unsigned long efi_get_max_initrd_addr(unsigned long image_addr)
{
return round_down(image_addr, EFI_PHYS_ALIGN) + SZ_512M;
return round_down(image_addr, SZ_4M) + SZ_512M;
}
struct efi_arm_entry_state {
......@@ -93,4 +86,9 @@ struct efi_arm_entry_state {
u32 sctlr_after_ebs;
};
static inline void efi_capsule_flush_cache_range(void *addr, int size)
{
__cpuc_flush_dcache_area(addr, size);
}
#endif /* _ASM_ARM_EFI_H */
......@@ -1877,6 +1877,7 @@ config EFI
select EFI_RUNTIME_WRAPPERS
select EFI_STUB
select EFI_GENERIC_STUB
imply IMA_SECURE_AND_OR_TRUSTED_BOOT
default y
help
This option provides support for runtime services provided
......
......@@ -64,12 +64,6 @@ efi_status_t __efi_rt_asm_wrapper(void *, const char *, ...);
#define EFI_KIMG_ALIGN \
(SEGMENT_ALIGN > THREAD_ALIGN ? SEGMENT_ALIGN : THREAD_ALIGN)
/* on arm64, the FDT may be located anywhere in system RAM */
static inline unsigned long efi_get_max_fdt_addr(unsigned long image_addr)
{
return ULONG_MAX;
}
/*
* On arm64, we have to ensure that the initrd ends up in the linear region,
* which is a 1 GB aligned region of size '1UL << (VA_BITS_MIN - 1)' that is
......@@ -141,4 +135,9 @@ static inline void efi_set_pgd(struct mm_struct *mm)
void efi_virtmap_load(void);
void efi_virtmap_unload(void);
static inline void efi_capsule_flush_cache_range(void *addr, int size)
{
__flush_dcache_area(addr, size);
}
#endif /* _ASM_EFI_H */
......@@ -27,12 +27,6 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
#define ARCH_EFI_IRQ_FLAGS_MASK (SR_IE | SR_SPIE)
/* on RISC-V, the FDT may be located anywhere in system RAM */
static inline unsigned long efi_get_max_fdt_addr(unsigned long image_addr)
{
return ULONG_MAX;
}
/* Load initrd at enough distance from DRAM start */
static inline unsigned long efi_get_max_initrd_addr(unsigned long image_addr)
{
......
......@@ -35,7 +35,7 @@ cflags-$(CONFIG_X86_32) := -march=i386
cflags-$(CONFIG_X86_64) := -mcmodel=small -mno-red-zone
KBUILD_CFLAGS += $(cflags-y)
KBUILD_CFLAGS += -mno-mmx -mno-sse
KBUILD_CFLAGS += -ffreestanding
KBUILD_CFLAGS += -ffreestanding -fshort-wchar
KBUILD_CFLAGS += -fno-stack-protector
KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member)
KBUILD_CFLAGS += $(call cc-disable-warning, gnu)
......
......@@ -213,8 +213,6 @@ static inline bool efi_is_64bit(void)
static inline bool efi_is_native(void)
{
if (!IS_ENABLED(CONFIG_X86_64))
return true;
return efi_is_64bit();
}
......@@ -382,4 +380,7 @@ static inline void efi_fake_memmap_early(void)
}
#endif
#define arch_ima_efi_boot_mode \
({ extern struct boot_params boot_params; boot_params.secure_boot; })
#endif /* _ASM_X86_EFI_H */
......@@ -161,5 +161,3 @@ ifeq ($(CONFIG_X86_64),y)
obj-$(CONFIG_MMCONF_FAM10H) += mmconf-fam10h_64.o
obj-y += vsmp_64.o
endif
obj-$(CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT) += ima_arch.o
......@@ -93,37 +93,22 @@ static efi_system_table_t __init *xen_efi_probe(void)
/*
* Determine whether we're in secure boot mode.
*
* Please keep the logic in sync with
* drivers/firmware/efi/libstub/secureboot.c:efi_get_secureboot().
*/
static enum efi_secureboot_mode xen_efi_get_secureboot(void)
{
static efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
static efi_guid_t shim_guid = EFI_SHIM_LOCK_GUID;
enum efi_secureboot_mode mode;
efi_status_t status;
u8 moksbstate, secboot, setupmode;
u8 moksbstate;
unsigned long size;
size = sizeof(secboot);
status = efi.get_variable(L"SecureBoot", &efi_variable_guid,
NULL, &size, &secboot);
if (status == EFI_NOT_FOUND)
return efi_secureboot_mode_disabled;
if (status != EFI_SUCCESS)
goto out_efi_err;
size = sizeof(setupmode);
status = efi.get_variable(L"SetupMode", &efi_variable_guid,
NULL, &size, &setupmode);
if (status != EFI_SUCCESS)
goto out_efi_err;
if (secboot == 0 || setupmode == 1)
return efi_secureboot_mode_disabled;
mode = efi_get_secureboot_mode(efi.get_variable);
if (mode == efi_secureboot_mode_unknown) {
pr_err("Could not determine UEFI Secure Boot status.\n");
return efi_secureboot_mode_unknown;
}
if (mode != efi_secureboot_mode_enabled)
return mode;
/* See if a user has put the shim into insecure mode. */
size = sizeof(moksbstate);
......@@ -140,10 +125,6 @@ static enum efi_secureboot_mode xen_efi_get_secureboot(void)
secure_boot_enabled:
pr_info("UEFI Secure Boot is enabled.\n");
return efi_secureboot_mode_enabled;
out_efi_err:
pr_err("Could not determine UEFI Secure Boot status.\n");
return efi_secureboot_mode_unknown;
}
void __init xen_efi_init(struct boot_params *boot_params)
......
......@@ -122,7 +122,7 @@ config EFI_ARMSTUB_DTB_LOADER
config EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER
bool "Enable the command line initrd loader" if !X86
depends on EFI_STUB && (EFI_GENERIC_STUB || X86)
default y
default y if X86
depends on !RISCV
help
Select this config option to add support for the initrd= command
......@@ -147,7 +147,7 @@ config EFI_BOOTLOADER_CONTROL
config EFI_CAPSULE_LOADER
tristate "EFI capsule loader"
depends on EFI
depends on EFI && !IA64
help
This option exposes a loader interface "/dev/efi_capsule_loader" for
users to load EFI capsules. This driver requires working runtime
......
......@@ -12,7 +12,10 @@ KASAN_SANITIZE_runtime-wrappers.o := n
obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
obj-$(CONFIG_EFI) += efi.o vars.o reboot.o memattr.o tpm.o
obj-$(CONFIG_EFI) += capsule.o memmap.o
obj-$(CONFIG_EFI) += memmap.o
ifneq ($(CONFIG_EFI_CAPSULE_LOADER),)
obj-$(CONFIG_EFI) += capsule.o
endif
obj-$(CONFIG_EFI_PARAMS_FROM_FDT) += fdtparams.o
obj-$(CONFIG_EFI_VARS) += efivars.o
obj-$(CONFIG_EFI_ESRT) += esrt.o
......
......@@ -12,6 +12,7 @@
#include <linux/highmem.h>
#include <linux/efi.h>
#include <linux/vmalloc.h>
#include <asm/efi.h>
#include <asm/io.h>
typedef struct {
......@@ -244,7 +245,7 @@ int efi_capsule_update(efi_capsule_header_t *capsule, phys_addr_t *pages)
for (i = 0; i < sg_count; i++) {
efi_capsule_block_desc_t *sglist;
sglist = kmap(sg_pages[i]);
sglist = kmap_atomic(sg_pages[i]);
for (j = 0; j < SGLIST_PER_PAGE && count > 0; j++) {
u64 sz = min_t(u64, imagesize,
......@@ -265,7 +266,18 @@ int efi_capsule_update(efi_capsule_header_t *capsule, phys_addr_t *pages)
else
sglist[j].data = page_to_phys(sg_pages[i + 1]);
kunmap(sg_pages[i]);
#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
/*
* At runtime, the firmware has no way to find out where the
* sglist elements are mapped, if they are mapped in the first
* place. Therefore, on architectures that can only perform
* cache maintenance by virtual address, the firmware is unable
* to perform this maintenance, and so it is up to the OS to do
* it instead.
*/
efi_capsule_flush_cache_range(sglist, PAGE_SIZE);
#endif
kunmap_atomic(sglist);
}
mutex_lock(&capsule_mutex);
......
......@@ -273,7 +273,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
install_memreserve_table();
status = allocate_new_fdt_and_exit_boot(handle, &fdt_addr,
efi_get_max_fdt_addr(image_addr),
initrd_addr, initrd_size,
cmdline_ptr, fdt_addr, fdt_size);
if (status != EFI_SUCCESS)
......
......@@ -750,7 +750,6 @@ efi_status_t efi_exit_boot_services(void *handle,
efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
unsigned long *new_fdt_addr,
unsigned long max_addr,
u64 initrd_addr, u64 initrd_size,
char *cmdline_ptr,
unsigned long fdt_addr,
......@@ -848,4 +847,6 @@ asmlinkage void __noreturn efi_enter_kernel(unsigned long entrypoint,
void efi_handle_post_ebs_state(void);
enum efi_secureboot_mode efi_get_secureboot(void);
#endif
......@@ -238,7 +238,6 @@ static efi_status_t exit_boot_func(struct efi_boot_memmap *map,
efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
unsigned long *new_fdt_addr,
unsigned long max_addr,
u64 initrd_addr, u64 initrd_size,
char *cmdline_ptr,
unsigned long fdt_addr,
......@@ -275,7 +274,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
efi_info("Exiting boot services and installing virtual address map...\n");
map.map = &memory_map;
status = efi_allocate_pages(MAX_FDT_SIZE, new_fdt_addr, max_addr);
status = efi_allocate_pages(MAX_FDT_SIZE, new_fdt_addr, ULONG_MAX);
if (status != EFI_SUCCESS) {
efi_err("Unable to allocate memory for new device tree.\n");
goto fail;
......
......@@ -12,44 +12,34 @@
#include "efistub.h"
/* BIOS variables */
static const efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
static const efi_char16_t efi_SecureBoot_name[] = L"SecureBoot";
static const efi_char16_t efi_SetupMode_name[] = L"SetupMode";
/* SHIM variables */
static const efi_guid_t shim_guid = EFI_SHIM_LOCK_GUID;
static const efi_char16_t shim_MokSBState_name[] = L"MokSBState";
static efi_status_t get_var(efi_char16_t *name, efi_guid_t *vendor, u32 *attr,
unsigned long *data_size, void *data)
{
return get_efi_var(name, vendor, attr, data_size, data);
}
/*
* Determine whether we're in secure boot mode.
*
* Please keep the logic in sync with
* arch/x86/xen/efi.c:xen_efi_get_secureboot().
*/
enum efi_secureboot_mode efi_get_secureboot(void)
{
u32 attr;
u8 secboot, setupmode, moksbstate;
unsigned long size;
enum efi_secureboot_mode mode;
efi_status_t status;
u8 moksbstate;
size = sizeof(secboot);
status = get_efi_var(efi_SecureBoot_name, &efi_variable_guid,
NULL, &size, &secboot);
if (status == EFI_NOT_FOUND)
return efi_secureboot_mode_disabled;
if (status != EFI_SUCCESS)
goto out_efi_err;
size = sizeof(setupmode);
status = get_efi_var(efi_SetupMode_name, &efi_variable_guid,
NULL, &size, &setupmode);
if (status != EFI_SUCCESS)
goto out_efi_err;
if (secboot == 0 || setupmode == 1)
return efi_secureboot_mode_disabled;
mode = efi_get_secureboot_mode(get_var);
if (mode == efi_secureboot_mode_unknown) {
efi_err("Could not determine UEFI Secure Boot status.\n");
return efi_secureboot_mode_unknown;
}
if (mode != efi_secureboot_mode_enabled)
return mode;
/*
* See if a user has put the shim into insecure mode. If so, and if the
......@@ -69,8 +59,4 @@ enum efi_secureboot_mode efi_get_secureboot(void)
secure_boot_enabled:
efi_info("UEFI Secure Boot is enabled.\n");
return efi_secureboot_mode_enabled;
out_efi_err:
efi_err("Could not determine UEFI Secure Boot status.\n");
return efi_secureboot_mode_unknown;
}
......@@ -715,8 +715,11 @@ unsigned long efi_main(efi_handle_t handle,
(IS_ENABLED(CONFIG_X86_32) && buffer_end > KERNEL_IMAGE_SIZE) ||
(IS_ENABLED(CONFIG_X86_64) && buffer_end > MAXMEM_X86_64_4LEVEL) ||
(image_offset == 0)) {
extern char _bss[];
status = efi_relocate_kernel(&bzimage_addr,
hdr->init_size, hdr->init_size,
(unsigned long)_bss - bzimage_addr,
hdr->init_size,
hdr->pref_address,
hdr->kernel_alignment,
LOAD_PHYSICAL_ADDR);
......
......@@ -663,6 +663,19 @@ static long efi_runtime_query_capsulecaps(unsigned long arg)
return rv;
}
static long efi_runtime_get_supported_mask(unsigned long arg)
{
unsigned int __user *supported_mask;
int rv = 0;
supported_mask = (unsigned int *)arg;
if (put_user(efi.runtime_supported_mask, supported_mask))
rv = -EFAULT;
return rv;
}
static long efi_test_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
......@@ -699,6 +712,9 @@ static long efi_test_ioctl(struct file *file, unsigned int cmd,
case EFI_RUNTIME_RESET_SYSTEM:
return efi_runtime_reset_system(arg);
case EFI_RUNTIME_GET_SUPPORTED_MASK:
return efi_runtime_get_supported_mask(arg);
}
return -ENOTTY;
......
......@@ -118,4 +118,7 @@ struct efi_resetsystem {
#define EFI_RUNTIME_RESET_SYSTEM \
_IOW('p', 0x0B, struct efi_resetsystem)
#define EFI_RUNTIME_GET_SUPPORTED_MASK \
_IOR('p', 0x0C, unsigned int)
#endif /* _DRIVERS_FIRMWARE_EFI_TEST_H_ */
......@@ -817,12 +817,6 @@ static inline bool efi_enabled(int feature)
static inline void
efi_reboot(enum reboot_mode reboot_mode, const char *__unused) {}
static inline bool
efi_capsule_pending(int *reset_type)
{
return false;
}
static inline bool efi_soft_reserve_enabled(void)
{
return false;
......@@ -1038,6 +1032,7 @@ bool efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
bool efivar_variable_is_removable(efi_guid_t vendor, const char *name,
size_t len);
#if IS_ENABLED(CONFIG_EFI_CAPSULE_LOADER)
extern bool efi_capsule_pending(int *reset_type);
extern int efi_capsule_supported(efi_guid_t guid, u32 flags,
......@@ -1045,6 +1040,9 @@ extern int efi_capsule_supported(efi_guid_t guid, u32 flags,
extern int efi_capsule_update(efi_capsule_header_t *capsule,
phys_addr_t *pages);
#else
static inline bool efi_capsule_pending(int *reset_type) { return false; }
#endif
#ifdef CONFIG_EFI_RUNTIME_MAP
int efi_runtime_map_init(struct kobject *);
......@@ -1089,7 +1087,28 @@ enum efi_secureboot_mode {
efi_secureboot_mode_disabled,
efi_secureboot_mode_enabled,
};
enum efi_secureboot_mode efi_get_secureboot(void);
static inline
enum efi_secureboot_mode efi_get_secureboot_mode(efi_get_variable_t *get_var)
{
u8 secboot, setupmode = 0;
efi_status_t status;
unsigned long size;
size = sizeof(secboot);
status = get_var(L"SecureBoot", &EFI_GLOBAL_VARIABLE_GUID, NULL, &size,
&secboot);
if (status == EFI_NOT_FOUND)
return efi_secureboot_mode_disabled;
if (status != EFI_SUCCESS)
return efi_secureboot_mode_unknown;
size = sizeof(setupmode);
get_var(L"SetupMode", &EFI_GLOBAL_VARIABLE_GUID, NULL, &size, &setupmode);
if (secboot == 0 || setupmode == 1)
return efi_secureboot_mode_disabled;
return efi_secureboot_mode_enabled;
}
#ifdef CONFIG_RESET_ATTACK_MITIGATION
void efi_enable_reset_attack_mitigation(void);
......
......@@ -14,3 +14,7 @@ ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o
ima-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o
ima-$(CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS) += ima_asymmetric_keys.o
ima-$(CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS) += ima_queue_keys.o
ifeq ($(CONFIG_EFI),y)
ima-$(CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT) += ima_efi.o
endif
......@@ -5,50 +5,29 @@
#include <linux/efi.h>
#include <linux/module.h>
#include <linux/ima.h>
#include <asm/efi.h>
extern struct boot_params boot_params;
#ifndef arch_ima_efi_boot_mode
#define arch_ima_efi_boot_mode efi_secureboot_mode_unset
#endif
static enum efi_secureboot_mode get_sb_mode(void)
{
efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
efi_status_t status;
unsigned long size;
u8 secboot, setupmode;
size = sizeof(secboot);
enum efi_secureboot_mode mode;
if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) {
pr_info("ima: secureboot mode unknown, no efi\n");
return efi_secureboot_mode_unknown;
}
/* Get variable contents into buffer */
status = efi.get_variable(L"SecureBoot", &efi_variable_guid,
NULL, &size, &secboot);
if (status == EFI_NOT_FOUND) {
mode = efi_get_secureboot_mode(efi.get_variable);
if (mode == efi_secureboot_mode_disabled)
pr_info("ima: secureboot mode disabled\n");
return efi_secureboot_mode_disabled;
}
if (status != EFI_SUCCESS) {
else if (mode == efi_secureboot_mode_unknown)
pr_info("ima: secureboot mode unknown\n");
return efi_secureboot_mode_unknown;
}
size = sizeof(setupmode);
status = efi.get_variable(L"SetupMode", &efi_variable_guid,
NULL, &size, &setupmode);
if (status != EFI_SUCCESS) /* ignore unknown SetupMode */
setupmode = 0;
if (secboot == 0 || setupmode == 1) {
pr_info("ima: secureboot mode disabled\n");
return efi_secureboot_mode_disabled;
}
else
pr_info("ima: secureboot mode enabled\n");
return efi_secureboot_mode_enabled;
return mode;
}
bool arch_ima_get_secureboot(void)
......@@ -57,7 +36,7 @@ bool arch_ima_get_secureboot(void)
static bool initialized;
if (!initialized && efi_enabled(EFI_BOOT)) {
sb_mode = boot_params.secure_boot;
sb_mode = arch_ima_efi_boot_mode;
if (sb_mode == efi_secureboot_mode_unset)
sb_mode = get_sb_mode();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment