From 5c537b3d0cf8c393dad2e61d49aade68f3af1401 Mon Sep 17 00:00:00 2001 From: dann frazier Date: Tue, 6 Sep 2022 09:28:22 -0600 Subject: [PATCH 06/13] 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 --- pe.c | 3 +++ include/compiler.h | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/pe.c b/pe.c index ba3e2bbc444..f94530a20c0 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"); diff --git a/include/compiler.h b/include/compiler.h index b4bf10319ee..b0d595f32c2 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 -- 2.37.1