Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1233090 > unrolled thread

[PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime

Started byMatt Fleming <matt@codeblueprint.co.uk>
First post2015-09-26 00:10 +0200
Last post2015-10-02 11:50 +0200
Articles 20 on this page of 32 — 9 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Matt Fleming <matt@codeblueprint.co.uk> - 2015-09-26 00:10 +0200
    Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Ingo Molnar <mingo@kernel.org> - 2015-09-26 08:00 +0200
      Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Ard Biesheuvel <ard.biesheuvel@linaro.org> - 2015-09-26 08:50 +0200
      Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Matt Fleming <matt@codeblueprint.co.uk> - 2015-09-26 15:50 +0200
        Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Ingo Molnar <mingo@kernel.org> - 2015-09-27 09:10 +0200
          Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Ard Biesheuvel <ard.biesheuvel@linaro.org> - 2015-09-28 08:50 +0200
            Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Ingo Molnar <mingo@kernel.org> - 2015-09-28 10:30 +0200
              Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Ard Biesheuvel <ard.biesheuvel@linaro.org> - 2015-09-28 12:00 +0200
                Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Ingo Molnar <mingo@kernel.org> - 2015-09-29 11:20 +0200
                  Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Ard Biesheuvel <ard.biesheuvel@linaro.org> - 2015-09-29 12:50 +0200
                    Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Matt Fleming <matt@codeblueprint.co.uk> - 2015-09-29 16:20 +0200
                  Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Matt Fleming <matt@codeblueprint.co.uk> - 2015-09-29 16:00 +0200
      Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Andy Lutomirski <luto@amacapital.net> - 2015-09-26 19:10 +0200
        Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime "H. Peter Anvin" <hpa@zytor.com> - 2015-09-26 19:30 +0200
          Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Ard Biesheuvel <ard.biesheuvel@linaro.org> - 2015-09-26 20:20 +0200
            Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Matt Fleming <matt@codeblueprint.co.uk> - 2015-09-26 22:00 +0200
              Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Ard Biesheuvel <ard.biesheuvel@linaro.org> - 2015-09-26 22:10 +0200
                Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime "H. Peter Anvin" <hpa@zytor.com> - 2015-09-26 22:30 +0200
                  Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Andy Lutomirski <luto@amacapital.net> - 2015-09-27 18:40 +0200
                    Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Matthew Garrett <mjg59@srcf.ucam.org> - 2015-09-27 20:40 +0200
                      Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Ingo Molnar <mingo@kernel.org> - 2015-09-28 08:20 +0200
                        Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Matthew Garrett <mjg59@srcf.ucam.org> - 2015-09-28 09:10 +0200
                          Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Laszlo Ersek <lersek@redhat.com> - 2015-09-30 00:00 +0200
                            Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Ard Biesheuvel <ard.biesheuvel@linaro.org> - 2015-09-30 11:40 +0200
                              Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Andy Lutomirski <luto@amacapital.net> - 2015-09-30 18:50 +0200
                                Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime James Bottomley <jbottomley@odin.com> - 2015-09-30 19:30 +0200
                        Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime "H. Peter Anvin" <hpa@zytor.com> - 2015-09-30 03:00 +0200
            Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime "H. Peter Anvin" <hpa@zytor.com> - 2015-09-26 22:00 +0200
          Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Matt Fleming <matt@codeblueprint.co.uk> - 2015-09-26 22:00 +0200
        Re: [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime Ingo Molnar <mingo@kernel.org> - 2015-09-27 09:00 +0200
    [tip:core/urgent] x86/efi:   Fix boot crash by mapping EFI memmap entries bottom-up at runtime,   instead of top-down tip-bot for Matt Fleming <tipbot@zytor.com> - 2015-10-01 15:00 +0200
      Re: [tip:core/urgent] x86/efi: Fix boot crash by mapping EFI memmap  entries bottom-up at runtime, instead of top-down Matt Fleming <matt@codeblueprint.co.uk> - 2015-10-02 11:50 +0200

Page 1 of 2  [1] 2  Next page →


#1233090 — [PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime

FromMatt Fleming <matt@codeblueprint.co.uk>
Date2015-09-26 00:10 +0200
Subject[PATCH 1/2] x86/efi: Map EFI memmap entries in-order at runtime
Message-ID<qcJlL-5Zx-7@gated-at.bofh.it>
From: Matt Fleming <matt.fleming@intel.com>

Beginning with UEFI v2.5 EFI_PROPERTIES_TABLE was introduced that
signals that the firmware PE/COFF loader supports splitting code and
data sections of PE/COFF images into separate EFI memory map entries.
This allows the kernel to map those regions with strict memory
protections, e.g. EFI_MEMORY_RO for code, EFI_MEMORY_XP for data, etc.

Unfortunately, an unwritten requirement of this new feature is that
the regions need to be mapped with the same offsets relative to each
other as observed in the EFI memory map. If this is not done crashes
like this may occur,

 [    0.006391] BUG: unable to handle kernel paging request at fffffffefe6086dd
 [    0.006923] IP: [<fffffffefe6086dd>] 0xfffffffefe6086dd
 [    0.007000] Call Trace:
 [    0.007000]  [<ffffffff8104c90e>] efi_call+0x7e/0x100
 [    0.007000]  [<ffffffff81602091>] ? virt_efi_set_variable+0x61/0x90
 [    0.007000]  [<ffffffff8104c583>] efi_delete_dummy_variable+0x63/0x70
 [    0.007000]  [<ffffffff81f4e4aa>] efi_enter_virtual_mode+0x383/0x392
 [    0.007000]  [<ffffffff81f37e1b>] start_kernel+0x38a/0x417
 [    0.007000]  [<ffffffff81f37495>] x86_64_start_reservations+0x2a/0x2c
 [    0.007000]  [<ffffffff81f37582>] x86_64_start_kernel+0xeb/0xef

Here 0xfffffffefe6086dd refers to an address the firmware expects to
be mapped but which the OS never claimed was mapped. The issue is that
included in these regions are relative addresses to other regions
which were emitted by the firmware toolchain before the "splitting" of
sections occurred at runtime.

Needless to say, we don't satisfy this unwritten requirement on x86_64
and instead map the EFI memory map entries in reverse order. The above
crash is almost certainly triggerable with any kernel newer than v3.13
because that's when we rewrote the EFI runtime region mapping code, in
commit d2f7cbe7b26a ("x86/efi: Runtime services virtual mapping"). For
kernel versions before v3.13 things may work by pure luck depending on
the fragmentation of the kernel virtual address space at the time we
map the EFI regions.

Instead of mapping the EFI memory map entries in reverse order, where
entry N has a higher virtual address than entry N+1, map them in the
same order as they appear in the EFI memory map to preserve this
relative offset between regions.

This patch has been kept as small as possible with the intention that
it should be applied aggressively to stable and distribution kernels.
It is very much a bugfix rather than support for a new feature, since
when EFI_PROPERTIES_TABLE is enabled we must map things as outlined
above to even boot - we have no way of asking the firmware not to
split the code/data regions.

In fact, this patch doesn't even make use of the more strict memory
protections available in UEFI v2.5. That will come later.

Reported-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Suggested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: "Lee, Chun-Yi" <jlee@suse.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Peter Jones <pjones@redhat.com>
Cc: James Bottomley <JBottomley@Odin.com>
Cc: Matthew Garrett <mjg59@srcf.ucam.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Dave Young <dyoung@redhat.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
---
 arch/x86/platform/efi/efi.c | 67 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 1db84c0758b7..6a28ded74211 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -705,6 +705,70 @@ out:
 }
 
 /*
+ * Iterate the EFI memory map in reverse order because the regions
+ * will be mapped top-down. The end result is the same as if we had
+ * mapped things forward, but doesn't require us to change the
+ * existing implementation of efi_map_region().
+ */
+static inline void *efi_map_next_entry_reverse(void *entry)
+{
+	/* Initial call */
+	if (!entry)
+		return memmap.map_end - memmap.desc_size;
+
+	entry -= memmap.desc_size;
+	if (entry < memmap.map)
+		return NULL;
+
+	return entry;
+}
+
+/*
+ * efi_map_next_entry - Return the next EFI memory map descriptor
+ * @entry: Previous EFI memory map descriptor
+ *
+ * This is a helper function to iterate over the EFI memory map, which
+ * we do in different orders depending on the current configuration.
+ *
+ * To begin traversing the memory map @entry must be %NULL.
+ *
+ * Returns %NULL when we reach the end of the memory map.
+ */
+static void *efi_map_next_entry(void *entry)
+{
+	if (!efi_enabled(EFI_OLD_MEMMAP) && efi_enabled(EFI_64BIT)) {
+		/*
+		 * Starting in UEFI v2.5 the EFI_PROPERTIES_TABLE
+		 * config table feature requires us to map all entries
+		 * in the same order as they appear in the EFI memory
+		 * map. That is to say, entry N must have a lower
+		 * virtual address than entry N+1. This is because the
+		 * firmware toolchain leaves relative references in
+		 * the code/data sections, which are split and become
+		 * separate EFI memory regions. Mapping things
+		 * out-of-order leads to the firmware accessing
+		 * unmapped addresses.
+		 *
+		 * Since we need to map things this way whether or not
+		 * the kernel actually makes use of
+		 * EFI_PROPERTIES_TABLE, let's just switch to this
+		 * scheme by default for 64-bit.
+		 */
+		return efi_map_next_entry_reverse(entry);
+	}
+
+	/* Initial call */
+	if (!entry)
+		return memmap.map;
+
+	entry += memmap.desc_size;
+	if (entry >= memmap.map_end)
+		return NULL;
+
+	return entry;
+}
+
+/*
  * Map the efi memory ranges of the runtime services and update new_mmap with
  * virtual addresses.
  */
@@ -714,7 +778,8 @@ static void * __init efi_map_regions(int *count, int *pg_shift)
 	unsigned long left = 0;
 	efi_memory_desc_t *md;
 
-	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+	p = NULL;
+	while ((p = efi_map_next_entry(p))) {
 		md = p;
 		if (!(md->attribute & EFI_MEMORY_RUNTIME)) {
 #ifdef CONFIG_X86_64
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1233149

FromIngo Molnar <mingo@kernel.org>
Date2015-09-26 08:00 +0200
Message-ID<qcQGB-7R0-1@gated-at.bofh.it>
In reply to#1233090
So this commit worries me.

This bug is a good find, and the fix is obviously needed and urgent, but I'm not 
sure about the implementation at all. (I've Cc:-ed a few more x86 low level 
gents.)

* Matt Fleming <matt@codeblueprint.co.uk> wrote:

>  /*
> + * Iterate the EFI memory map in reverse order because the regions
> + * will be mapped top-down. The end result is the same as if we had
> + * mapped things forward, but doesn't require us to change the
> + * existing implementation of efi_map_region().
> + */
> +static inline void *efi_map_next_entry_reverse(void *entry)
> +{
> +	/* Initial call */
> +	if (!entry)
> +		return memmap.map_end - memmap.desc_size;
> +
> +	entry -= memmap.desc_size;
> +	if (entry < memmap.map)
> +		return NULL;
> +
> +	return entry;
> +}
> +
> +/*
> + * efi_map_next_entry - Return the next EFI memory map descriptor
> + * @entry: Previous EFI memory map descriptor
> + *
> + * This is a helper function to iterate over the EFI memory map, which
> + * we do in different orders depending on the current configuration.
> + *
> + * To begin traversing the memory map @entry must be %NULL.
> + *
> + * Returns %NULL when we reach the end of the memory map.
> + */
> +static void *efi_map_next_entry(void *entry)
> +{
> +	if (!efi_enabled(EFI_OLD_MEMMAP) && efi_enabled(EFI_64BIT)) {
> +		/*
> +		 * Starting in UEFI v2.5 the EFI_PROPERTIES_TABLE
> +		 * config table feature requires us to map all entries
> +		 * in the same order as they appear in the EFI memory
> +		 * map. That is to say, entry N must have a lower
> +		 * virtual address than entry N+1. This is because the
> +		 * firmware toolchain leaves relative references in
> +		 * the code/data sections, which are split and become
> +		 * separate EFI memory regions. Mapping things
> +		 * out-of-order leads to the firmware accessing
> +		 * unmapped addresses.
> +		 *
> +		 * Since we need to map things this way whether or not
> +		 * the kernel actually makes use of
> +		 * EFI_PROPERTIES_TABLE, let's just switch to this
> +		 * scheme by default for 64-bit.

The thing is, if relative accesses between these 'sections' do happen then the 
requirement is much stronger than just 'ordered by addresses' - then we must map 
them continuously and as a single block!

So at minimum the comment should say that. But I think we want more:


> +		 */
> +		return efi_map_next_entry_reverse(entry);
> +	}
> +
> +	/* Initial call */
> +	if (!entry)
> +		return memmap.map;
> +
> +	entry += memmap.desc_size;
> +	if (entry >= memmap.map_end)
> +		return NULL;
> +
> +	return entry;
> +}
> +
> +/*
>   * Map the efi memory ranges of the runtime services and update new_mmap with
>   * virtual addresses.
>   */
> @@ -714,7 +778,8 @@ static void * __init efi_map_regions(int *count, int *pg_shift)
>  	unsigned long left = 0;
>  	efi_memory_desc_t *md;
>  
> -	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
> +	p = NULL;
> +	while ((p = efi_map_next_entry(p))) {
>  		md = p;
>  		if (!(md->attribute & EFI_MEMORY_RUNTIME)) {

So why is this 64-bit only? Is 32-bit not affected because there we allocate 
virtual addresses bottom-up?

This would be a lot clearer if we just mapped the entries in order, no questions 
asked. Conditions like this:

> +	if (!efi_enabled(EFI_OLD_MEMMAP) && efi_enabled(EFI_64BIT)) {

... just invite confusion and possible corner cases where we end up mapping them 
wrong.

So could we make the whole code obviously bottom-up? Such as first calculating the 
size of virtual memory needed, then allocating a _single_, obviously continuous 
mapping, and then doing a very clear in-order mapping within that window? That 
would remove any bitness and legacy dependencies.

Good virtual memory layout is so critical for any third party code that this 
should be the central property of the whole approach, not just some side condition 
somewhere in an iteration loop.

Thanks,

	Ingo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1233158

FromArd Biesheuvel <ard.biesheuvel@linaro.org>
Date2015-09-26 08:50 +0200
Message-ID<qcRt0-Af-3@gated-at.bofh.it>
In reply to#1233149
On 25 September 2015 at 22:56, Ingo Molnar <mingo@kernel.org> wrote:
>
> So this commit worries me.
>
> This bug is a good find, and the fix is obviously needed and urgent, but I'm not
> sure about the implementation at all. (I've Cc:-ed a few more x86 low level
> gents.)
>
> * Matt Fleming <matt@codeblueprint.co.uk> wrote:
>
>>  /*
>> + * Iterate the EFI memory map in reverse order because the regions
>> + * will be mapped top-down. The end result is the same as if we had
>> + * mapped things forward, but doesn't require us to change the
>> + * existing implementation of efi_map_region().
>> + */
>> +static inline void *efi_map_next_entry_reverse(void *entry)
>> +{
>> +     /* Initial call */
>> +     if (!entry)
>> +             return memmap.map_end - memmap.desc_size;
>> +
>> +     entry -= memmap.desc_size;
>> +     if (entry < memmap.map)
>> +             return NULL;
>> +
>> +     return entry;
>> +}
>> +
>> +/*
>> + * efi_map_next_entry - Return the next EFI memory map descriptor
>> + * @entry: Previous EFI memory map descriptor
>> + *
>> + * This is a helper function to iterate over the EFI memory map, which
>> + * we do in different orders depending on the current configuration.
>> + *
>> + * To begin traversing the memory map @entry must be %NULL.
>> + *
>> + * Returns %NULL when we reach the end of the memory map.
>> + */
>> +static void *efi_map_next_entry(void *entry)
>> +{
>> +     if (!efi_enabled(EFI_OLD_MEMMAP) && efi_enabled(EFI_64BIT)) {
>> +             /*
>> +              * Starting in UEFI v2.5 the EFI_PROPERTIES_TABLE
>> +              * config table feature requires us to map all entries
>> +              * in the same order as they appear in the EFI memory
>> +              * map. That is to say, entry N must have a lower
>> +              * virtual address than entry N+1. This is because the
>> +              * firmware toolchain leaves relative references in
>> +              * the code/data sections, which are split and become
>> +              * separate EFI memory regions. Mapping things
>> +              * out-of-order leads to the firmware accessing
>> +              * unmapped addresses.
>> +              *
>> +              * Since we need to map things this way whether or not
>> +              * the kernel actually makes use of
>> +              * EFI_PROPERTIES_TABLE, let's just switch to this
>> +              * scheme by default for 64-bit.
>
> The thing is, if relative accesses between these 'sections' do happen then the
> requirement is much stronger than just 'ordered by addresses' - then we must map
> them continuously and as a single block!
>

The primary difference between pre-2.5 and 2.5 with this feature
enabled is that formerly, each PE/COFF image in memory would be
covered by at most a single EfiRuntimeServicesCode region, and now, a
single PE/COFF image may be split into different regions. It is only
relative references *inside* such a PE/COFF image that we are
concerned about, since no symbol references exist between separate
ones.

Also, it is not only relative references inside the PE/COFF image that
cause the problem. Another aspect is that the offset that is applied
to all absolute references at relocation time is derived from the
offset of the base of the PE/COFF image. If part of the PE/COFF image
(the .data section) is moved relatively to the code section, these
absolute references are fixed up incorrectly. This is actually a
problem that we could solve at the firmware side, but since PE/COFF
does not really tolerate being split up like that, the correct fix is
to keep all regions belonging to a single PE/COFF image adjacent.
Since we can't tell which those regions are, the next best approach is
to keep all adjacent regions with the EFI_MEMORY_RUNTIME attribute
adjacent in the VA mapping.

-- 
Ard.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1233204

FromMatt Fleming <matt@codeblueprint.co.uk>
Date2015-09-26 15:50 +0200
Message-ID<qcY1s-1z3-11@gated-at.bofh.it>
In reply to#1233149
On Sat, 26 Sep, at 07:56:43AM, Ingo Molnar wrote:
> 
> So this commit worries me.
> 
> This bug is a good find, and the fix is obviously needed and urgent, but I'm not 
> sure about the implementation at all. (I've Cc:-ed a few more x86 low level 
> gents.)
 
Thanks, the more the merrier.

> * Matt Fleming <matt@codeblueprint.co.uk> wrote:
> 
> >  /*
> > + * Iterate the EFI memory map in reverse order because the regions
> > + * will be mapped top-down. The end result is the same as if we had
> > + * mapped things forward, but doesn't require us to change the
> > + * existing implementation of efi_map_region().
> > + */
> > +static inline void *efi_map_next_entry_reverse(void *entry)
> > +{
> > +	/* Initial call */
> > +	if (!entry)
> > +		return memmap.map_end - memmap.desc_size;
> > +
> > +	entry -= memmap.desc_size;
> > +	if (entry < memmap.map)
> > +		return NULL;
> > +
> > +	return entry;
> > +}
> > +
> > +/*
> > + * efi_map_next_entry - Return the next EFI memory map descriptor
> > + * @entry: Previous EFI memory map descriptor
> > + *
> > + * This is a helper function to iterate over the EFI memory map, which
> > + * we do in different orders depending on the current configuration.
> > + *
> > + * To begin traversing the memory map @entry must be %NULL.
> > + *
> > + * Returns %NULL when we reach the end of the memory map.
> > + */
> > +static void *efi_map_next_entry(void *entry)
> > +{
> > +	if (!efi_enabled(EFI_OLD_MEMMAP) && efi_enabled(EFI_64BIT)) {
> > +		/*
> > +		 * Starting in UEFI v2.5 the EFI_PROPERTIES_TABLE
> > +		 * config table feature requires us to map all entries
> > +		 * in the same order as they appear in the EFI memory
> > +		 * map. That is to say, entry N must have a lower
> > +		 * virtual address than entry N+1. This is because the
> > +		 * firmware toolchain leaves relative references in
> > +		 * the code/data sections, which are split and become
> > +		 * separate EFI memory regions. Mapping things
> > +		 * out-of-order leads to the firmware accessing
> > +		 * unmapped addresses.
> > +		 *
> > +		 * Since we need to map things this way whether or not
> > +		 * the kernel actually makes use of
> > +		 * EFI_PROPERTIES_TABLE, let's just switch to this
> > +		 * scheme by default for 64-bit.
> 
> The thing is, if relative accesses between these 'sections' do happen then the 
> requirement is much stronger than just 'ordered by addresses' - then we must map 
> them continuously and as a single block!
> 
> So at minimum the comment should say that. But I think we want more:
 
Well, the firmware doesn't place arbitrary gaps between these runtime
image sections in memory, they still get loaded into memory by the
firmware the old-fashioned way (as one contiguous blob). It's just
that we've now got two memory map entries for the single PE/COFF
image. Also, it's only sections from the same PE/COFF image that
reference each other (but like Ard said, we can't tell from the memmap
which entries are for a single PE/COFF image).

Because EFI memory map entries that are part of the same PE/COFF image
will be at consecutive addresses, we'll also map them contiguously in
the kernel virtual address space, because that's how the current code
works - it's just that the current code maps them backwards.

Yeah, I'm completely in favour of improving any of the comments. 
 
> > +		 */
> > +		return efi_map_next_entry_reverse(entry);
> > +	}
> > +
> > +	/* Initial call */
> > +	if (!entry)
> > +		return memmap.map;
> > +
> > +	entry += memmap.desc_size;
> > +	if (entry >= memmap.map_end)
> > +		return NULL;
> > +
> > +	return entry;
> > +}
> > +
> > +/*
> >   * Map the efi memory ranges of the runtime services and update new_mmap with
> >   * virtual addresses.
> >   */
> > @@ -714,7 +778,8 @@ static void * __init efi_map_regions(int *count, int *pg_shift)
> >  	unsigned long left = 0;
> >  	efi_memory_desc_t *md;
> >  
> > -	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
> > +	p = NULL;
> > +	while ((p = efi_map_next_entry(p))) {
> >  		md = p;
> >  		if (!(md->attribute & EFI_MEMORY_RUNTIME)) {
> 
> So why is this 64-bit only? Is 32-bit not affected because there we allocate 
> virtual addresses bottom-up?
 
32-bit would potentially be effected if 32-bit firmware ever enabled
the EFI_PROPERTIES_TABLE feature. Whether or not it worked would
depend on the fragemntation of the virtual memory space when we map
the EFI regions.

But I'm not aware of any 32-bit firmware shipping with Properties
Table support, and fixing it in the kernel like we do for x86-64 would
require changing the EFI region mapping code. That's something I
wanted to avoid for this patch since it needs to be applied to stable,
and especially when we haven't seen the feature being used in the
wild.

> This would be a lot clearer if we just mapped the entries in order, no questions 
> asked. Conditions like this:
> 
> > +	if (!efi_enabled(EFI_OLD_MEMMAP) && efi_enabled(EFI_64BIT)) {
> 
> ... just invite confusion and possible corner cases where we end up mapping them 
> wrong.
 
When we introduced the top-down scheme in commit d2f7cbe7b26a
("x86/efi: Runtime services virtual mapping") we also introduced the
"efi=old_map" kernel parameter to force the old virtual address
allocation scheme exactly because we were concerned we might run into
firmware "issues" with the way we mapped things.

That concern hasn't gone away now - it's intensified.

The above conditional just codifies a config combination that we've
always treated differently, and the conditional logic is only
necessary because this is generic x86 code.

I agree that it would be nicer without the conditional code, but
forcing the same allocation scheme across 32-bit and 64-bit is a
*much* bigger change than what is proposed here. Not just in terms of
patch size, but also in terms of risk.

> So could we make the whole code obviously bottom-up? Such as first calculating the 
> size of virtual memory needed, then allocating a _single_, obviously continuous 
> mapping, and then doing a very clear in-order mapping within that window? That 
> would remove any bitness and legacy dependencies.
 
So, we could, and in fact the first version of this patch did just
that. You can find it here,

  https://lkml.kernel.org/r/1441372447-23439-1-git-send-email-matt@codeblueprint.co.uk

But Ard suggested re-using the existing code and simply changing the
order we map the memmap entries in. And given the constraint for a
small patch for backporting, I think it's a better solution. The
actual virtual addresses we pick are exactly the same with the two
patches.

-- 
Matt Fleming, Intel Open Source Technology Center
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1233630

FromIngo Molnar <mingo@kernel.org>
Date2015-09-27 09:10 +0200
Message-ID<qdefT-8pw-5@gated-at.bofh.it>
In reply to#1233204
* Matt Fleming <matt@codeblueprint.co.uk> wrote:

> > So could we make the whole code obviously bottom-up? Such as first calculating 
> > the size of virtual memory needed, then allocating a _single_, obviously 
> > continuous mapping, and then doing a very clear in-order mapping within that 
> > window? That would remove any bitness and legacy dependencies.
>  
> So, we could, and in fact the first version of this patch did just that. You can 
> find it here,
> 
>   https://lkml.kernel.org/r/1441372447-23439-1-git-send-email-matt@codeblueprint.co.uk
> 
> But Ard suggested re-using the existing code and simply changing the order we 
> map the memmap entries in.

Such implementational arguments (which are an internal cost) never trump 
compatibility and robustness concerns (which are an external constraint).

> [...] And given the constraint for a small patch for backporting, I think it's a 
> better solution. [...]

Ugh, backporting size is _even less_ of a valid argument when it comes to firmware 
support correctness!

We can (perhaps) use these already existing patches as a simpler backport, but 
there's absolutely no reason to keep that code as a solution:

> [...] The actual virtual addresses we pick are exactly the same with the two 
> patches.

So I'm NAK-ing this for now:

 - The code is it reads today pretends to be an 'allocator'. It is _NOT_ an
   allocator, because all the sections have already been determined by the
   firmware, and, as we just learned the hard way, we do not want to deviate from 
   that! There's nothing to 'allocate'!

   What these patches seem to implement is an elaborate 'allocator' that ends up
   doing nothing on 'new 64-bit' ...

 - The 32-bit and 64-bit and 'old_mmap' asymmetries:

	if (!efi_enabled(EFI_OLD_MEMMAP) && efi_enabled(EFI_64BIT)) {

   seem fragile and nonsensical. The question is: is it possible for the whole EFI
   image to be larger than a couple of megabytes? If not then 32-bit should just
   mirror the firmware layout as well, and if EFI_OLD_MEMMAP does anything
   differently from this _obvious_ 1:1 mapping of the EFI memory offsets then it's
   not worth keeping as a legacy, because there's just nothing better than
   mirroring the firmware layout.

My suggestion would be to just 1:1 map what the EFI tables describe, modulo the 
single absolute offset by which we shift the whole thing to a single base.

Is there any technical reason why we'd want to deviate from that? Gigabytes of 
tables or gigabytes of holes that 32-bit cannot handle? Firmware that wants an OS 
layout that differs from the firmware layout?

Also, nobody seems to be asking the obvious hardware compatibility question when 
trying to implement a standard influenced in great part by an entity that is 
partly ignorant of and partly hostile to Linux: how does Windows map the EFI 
sections, under what OSs are these firmware versions tested? I suspect no firmware 
is released that crashes on bootup on all OSs that can run on that hardware, 
right?

Thanks,

	Ingo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1233887

FromArd Biesheuvel <ard.biesheuvel@linaro.org>
Date2015-09-28 08:50 +0200
Message-ID<qdAq6-6nd-17@gated-at.bofh.it>
In reply to#1233630
On 27 September 2015 at 08:03, Ingo Molnar <mingo@kernel.org> wrote:
>
> * Matt Fleming <matt@codeblueprint.co.uk> wrote:
>
[...]
>> [...] The actual virtual addresses we pick are exactly the same with the two
>> patches.
>
> So I'm NAK-ing this for now:
>
>  - The code is it reads today pretends to be an 'allocator'. It is _NOT_ an
>    allocator, because all the sections have already been determined by the
>    firmware, and, as we just learned the hard way, we do not want to deviate from
>    that! There's nothing to 'allocate'!
>
>    What these patches seem to implement is an elaborate 'allocator' that ends up
>    doing nothing on 'new 64-bit' ...
>
>  - The 32-bit and 64-bit and 'old_mmap' asymmetries:
>
>         if (!efi_enabled(EFI_OLD_MEMMAP) && efi_enabled(EFI_64BIT)) {
>
>    seem fragile and nonsensical. The question is: is it possible for the whole EFI
>    image to be larger than a couple of megabytes? If not then 32-bit should just
>    mirror the firmware layout as well, and if EFI_OLD_MEMMAP does anything
>    differently from this _obvious_ 1:1 mapping of the EFI memory offsets then it's
>    not worth keeping as a legacy, because there's just nothing better than
>    mirroring the firmware layout.
>
> My suggestion would be to just 1:1 map what the EFI tables describe, modulo the
> single absolute offset by which we shift the whole thing to a single base.
>
> Is there any technical reason why we'd want to deviate from that? Gigabytes of
> tables or gigabytes of holes that 32-bit cannot handle? Firmware that wants an OS
> layout that differs from the firmware layout?
>

The combined EFI_MEMORY_RUNTIME regions could span the entire 1:1
addressable PA space. They usually don't but it is a possibility,
which means 32-bit will not generally be able to support this
approach. For 64-bit ARM, there are some minor complications when the
base of RAM is up very high in physical memory, but we already fixed
that for the boot time ID map and for KVM.

> Also, nobody seems to be asking the obvious hardware compatibility question when
> trying to implement a standard influenced in great part by an entity that is
> partly ignorant of and partly hostile to Linux: how does Windows map the EFI
> sections, under what OSs are these firmware versions tested? I suspect no firmware
> is released that crashes on bootup on all OSs that can run on that hardware,
> right?
>

Interestingly, it was the other way around this time. The engineers
that implemented this feature for EDK2 could not boot Windows 8
anymore, because it supposedly maps the regions in reverse order as
well (and MS too will need to backport a fix that inverts the mapping
order). The engineers also tested Linux/x86, by means of a SUSE
installer image, which booted fine, most likely due to the fact that
it is an older version which still uses the old memmap layout.

My concern with all of this is that this security feature will become
an obscure opt-in feature rather than something UEFIv2.5 firmware
implementations can enable by default.
-- 
Ard.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1233939

FromIngo Molnar <mingo@kernel.org>
Date2015-09-28 10:30 +0200
Message-ID<qdBYS-h9-21@gated-at.bofh.it>
In reply to#1233887
* Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:

> On 27 September 2015 at 08:03, Ingo Molnar <mingo@kernel.org> wrote:
> >
> > * Matt Fleming <matt@codeblueprint.co.uk> wrote:
> >
> [...]
> >> [...] The actual virtual addresses we pick are exactly the same with the two
> >> patches.
> >
> > So I'm NAK-ing this for now:
> >
> >  - The code is it reads today pretends to be an 'allocator'. It is _NOT_ an
> >    allocator, because all the sections have already been determined by the
> >    firmware, and, as we just learned the hard way, we do not want to deviate from
> >    that! There's nothing to 'allocate'!
> >
> >    What these patches seem to implement is an elaborate 'allocator' that ends up
> >    doing nothing on 'new 64-bit' ...
> >
> >  - The 32-bit and 64-bit and 'old_mmap' asymmetries:
> >
> >         if (!efi_enabled(EFI_OLD_MEMMAP) && efi_enabled(EFI_64BIT)) {
> >
> >    seem fragile and nonsensical. The question is: is it possible for the whole EFI
> >    image to be larger than a couple of megabytes? If not then 32-bit should just
> >    mirror the firmware layout as well, and if EFI_OLD_MEMMAP does anything
> >    differently from this _obvious_ 1:1 mapping of the EFI memory offsets then it's
> >    not worth keeping as a legacy, because there's just nothing better than
> >    mirroring the firmware layout.
> >
> > My suggestion would be to just 1:1 map what the EFI tables describe, modulo the
> > single absolute offset by which we shift the whole thing to a single base.
> >
> > Is there any technical reason why we'd want to deviate from that? Gigabytes of
> > tables or gigabytes of holes that 32-bit cannot handle? Firmware that wants an OS
> > layout that differs from the firmware layout?
> >
> 
> The combined EFI_MEMORY_RUNTIME regions could span the entire 1:1 addressable PA 
> space. They usually don't but it is a possibility, which means 32-bit will not 
> generally be able to support this approach. [...]

Ok, that's a good argument which invalidates my NAK.

> [...] For 64-bit ARM, there are some minor complications when the base of RAM is 
> up very high in physical memory, but we already fixed that for the boot time ID 
> map and for KVM.
> 
> > Also, nobody seems to be asking the obvious hardware compatibility question 
> > when trying to implement a standard influenced in great part by an entity that 
> > is partly ignorant of and partly hostile to Linux: how does Windows map the 
> > EFI sections, under what OSs are these firmware versions tested? I suspect no 
> > firmware is released that crashes on bootup on all OSs that can run on that 
> > hardware, right?
> 
> Interestingly, it was the other way around this time. The engineers that 
> implemented this feature for EDK2 could not boot Windows 8 anymore, because it 
> supposedly maps the regions in reverse order as well (and MS too will need to 
> backport a fix that inverts the mapping order). The engineers also tested 
> Linux/x86, by means of a SUSE installer image, which booted fine, most likely 
> due to the fact that it is an older version which still uses the old memmap 
> layout.

That's nice to hear!

> My concern with all of this is that this security feature will become an obscure 
> opt-in feature rather than something UEFIv2.5 firmware implementations can 
> enable by default.

Ok, so I think the patches are mostly fine after all, except that I don't think 
the condition on 64-bit makes any sense:

+       if (!efi_enabled(EFI_OLD_MEMMAP) && efi_enabled(EFI_64BIT)) {

I can see us being nervous wrt. backported patches, but is there any strong reason 
to not follow this up with a third (non-backported) patch that changes this to:

+       if (!efi_enabled(EFI_OLD_MEMMAP)) {

for v4.4?

Thanks,

	Ingo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1233998

FromArd Biesheuvel <ard.biesheuvel@linaro.org>
Date2015-09-28 12:00 +0200
Message-ID<qdDnX-28T-7@gated-at.bofh.it>
In reply to#1233939
On 28 September 2015 at 09:22, Ingo Molnar <mingo@kernel.org> wrote:
>
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>
>> On 27 September 2015 at 08:03, Ingo Molnar <mingo@kernel.org> wrote:
>> >
>> > * Matt Fleming <matt@codeblueprint.co.uk> wrote:
>> >
>> [...]
>> >> [...] The actual virtual addresses we pick are exactly the same with the two
>> >> patches.
>> >
>> > So I'm NAK-ing this for now:
>> >
>> >  - The code is it reads today pretends to be an 'allocator'. It is _NOT_ an
>> >    allocator, because all the sections have already been determined by the
>> >    firmware, and, as we just learned the hard way, we do not want to deviate from
>> >    that! There's nothing to 'allocate'!
>> >
>> >    What these patches seem to implement is an elaborate 'allocator' that ends up
>> >    doing nothing on 'new 64-bit' ...
>> >
>> >  - The 32-bit and 64-bit and 'old_mmap' asymmetries:
>> >
>> >         if (!efi_enabled(EFI_OLD_MEMMAP) && efi_enabled(EFI_64BIT)) {
>> >
>> >    seem fragile and nonsensical. The question is: is it possible for the whole EFI
>> >    image to be larger than a couple of megabytes? If not then 32-bit should just
>> >    mirror the firmware layout as well, and if EFI_OLD_MEMMAP does anything
>> >    differently from this _obvious_ 1:1 mapping of the EFI memory offsets then it's
>> >    not worth keeping as a legacy, because there's just nothing better than
>> >    mirroring the firmware layout.
>> >
>> > My suggestion would be to just 1:1 map what the EFI tables describe, modulo the
>> > single absolute offset by which we shift the whole thing to a single base.
>> >
>> > Is there any technical reason why we'd want to deviate from that? Gigabytes of
>> > tables or gigabytes of holes that 32-bit cannot handle? Firmware that wants an OS
>> > layout that differs from the firmware layout?
>> >
>>
>> The combined EFI_MEMORY_RUNTIME regions could span the entire 1:1 addressable PA
>> space. They usually don't but it is a possibility, which means 32-bit will not
>> generally be able to support this approach. [...]
>
> Ok, that's a good argument which invalidates my NAK.
>
>> [...] For 64-bit ARM, there are some minor complications when the base of RAM is
>> up very high in physical memory, but we already fixed that for the boot time ID
>> map and for KVM.
>>
>> > Also, nobody seems to be asking the obvious hardware compatibility question
>> > when trying to implement a standard influenced in great part by an entity that
>> > is partly ignorant of and partly hostile to Linux: how does Windows map the
>> > EFI sections, under what OSs are these firmware versions tested? I suspect no
>> > firmware is released that crashes on bootup on all OSs that can run on that
>> > hardware, right?
>>
>> Interestingly, it was the other way around this time. The engineers that
>> implemented this feature for EDK2 could not boot Windows 8 anymore, because it
>> supposedly maps the regions in reverse order as well (and MS too will need to
>> backport a fix that inverts the mapping order). The engineers also tested
>> Linux/x86, by means of a SUSE installer image, which booted fine, most likely
>> due to the fact that it is an older version which still uses the old memmap
>> layout.
>
> That's nice to hear!
>
>> My concern with all of this is that this security feature will become an obscure
>> opt-in feature rather than something UEFIv2.5 firmware implementations can
>> enable by default.
>
> Ok, so I think the patches are mostly fine after all,

That is good to hear.

> except that I don't think
> the condition on 64-bit makes any sense:
>
> +       if (!efi_enabled(EFI_OLD_MEMMAP) && efi_enabled(EFI_64BIT)) {
>
> I can see us being nervous wrt. backported patches, but is there any strong reason
> to not follow this up with a third (non-backported) patch that changes this to:
>
> +       if (!efi_enabled(EFI_OLD_MEMMAP)) {
>
> for v4.4?
>

The 32-bit side essentially implements the old memmap only, which is
the the bottom-up version. So old memmap will be implied by 32-bit but
not set in the EFI flags, resulting in the reverse enumeration being
used with the bottom-up mapping logic. The net result of that is that
we create the same problem for 32-bit that we are trying to solve for
64-bit, i.e., the regions will end up in reverse order in the VA
mapping.

To deobfuscate this particular conditional, we could set
EFI_OLD_MEMMAP unconditionally on 32-bit x86. Or we could reshuffle
variables and conditionals in various other way. I am not convinced
that the overall end result will be any better though.

-- 
Ard.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1234901

FromIngo Molnar <mingo@kernel.org>
Date2015-09-29 11:20 +0200
Message-ID<qdZeQ-2b3-45@gated-at.bofh.it>
In reply to#1233998
* Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:

> > except that I don't think
> > the condition on 64-bit makes any sense:
> >
> > +       if (!efi_enabled(EFI_OLD_MEMMAP) && efi_enabled(EFI_64BIT)) {
> >
> > I can see us being nervous wrt. backported patches, but is there any strong reason
> > to not follow this up with a third (non-backported) patch that changes this to:
> >
> > +       if (!efi_enabled(EFI_OLD_MEMMAP)) {
> >
> > for v4.4?
> >
> 
> The 32-bit side essentially implements the old memmap only, which is the the 
> bottom-up version. So old memmap will be implied by 32-bit but not set in the 
> EFI flags, resulting in the reverse enumeration being used with the bottom-up 
> mapping logic. The net result of that is that we create the same problem for 
> 32-bit that we are trying to solve for 64-bit, i.e., the regions will end up in 
> reverse order in the VA mapping.
> 
> To deobfuscate this particular conditional, we could set EFI_OLD_MEMMAP 
> unconditionally on 32-bit x86. Or we could reshuffle variables and conditionals 
> in various other way.

Setting EFI_OLD_MEMMAP would be fine, if doing that has no bad side effects.

> [...] I am not convinced that the overall end result will be any better though.

That's not true, we change an obscure, implicit dependency on 32-bit detail to an 
explicit EFI_OLD_MEMMAP flag that shows exactly what's happening. That's a clear 
improvement.

Thanks,

	Ingo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1234965

FromArd Biesheuvel <ard.biesheuvel@linaro.org>
Date2015-09-29 12:50 +0200
Message-ID<qe0DU-44m-19@gated-at.bofh.it>
In reply to#1234901
On 29 September 2015 at 11:12, Ingo Molnar <mingo@kernel.org> wrote:
>
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>
>> > except that I don't think
>> > the condition on 64-bit makes any sense:
>> >
>> > +       if (!efi_enabled(EFI_OLD_MEMMAP) && efi_enabled(EFI_64BIT)) {
>> >
>> > I can see us being nervous wrt. backported patches, but is there any strong reason
>> > to not follow this up with a third (non-backported) patch that changes this to:
>> >
>> > +       if (!efi_enabled(EFI_OLD_MEMMAP)) {
>> >
>> > for v4.4?
>> >
>>
>> The 32-bit side essentially implements the old memmap only, which is the the
>> bottom-up version. So old memmap will be implied by 32-bit but not set in the
>> EFI flags, resulting in the reverse enumeration being used with the bottom-up
>> mapping logic. The net result of that is that we create the same problem for
>> 32-bit that we are trying to solve for 64-bit, i.e., the regions will end up in
>> reverse order in the VA mapping.
>>
>> To deobfuscate this particular conditional, we could set EFI_OLD_MEMMAP
>> unconditionally on 32-bit x86. Or we could reshuffle variables and conditionals
>> in various other way.
>
> Setting EFI_OLD_MEMMAP would be fine, if doing that has no bad side effects.
>
>> [...] I am not convinced that the overall end result will be any better though.
>
> That's not true, we change an obscure, implicit dependency on 32-bit detail to an
> explicit EFI_OLD_MEMMAP flag that shows exactly what's happening. That's a clear
> improvement.
>

OK, fair enough. I agree that setting the flag for 32-bit would be
semantically correct. I will leave it to Matt to comment whether it is
reasonable in terms of changes to other parts of the code.

Thanks,
Ard.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1235149

FromMatt Fleming <matt@codeblueprint.co.uk>
Date2015-09-29 16:20 +0200
Message-ID<qe3V9-rR-29@gated-at.bofh.it>
In reply to#1234965
On Tue, 29 Sep, at 12:41:23PM, Ard Biesheuvel wrote:
> 
> OK, fair enough. I agree that setting the flag for 32-bit would be
> semantically correct. I will leave it to Matt to comment whether it is
> reasonable in terms of changes to other parts of the code.

It should be pretty minimal. Let me take a swing at the patch.
 
-- 
Matt Fleming, Intel Open Source Technology Center
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1235089

FromMatt Fleming <matt@codeblueprint.co.uk>
Date2015-09-29 16:00 +0200
Message-ID<qe3BM-8he-11@gated-at.bofh.it>
In reply to#1234901
On Tue, 29 Sep, at 11:12:30AM, Ingo Molnar wrote:
> 
> * Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> 
> > > except that I don't think
> > > the condition on 64-bit makes any sense:
> > >
> > > +       if (!efi_enabled(EFI_OLD_MEMMAP) && efi_enabled(EFI_64BIT)) {
> > >
> > > I can see us being nervous wrt. backported patches, but is there any strong reason
> > > to not follow this up with a third (non-backported) patch that changes this to:
> > >
> > > +       if (!efi_enabled(EFI_OLD_MEMMAP)) {
> > >
> > > for v4.4?
> > >
> > 
> > The 32-bit side essentially implements the old memmap only, which is the the 
> > bottom-up version. So old memmap will be implied by 32-bit but not set in the 
> > EFI flags, resulting in the reverse enumeration being used with the bottom-up 
> > mapping logic. The net result of that is that we create the same problem for 
> > 32-bit that we are trying to solve for 64-bit, i.e., the regions will end up in 
> > reverse order in the VA mapping.
> > 
> > To deobfuscate this particular conditional, we could set EFI_OLD_MEMMAP 
> > unconditionally on 32-bit x86. Or we could reshuffle variables and conditionals 
> > in various other way.
> 
> Setting EFI_OLD_MEMMAP would be fine, if doing that has no bad side effects.
 
Right, I think that's a very good suggestion, because like Ard
mentioned, since EFI_OLD_MEMMAP is implied for 32-bit (there's no
other way to map stuff currently), so it makes sense to force set the
bit.

> > [...] I am not convinced that the overall end result will be any better though.
> 
> That's not true, we change an obscure, implicit dependency on 32-bit detail to an 
> explicit EFI_OLD_MEMMAP flag that shows exactly what's happening. That's a clear 
> improvement.

Agreed.

-- 
Matt Fleming, Intel Open Source Technology Center
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1233232

FromAndy Lutomirski <luto@amacapital.net>
Date2015-09-26 19:10 +0200
Message-ID<qd18Z-6cT-9@gated-at.bofh.it>
In reply to#1233149
On Fri, Sep 25, 2015 at 10:56 PM, Ingo Molnar <mingo@kernel.org> wrote:
>
> So this commit worries me.
>
> This bug is a good find, and the fix is obviously needed and urgent, but I'm not
> sure about the implementation at all. (I've Cc:-ed a few more x86 low level
> gents.)
>
> * Matt Fleming <matt@codeblueprint.co.uk> wrote:
>> +             /*
>> +              * Starting in UEFI v2.5 the EFI_PROPERTIES_TABLE
>> +              * config table feature requires us to map all entries
>> +              * in the same order as they appear in the EFI memory
>> +              * map. That is to say, entry N must have a lower
>> +              * virtual address than entry N+1. This is because the
>> +              * firmware toolchain leaves relative references in
>> +              * the code/data sections, which are split and become
>> +              * separate EFI memory regions. Mapping things
>> +              * out-of-order leads to the firmware accessing
>> +              * unmapped addresses.
>> +              *

I'm clearly missing something.  What is EFI doing that it doesn't care
how big the gap between sections is but it still requires them to be
in order?  It's not as though x86_64 has an addressing mode that
allows only non-negative offsets.

--Andy
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1233243

From"H. Peter Anvin" <hpa@zytor.com>
Date2015-09-26 19:30 +0200
Message-ID<qd1sl-6zC-15@gated-at.bofh.it>
In reply to#1233232
I think it "works" because the affected BIOSes don't put spaces between the chunks.  I have discussed this with Matt.

On September 26, 2015 10:01:14 AM PDT, Andy Lutomirski <luto@amacapital.net> wrote:
>On Fri, Sep 25, 2015 at 10:56 PM, Ingo Molnar <mingo@kernel.org> wrote:
>>
>> So this commit worries me.
>>
>> This bug is a good find, and the fix is obviously needed and urgent,
>but I'm not
>> sure about the implementation at all. (I've Cc:-ed a few more x86 low
>level
>> gents.)
>>
>> * Matt Fleming <matt@codeblueprint.co.uk> wrote:
>>> +             /*
>>> +              * Starting in UEFI v2.5 the EFI_PROPERTIES_TABLE
>>> +              * config table feature requires us to map all entries
>>> +              * in the same order as they appear in the EFI memory
>>> +              * map. That is to say, entry N must have a lower
>>> +              * virtual address than entry N+1. This is because the
>>> +              * firmware toolchain leaves relative references in
>>> +              * the code/data sections, which are split and become
>>> +              * separate EFI memory regions. Mapping things
>>> +              * out-of-order leads to the firmware accessing
>>> +              * unmapped addresses.
>>> +              *
>
>I'm clearly missing something.  What is EFI doing that it doesn't care
>how big the gap between sections is but it still requires them to be
>in order?  It's not as though x86_64 has an addressing mode that
>allows only non-negative offsets.
>
>--Andy

-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1233261

FromArd Biesheuvel <ard.biesheuvel@linaro.org>
Date2015-09-26 20:20 +0200
Message-ID<qd2eK-7JC-25@gated-at.bofh.it>
In reply to#1233243
On 26 September 2015 at 10:20, H. Peter Anvin <hpa@zytor.com> wrote:
> I think it "works" because the affected BIOSes don't put spaces between the chunks.  I have discussed this with Matt.
>

Forgive the ASCII art but perhaps an illustration might help:

before the 2.5 feature, PE/COFF runtime images were remapped as
illustrated here:

                                PA                        VA
+---------------+         +---------------+
|               |         |               |
| PE/COFF .text |         |    EFI        |
|               |         |    Runtime    |
+- - - - - - - -+    =>   |    Services   |----+
|               |         |    Code       |    |    :               :
| PE/COFF .data |         |               |    |    :               :
|               |         |               |    |    +---------------+
+---------------+         +---------------+    |    |               |
|               |         |               |    |    |    EFI        |
:               :         :               :    |    |    Runtime    |
:               :         :               :    +--->|    Services   |
|               |         |               |         |    Code       |
+---------------+         +---------------+         |               |
|               |         |               |         |               |
| PE/COFF .text |         |    EFI        |         +---------------+
|               |         |    Runtime    |         :      gap      :
+- - - - - - - -+    =>   |    Services   |---+     +---------------+
|               |         |    Code       |   |     |               |
| PE/COFF .data |         |               |   |     |    EFI        |
|               |         |               |   |     |    Runtime    |
+---------------+         +---------------+   +---->|    Services   |
|               |         |               |         |    Code       |
:               :         :               :         |               |
:               :         :               :         |               |
:               :         :               :         +---------------+
:               :         :               :         :               :

Since the affected symbol references only exist between PE/COFF .text
and PE/COFF .data, there is never a problem since each is PE/COFF
image is mapped as a single region.
However, with the new feature enabled, this no longer holds:
                                PA                        VA
+---------------+         +---------------+
|               |         |               |
| PE/COFF .text |         |    RtServices |----+
|               |         |    Code       |    |
+- - - - - - - -+    =>   +---------------+    |    +---------------+
|               |         |    RtServices |    +--->|    RtServices |
| PE/COFF .data |         |    Data       |         |    Code       |
|               |         |               |----+    +---------------+
+---------------+         +---------------+    |    :     gap       :
|               |         |               |    |    +---------------+
:               :         :               :    +--->|    RtServices |
:               :         :               :         |    Data       |
|               |         |               |         +---------------+
+---------------+         +---------------+         :     gap       :
|               |         |               |         +---------------+
| PE/COFF .text |         |    RtServices |-------->|    RtServices |
|               |         |    Code       |         |    Code       |
+- - - - - - - -+    =>   +---------------+         +---------------+
|               |         |    RtServices |         :     gap       :
| PE/COFF .data |         |    Data       |---+     +---------------+
|               |         |               |   |     |    RtServices |
+---------------+         +---------------+   +---->|    Data       |
|               |         |               |         |               |
:               :         :               :         +---------------+
:               :         :               :         :               :
:               :         :               :         :               :

The illustration uses gaps, but obviously, this applies equally to
inverting the mapping order, since the PE/COFF .text and .data
sections will end up out of order.

-- 
Ard.


> On September 26, 2015 10:01:14 AM PDT, Andy Lutomirski <luto@amacapital.net> wrote:
>>On Fri, Sep 25, 2015 at 10:56 PM, Ingo Molnar <mingo@kernel.org> wrote:
>>>
>>> So this commit worries me.
>>>
>>> This bug is a good find, and the fix is obviously needed and urgent,
>>but I'm not
>>> sure about the implementation at all. (I've Cc:-ed a few more x86 low
>>level
>>> gents.)
>>>
>>> * Matt Fleming <matt@codeblueprint.co.uk> wrote:
>>>> +             /*
>>>> +              * Starting in UEFI v2.5 the EFI_PROPERTIES_TABLE
>>>> +              * config table feature requires us to map all entries
>>>> +              * in the same order as they appear in the EFI memory
>>>> +              * map. That is to say, entry N must have a lower
>>>> +              * virtual address than entry N+1. This is because the
>>>> +              * firmware toolchain leaves relative references in
>>>> +              * the code/data sections, which are split and become
>>>> +              * separate EFI memory regions. Mapping things
>>>> +              * out-of-order leads to the firmware accessing
>>>> +              * unmapped addresses.
>>>> +              *
>>
>>I'm clearly missing something.  What is EFI doing that it doesn't care
>>how big the gap between sections is but it still requires them to be
>>in order?  It's not as though x86_64 has an addressing mode that
>>allows only non-negative offsets.
>>
>>--Andy
>
> --
> Sent from my Android device with K-9 Mail. Please excuse my brevity.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1233285

FromMatt Fleming <matt@codeblueprint.co.uk>
Date2015-09-26 22:00 +0200
Message-ID<qd3Nw-1lI-27@gated-at.bofh.it>
In reply to#1233261
On Sat, 26 Sep, at 12:49:26PM, H. Peter Anvin wrote:
>
> It is still a hack unless all relative offsets are preserved.  That
> is actually simpler, even: no sorting necessary.

Unless I'm missing something, preserving relative offsets is exactly
what we do today, modulo PMD_SIZE gaps.

-- 
Matt Fleming, Intel Open Source Technology Center
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1233288

FromArd Biesheuvel <ard.biesheuvel@linaro.org>
Date2015-09-26 22:10 +0200
Message-ID<qd3Xb-1Ms-3@gated-at.bofh.it>
In reply to#1233285
> On 26 sep. 2015, at 12:57, Matt Fleming <matt@codeblueprint.co.uk> wrote:
> 
>> On Sat, 26 Sep, at 12:49:26PM, H. Peter Anvin wrote:
>> 
>> It is still a hack unless all relative offsets are preserved.  That
>> is actually simpler, even: no sorting necessary.
> 
> Unless I'm missing something, preserving relative offsets is exactly
> what we do today, modulo PMD_SIZE gaps.
> 

I think what Peter means is preserving the relative offsets inside the entire 1:1 space.

This is not at all what we do currently, and i don't think it is generally feasible on 32-bit (since the physical range may conflict with the virtual kernel mappings)

However, on 64 bit (both arm and x86), this boils down to not calling setVA() in the first place, which i'm all in favor of.
-- 
Ard.

> -- 
> Matt Fleming, Intel Open Source Technology Center
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1233295

From"H. Peter Anvin" <hpa@zytor.com>
Date2015-09-26 22:30 +0200
Message-ID<qd4gx-28W-3@gated-at.bofh.it>
In reply to#1233288
Sadly a lot of firmware is known to fail in that configuration :(  That was very much our guest choice.

I don't actually think it is all that infeasible to keep relative offsets consistent for the regions we have to map. PMD_SIZE is not a very large chunk so it could be a problem.

On September 26, 2015 1:09:17 PM PDT, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>
>> On 26 sep. 2015, at 12:57, Matt Fleming <matt@codeblueprint.co.uk>
>wrote:
>> 
>>> On Sat, 26 Sep, at 12:49:26PM, H. Peter Anvin wrote:
>>> 
>>> It is still a hack unless all relative offsets are preserved.  That
>>> is actually simpler, even: no sorting necessary.
>> 
>> Unless I'm missing something, preserving relative offsets is exactly
>> what we do today, modulo PMD_SIZE gaps.
>> 
>
>I think what Peter means is preserving the relative offsets inside the
>entire 1:1 space.
>
>This is not at all what we do currently, and i don't think it is
>generally feasible on 32-bit (since the physical range may conflict
>with the virtual kernel mappings)
>
>However, on 64 bit (both arm and x86), this boils down to not calling
>setVA() in the first place, which i'm all in favor of.

-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1233706

FromAndy Lutomirski <luto@amacapital.net>
Date2015-09-27 18:40 +0200
Message-ID<qdn9w-4ba-9@gated-at.bofh.it>
In reply to#1233295
On Sep 26, 2015 1:19 PM, "H. Peter Anvin" <hpa@zytor.com> wrote:
>
> Sadly a lot of firmware is known to fail in that configuration :(  That was very much our guest choice.
>

Why can't we map everything completely 1:1 (VA = PA) and call the
setVA thing but pass it literally the identity.

Firmwares that need it to be called will work, and firmwares that fail
to update all offsets will be fine because there's nothing to update.

--Andy
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1233731

FromMatthew Garrett <mjg59@srcf.ucam.org>
Date2015-09-27 20:40 +0200
Message-ID<qdp1E-6RN-13@gated-at.bofh.it>
In reply to#1233706
On Sun, Sep 27, 2015 at 09:30:48AM -0700, Andy Lutomirski wrote:
> On Sep 26, 2015 1:19 PM, "H. Peter Anvin" <hpa@zytor.com> wrote:
> >
> > Sadly a lot of firmware is known to fail in that configuration :(  That was very much our guest choice.
> >
> 
> Why can't we map everything completely 1:1 (VA = PA) and call the
> setVA thing but pass it literally the identity.

Last time I tried this I found that some firmware makes assumptions 
about having high addresses.

-- 
Matthew Garrett | mjg59@srcf.ucam.org
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | linux.kernel


csiph-web