On Mon, 11 Feb 2019 at 11:10, Chao Fan <fanc.fnst@xxxxxxxxxxxxxx> wrote: > > On Mon, Feb 11, 2019 at 09:57:02AM +0000, Ard Biesheuvel wrote: > >On Mon, 11 Feb 2019 at 10:56, Chao Fan <fanc.fnst@xxxxxxxxxxxxxx> wrote: > >> > >> On Mon, Feb 11, 2019 at 09:46:03AM +0000, Ard Biesheuvel wrote: > >> >On Mon, 11 Feb 2019 at 01:22, Borislav Petkov <bp@xxxxxxxxx> wrote: > >> >> > >> >> On Fri, Feb 08, 2019 at 10:53:22PM +0100, Borislav Petkov wrote: > >> >> > On Fri, Feb 08, 2019 at 12:44:51PM -0800, Guenter Roeck wrote: > >> >> > > Yes, the kernel boots if I comment out that function and have it return 0. > >> >> > > >> >> > Thanks, this localizes the issue significantly. > >> >> > >> >> Some observations: > >> >> > >> >> } else { > >> >> efi_config_table_32_t *tmp_table; > >> >> > >> >> tmp_table = config_tables; > >> >> guid = tmp_table->guid; <--- * > >> >> table = tmp_table->table; > >> >> } > >> >> > >> >> It blows up at that tmp_table->guid deref above. Singlestepping through > >> >> it with gdb shows: > >> >> > >> >> # arch/x86/boot/compressed/acpi.c:114: guid = tmp_table->guid; > >> >> movq (%rdi), %rax # MEM[(struct efi_config_table_32_t *)config_tables_37].guid, guid > >> >> movq 8(%rdi), %rsi # MEM[(struct efi_config_table_32_t *)config_tables_37].guid, guid > >> >> # arch/x86/boot/compressed/acpi.c:115: table = tmp_table->table; > >> >> movl 16(%rdi), %r10d # MEM[(struct efi_config_table_32_t *)config_tables_37].table, table > >> >> jmp .L30 # > >> >> > >> >> and %rdi has: > >> >> > >> >> rdi 0x630646870 > >> >> > >> >> which is an address above 4G but we're using a 32-bit EFI BIOS. > >> >> > >> >> Which begs the question whether EFI system tables can even be mapped at > >> >> something above 4G with a 32-bit EFI and whether that could work ok. > >> >> Hmm. > >> >> > >> >> Lemme add Ard and mfleming for insight here. > >> >> > >> > > >> >-ENOCONTEXT, but let me try in any case: > >> > > >> >linux/efi.h has > >> > > >> >typedef struct { > >> > efi_guid_t guid; > >> > u32 table; > >> >} efi_config_table_32_t; > >> > > >> >so if we end up with more than 32 bits set in table, there is > >> >something seriously wrong. > >> > > >> >The size of efi_config_table_32_t deviates from efi_config_table_64_t, > >> >so you will have to ensure that you are using the correct stride when > >> >iterating over config_tables. > >> > >> Here I use signature to judge it. > >> If the signature is EFI64_LOADER_SIGNATURE, I will use efi_config_table_64_t, > >> if the signature is EFI32_LOADER_SIGNATURE, I will use efi_config_table_32_t. > >> But the efi32 whose signature is EFI32_LOADER_SIGNATURE points to a > >> address above 4G, I am not sure whether this is normal and works well. > >> > > > >This is impossible. The 'table' member of efi_config_table_32_t is > >only 32 bits wide, so how can it contain an address over 4 GB ? > > Maybe I mislead you. In my code, I need to find the eficonfig_table_*. > After that, I should type cast it to right > efi_config_table_32_t or efi_config_table_64_t. > > Then my judgment is to compare its efi_info->efi_loader_signature. > If it's EFI64_LOADER_SIGNATURE, I will type cast it to efi_config_table_64_t. > If it's EFI32_LOADER_SIGNATURE, I will type cast it to efi_config_table_32_t. > > But here is a issue, its signature matches EFI32_LOADER_SIGNATURE, but > it's table member is above 4G, but I use efi_config_table_32_t. That cause a problem. > That still does not explain how 'table' can assume a value > 4 GB after assigning the contents of a u32 to it.
![]() |