Kexec bypasses EFI's switch to virtual mode. In exchange, it has its own routine, kexec_enter_virtual_mode(), which replays the mappings made by the original kernel. Unfortunately, that function fails to reinstate EFI's memory attributes, which would've otherwise been set after entering virtual mode. Remediate this by calling efi_runtime_update_mappings() within kexec's routine.
Cc: stable@vger.kernel.org Fixes: 18141e89a76c ("x86/efi: Add support for EFI_MEMORY_ATTRIBUTES_TABLE") Signed-off-by: Nicolas Saenz Julienne nsaenz@amazon.com
---
Notes: - Tested with QEMU/OVMF.
arch/x86/platform/efi/efi.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 375ebd78296a..a7ff189421c3 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -765,6 +765,7 @@ static void __init kexec_enter_virtual_mode(void)
efi_sync_low_kernel_mappings(); efi_native_runtime_setup(); + efi_runtime_update_mappings(); #endif }
On Tue, 12 Nov 2024 at 19:53, Nicolas Saenz Julienne nsaenz@amazon.com wrote:
Kexec bypasses EFI's switch to virtual mode. In exchange, it has its own routine, kexec_enter_virtual_mode(), which replays the mappings made by the original kernel. Unfortunately, that function fails to reinstate EFI's memory attributes, which would've otherwise been set after entering virtual mode. Remediate this by calling efi_runtime_update_mappings() within kexec's routine.
Cc: stable@vger.kernel.org Fixes: 18141e89a76c ("x86/efi: Add support for EFI_MEMORY_ATTRIBUTES_TABLE") Signed-off-by: Nicolas Saenz Julienne nsaenz@amazon.com
Notes:
- Tested with QEMU/OVMF.
I'll queue these up, but I am going drop the cc stable: the memory attributes table is an overlay of the EFI memory map with restricted permissions for EFI runtime services regions, which are only mapped while a EFI runtime call is in progress.
So if the table is not taken into account after kexec, the runtime code and data mappings will all be RWX but I think this is a situation we can live with. If nothing breaks, we can always revisit this later if there is an actual need.
Thanks,
arch/x86/platform/efi/efi.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 375ebd78296a..a7ff189421c3 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -765,6 +765,7 @@ static void __init kexec_enter_virtual_mode(void)
efi_sync_low_kernel_mappings(); efi_native_runtime_setup();
efi_runtime_update_mappings();
#endif }
-- 2.40.1
On Fri Nov 15, 2024 at 4:39 PM UTC, Ard Biesheuvel wrote:
On Tue, 12 Nov 2024 at 19:53, Nicolas Saenz Julienne nsaenz@amazon.com wrote:
Kexec bypasses EFI's switch to virtual mode. In exchange, it has its own routine, kexec_enter_virtual_mode(), which replays the mappings made by the original kernel. Unfortunately, that function fails to reinstate EFI's memory attributes, which would've otherwise been set after entering virtual mode. Remediate this by calling efi_runtime_update_mappings() within kexec's routine.
Cc: stable@vger.kernel.org Fixes: 18141e89a76c ("x86/efi: Add support for EFI_MEMORY_ATTRIBUTES_TABLE") Signed-off-by: Nicolas Saenz Julienne nsaenz@amazon.com
Notes:
- Tested with QEMU/OVMF.
I'll queue these up,
Thanks!
but I am going drop the cc stable: the memory attributes table is an overlay of the EFI memory map with restricted permissions for EFI runtime services regions, which are only mapped while a EFI runtime call is in progress.
So if the table is not taken into account after kexec, the runtime code and data mappings will all be RWX but I think this is a situation we can live with. If nothing breaks, we can always revisit this later if there is an actual need.
My intention was backporting the fix all the way to 'stable/linux-5.10.y'. But I'm happy to wait, or even to maintain an internal backport. It's simple enough.
Nicolas
Hi,
On Wed, 13 Nov 2024 at 02:53, Nicolas Saenz Julienne nsaenz@amazon.com wrote:
Kexec bypasses EFI's switch to virtual mode. In exchange, it has its own routine, kexec_enter_virtual_mode(), which replays the mappings made by the original kernel. Unfortunately, that function fails to reinstate EFI's memory attributes, which would've otherwise been set after entering virtual mode. Remediate this by calling efi_runtime_update_mappings() within kexec's routine.
In the function __map_region(), there are playing with the flags similar to the efi_runtime_update_mappings though it looks a little different. Is this extra callback really necessary?
Have you seen a real bug happened?
Cc: stable@vger.kernel.org Fixes: 18141e89a76c ("x86/efi: Add support for EFI_MEMORY_ATTRIBUTES_TABLE") Signed-off-by: Nicolas Saenz Julienne nsaenz@amazon.com
Notes:
- Tested with QEMU/OVMF.
arch/x86/platform/efi/efi.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 375ebd78296a..a7ff189421c3 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -765,6 +765,7 @@ static void __init kexec_enter_virtual_mode(void)
efi_sync_low_kernel_mappings(); efi_native_runtime_setup();
efi_runtime_update_mappings();
#endif }
-- 2.40.1
Thanks Dave
Hi Dave,
On Fri Nov 22, 2024 at 1:03 PM UTC, Dave Young wrote:
On Wed, 13 Nov 2024 at 02:53, Nicolas Saenz Julienne nsaenz@amazon.com wrote:
Kexec bypasses EFI's switch to virtual mode. In exchange, it has its own routine, kexec_enter_virtual_mode(), which replays the mappings made by the original kernel. Unfortunately, that function fails to reinstate EFI's memory attributes, which would've otherwise been set after entering virtual mode. Remediate this by calling efi_runtime_update_mappings() within kexec's routine.
In the function __map_region(), there are playing with the flags similar to the efi_runtime_update_mappings though it looks a little different. Is this extra callback really necessary?
EFI Memory attributes aren't tracked through `/sys/firmware/efi/runtime-map`, and as such, whatever happens in `__map_region()` after kexec will not honor them.
Have you seen a real bug happened?
If lowered security posture after kexec counts as a bug, yes. The system remains stable otherwise.
Nicolas
Hi Nicolas,
On Thu, 28 Nov 2024 at 23:58, Nicolas Saenz Julienne nsaenz@amazon.com wrote:
Hi Dave,
On Fri Nov 22, 2024 at 1:03 PM UTC, Dave Young wrote:
On Wed, 13 Nov 2024 at 02:53, Nicolas Saenz Julienne nsaenz@amazon.com wrote:
Kexec bypasses EFI's switch to virtual mode. In exchange, it has its own routine, kexec_enter_virtual_mode(), which replays the mappings made by the original kernel. Unfortunately, that function fails to reinstate EFI's memory attributes, which would've otherwise been set after entering virtual mode. Remediate this by calling efi_runtime_update_mappings() within kexec's routine.
In the function __map_region(), there are playing with the flags similar to the efi_runtime_update_mappings though it looks a little different. Is this extra callback really necessary?
EFI Memory attributes aren't tracked through `/sys/firmware/efi/runtime-map`, and as such, whatever happens in `__map_region()` after kexec will not honor them.
From the comment below the reason to do the mappings update is that firmware could perform some fixups. But for kexec case I think doing the mapping correctly in the mapping code would be good enough.
/* * Apply more restrictive page table mapping attributes now that * SVAM() has been called and the firmware has performed all * necessary relocation fixups for the new virtual addresses. */ efi_runtime_update_mappings();
Otherwise /sys/firmware/efi/runtime-map is a copy for kexec-tools to create the virtual efi memmap, but I think the __map_region is called after kexecing into the 2nd kernel, so I feel that at that time the mem attr table should be usable.
Anyway thanks for explaining about this. It is indeed something to improve. I have no strong opinion as your code will also work.
Have you seen a real bug happened?
If lowered security posture after kexec counts as a bug, yes. The system remains stable otherwise.
Nicolas
Thanks Dave
On Fri, 29 Nov 2024 at 15:11, Dave Young dyoung@redhat.com wrote:
Hi Nicolas,
On Thu, 28 Nov 2024 at 23:58, Nicolas Saenz Julienne nsaenz@amazon.com wrote:
Hi Dave,
On Fri Nov 22, 2024 at 1:03 PM UTC, Dave Young wrote:
On Wed, 13 Nov 2024 at 02:53, Nicolas Saenz Julienne nsaenz@amazon.com wrote:
Kexec bypasses EFI's switch to virtual mode. In exchange, it has its own routine, kexec_enter_virtual_mode(), which replays the mappings made by the original kernel. Unfortunately, that function fails to reinstate EFI's memory attributes, which would've otherwise been set after entering virtual mode. Remediate this by calling efi_runtime_update_mappings() within kexec's routine.
In the function __map_region(), there are playing with the flags similar to the efi_runtime_update_mappings though it looks a little different. Is this extra callback really necessary?
EFI Memory attributes aren't tracked through `/sys/firmware/efi/runtime-map`, and as such, whatever happens in `__map_region()` after kexec will not honor them.
From the comment below the reason to do the mappings update is that firmware could perform some fixups. But for kexec case I think doing the mapping correctly in the mapping code would be good enough.
/* * Apply more restrictive page table mapping attributes now that * SVAM() has been called and the firmware has performed all * necessary relocation fixups for the new virtual addresses. */ efi_runtime_update_mappings();
Otherwise /sys/firmware/efi/runtime-map is a copy for kexec-tools to create the virtual efi memmap, but I think the __map_region is called after kexecing into the 2nd kernel, so I feel that at that time the mem attr table should be usable.
Another thing I'm not sure why the updated mem attr is not stored in the memmap md descriptor "attribute" field, if that is possible then the runtime-map will carry them, anyway, the __map_region still needs tweaking to use the attribute.
Anyway thanks for explaining about this. It is indeed something to improve. I have no strong opinion as your code will also work.
Have you seen a real bug happened?
If lowered security posture after kexec counts as a bug, yes. The system remains stable otherwise.
Nicolas
Thanks Dave
On Fri Nov 29, 2024 at 7:31 AM UTC, Dave Young wrote:
CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you can confirm the sender and know the content is safe.
On Fri, 29 Nov 2024 at 15:11, Dave Young dyoung@redhat.com wrote:
Hi Nicolas,
On Thu, 28 Nov 2024 at 23:58, Nicolas Saenz Julienne nsaenz@amazon.com wrote:
Hi Dave,
On Fri Nov 22, 2024 at 1:03 PM UTC, Dave Young wrote:
On Wed, 13 Nov 2024 at 02:53, Nicolas Saenz Julienne nsaenz@amazon.com wrote:
Kexec bypasses EFI's switch to virtual mode. In exchange, it has its own routine, kexec_enter_virtual_mode(), which replays the mappings made by the original kernel. Unfortunately, that function fails to reinstate EFI's memory attributes, which would've otherwise been set after entering virtual mode. Remediate this by calling efi_runtime_update_mappings() within kexec's routine.
In the function __map_region(), there are playing with the flags similar to the efi_runtime_update_mappings though it looks a little different. Is this extra callback really necessary?
EFI Memory attributes aren't tracked through `/sys/firmware/efi/runtime-map`, and as such, whatever happens in `__map_region()` after kexec will not honor them.
From the comment below the reason to do the mappings update is that firmware could perform some fixups. But for kexec case I think doing the mapping correctly in the mapping code would be good enough.
/* * Apply more restrictive page table mapping attributes now that * SVAM() has been called and the firmware has performed all * necessary relocation fixups for the new virtual addresses. */ efi_runtime_update_mappings();
Otherwise /sys/firmware/efi/runtime-map is a copy for kexec-tools to create the virtual efi memmap, but I think the __map_region is called after kexecing into the 2nd kernel, so I feel that at that time the mem attr table should be usable.
Another thing I'm not sure why the updated mem attr is not stored in the memmap md descriptor "attribute" field, if that is possible then the runtime-map will carry them, anyway, the __map_region still needs tweaking to use the attribute.
AFAIK there isn't a technical reason we why couldn't do it through the runtime-map, but it's annoying to do so because EFI Memory Attributes are allowed to segment EFI memory regions into smaller sections with distinct attributes. We'd have to carefully update the kernel's representation of the EFI runtime memory map as we apply the attributes (the one that's ultimately used to populate `/sys/firmware/efi/runtime-map`).
On the other hand, the config table and memory region that holds the attributes is already being persisted through kexec, so using it is straightforward.
Nicolas
linux-stable-mirror@lists.linaro.org