From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-dy1-f178.google.com (mail-dy1-f178.google.com [74.125.82.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 593143AD528 for ; Sat, 3 Oct 2026 09:40:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.178 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791020427; cv=none; b=Q+W5XMF0QAaz9vTf1X7w98T36n2TUehrWfFCG8NY9R81INZgksk8aCoz4/fJDFavCGDSzjtX6uxb0nRIU8pyQ9mz9CywrYspE+Jabb0PelPtz0diKt4ZKy1da6hExG/uUz5Er/994gtGsfic6d8POsGeZFw2EWrHC+RXOMoq4fg= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791020427; c=relaxed/simple; bh=RA39MnveqAgjclwXw3oUk344huvfzEMR/AULj89t0IM=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type; b=OZW5RvVDsLt/eQJ1UcXBzev4PQHqysPe/FfwzBAls/ff78f6VwMNc42EUeldjJuHvAHxARlKjzPG0edeagavchOeCHo4OpVZBJ5xmb6CBFpsrxkYEqHfF/pWFKJq7U+OfIU2XmoxplS9B4jgwQmruvlnJ/eBA57GztvmGIcvRbE= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=RLXiejWy; arc=none smtp.client-ip=74.125.82.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="RLXiejWy" Received: by mail-dy1-f178.google.com with SMTP id 5a478bee46e88-34bb8b31647so648998eec.0 for ; Sat, 03 Oct 2026 02:40:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1791020424; x=1791625224; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:message-id:date :subject:cc:to:from:from:to:cc:subject:date:message-id:reply-to :content-type; bh=nfYeoE0FlNoYRCBgtkrLlvam3mS1qxhXTtp4SykzoVE=; b=RLXiejWyG01L35nBRF9p7O9PODenMWnqQSK5kLLgWlMXd5KnoKwOOw4bQEZbO1yFyo z/m4LnvXCdOdxHuNEEfI7SFx/b7Li4SlKNtmhTE2/EoJoWaxZDO6RzMsaOIW6ER0JcsC QCp6CHUt02CvqytTXS8slU2+RtpFoT3+tP3Ivu+HhIHIvRWOCa80nAYi10spkGnR+Bz/ eflE7UApBANAiCuZA767gJGbwvB02w8Ki28tJuuOxlebyJetbKcQruqv7mXkt4PSE/9G uKqUKt88SikuavejNWhn4NXPwLmNJj2UFwsD0Pjg+YC84uyUvubur6/doPDJ+fimB/+O bkRA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1791020424; x=1791625224; h=content-transfer-encoding:content-type:mime-version:message-id:date :subject:cc:to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject :date:message-id:reply-to:content-type; bh=nfYeoE0FlNoYRCBgtkrLlvam3mS1qxhXTtp4SykzoVE=; b=fZE29iGHGXtVmbnppevsgJqkfbvDLxTEHHjrBwJsNFrLdoCGzfw2hBuRGboYhsckXc GxvFqH6UDFHnxVs9aPmcq0yqaFGeMzirQM84cbAngvDgZsEJW1I1TaWgSuXsnw7kfD7x +cVHlxsKuE9m78jj2tH/MerhPW836tVO+iEHciLDeO6HBPPm/RbcsdMlyHlkAXApr1qI Oqwe3uhKDJJfS2fXev8YfSgSJj/blb5Z0AdmbE6aD9SFQ/jCnBJZ2sfbx93NIUUokmVT Qwyj7Q6sy9EwZJbbpWlcAnAvUOfjAVFFRM2LMwg53H2KR3LkDWx50kE90kRglTeGePjM asJw== X-Forwarded-Encrypted: i=1; AKwUvBwcemSvq5MdsoaDXB/RnOtvbfS465tt4oWfsM4/v8v6oP2NWpt2/2FxjfqLzujl2l02KdiiAvUatMefvh0=@vger.kernel.org X-Gm-Message-State: AFq9FYLI7w+FjGbWe/VrCCO7pdHTLYbbVgsxBMKBGDNj2HC88UxJyLoN hv5PUtbTuP8Rzss9qWmcSjJep3QsIl8ANL57zBNn3mwiGz557GwNRE+T X-Gm-Gg: AYBFou2ILZDCEnCanmpZi4j5e+3R+o9xB2S/jOQic2tHKRT0IY986vuAcwsv3zoKXrO lH1j3y6CgtnOCj6Tdwr0LNU2bLOlVDexkfl6Ov5RWJjAIfMftVQaq3O4CUrrs6lwQ7aVgYYiT5x MK2e8Zlo2uOIasLmTfHJvEdVs7p+rLerrfxakRQBsPqWenbGD1tnPnn5DqKcjRhiYvyHVuAMwBH fVH4sGnH1FLlpGJQYCDId0xZN84KsS02jI2cvrIPc8f0uvQHwD6HLB1QQQhsrVQ7ok9mr25Y7PY DUKBOuK+M3zIA62NDuLssz8ixWJPlk4eAABehXRVma8knpxuyUb7QRN4KFyBo2/OwndxWAzgflg M1iV+pcROEWSt+J1QmVDTE+kxhtuZAjF0P/fDnfL41aHkqYOdgt/GX2+KRxZBCvXmSPSYEAWNkq KyUkMdjjTduBbXFLH+lvFO0oFNvjPFzj/vXYsisGRk1N5vuXqekqP8zGYBe8ktIJQRiYqGs1XlU AIeN1e8Vecbnh6wRVP9LE5zKfgwSLlRdxppQCp7OsDTYVdgAg== X-Received: by 2002:a05:693c:88dc:10b0:33b:e264:362a with SMTP id 5a478bee46e88-351113c0c4emr2626032eec.13.1791020424112; Sat, 03 Oct 2026 02:40:24 -0700 (PDT) Received: from li-1a3e774c-28e4-11b2-a85c-acc9f2883e29.ibm.com.com ([106.51.165.23]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-34f1500b59bsm13653306eec.28.2026.10.03.02.40.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 03 Oct 2026 02:40:23 -0700 (PDT) From: "Mukesh Kumar Chaurasiya (IBM)" To: ryabinin.a.a@gmail.com, glider@google.com, andreyknvl@gmail.com, dvyukov@google.com, vincenzo.frascino@arm.com, maddy@linux.ibm.com, mpe@ellerman.id.au, npiggin@gmail.com, chleroy@kernel.org, ritesh.list@gmail.com, sshegde@linux.ibm.com, kees@kernel.org, mkchauras@gmail.com, mahesh@linux.ibm.com, nikhilks@linux.ibm.com, amachhiw@linux.ibm.com, sayalip@linux.ibm.com, robh@kernel.org, mkchauras@linux.ibm.com, kasan-dev@googlegroups.com, linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org Cc: Venkat Rao Bagalkote Subject: [PATCH V4] powerpc/kasan: fix r2 corruption in mem*() on GENERIC_ENTRY with old compilers Date: Sat, 3 Oct 2026 15:10:06 +0530 Message-ID: <20261003094006.3404731-1-mkchauras@gmail.com> X-Mailer: git-send-email 2.55.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Closes: https://lore.kernel.org/all/96dae110-f79b-4e54-8a9b-514369019b5d@linux.ibm.com Tested-by: Venkat Rao Bagalkote Signed-off-by: Mukesh Kumar Chaurasiya (IBM) --- Changelog: V3 -> V4: - Kasan only disabled for mem intrinsics function for older compilers V3: https://lore.kernel.org/all/20260915100938.1337401-1-mkchauras@gmail.com V2 -> V3: - *dest = *src used instead of memcpy in cputable.c and prom_init.c V2: https://lore.kernel.org/all/20260911180536.3234640-2-mkchauras@gmail.com V1 -> V2: - Comments reworded - Commit message reworded V1: https://lore.kernel.org/all/20260908064948.999530-1-mkchauras@gmail.com arch/powerpc/include/asm/kasan.h | 15 --------------- arch/powerpc/include/asm/string.h | 21 +-------------------- arch/powerpc/kernel/cputable.c | 14 +++----------- arch/powerpc/kernel/prom_init.c | 10 ++-------- arch/powerpc/kernel/prom_init_check.sh | 15 +-------------- arch/powerpc/lib/copy_32.S | 10 +++------- arch/powerpc/lib/mem_64.S | 7 ++----- arch/powerpc/lib/memcpy_64.S | 4 +--- 8 files changed, 13 insertions(+), 83 deletions(-) diff --git a/arch/powerpc/include/asm/kasan.h b/arch/powerpc/include/asm/kasan.h index a690e7da53c2..599a9e02af02 100644 --- a/arch/powerpc/include/asm/kasan.h +++ b/arch/powerpc/include/asm/kasan.h @@ -2,21 +2,6 @@ #ifndef __ASM_KASAN_H #define __ASM_KASAN_H -#if defined(CONFIG_KASAN) && !defined(CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX) -#define _GLOBAL_KASAN(fn) \ - _GLOBAL(fn); \ - _GLOBAL(__##fn) -#define _GLOBAL_TOC_KASAN(fn) \ - _GLOBAL_TOC(fn); \ - _GLOBAL_TOC(__##fn) -#define EXPORT_SYMBOL_KASAN(fn) \ - EXPORT_SYMBOL(__##fn) -#else /* CONFIG_KASAN && !CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX */ -#define _GLOBAL_KASAN(fn) _GLOBAL(fn) -#define _GLOBAL_TOC_KASAN(fn) _GLOBAL_TOC(fn) -#define EXPORT_SYMBOL_KASAN(fn) -#endif /* CONFIG_KASAN && !CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX */ - #ifndef __ASSEMBLER__ #include diff --git a/arch/powerpc/include/asm/string.h b/arch/powerpc/include/asm/string.h index 1981bd4036b5..161b949683b3 100644 --- a/arch/powerpc/include/asm/string.h +++ b/arch/powerpc/include/asm/string.h @@ -29,29 +29,10 @@ extern void * memchr(const void *,int,__kernel_size_t); void memcpy_flushcache(void *dest, const void *src, size_t size); #ifdef CONFIG_KASAN -/* __mem variants are used by KASAN to implement instrumented meminstrinsics. */ -#ifdef CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX +/* Used by mm/kasan as raw backends to bypass KASAN checking. */ #define __memset memset #define __memcpy memcpy #define __memmove memmove -#else /* CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX */ -void *__memset(void *s, int c, __kernel_size_t count); -void *__memcpy(void *to, const void *from, __kernel_size_t n); -void *__memmove(void *to, const void *from, __kernel_size_t n); -#ifndef __SANITIZE_ADDRESS__ -/* - * For files that are not instrumented (e.g. mm/slub.c) we - * should use not instrumented version of mem* functions. - */ -#define memcpy(dst, src, len) __memcpy(dst, src, len) -#define memmove(dst, src, len) __memmove(dst, src, len) -#define memset(s, c, n) __memset(s, c, n) - -#ifndef __NO_FORTIFY -#define __NO_FORTIFY /* FORTIFY_SOURCE uses __builtin_memcpy, etc. */ -#endif -#endif /* !__SANITIZE_ADDRESS__ */ -#endif /* CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX */ #endif /* CONFIG_KASAN */ #ifdef CONFIG_PPC64 diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 6f6801da9dc1..4731e27bb7bc 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -35,12 +35,7 @@ void __init set_cur_cpu_spec(struct cpu_spec *s) struct cpu_spec *t = &the_cpu_spec; t = PTRRELOC(t); - /* - * use memcpy() instead of *t = *s so that GCC replaces it - * by __memcpy() when KASAN is active - */ - memcpy(t, s, sizeof(*t)); - + *t = *s; *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec; } @@ -53,11 +48,8 @@ static struct cpu_spec * __init setup_cpu_spec(unsigned long offset, t = PTRRELOC(t); old = *t; - /* - * Copy everything, then do fixups. Use memcpy() instead of *t = *s - * so that GCC replaces it by __memcpy() when KASAN is active - */ - memcpy(t, s, sizeof(*t)); + /* Copy everything, then do fixups. */ + *t = *s; /* * If we are overriding a previous value derived from the real diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index eb9f556b0937..e8e071024da5 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -1362,14 +1362,8 @@ static void __init prom_check_platform_support(void) int prop_len = prom_getproplen(prom.chosen, "ibm,arch-vec-5-platform-support"); - /* - * First copy the architecture vec template - * - * use memcpy() instead of *vec = *vec_template so that GCC replaces it - * by __memcpy() when KASAN is active - */ - memcpy(&ibm_architecture_vec, &ibm_architecture_vec_template, - sizeof(ibm_architecture_vec)); + /* First copy the architecture vec template */ + ibm_architecture_vec = ibm_architecture_vec_template; prom_strscpy_pad(ibm_architecture_vec.vec7.os_id, linux_banner, 256); diff --git a/arch/powerpc/kernel/prom_init_check.sh b/arch/powerpc/kernel/prom_init_check.sh index 3090b97258ae..3155cc722e48 100644 --- a/arch/powerpc/kernel/prom_init_check.sh +++ b/arch/powerpc/kernel/prom_init_check.sh @@ -13,21 +13,8 @@ # If you really need to reference something from prom_init.o add # it to the list below: -has_renamed_memintrinsics() -{ - grep -q "^CONFIG_KASAN=y$" "${KCONFIG_CONFIG}" && \ - ! grep -q "^CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX=y" "${KCONFIG_CONFIG}" -} - -if has_renamed_memintrinsics -then - MEM_FUNCS="__memcpy __memset" -else - MEM_FUNCS="memcpy memset" -fi - WHITELIST="add_reloc_offset __bss_start __bss_stop copy_and_flush -_end enter_prom $MEM_FUNCS reloc_offset __secondary_hold +_end enter_prom memcpy memset reloc_offset __secondary_hold __secondary_hold_acknowledge __secondary_hold_spinloop __start logo_linux_clut224 btext_prepare_BAT reloc_got2 kernstart_addr memstart_addr linux_banner _stext diff --git a/arch/powerpc/lib/copy_32.S b/arch/powerpc/lib/copy_32.S index 933b685e7ab6..97eb9ca0cc23 100644 --- a/arch/powerpc/lib/copy_32.S +++ b/arch/powerpc/lib/copy_32.S @@ -10,7 +10,6 @@ #include #include #include -#include #define COPY_16_BYTES \ lwz r7,4(r4); \ @@ -87,7 +86,7 @@ EXPORT_SYMBOL(memset16) * We therefore skip the optimised bloc that uses dcbz. This jump is * replaced by a nop once cache is active. This is done in machine_init() */ -_GLOBAL_KASAN(memset) +_GLOBAL(memset) cmplwi 0,r5,4 blt 7f @@ -147,7 +146,6 @@ _GLOBAL_KASAN(memset) bdnz 9b blr EXPORT_SYMBOL(memset) -EXPORT_SYMBOL_KASAN(memset) /* * This version uses dcbz on the complete cache lines in the @@ -160,12 +158,12 @@ EXPORT_SYMBOL_KASAN(memset) * We therefore jump to generic_memcpy which doesn't use dcbz. This jump is * replaced by a nop once cache is active. This is done in machine_init() */ -_GLOBAL_KASAN(memmove) +_GLOBAL(memmove) cmplw 0,r3,r4 bgt backwards_memcpy /* fall through */ -_GLOBAL_KASAN(memcpy) +_GLOBAL(memcpy) 1: b generic_memcpy patch_site 1b, patch__memcpy_nocache @@ -241,8 +239,6 @@ _GLOBAL_KASAN(memcpy) 65: blr EXPORT_SYMBOL(memcpy) EXPORT_SYMBOL(memmove) -EXPORT_SYMBOL_KASAN(memcpy) -EXPORT_SYMBOL_KASAN(memmove) generic_memcpy: srwi. r7,r5,3 diff --git a/arch/powerpc/lib/mem_64.S b/arch/powerpc/lib/mem_64.S index 6fd06cd20faa..40eaedd31486 100644 --- a/arch/powerpc/lib/mem_64.S +++ b/arch/powerpc/lib/mem_64.S @@ -8,7 +8,6 @@ #include #include #include -#include #ifndef CONFIG_KASAN _GLOBAL(__memset16) @@ -29,7 +28,7 @@ EXPORT_SYMBOL(__memset32) EXPORT_SYMBOL(__memset64) #endif -_GLOBAL_KASAN(memset) +_GLOBAL(memset) neg r0,r3 rlwimi r4,r4,8,16,23 andi. r0,r0,7 /* # bytes to be 8-byte aligned */ @@ -95,9 +94,8 @@ _GLOBAL_KASAN(memset) stb r4,0(r6) blr EXPORT_SYMBOL(memset) -EXPORT_SYMBOL_KASAN(memset) -_GLOBAL_TOC_KASAN(memmove) +_GLOBAL_TOC(memmove) cmplw 0,r3,r4 bgt backwards_memcpy b memcpy @@ -139,4 +137,3 @@ _GLOBAL(backwards_memcpy) mtctr r7 b 1b EXPORT_SYMBOL(memmove) -EXPORT_SYMBOL_KASAN(memmove) diff --git a/arch/powerpc/lib/memcpy_64.S b/arch/powerpc/lib/memcpy_64.S index b5a67e20143f..0cedd455231a 100644 --- a/arch/powerpc/lib/memcpy_64.S +++ b/arch/powerpc/lib/memcpy_64.S @@ -7,7 +7,6 @@ #include #include #include -#include #ifndef SELFTEST_CASE /* For big-endian, 0 == most CPUs, 1 == POWER6, 2 == Cell */ @@ -15,7 +14,7 @@ #endif .align 7 -_GLOBAL_TOC_KASAN(memcpy) +_GLOBAL_TOC(memcpy) BEGIN_FTR_SECTION #ifdef __LITTLE_ENDIAN__ cmpdi cr7,r5,0 @@ -227,4 +226,3 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD) blr #endif EXPORT_SYMBOL(memcpy) -EXPORT_SYMBOL_KASAN(memcpy) -- 2.55.0