Skip to content

Commit e130a92

Browse files
committed
Merge branch 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull EFI fixes from Ingo Molnar: "Three fixes to EFI mixed boot mode, mostly related to x86-64 vmap stacks activated years ago, bug-fixed recently for EFI, which had knock-on effects of various 1:1 mapping assumptions in mixed mode. There's also a READ_ONCE() fix for reading an mmap-ed EFI firmware data field only once, out of caution" * 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: efi: READ_ONCE rng seed size before munmap efi/x86: Handle by-ref arguments covering multiple pages in mixed mode efi/x86: Remove support for EFI time and counter services in mixed mode efi/x86: Align GUIDs to their size in the mixed mode runtime wrapper
2 parents 98d54f8 + be36f9e commit e130a92

File tree

2 files changed

+54
-101
lines changed

2 files changed

+54
-101
lines changed

arch/x86/platform/efi/efi_64.c

Lines changed: 52 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -180,24 +180,21 @@ void efi_sync_low_kernel_mappings(void)
180180
static inline phys_addr_t
181181
virt_to_phys_or_null_size(void *va, unsigned long size)
182182
{
183-
bool bad_size;
183+
phys_addr_t pa;
184184

185185
if (!va)
186186
return 0;
187187

188188
if (virt_addr_valid(va))
189189
return virt_to_phys(va);
190190

191-
/*
192-
* A fully aligned variable on the stack is guaranteed not to
193-
* cross a page bounary. Try to catch strings on the stack by
194-
* checking that 'size' is a power of two.
195-
*/
196-
bad_size = size > PAGE_SIZE || !is_power_of_2(size);
191+
pa = slow_virt_to_phys(va);
197192

198-
WARN_ON(!IS_ALIGNED((unsigned long)va, size) || bad_size);
193+
/* check if the object crosses a page boundary */
194+
if (WARN_ON((pa ^ (pa + size - 1)) & PAGE_MASK))
195+
return 0;
199196

200-
return slow_virt_to_phys(va);
197+
return pa;
201198
}
202199

203200
#define virt_to_phys_or_null(addr) \
@@ -568,85 +565,25 @@ efi_thunk_set_virtual_address_map(unsigned long memory_map_size,
568565

569566
static efi_status_t efi_thunk_get_time(efi_time_t *tm, efi_time_cap_t *tc)
570567
{
571-
efi_status_t status;
572-
u32 phys_tm, phys_tc;
573-
unsigned long flags;
574-
575-
spin_lock(&rtc_lock);
576-
spin_lock_irqsave(&efi_runtime_lock, flags);
577-
578-
phys_tm = virt_to_phys_or_null(tm);
579-
phys_tc = virt_to_phys_or_null(tc);
580-
581-
status = efi_thunk(get_time, phys_tm, phys_tc);
582-
583-
spin_unlock_irqrestore(&efi_runtime_lock, flags);
584-
spin_unlock(&rtc_lock);
585-
586-
return status;
568+
return EFI_UNSUPPORTED;
587569
}
588570

589571
static efi_status_t efi_thunk_set_time(efi_time_t *tm)
590572
{
591-
efi_status_t status;
592-
u32 phys_tm;
593-
unsigned long flags;
594-
595-
spin_lock(&rtc_lock);
596-
spin_lock_irqsave(&efi_runtime_lock, flags);
597-
598-
phys_tm = virt_to_phys_or_null(tm);
599-
600-
status = efi_thunk(set_time, phys_tm);
601-
602-
spin_unlock_irqrestore(&efi_runtime_lock, flags);
603-
spin_unlock(&rtc_lock);
604-
605-
return status;
573+
return EFI_UNSUPPORTED;
606574
}
607575

608576
static efi_status_t
609577
efi_thunk_get_wakeup_time(efi_bool_t *enabled, efi_bool_t *pending,
610578
efi_time_t *tm)
611579
{
612-
efi_status_t status;
613-
u32 phys_enabled, phys_pending, phys_tm;
614-
unsigned long flags;
615-
616-
spin_lock(&rtc_lock);
617-
spin_lock_irqsave(&efi_runtime_lock, flags);
618-
619-
phys_enabled = virt_to_phys_or_null(enabled);
620-
phys_pending = virt_to_phys_or_null(pending);
621-
phys_tm = virt_to_phys_or_null(tm);
622-
623-
status = efi_thunk(get_wakeup_time, phys_enabled,
624-
phys_pending, phys_tm);
625-
626-
spin_unlock_irqrestore(&efi_runtime_lock, flags);
627-
spin_unlock(&rtc_lock);
628-
629-
return status;
580+
return EFI_UNSUPPORTED;
630581
}
631582

632583
static efi_status_t
633584
efi_thunk_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
634585
{
635-
efi_status_t status;
636-
u32 phys_tm;
637-
unsigned long flags;
638-
639-
spin_lock(&rtc_lock);
640-
spin_lock_irqsave(&efi_runtime_lock, flags);
641-
642-
phys_tm = virt_to_phys_or_null(tm);
643-
644-
status = efi_thunk(set_wakeup_time, enabled, phys_tm);
645-
646-
spin_unlock_irqrestore(&efi_runtime_lock, flags);
647-
spin_unlock(&rtc_lock);
648-
649-
return status;
586+
return EFI_UNSUPPORTED;
650587
}
651588

652589
static unsigned long efi_name_size(efi_char16_t *name)
@@ -658,21 +595,28 @@ static efi_status_t
658595
efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor,
659596
u32 *attr, unsigned long *data_size, void *data)
660597
{
598+
u8 buf[24] __aligned(8);
599+
efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
661600
efi_status_t status;
662601
u32 phys_name, phys_vendor, phys_attr;
663602
u32 phys_data_size, phys_data;
664603
unsigned long flags;
665604

666605
spin_lock_irqsave(&efi_runtime_lock, flags);
667606

607+
*vnd = *vendor;
608+
668609
phys_data_size = virt_to_phys_or_null(data_size);
669-
phys_vendor = virt_to_phys_or_null(vendor);
610+
phys_vendor = virt_to_phys_or_null(vnd);
670611
phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
671612
phys_attr = virt_to_phys_or_null(attr);
672613
phys_data = virt_to_phys_or_null_size(data, *data_size);
673614

674-
status = efi_thunk(get_variable, phys_name, phys_vendor,
675-
phys_attr, phys_data_size, phys_data);
615+
if (!phys_name || (data && !phys_data))
616+
status = EFI_INVALID_PARAMETER;
617+
else
618+
status = efi_thunk(get_variable, phys_name, phys_vendor,
619+
phys_attr, phys_data_size, phys_data);
676620

677621
spin_unlock_irqrestore(&efi_runtime_lock, flags);
678622

@@ -683,19 +627,25 @@ static efi_status_t
683627
efi_thunk_set_variable(efi_char16_t *name, efi_guid_t *vendor,
684628
u32 attr, unsigned long data_size, void *data)
685629
{
630+
u8 buf[24] __aligned(8);
631+
efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
686632
u32 phys_name, phys_vendor, phys_data;
687633
efi_status_t status;
688634
unsigned long flags;
689635

690636
spin_lock_irqsave(&efi_runtime_lock, flags);
691637

638+
*vnd = *vendor;
639+
692640
phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
693-
phys_vendor = virt_to_phys_or_null(vendor);
641+
phys_vendor = virt_to_phys_or_null(vnd);
694642
phys_data = virt_to_phys_or_null_size(data, data_size);
695643

696-
/* If data_size is > sizeof(u32) we've got problems */
697-
status = efi_thunk(set_variable, phys_name, phys_vendor,
698-
attr, data_size, phys_data);
644+
if (!phys_name || !phys_data)
645+
status = EFI_INVALID_PARAMETER;
646+
else
647+
status = efi_thunk(set_variable, phys_name, phys_vendor,
648+
attr, data_size, phys_data);
699649

700650
spin_unlock_irqrestore(&efi_runtime_lock, flags);
701651

@@ -707,20 +657,26 @@ efi_thunk_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
707657
u32 attr, unsigned long data_size,
708658
void *data)
709659
{
660+
u8 buf[24] __aligned(8);
661+
efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
710662
u32 phys_name, phys_vendor, phys_data;
711663
efi_status_t status;
712664
unsigned long flags;
713665

714666
if (!spin_trylock_irqsave(&efi_runtime_lock, flags))
715667
return EFI_NOT_READY;
716668

669+
*vnd = *vendor;
670+
717671
phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
718-
phys_vendor = virt_to_phys_or_null(vendor);
672+
phys_vendor = virt_to_phys_or_null(vnd);
719673
phys_data = virt_to_phys_or_null_size(data, data_size);
720674

721-
/* If data_size is > sizeof(u32) we've got problems */
722-
status = efi_thunk(set_variable, phys_name, phys_vendor,
723-
attr, data_size, phys_data);
675+
if (!phys_name || !phys_data)
676+
status = EFI_INVALID_PARAMETER;
677+
else
678+
status = efi_thunk(set_variable, phys_name, phys_vendor,
679+
attr, data_size, phys_data);
724680

725681
spin_unlock_irqrestore(&efi_runtime_lock, flags);
726682

@@ -732,39 +688,36 @@ efi_thunk_get_next_variable(unsigned long *name_size,
732688
efi_char16_t *name,
733689
efi_guid_t *vendor)
734690
{
691+
u8 buf[24] __aligned(8);
692+
efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
735693
efi_status_t status;
736694
u32 phys_name_size, phys_name, phys_vendor;
737695
unsigned long flags;
738696

739697
spin_lock_irqsave(&efi_runtime_lock, flags);
740698

699+
*vnd = *vendor;
700+
741701
phys_name_size = virt_to_phys_or_null(name_size);
742-
phys_vendor = virt_to_phys_or_null(vendor);
702+
phys_vendor = virt_to_phys_or_null(vnd);
743703
phys_name = virt_to_phys_or_null_size(name, *name_size);
744704

745-
status = efi_thunk(get_next_variable, phys_name_size,
746-
phys_name, phys_vendor);
705+
if (!phys_name)
706+
status = EFI_INVALID_PARAMETER;
707+
else
708+
status = efi_thunk(get_next_variable, phys_name_size,
709+
phys_name, phys_vendor);
747710

748711
spin_unlock_irqrestore(&efi_runtime_lock, flags);
749712

713+
*vendor = *vnd;
750714
return status;
751715
}
752716

753717
static efi_status_t
754718
efi_thunk_get_next_high_mono_count(u32 *count)
755719
{
756-
efi_status_t status;
757-
u32 phys_count;
758-
unsigned long flags;
759-
760-
spin_lock_irqsave(&efi_runtime_lock, flags);
761-
762-
phys_count = virt_to_phys_or_null(count);
763-
status = efi_thunk(get_next_high_mono_count, phys_count);
764-
765-
spin_unlock_irqrestore(&efi_runtime_lock, flags);
766-
767-
return status;
720+
return EFI_UNSUPPORTED;
768721
}
769722

770723
static void

drivers/firmware/efi/efi.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
552552

553553
seed = early_memremap(efi.rng_seed, sizeof(*seed));
554554
if (seed != NULL) {
555-
size = seed->size;
555+
size = READ_ONCE(seed->size);
556556
early_memunmap(seed, sizeof(*seed));
557557
} else {
558558
pr_err("Could not map UEFI random seed!\n");
@@ -562,7 +562,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
562562
sizeof(*seed) + size);
563563
if (seed != NULL) {
564564
pr_notice("seeding entropy pool\n");
565-
add_bootloader_randomness(seed->bits, seed->size);
565+
add_bootloader_randomness(seed->bits, size);
566566
early_memunmap(seed, sizeof(*seed) + size);
567567
} else {
568568
pr_err("Could not map UEFI random seed!\n");

0 commit comments

Comments
 (0)