diff options
| author | Mukesh Kumar Chaurasiya (IBM) <mkchauras@gmail.com> | 2026-10-03 15:10:06 +0530 |
|---|---|---|
| committer | Madhavan Srinivasan <maddy@linux.ibm.com> | 2026-10-12 09:30:48 +0530 |
| commit | de5a7fedf5061bdf6823eb509353bd7c128e34b5 (patch) | |
| tree | bd1eabf5c7b0daab40776f36e6de80084005188a /scripts | |
| parent | 8fa763bc3ee9bd215476ab91ee480c649eaa4b29 (diff) | |
powerpc/kasan: fix r2 corruption in mem*() on GENERIC_ENTRY with old compilers
commit bee25f97ad24 ("powerpc: Enable GENERIC_ENTRY feature") introduced
a bug that, when CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX is not
set, expand to two consecutive ELFv2 global entry points for the
same function body:
_GLOBAL_TOC_KASAN(memcpy) expands to:
_GLOBAL_TOC(memcpy);
_GLOBAL_TOC(__memcpy)
On powerpc64le this produces:
memcpy:
addis r2,r12,(.TOC.-0b)@ha <- global entry, sets up r2
addi r2,r2,(.TOC.-0b)@l
.localentry memcpy,.-memcpy <- local entry at memcpy+8
__memcpy:
addis r2,r12,(.TOC.-0b)@ha <- memcpy+8: __memcpy global entry
addi r2,r2,(.TOC.-0b)@l
.localentry __memcpy,.-__memcpy
The assembler sets memcpy's st_other field so its local entry offset is
8 bytes past the global entry point. The linker resolves same-TOC
calls to the local entry, so every same-TOC caller of memcpy() lands
at memcpy+8 — which is the beginning of the __memcpy global-entry TOC
prologue. That prologue uses r12 as the base to recompute r2, but r12
holds whatever the caller left in it (not the address of memcpy+8).
The result is r2 pointing at garbage on return. Same-TOC callers do
not reload r2 after the call, so the first TOC-relative access after
returning from memcpy() or memmove() crashes or silently corrupts data.
With GENERIC_ENTRY selected, mm/kasan/shadow.c no longer provides its
own memcpy()/memmove()/memset() wrappers, so on a toolchain without
-mllvm -asan-kernel-mem-intrinsic-prefix=1 (e.g. GCC 9) every
instrumented file resolves mem*() directly to the assembly symbols and
hits this corrupt-r2 path. This manifests as an early boot hang unique
to powerpc with GCC 9 and CONFIG_KASAN=y.
Fix this by removing the dual-entry macros entirely. The assembly
files in mem_64.S, memcpy_64.S and copy_32.S now use plain
_GLOBAL()/_GLOBAL_TOC() for memset/memcpy/memmove, emitting a single
correct ELFv2 entry point. The __mem* aliases required by mm/kasan
(used in mm/kasan/shadow.c and mm/kasan/generic.c as raw backends to
bypass KASAN checking) are provided entirely through the #define
redirections in asm/string.h, which already handles both the
CC_HAS_KASAN_MEMINTRINSIC_PREFIX and non-prefix cases in C.
As a consequence the _GLOBAL_KASAN(), _GLOBAL_TOC_KASAN() and
EXPORT_SYMBOL_KASAN() macros have no remaining users and are removed
from asm/kasan.h. The has_renamed_memintrinsics() branch in
prom_init_check.sh, which conditionally whitelisted __memcpy/__memset
when CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX was absent, is dead code
after this change and is removed; the whitelist now unconditionally
lists memcpy and memset.
Fixes: bee25f97ad24 ("powerpc: Enable GENERIC_ENTRY feature")
Reported-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com>
Closes: https://lore.kernel.org/all/96dae110-f79b-4e54-8a9b-514369019b5d@linux.ibm.com
Tested-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com>
Signed-off-by: Mukesh Kumar Chaurasiya (IBM) <mkchauras@gmail.com>
[Maddy: Fixed commit message to avoid checkpatch error]
Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
Link: https://patch.msgid.link/20261003094006.3404731-1-mkchauras@gmail.com
Diffstat (limited to 'scripts')
0 files changed, 0 insertions, 0 deletions
