summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordann frazier <dann.frazier@canonical.com>2022-09-06 09:28:22 -0600
committerPeter Jones <pjones@redhat.com>2022-10-04 13:53:11 -0400
commit5c537b3d0cf8c393dad2e61d49aade68f3af1401 (patch)
tree8fefad58abc1d369a75debb0513bab494d7f3a98
parent14d63398298c8de23036a4cf61594108b7345863 (diff)
downloadefi-boot-shim-5c537b3d0cf8c393dad2e61d49aade68f3af1401.tar.gz
efi-boot-shim-5c537b3d0cf8c393dad2e61d49aade68f3af1401.zip
shim: Flush the memory region from i-cache before execution
We've seen crashes in early GRUB code on an ARM Cortex-A72-based platform that point at seemingly harmless instructions. Flushing the i-cache of those instructions prior to executing has been shown to avoid the problem, which has parallels with this story: https://www.mail-archive.com/osv-dev@googlegroups.com/msg06203.html Add a cache flushing utility function and provide an implementation using a GCC intrinsic. This will need to be extended to support other compilers. Note that this intrinsic is a no-op for x86 platforms. This fixes issue #498. Signed-off-by: dann frazier <dann.frazier@canonical.com>
-rw-r--r--include/compiler.h6
-rw-r--r--pe.c3
2 files changed, 9 insertions, 0 deletions
diff --git a/include/compiler.h b/include/compiler.h
index b4bf1031..b0d595f3 100644
--- a/include/compiler.h
+++ b/include/compiler.h
@@ -192,5 +192,11 @@
*/
#define unreachable() __builtin_unreachable()
+#if defined(__GNUC__)
+#define cache_invalidate(begin, end) __builtin___clear_cache(begin, end)
+#else /* __GNUC__ */
+#error shim has no cache_invalidate() implementation for this compiler
+#endif /* __GNUC__ */
+
#endif /* !COMPILER_H_ */
// vim:fenc=utf-8:tw=75:et
diff --git a/pe.c b/pe.c
index ba3e2bbc..f94530a2 100644
--- a/pe.c
+++ b/pe.c
@@ -1196,6 +1196,9 @@ handle_image (void *data, unsigned int datasize,
CopyMem(buffer, data, context.SizeOfHeaders);
+ /* Flush the instruction cache for the region holding the image */
+ cache_invalidate(buffer, buffer + context.ImageSize);
+
*entry_point = ImageAddress(buffer, context.ImageSize, context.EntryPoint);
if (!*entry_point) {
perror(L"Entry point is invalid\n");