[PATCH 2/3] arm64: patching: Fix instruction byte order in aarch64_insn_set()

From: Rui Qi

Date: Sat Oct 10 2026 - 04:51:29 EST


aarch64_insn_set() passes the host-endian u32 instruction straight to
text_poke_memset(), which memset32()'s it into memory in host byte order.
AArch64 instructions must be little-endian in memory, so on a big-endian
kernel the written bytes are reversed and the CPU takes an UNDEFINED
instruction exception when fetching them. The sibling aarch64_insn_write()
already converts with cpu_to_le32(); aarch64_insn_set() does not.

This is reachable in-tree: bpf_arch_text_invalidate() fills freed JIT
regions with AARCH64_BREAK_FAULT through aarch64_insn_set(), and arm64
selects HAVE_EBPF_JIT without a big-endian guard, so the path is taken on
BE kernels with BPF JIT. The direct-fill loop in the same file already
cpu_to_le32()'s the constant, confirming the expected byte order.

Convert the instruction to little-endian before the memset, mirroring
aarch64_insn_write(). On LE the conversion is a no-op, so behaviour is
unchanged.

Fixes: 451c3cab9a65e656c3b3d106831fc02d56b8c34a ("arm64: patching: implement text_poke API")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Rui Qi <qirui.001@xxxxxxxxxxxxx>
---
arch/arm64/kernel/patching.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/patching.c b/arch/arm64/kernel/patching.c
index 09f019c6547a..ffd790b2b277 100644
--- a/arch/arm64/kernel/patching.c
+++ b/arch/arm64/kernel/patching.c
@@ -170,10 +170,12 @@ noinstr void *aarch64_insn_copy(void *dst, void *src, size_t len)
*/
noinstr void *aarch64_insn_set(void *dst, u32 insn, size_t len)
{
+ __le32 __insn = cpu_to_le32(insn);
+
if ((uintptr_t)dst & 0x3)
return NULL;

- return __text_poke(text_poke_memset, dst, &insn, len);
+ return __text_poke(text_poke_memset, dst, &__insn, len);
}

int __kprobes aarch64_insn_patch_text_nosync(void *addr, u32 insn)
--
2.20.1