0026-efi-Fix-use-after-free-in-halt-reboot-path.patch 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. From 8a6d6299efcffd14c1130942195e6c0d9b50cacd Mon Sep 17 00:00:00 2001
  2. From: Alexey Makhalov <amakhalov@vmware.com>
  3. Date: Mon, 20 Jul 2020 23:03:05 +0000
  4. Subject: [PATCH] efi: Fix use-after-free in halt/reboot path
  5. MIME-Version: 1.0
  6. Content-Type: text/plain; charset=UTF-8
  7. Content-Transfer-Encoding: 8bit
  8. commit 92bfc33db984 ("efi: Free malloc regions on exit")
  9. introduced memory freeing in grub_efi_fini(), which is
  10. used not only by exit path but by halt/reboot one as well.
  11. As result of memory freeing, code and data regions used by
  12. modules, such as halt, reboot, acpi (used by halt) also got
  13. freed. After return to module code, CPU executes, filled
  14. by UEFI firmware (tested with edk2), 0xAFAFAFAF pattern as
  15. a code. Which leads to #UD exception later.
  16. grub> halt
  17. !!!! X64 Exception Type - 06(#UD - Invalid Opcode) CPU Apic ID - 00000000 !!!!
  18. RIP - 0000000003F4EC28, CS - 0000000000000038, RFLAGS - 0000000000200246
  19. RAX - 0000000000000000, RCX - 00000000061DA188, RDX - 0A74C0854DC35D41
  20. RBX - 0000000003E10E08, RSP - 0000000007F0F860, RBP - 0000000000000000
  21. RSI - 00000000064DB768, RDI - 000000000832C5C3
  22. R8 - 0000000000000002, R9 - 0000000000000000, R10 - 00000000061E2E52
  23. R11 - 0000000000000020, R12 - 0000000003EE5C1F, R13 - 00000000061E0FF4
  24. R14 - 0000000003E10D80, R15 - 00000000061E2F60
  25. DS - 0000000000000030, ES - 0000000000000030, FS - 0000000000000030
  26. GS - 0000000000000030, SS - 0000000000000030
  27. CR0 - 0000000080010033, CR2 - 0000000000000000, CR3 - 0000000007C01000
  28. CR4 - 0000000000000668, CR8 - 0000000000000000
  29. DR0 - 0000000000000000, DR1 - 0000000000000000, DR2 - 0000000000000000
  30. DR3 - 0000000000000000, DR6 - 00000000FFFF0FF0, DR7 - 0000000000000400
  31. GDTR - 00000000079EEA98 0000000000000047, LDTR - 0000000000000000
  32. IDTR - 0000000007598018 0000000000000FFF, TR - 0000000000000000
  33. FXSAVE_STATE - 0000000007F0F4C0
  34. Proposal here is to continue to free allocated memory for
  35. exit boot services path but keep it for halt/reboot path
  36. as it won't be much security concern here.
  37. Introduced GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY
  38. loader flag to be used by efi halt/reboot path.
  39. Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
  40. Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
  41. Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
  42. Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
  43. ---
  44. grub-core/kern/arm/efi/init.c | 3 +++
  45. grub-core/kern/arm64/efi/init.c | 3 +++
  46. grub-core/kern/efi/efi.c | 3 ++-
  47. grub-core/kern/efi/init.c | 1 -
  48. grub-core/kern/i386/efi/init.c | 9 +++++++--
  49. grub-core/kern/ia64/efi/init.c | 9 +++++++--
  50. grub-core/kern/riscv/efi/init.c | 3 +++
  51. grub-core/lib/efi/halt.c | 3 ++-
  52. include/grub/loader.h | 1 +
  53. 9 files changed, 28 insertions(+), 7 deletions(-)
  54. diff --git a/grub-core/kern/arm/efi/init.c b/grub-core/kern/arm/efi/init.c
  55. index 06df60e2f..40c3b467f 100644
  56. --- a/grub-core/kern/arm/efi/init.c
  57. +++ b/grub-core/kern/arm/efi/init.c
  58. @@ -71,4 +71,7 @@ grub_machine_fini (int flags)
  59. efi_call_1 (b->close_event, tmr_evt);
  60. grub_efi_fini ();
  61. +
  62. + if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
  63. + grub_efi_memory_fini ();
  64. }
  65. diff --git a/grub-core/kern/arm64/efi/init.c b/grub-core/kern/arm64/efi/init.c
  66. index 6224999ec..5010caefd 100644
  67. --- a/grub-core/kern/arm64/efi/init.c
  68. +++ b/grub-core/kern/arm64/efi/init.c
  69. @@ -57,4 +57,7 @@ grub_machine_fini (int flags)
  70. return;
  71. grub_efi_fini ();
  72. +
  73. + if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
  74. + grub_efi_memory_fini ();
  75. }
  76. diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
  77. index c97969a65..9cfd88d77 100644
  78. --- a/grub-core/kern/efi/efi.c
  79. +++ b/grub-core/kern/efi/efi.c
  80. @@ -157,7 +157,8 @@ grub_efi_get_loaded_image (grub_efi_handle_t image_handle)
  81. void
  82. grub_reboot (void)
  83. {
  84. - grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
  85. + grub_machine_fini (GRUB_LOADER_FLAG_NORETURN |
  86. + GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY);
  87. efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
  88. GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL);
  89. for (;;) ;
  90. diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
  91. index 3dfdf2d22..2c31847bf 100644
  92. --- a/grub-core/kern/efi/init.c
  93. +++ b/grub-core/kern/efi/init.c
  94. @@ -80,5 +80,4 @@ grub_efi_fini (void)
  95. {
  96. grub_efidisk_fini ();
  97. grub_console_fini ();
  98. - grub_efi_memory_fini ();
  99. }
  100. diff --git a/grub-core/kern/i386/efi/init.c b/grub-core/kern/i386/efi/init.c
  101. index da499aba0..deb2eacd8 100644
  102. --- a/grub-core/kern/i386/efi/init.c
  103. +++ b/grub-core/kern/i386/efi/init.c
  104. @@ -39,6 +39,11 @@ grub_machine_init (void)
  105. void
  106. grub_machine_fini (int flags)
  107. {
  108. - if (flags & GRUB_LOADER_FLAG_NORETURN)
  109. - grub_efi_fini ();
  110. + if (!(flags & GRUB_LOADER_FLAG_NORETURN))
  111. + return;
  112. +
  113. + grub_efi_fini ();
  114. +
  115. + if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
  116. + grub_efi_memory_fini ();
  117. }
  118. diff --git a/grub-core/kern/ia64/efi/init.c b/grub-core/kern/ia64/efi/init.c
  119. index b5ecbd091..f1965571b 100644
  120. --- a/grub-core/kern/ia64/efi/init.c
  121. +++ b/grub-core/kern/ia64/efi/init.c
  122. @@ -70,6 +70,11 @@ grub_machine_init (void)
  123. void
  124. grub_machine_fini (int flags)
  125. {
  126. - if (flags & GRUB_LOADER_FLAG_NORETURN)
  127. - grub_efi_fini ();
  128. + if (!(flags & GRUB_LOADER_FLAG_NORETURN))
  129. + return;
  130. +
  131. + grub_efi_fini ();
  132. +
  133. + if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
  134. + grub_efi_memory_fini ();
  135. }
  136. diff --git a/grub-core/kern/riscv/efi/init.c b/grub-core/kern/riscv/efi/init.c
  137. index 7eb1969d0..38795fe67 100644
  138. --- a/grub-core/kern/riscv/efi/init.c
  139. +++ b/grub-core/kern/riscv/efi/init.c
  140. @@ -73,4 +73,7 @@ grub_machine_fini (int flags)
  141. return;
  142. grub_efi_fini ();
  143. +
  144. + if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
  145. + grub_efi_memory_fini ();
  146. }
  147. diff --git a/grub-core/lib/efi/halt.c b/grub-core/lib/efi/halt.c
  148. index 5859f0498..29d413641 100644
  149. --- a/grub-core/lib/efi/halt.c
  150. +++ b/grub-core/lib/efi/halt.c
  151. @@ -28,7 +28,8 @@
  152. void
  153. grub_halt (void)
  154. {
  155. - grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
  156. + grub_machine_fini (GRUB_LOADER_FLAG_NORETURN |
  157. + GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY);
  158. #if !defined(__ia64__) && !defined(__arm__) && !defined(__aarch64__) && \
  159. !defined(__riscv)
  160. grub_acpi_halt ();
  161. diff --git a/include/grub/loader.h b/include/grub/loader.h
  162. index 7f82a499f..b20864282 100644
  163. --- a/include/grub/loader.h
  164. +++ b/include/grub/loader.h
  165. @@ -33,6 +33,7 @@ enum
  166. {
  167. GRUB_LOADER_FLAG_NORETURN = 1,
  168. GRUB_LOADER_FLAG_PXE_NOT_UNLOAD = 2,
  169. + GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY = 4,
  170. };
  171. void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) (void),
  172. --
  173. 2.26.2