* [PATCH] efi/libstub: disable file loading and page deallocation in mixed mode
@ 2019-12-13 9:11 Ard Biesheuvel
2019-12-13 12:29 ` Hans de Goede
0 siblings, 1 reply; 8+ messages in thread
From: Ard Biesheuvel @ 2019-12-13 9:11 UTC (permalink / raw)
To: linux-efi; +Cc: hdegoede, matthewgarrett, Ard Biesheuvel
EFI mixed mode is a nice hack, since it allows us to run 64-bit Linux
on low end x86_64 machines that shipped with 32-bit UEFI as they were
built to run 32-bit Windows only.
Mixed mode relies on the ability to convert calls made using the
64-bit calling convention into calls using the 32-bit one. This
involves pushing a 32-bit word onto the stack for each argument
passed in a 64-bit register, relying on the fact that all quantities
that are the native size or smaller (including pointers) can be safely
truncated to 32 bits. (In the pointer case, we rely on the fact that
we are still executing in the firmware context, which uses a 1:1
mapping that can only access the lower 4 GB of the address space)
For types that are explicitly 64 bits wide, such as EFI_PHYSICAL_ADDRESS
or UINT64, this assumption doesn't hold. The correct way to marshall
such a call would be to push two consecutive 32-bit words onto the
stack, but given that the naive thunking code has no knowledge
whatsoever of the prototype of the function it is invoking, all we can
do is avoid calling such functions altogether.
The FreePages() boot service is affected by this, so we should not call
that at all in mixed mode. In practice, this doesn't change much, since
in the past, these calls would have been made with a bogus address, and
so we were leaking this memory already. Note that the scope of this leak
is the EFI execution context only, so it makes no difference for Linux.
The other piece of functionality that we need to disable is loading files
passed via file=xxxx on the command line, given that the Open() method
takes two UINT64s as well.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
.../firmware/efi/libstub/efi-stub-helper.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 0f3dbfed6306..f1f316e96819 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -353,7 +353,12 @@ void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,
{
unsigned long nr_pages;
- if (!size)
+ /*
+ * Mixed mode does not support calling firmware routines that take
+ * explicit 64-bit wide arguments. So all we can do is leak the
+ * allocation.
+ */
+ if (!size || (IS_ENABLED(CONFIG_EFI_MIXED) && !efi_is_64bit()))
return;
nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
@@ -536,6 +541,18 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
char *str;
int i, j, k;
+ /*
+ * Using firmware services to load files is not supported in mixed mode
+ * systems, because it involves calling functions that have 64-bit wide
+ * parameters in their prototypes, which are not marshalled correctly
+ * by the thunking code.
+ */
+ if (IS_ENABLED(CONFIG_EFI_MIXED) && !efi_is_64bit()) {
+ pr_efi(sys_table_arg,
+ "Ignoring file= arguments on mixed mode system\n");
+ return EFI_SUCCESS;
+ }
+
file_addr = 0;
file_size_total = 0;
--
2.17.1
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH] efi/libstub: disable file loading and page deallocation in mixed mode
2019-12-13 9:11 [PATCH] efi/libstub: disable file loading and page deallocation in mixed mode Ard Biesheuvel
@ 2019-12-13 12:29 ` Hans de Goede
2019-12-13 18:49 ` Ard Biesheuvel
0 siblings, 1 reply; 8+ messages in thread
From: Hans de Goede @ 2019-12-13 12:29 UTC (permalink / raw)
To: Ard Biesheuvel, linux-efi; +Cc: matthewgarrett
Hi,
On 13-12-2019 10:11, Ard Biesheuvel wrote:
> EFI mixed mode is a nice hack, since it allows us to run 64-bit Linux
> on low end x86_64 machines that shipped with 32-bit UEFI as they were
> built to run 32-bit Windows only.
>
> Mixed mode relies on the ability to convert calls made using the
> 64-bit calling convention into calls using the 32-bit one. This
> involves pushing a 32-bit word onto the stack for each argument
> passed in a 64-bit register, relying on the fact that all quantities
> that are the native size or smaller (including pointers) can be safely
> truncated to 32 bits. (In the pointer case, we rely on the fact that
> we are still executing in the firmware context, which uses a 1:1
> mapping that can only access the lower 4 GB of the address space)
>
> For types that are explicitly 64 bits wide, such as EFI_PHYSICAL_ADDRESS
> or UINT64, this assumption doesn't hold. The correct way to marshall
> such a call would be to push two consecutive 32-bit words onto the
> stack, but given that the naive thunking code has no knowledge
> whatsoever of the prototype of the function it is invoking, all we can
> do is avoid calling such functions altogether.
>
> The FreePages() boot service is affected by this, so we should not call
> that at all in mixed mode. In practice, this doesn't change much, since
> in the past, these calls would have been made with a bogus address, and
> so we were leaking this memory already. Note that the scope of this leak
> is the EFI execution context only, so it makes no difference for Linux.
>
> The other piece of functionality that we need to disable is loading files
> passed via file=xxxx on the command line, given that the Open() method
> takes two UINT64s as well.
>
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Just ignoring the file= arguments is fine with me, as you say this has
been broken on mixed-mode since forever so likely no-one is using it:
Acked-by: Hans de Goede <hdegoede@redhat.com>
Regards,
Hans
> ---
> .../firmware/efi/libstub/efi-stub-helper.c | 19 ++++++++++++++++++-
> 1 file changed, 18 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
> index 0f3dbfed6306..f1f316e96819 100644
> --- a/drivers/firmware/efi/libstub/efi-stub-helper.c
> +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
> @@ -353,7 +353,12 @@ void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,
> {
> unsigned long nr_pages;
>
> - if (!size)
> + /*
> + * Mixed mode does not support calling firmware routines that take
> + * explicit 64-bit wide arguments. So all we can do is leak the
> + * allocation.
> + */
> + if (!size || (IS_ENABLED(CONFIG_EFI_MIXED) && !efi_is_64bit()))
> return;
>
> nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
> @@ -536,6 +541,18 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
> char *str;
> int i, j, k;
>
> + /*
> + * Using firmware services to load files is not supported in mixed mode
> + * systems, because it involves calling functions that have 64-bit wide
> + * parameters in their prototypes, which are not marshalled correctly
> + * by the thunking code.
> + */
> + if (IS_ENABLED(CONFIG_EFI_MIXED) && !efi_is_64bit()) {
> + pr_efi(sys_table_arg,
> + "Ignoring file= arguments on mixed mode system\n");
> + return EFI_SUCCESS;
> + }
> +
> file_addr = 0;
> file_size_total = 0;
>
>
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH] efi/libstub: disable file loading and page deallocation in mixed mode
2019-12-13 12:29 ` Hans de Goede
@ 2019-12-13 18:49 ` Ard Biesheuvel
2019-12-13 19:56 ` Hans de Goede
0 siblings, 1 reply; 8+ messages in thread
From: Ard Biesheuvel @ 2019-12-13 18:49 UTC (permalink / raw)
To: Hans de Goede; +Cc: Ard Biesheuvel, linux-efi, Matthew Garrett
On Fri, 13 Dec 2019 at 13:29, Hans de Goede <hdegoede@redhat.com> wrote:
>
> Hi,
>
> On 13-12-2019 10:11, Ard Biesheuvel wrote:
> > EFI mixed mode is a nice hack, since it allows us to run 64-bit Linux
> > on low end x86_64 machines that shipped with 32-bit UEFI as they were
> > built to run 32-bit Windows only.
> >
> > Mixed mode relies on the ability to convert calls made using the
> > 64-bit calling convention into calls using the 32-bit one. This
> > involves pushing a 32-bit word onto the stack for each argument
> > passed in a 64-bit register, relying on the fact that all quantities
> > that are the native size or smaller (including pointers) can be safely
> > truncated to 32 bits. (In the pointer case, we rely on the fact that
> > we are still executing in the firmware context, which uses a 1:1
> > mapping that can only access the lower 4 GB of the address space)
> >
> > For types that are explicitly 64 bits wide, such as EFI_PHYSICAL_ADDRESS
> > or UINT64, this assumption doesn't hold. The correct way to marshall
> > such a call would be to push two consecutive 32-bit words onto the
> > stack, but given that the naive thunking code has no knowledge
> > whatsoever of the prototype of the function it is invoking, all we can
> > do is avoid calling such functions altogether.
> >
> > The FreePages() boot service is affected by this, so we should not call
> > that at all in mixed mode. In practice, this doesn't change much, since
> > in the past, these calls would have been made with a bogus address, and
> > so we were leaking this memory already. Note that the scope of this leak
> > is the EFI execution context only, so it makes no difference for Linux.
> >
> > The other piece of functionality that we need to disable is loading files
> > passed via file=xxxx on the command line, given that the Open() method
> > takes two UINT64s as well.
> >
> > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
>
> Just ignoring the file= arguments is fine with me, as you say this has
> been broken on mixed-mode since forever so likely no-one is using it:
>
> Acked-by: Hans de Goede <hdegoede@redhat.com>
>
Thanks.
Do you have any recommendations on how to test this? Are you using GRUB to boot?
I am trying to test the random.c failure using QEMU+OVMF, which
implements the EFI_RNG_PROTOCOL on top of virtio-rng-pci, but I cannot
reproduce the failure.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] efi/libstub: disable file loading and page deallocation in mixed mode
2019-12-13 18:49 ` Ard Biesheuvel
@ 2019-12-13 19:56 ` Hans de Goede
2019-12-13 20:08 ` Ard Biesheuvel
0 siblings, 1 reply; 8+ messages in thread
From: Hans de Goede @ 2019-12-13 19:56 UTC (permalink / raw)
To: Ard Biesheuvel; +Cc: Ard Biesheuvel, linux-efi, Matthew Garrett
Hi,
On 12/13/19 7:49 PM, Ard Biesheuvel wrote:
> On Fri, 13 Dec 2019 at 13:29, Hans de Goede <hdegoede@redhat.com> wrote:
>>
>> Hi,
>>
>> On 13-12-2019 10:11, Ard Biesheuvel wrote:
>>> EFI mixed mode is a nice hack, since it allows us to run 64-bit Linux
>>> on low end x86_64 machines that shipped with 32-bit UEFI as they were
>>> built to run 32-bit Windows only.
>>>
>>> Mixed mode relies on the ability to convert calls made using the
>>> 64-bit calling convention into calls using the 32-bit one. This
>>> involves pushing a 32-bit word onto the stack for each argument
>>> passed in a 64-bit register, relying on the fact that all quantities
>>> that are the native size or smaller (including pointers) can be safely
>>> truncated to 32 bits. (In the pointer case, we rely on the fact that
>>> we are still executing in the firmware context, which uses a 1:1
>>> mapping that can only access the lower 4 GB of the address space)
>>>
>>> For types that are explicitly 64 bits wide, such as EFI_PHYSICAL_ADDRESS
>>> or UINT64, this assumption doesn't hold. The correct way to marshall
>>> such a call would be to push two consecutive 32-bit words onto the
>>> stack, but given that the naive thunking code has no knowledge
>>> whatsoever of the prototype of the function it is invoking, all we can
>>> do is avoid calling such functions altogether.
>>>
>>> The FreePages() boot service is affected by this, so we should not call
>>> that at all in mixed mode. In practice, this doesn't change much, since
>>> in the past, these calls would have been made with a bogus address, and
>>> so we were leaking this memory already. Note that the scope of this leak
>>> is the EFI execution context only, so it makes no difference for Linux.
>>>
>>> The other piece of functionality that we need to disable is loading files
>>> passed via file=xxxx on the command line, given that the Open() method
>>> takes two UINT64s as well.
>>>
>>> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
>>
>> Just ignoring the file= arguments is fine with me, as you say this has
>> been broken on mixed-mode since forever so likely no-one is using it:
>>
>> Acked-by: Hans de Goede <hdegoede@redhat.com>
>>
>
> Thanks.
>
> Do you have any recommendations on how to test this? Are you using GRUB to boot?
>
> I am trying to test the random.c failure using QEMU+OVMF, which
> implements the EFI_RNG_PROTOCOL on top of virtio-rng-pci, but I cannot
> reproduce the failure.
I hit the random.c issue when testing a 5.5-rc1 x86_64 kernel on a Bay Trail
tablet. Almost any Bay Trail hw will come with 32 bit uefi because when Bay
Trail tablets (and 2-in-1s) first hit the market the 64 bit Windows drivers
were not ready yet and running 32 bit Windows requires a 32 bit UEFI
(Bay Trail devices do not have a classic bios mode / CSM).
A popular model example machine of such a setup is The Asus T100TA 2-in-1.
I'm using a standard Fedora install on these machines which goes:
UEFI -> 32-bit-secureboot-shim -> 32-bit-uefi-grub -> 64 bit kernel
Regards,
Hans
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] efi/libstub: disable file loading and page deallocation in mixed mode
2019-12-13 19:56 ` Hans de Goede
@ 2019-12-13 20:08 ` Ard Biesheuvel
[not found] ` <f276df9f-83b4-e404-bcfc-91f0212a5fc0@redhat.com>
0 siblings, 1 reply; 8+ messages in thread
From: Ard Biesheuvel @ 2019-12-13 20:08 UTC (permalink / raw)
To: Hans de Goede; +Cc: Ard Biesheuvel, linux-efi, Matthew Garrett
On Fri, 13 Dec 2019 at 20:56, Hans de Goede <hdegoede@redhat.com> wrote:
>
> Hi,
>
> On 12/13/19 7:49 PM, Ard Biesheuvel wrote:
> > On Fri, 13 Dec 2019 at 13:29, Hans de Goede <hdegoede@redhat.com> wrote:
> >>
> >> Hi,
> >>
> >> On 13-12-2019 10:11, Ard Biesheuvel wrote:
> >>> EFI mixed mode is a nice hack, since it allows us to run 64-bit Linux
> >>> on low end x86_64 machines that shipped with 32-bit UEFI as they were
> >>> built to run 32-bit Windows only.
> >>>
> >>> Mixed mode relies on the ability to convert calls made using the
> >>> 64-bit calling convention into calls using the 32-bit one. This
> >>> involves pushing a 32-bit word onto the stack for each argument
> >>> passed in a 64-bit register, relying on the fact that all quantities
> >>> that are the native size or smaller (including pointers) can be safely
> >>> truncated to 32 bits. (In the pointer case, we rely on the fact that
> >>> we are still executing in the firmware context, which uses a 1:1
> >>> mapping that can only access the lower 4 GB of the address space)
> >>>
> >>> For types that are explicitly 64 bits wide, such as EFI_PHYSICAL_ADDRESS
> >>> or UINT64, this assumption doesn't hold. The correct way to marshall
> >>> such a call would be to push two consecutive 32-bit words onto the
> >>> stack, but given that the naive thunking code has no knowledge
> >>> whatsoever of the prototype of the function it is invoking, all we can
> >>> do is avoid calling such functions altogether.
> >>>
> >>> The FreePages() boot service is affected by this, so we should not call
> >>> that at all in mixed mode. In practice, this doesn't change much, since
> >>> in the past, these calls would have been made with a bogus address, and
> >>> so we were leaking this memory already. Note that the scope of this leak
> >>> is the EFI execution context only, so it makes no difference for Linux.
> >>>
> >>> The other piece of functionality that we need to disable is loading files
> >>> passed via file=xxxx on the command line, given that the Open() method
> >>> takes two UINT64s as well.
> >>>
> >>> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> >>
> >> Just ignoring the file= arguments is fine with me, as you say this has
> >> been broken on mixed-mode since forever so likely no-one is using it:
> >>
> >> Acked-by: Hans de Goede <hdegoede@redhat.com>
> >>
> >
> > Thanks.
> >
> > Do you have any recommendations on how to test this? Are you using GRUB to boot?
> >
> > I am trying to test the random.c failure using QEMU+OVMF, which
> > implements the EFI_RNG_PROTOCOL on top of virtio-rng-pci, but I cannot
> > reproduce the failure.
>
> I hit the random.c issue when testing a 5.5-rc1 x86_64 kernel on a Bay Trail
> tablet. Almost any Bay Trail hw will come with 32 bit uefi because when Bay
> Trail tablets (and 2-in-1s) first hit the market the 64 bit Windows drivers
> were not ready yet and running 32 bit Windows requires a 32 bit UEFI
> (Bay Trail devices do not have a classic bios mode / CSM).
>
> A popular model example machine of such a setup is The Asus T100TA 2-in-1.
>
> I'm using a standard Fedora install on these machines which goes:
> UEFI -> 32-bit-secureboot-shim -> 32-bit-uefi-grub -> 64 bit kernel
>
And after applying the fix, do you now get a RNG=0x.... on the line
that has ACPI, SMBIOS etc?
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2019-12-14 17:07 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-12-13 9:11 [PATCH] efi/libstub: disable file loading and page deallocation in mixed mode Ard Biesheuvel
2019-12-13 12:29 ` Hans de Goede
2019-12-13 18:49 ` Ard Biesheuvel
2019-12-13 19:56 ` Hans de Goede
2019-12-13 20:08 ` Ard Biesheuvel
[not found] ` <f276df9f-83b4-e404-bcfc-91f0212a5fc0@redhat.com>
2019-12-13 20:16 ` Ard Biesheuvel
2019-12-14 15:21 ` Hans de Goede
2019-12-14 17:07 ` Ard Biesheuvel
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.