From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id AEF52CA0FE7 for ; Mon, 25 Aug 2025 20:25:57 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 05B9B8E006D; Mon, 25 Aug 2025 16:25:57 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 0091B8E0038; Mon, 25 Aug 2025 16:25:56 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id E61248E006D; Mon, 25 Aug 2025 16:25:56 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id D18D88E0038 for ; Mon, 25 Aug 2025 16:25:56 -0400 (EDT) Received: from smtpin05.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay07.hostedemail.com (Postfix) with ESMTP id 8EC2D16053D for ; Mon, 25 Aug 2025 20:25:56 +0000 (UTC) X-FDA: 83816411112.05.154299A Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.11]) by imf08.hostedemail.com (Postfix) with ESMTP id 5021416000D for ; Mon, 25 Aug 2025 20:25:54 +0000 (UTC) Authentication-Results: imf08.hostedemail.com; dkim=pass header.d=intel.com header.s=Intel header.b=YkHyYmAC; spf=pass (imf08.hostedemail.com: domain of maciej.wieczor-retman@intel.com designates 192.198.163.11 as permitted sender) smtp.mailfrom=maciej.wieczor-retman@intel.com; dmarc=pass (policy=none) header.from=intel.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1756153554; a=rsa-sha256; cv=none; b=HmRSiD1/Kjc0wPsDGAbzR5Go09BdV8bFqdgQkKQ92VPZY0X4uq1MS0X4vxfiWLcGvM7jUA sxlQg3VnGh7GfvBlshSTsNihz4qZjRyAS50uP9ilmuG8QO7WB4ASDMiUKZraFkDPvQ5bZ4 ZmuqwCgpC8NIPUK7SRsGxYHHoWGwqTI= ARC-Authentication-Results: i=1; imf08.hostedemail.com; dkim=pass header.d=intel.com header.s=Intel header.b=YkHyYmAC; spf=pass (imf08.hostedemail.com: domain of maciej.wieczor-retman@intel.com designates 192.198.163.11 as permitted sender) smtp.mailfrom=maciej.wieczor-retman@intel.com; dmarc=pass (policy=none) header.from=intel.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1756153554; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=uHTJ9s9YMvaM2p0Fv0kvWS50c+p1aRICOMM/MPFtDD8=; b=QLdfA6qVYnYSl+VaNL97LPj4eSkSq25xuZ1eZQyNCZyVzIzOanEaIJuQkF6irFN/6gTIff 8iU8QhfIah54NdAR+ZHKdWsxyWxw6rnC7IP1RCarlNXVfM0s76esrHb7QKRBMUd/Y9qjP0 lVYuhmlKXIj/EJd5iVmc1TcABNDQEU8= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1756153554; x=1787689554; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ylJQkJrpIfLpcFXTqJ0788ur27jC/xlUxXzYUcEtc4o=; b=YkHyYmACXn6DAMTCf2abyBkjgaBVpPRQ8VbMg6wld1cvaposaB5lV9+2 0ic4Ymn4YX9pBLi2K8Xb5gGP+o3SMJXOrmblXfEmYx/90/zZuHvnZvsPN /wzbVNxhXhab8j5V1bHoG9FpNG404scSRUt6MK7cu/TZMnBdq6o5hIopn nOVVHUUW3YFhuAz4MaUHCjWELxfX3ZIPZlPqqYBMb696w8zPgE+eEmVgS JbJAQwgcE/xBiV5KWZEeFkC5gbjfDd05b7fYJX9RWDcUqqrqVPJJ2YnhJ DLwrJ3frk4WAZ6UDBGEvFYhAXgkgWU7ah8Ac1eTwGpXYNPT0e3Du/RLVe A==; X-CSE-ConnectionGUID: 4lTjkMgoS2qC0nqy3ihRZQ== X-CSE-MsgGUID: 2CLqst7GRQ27ELtJ51P79g== X-IronPort-AV: E=McAfee;i="6800,10657,11533"; a="68970266" X-IronPort-AV: E=Sophos;i="6.18,214,1751266800"; d="scan'208";a="68970266" Received: from fmviesa008.fm.intel.com ([10.60.135.148]) by fmvoesa105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Aug 2025 13:25:52 -0700 X-CSE-ConnectionGUID: mFiywEvyTiCAxUVk2a9p/Q== X-CSE-MsgGUID: DHS3og96Q0yCJmHB4RsCnA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.18,214,1751266800"; d="scan'208";a="169779868" Received: from bergbenj-mobl1.ger.corp.intel.com (HELO wieczorr-mobl1.intel.com) ([10.245.245.6]) by fmviesa008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Aug 2025 13:25:30 -0700 From: Maciej Wieczor-Retman To: sohil.mehta@intel.com, baohua@kernel.org, david@redhat.com, kbingham@kernel.org, weixugc@google.com, Liam.Howlett@oracle.com, alexandre.chartre@oracle.com, kas@kernel.org, mark.rutland@arm.com, trintaeoitogc@gmail.com, axelrasmussen@google.com, yuanchu@google.com, joey.gouly@arm.com, samitolvanen@google.com, joel.granados@kernel.org, graf@amazon.com, vincenzo.frascino@arm.com, kees@kernel.org, ardb@kernel.org, thiago.bauermann@linaro.org, glider@google.com, thuth@redhat.com, kuan-ying.lee@canonical.com, pasha.tatashin@soleen.com, nick.desaulniers+lkml@gmail.com, vbabka@suse.cz, kaleshsingh@google.com, justinstitt@google.com, catalin.marinas@arm.com, alexander.shishkin@linux.intel.com, samuel.holland@sifive.com, dave.hansen@linux.intel.com, corbet@lwn.net, xin@zytor.com, dvyukov@google.com, tglx@linutronix.de, scott@os.amperecomputing.com, jason.andryuk@amd.com, morbo@google.com, nathan@kernel.org, lorenzo.stoakes@oracle.com, mingo@redhat.com, brgerst@gmail.com, kristina.martsenko@arm.com, bigeasy@linutronix.de, luto@kernel.org, jgross@suse.com, jpoimboe@kernel.org, urezki@gmail.com, mhocko@suse.com, ada.coupriediaz@arm.com, hpa@zytor.com, maciej.wieczor-retman@intel.com, leitao@debian.org, peterz@infradead.org, wangkefeng.wang@huawei.com, surenb@google.com, ziy@nvidia.com, smostafa@google.com, ryabinin.a.a@gmail.com, ubizjak@gmail.com, jbohac@suse.cz, broonie@kernel.org, akpm@linux-foundation.org, guoweikang.kernel@gmail.com, rppt@kernel.org, pcc@google.com, jan.kiszka@siemens.com, nicolas.schier@linux.dev, will@kernel.org, andreyknvl@gmail.com, jhubbard@nvidia.com, bp@alien8.de Cc: x86@kernel.org, linux-doc@vger.kernel.org, linux-mm@kvack.org, llvm@lists.linux.dev, linux-kbuild@vger.kernel.org, kasan-dev@googlegroups.com, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH v5 01/19] kasan: sw_tags: Use arithmetic shift for shadow computation Date: Mon, 25 Aug 2025 22:24:26 +0200 Message-ID: <7e314394fc5643def4cd4c6f34ebe09c85c43852.1756151769.git.maciej.wieczor-retman@intel.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Rspamd-Server: rspam08 X-Rspamd-Queue-Id: 5021416000D X-Stat-Signature: nuq6nofgduq6msr815ekafzanbfrwb6m X-Rspam-User: X-HE-Tag: 1756153554-251357 X-HE-Meta: U2FsdGVkX1/PXXXxiiQddUG9PA9HFoVYo9NpfE0KK8wOXigQtHHk/wnBqa+kCob5UAdmok7H4JK8pHdYPaIxyRf9q+xjXo2cH2XgUQktxcm681H3i/gcHwRGy4U3iRhUNEnjlSS7C6Z+rpDjaFgMKY9aSWZTcU55wzrjTT3HjjTQ6F8HedCGkhl36WsglXvoJJph8ZCWXR9fOw2hN3ksBRSgTfi4G14Z605xKIiaCladUp2gBAsa9vTic6U0swz4IE0I5orUSYH9Gv+pPFRqfdk6MnomxSsmdrvueaZAInC3J5lV8kCNzGBAa5pFw4qKYEZNQSFbYdGYRPWIp/+FVsIlyGJ+Hxx8YwS/GBQ7Ds4Nh39rYRriDJDEJBTT5EO1BNNZNoaCbs3TERxU5mtxpP3igvLLZrB6BSK66nNkRQRd9T5SuMbNLV5mAhW7allY/vbdnypA6DftRlvWU5IrbftwdKgMFDIgXxsvLHpf5k4SSJDyXFqsFhwULVbaQ6edGTBuQ8jgrx38YeNcpXFpvI2rRhDiNn/u7nszt3lqDUbuFvUMAgs25rG+zffyxl7ugBa+4NuSpQzstxvmxR8GFMPnce3pUJjnCQJhjDMIrit9pMn2T0zEVHBOEfJ5GXduVJq/G6dh63CpU8c/WWTTU6nRyUtMPAZgaEAfsvbEyMzW940EAmxgWTXBy0gankKc5J9lHJuW1Y5r3QILZ4naa1zv/ujgJfEzn96liXW8wgzCMOlm2R9lix+YJ/kGdCYZO0RU6vRS15MhFUC/TSpaBie1jXN1ojJWjIo/K94Uc3LZrEQImjOc3tdYyJ04pNGfxDQLwkaOLIV5oFwCkBk4UWa8EP3y/VUGByA6lANPWn2WqUc+H7ouB3FkatdBm5HuU65VuovYpFW4sQv1jEQGg44b2vfPaJ7kZAiCQOPXOP4NL/TRINYGSMys+8H6gW0o58SN3e7+DpGC98nDYyr 9axz5s/B NK7QPC/yBC+E2qkgMrNBltYWpL4+Y/M1o9XhLX79y74WDQd9jgFOBdFcz5EKdzN/J44PbYuPGyVBjowgrpsbMsEEWrNmJoWgl+47aF/OvN3Wphl0YK3qZrMa5bvN93oduod4aTIR4cy1CcWrK1oLR/VB6p3ph2sPMHfe2saMzcMQakM35TAyfcL9sajYoBTuHAwtvzgwxxwARwhNS2iwZGB33hN1UsT+y+n+jqbK/FQ3hvLwrm0Qu4nxjlR4dbIK7+mONPPykqSxJlw/8QoQk7OKseI7O8rtiBvO7NQx1KBSfUMrilz//Qhb5dDJ0UewIlvpdbwnKNcpnahky+UvVtSt7P6MimzOQjJlc8pkqXEzo690eLBfCqvHOhmY0X9ZkhfNx X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: From: Samuel Holland Currently, kasan_mem_to_shadow() uses a logical right shift, which turns canonical kernel addresses into non-canonical addresses by clearing the high KASAN_SHADOW_SCALE_SHIFT bits. The value of KASAN_SHADOW_OFFSET is then chosen so that the addition results in a canonical address for the shadow memory. For KASAN_GENERIC, this shift/add combination is ABI with the compiler, because KASAN_SHADOW_OFFSET is used in compiler-generated inline tag checks[1], which must only attempt to dereference canonical addresses. However, for KASAN_SW_TAGS we have some freedom to change the algorithm without breaking the ABI. Because TBI is enabled for kernel addresses, the top bits of shadow memory addresses computed during tag checks are irrelevant, and so likewise are the top bits of KASAN_SHADOW_OFFSET. This is demonstrated by the fact that LLVM uses a logical right shift in the tag check fast path[2] but a sbfx (signed bitfield extract) instruction in the slow path[3] without causing any issues. Using an arithmetic shift in kasan_mem_to_shadow() provides a number of benefits: 1) The memory layout doesn't change but is easier to understand. KASAN_SHADOW_OFFSET becomes a canonical memory address, and the shifted pointer becomes a negative offset, so KASAN_SHADOW_OFFSET == KASAN_SHADOW_END regardless of the shift amount or the size of the virtual address space. 2) KASAN_SHADOW_OFFSET becomes a simpler constant, requiring only one instruction to load instead of two. Since it must be loaded in each function with a tag check, this decreases kernel text size by 0.5%. 3) This shift and the sign extension from kasan_reset_tag() can be combined into a single sbfx instruction. When this same algorithm change is applied to the compiler, it removes an instruction from each inline tag check, further reducing kernel text size by an additional 4.6%. These benefits extend to other architectures as well. On RISC-V, where the baseline ISA does not shifted addition or have an equivalent to the sbfx instruction, loading KASAN_SHADOW_OFFSET is reduced from 3 to 2 instructions, and kasan_mem_to_shadow(kasan_reset_tag(addr)) similarly combines two consecutive right shifts. Link: https://github.com/llvm/llvm-project/blob/llvmorg-20-init/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp#L1316 [1] Link: https://github.com/llvm/llvm-project/blob/llvmorg-20-init/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp#L895 [2] Link: https://github.com/llvm/llvm-project/blob/llvmorg-20-init/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp#L669 [3] Signed-off-by: Samuel Holland Signed-off-by: Maciej Wieczor-Retman --- Changelog v5: (Maciej) - (u64) -> (unsigned long) in report.c Changelog v4: (Maciej) - Revert x86 to signed mem_to_shadow mapping. - Remove last two paragraphs since they were just poorer duplication of the comments in kasan_non_canonical_hook(). Changelog v3: (Maciej) - Fix scripts/gdb/linux/kasan.py so the new signed mem_to_shadow() is reflected there. - Fix Documentation/arch/arm64/kasan-offsets.sh to take new offsets into account. - Made changes to the kasan_non_canonical_hook() according to upstream discussion. Settled on overflow on both ranges and separate checks for x86 and arm. Changelog v2: (Maciej) - Correct address range that's checked in kasan_non_canonical_hook(). Adjust the comment inside. - Remove part of comment from arch/arm64/include/asm/memory.h. - Append patch message paragraph about the overflow in kasan_non_canonical_hook(). Documentation/arch/arm64/kasan-offsets.sh | 8 +++-- arch/arm64/Kconfig | 10 +++---- arch/arm64/include/asm/memory.h | 14 ++++++++- arch/arm64/mm/kasan_init.c | 7 +++-- include/linux/kasan.h | 10 +++++-- mm/kasan/report.c | 36 ++++++++++++++++++++--- scripts/gdb/linux/kasan.py | 3 ++ scripts/gdb/linux/mm.py | 5 ++-- 8 files changed, 75 insertions(+), 18 deletions(-) mode change 100644 => 100755 Documentation/arch/arm64/kasan-offsets.sh diff --git a/Documentation/arch/arm64/kasan-offsets.sh b/Documentation/arch/arm64/kasan-offsets.sh old mode 100644 new mode 100755 index 2dc5f9e18039..ce777c7c7804 --- a/Documentation/arch/arm64/kasan-offsets.sh +++ b/Documentation/arch/arm64/kasan-offsets.sh @@ -5,8 +5,12 @@ print_kasan_offset () { printf "%02d\t" $1 - printf "0x%08x00000000\n" $(( (0xffffffff & (-1 << ($1 - 1 - 32))) \ - - (1 << (64 - 32 - $2)) )) + if [[ $2 -ne 4 ]] then + printf "0x%08x00000000\n" $(( (0xffffffff & (-1 << ($1 - 1 - 32))) \ + - (1 << (64 - 32 - $2)) )) + else + printf "0x%08x00000000\n" $(( (0xffffffff & (-1 << ($1 - 1 - 32))) )) + fi } echo KASAN_SHADOW_SCALE_SHIFT = 3 diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index e9bbfacc35a6..82cbfc7d1233 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -431,11 +431,11 @@ config KASAN_SHADOW_OFFSET default 0xdffffe0000000000 if ARM64_VA_BITS_42 && !KASAN_SW_TAGS default 0xdfffffc000000000 if ARM64_VA_BITS_39 && !KASAN_SW_TAGS default 0xdffffff800000000 if ARM64_VA_BITS_36 && !KASAN_SW_TAGS - default 0xefff800000000000 if (ARM64_VA_BITS_48 || (ARM64_VA_BITS_52 && !ARM64_16K_PAGES)) && KASAN_SW_TAGS - default 0xefffc00000000000 if (ARM64_VA_BITS_47 || ARM64_VA_BITS_52) && ARM64_16K_PAGES && KASAN_SW_TAGS - default 0xeffffe0000000000 if ARM64_VA_BITS_42 && KASAN_SW_TAGS - default 0xefffffc000000000 if ARM64_VA_BITS_39 && KASAN_SW_TAGS - default 0xeffffff800000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS + default 0xffff800000000000 if (ARM64_VA_BITS_48 || (ARM64_VA_BITS_52 && !ARM64_16K_PAGES)) && KASAN_SW_TAGS + default 0xffffc00000000000 if (ARM64_VA_BITS_47 || ARM64_VA_BITS_52) && ARM64_16K_PAGES && KASAN_SW_TAGS + default 0xfffffe0000000000 if ARM64_VA_BITS_42 && KASAN_SW_TAGS + default 0xffffffc000000000 if ARM64_VA_BITS_39 && KASAN_SW_TAGS + default 0xfffffff800000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS default 0xffffffffffffffff config UNWIND_TABLES diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index 5213248e081b..277d56ceeb01 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -89,7 +89,15 @@ * * KASAN_SHADOW_END is defined first as the shadow address that corresponds to * the upper bound of possible virtual kernel memory addresses UL(1) << 64 - * according to the mapping formula. + * according to the mapping formula. For Generic KASAN, the address in the + * mapping formula is treated as unsigned (part of the compiler's ABI), so the + * end of the shadow memory region is at a large positive offset from + * KASAN_SHADOW_OFFSET. For Software Tag-Based KASAN, the address in the + * formula is treated as signed. Since all kernel addresses are negative, they + * map to shadow memory below KASAN_SHADOW_OFFSET, making KASAN_SHADOW_OFFSET + * itself the end of the shadow memory region. (User pointers are positive and + * would map to shadow memory above KASAN_SHADOW_OFFSET, but shadow memory is + * not allocated for them.) * * KASAN_SHADOW_START is defined second based on KASAN_SHADOW_END. The shadow * memory start must map to the lowest possible kernel virtual memory address @@ -100,7 +108,11 @@ */ #if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS) #define KASAN_SHADOW_OFFSET _AC(CONFIG_KASAN_SHADOW_OFFSET, UL) +#ifdef CONFIG_KASAN_GENERIC #define KASAN_SHADOW_END ((UL(1) << (64 - KASAN_SHADOW_SCALE_SHIFT)) + KASAN_SHADOW_OFFSET) +#else +#define KASAN_SHADOW_END KASAN_SHADOW_OFFSET +#endif #define _KASAN_SHADOW_START(va) (KASAN_SHADOW_END - (UL(1) << ((va) - KASAN_SHADOW_SCALE_SHIFT))) #define KASAN_SHADOW_START _KASAN_SHADOW_START(vabits_actual) #define PAGE_END KASAN_SHADOW_START diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c index d541ce45daeb..dc2de12c4f26 100644 --- a/arch/arm64/mm/kasan_init.c +++ b/arch/arm64/mm/kasan_init.c @@ -198,8 +198,11 @@ static bool __init root_level_aligned(u64 addr) /* The early shadow maps everything to a single page of zeroes */ asmlinkage void __init kasan_early_init(void) { - BUILD_BUG_ON(KASAN_SHADOW_OFFSET != - KASAN_SHADOW_END - (1UL << (64 - KASAN_SHADOW_SCALE_SHIFT))); + if (IS_ENABLED(CONFIG_KASAN_GENERIC)) + BUILD_BUG_ON(KASAN_SHADOW_OFFSET != + KASAN_SHADOW_END - (1UL << (64 - KASAN_SHADOW_SCALE_SHIFT))); + else + BUILD_BUG_ON(KASAN_SHADOW_OFFSET != KASAN_SHADOW_END); BUILD_BUG_ON(!IS_ALIGNED(_KASAN_SHADOW_START(VA_BITS), SHADOW_ALIGN)); BUILD_BUG_ON(!IS_ALIGNED(_KASAN_SHADOW_START(VA_BITS_MIN), SHADOW_ALIGN)); BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_END, SHADOW_ALIGN)); diff --git a/include/linux/kasan.h b/include/linux/kasan.h index 890011071f2b..b396feca714f 100644 --- a/include/linux/kasan.h +++ b/include/linux/kasan.h @@ -61,8 +61,14 @@ int kasan_populate_early_shadow(const void *shadow_start, #ifndef kasan_mem_to_shadow static inline void *kasan_mem_to_shadow(const void *addr) { - return (void *)((unsigned long)addr >> KASAN_SHADOW_SCALE_SHIFT) - + KASAN_SHADOW_OFFSET; + void *scaled; + + if (IS_ENABLED(CONFIG_KASAN_GENERIC)) + scaled = (void *)((unsigned long)addr >> KASAN_SHADOW_SCALE_SHIFT); + else + scaled = (void *)((long)addr >> KASAN_SHADOW_SCALE_SHIFT); + + return KASAN_SHADOW_OFFSET + scaled; } #endif diff --git a/mm/kasan/report.c b/mm/kasan/report.c index 62c01b4527eb..50d487a0687a 100644 --- a/mm/kasan/report.c +++ b/mm/kasan/report.c @@ -642,11 +642,39 @@ void kasan_non_canonical_hook(unsigned long addr) const char *bug_type; /* - * All addresses that came as a result of the memory-to-shadow mapping - * (even for bogus pointers) must be >= KASAN_SHADOW_OFFSET. + * For Generic KASAN, kasan_mem_to_shadow() uses the logical right shift + * and never overflows with the chosen KASAN_SHADOW_OFFSET values (on + * both x86 and arm64). Thus, the possible shadow addresses (even for + * bogus pointers) belong to a single contiguous region that is the + * result of kasan_mem_to_shadow() applied to the whole address space. */ - if (addr < KASAN_SHADOW_OFFSET) - return; + if (IS_ENABLED(CONFIG_KASAN_GENERIC)) { + if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0UL)) || + addr > (unsigned long)kasan_mem_to_shadow((void *)(~0UL))) + return; + } + + /* + * For Software Tag-Based KASAN, kasan_mem_to_shadow() uses the + * arithmetic shift. Normally, this would make checking for a possible + * shadow address complicated, as the shadow address computation + * operation would overflow only for some memory addresses. However, due + * to the chosen KASAN_SHADOW_OFFSET values and the fact the + * kasan_mem_to_shadow() only operates on pointers with the tag reset, + * the overflow always happens. + * + * For arm64, the top byte of the pointer gets reset to 0xFF. Thus, the + * possible shadow addresses belong to a region that is the result of + * kasan_mem_to_shadow() applied to the memory range + * [0xFF000000000000, 0xFFFFFFFFFFFFFFFF]. Despite the overflow, the + * resulting possible shadow region is contiguous, as the overflow + * happens for both 0xFF000000000000 and 0xFFFFFFFFFFFFFFFF. + */ + if (IS_ENABLED(CONFIG_KASAN_SW_TAGS) && IS_ENABLED(CONFIG_ARM64)) { + if (addr < (unsigned long)kasan_mem_to_shadow((void *)(0xFFUL << 56)) || + addr > (unsigned long)kasan_mem_to_shadow((void *)(~0UL))) + return; + } orig_addr = (unsigned long)kasan_shadow_to_mem((void *)addr); diff --git a/scripts/gdb/linux/kasan.py b/scripts/gdb/linux/kasan.py index 56730b3fde0b..fca39968d308 100644 --- a/scripts/gdb/linux/kasan.py +++ b/scripts/gdb/linux/kasan.py @@ -8,6 +8,7 @@ import gdb from linux import constants, mm +from ctypes import c_int64 as s64 def help(): t = """Usage: lx-kasan_mem_to_shadow [Hex memory addr] @@ -39,6 +40,8 @@ class KasanMemToShadow(gdb.Command): else: help() def kasan_mem_to_shadow(self, addr): + if constants.CONFIG_KASAN_SW_TAGS: + addr = s64(addr) return (addr >> self.p_ops.KASAN_SHADOW_SCALE_SHIFT) + self.p_ops.KASAN_SHADOW_OFFSET KasanMemToShadow() diff --git a/scripts/gdb/linux/mm.py b/scripts/gdb/linux/mm.py index 7571aebbe650..2e63f3dedd53 100644 --- a/scripts/gdb/linux/mm.py +++ b/scripts/gdb/linux/mm.py @@ -110,12 +110,13 @@ class aarch64_page_ops(): self.KERNEL_END = gdb.parse_and_eval("_end") if constants.LX_CONFIG_KASAN_GENERIC or constants.LX_CONFIG_KASAN_SW_TAGS: + self.KASAN_SHADOW_OFFSET = constants.LX_CONFIG_KASAN_SHADOW_OFFSET if constants.LX_CONFIG_KASAN_GENERIC: self.KASAN_SHADOW_SCALE_SHIFT = 3 + self.KASAN_SHADOW_END = (1 << (64 - self.KASAN_SHADOW_SCALE_SHIFT)) + self.KASAN_SHADOW_OFFSET else: self.KASAN_SHADOW_SCALE_SHIFT = 4 - self.KASAN_SHADOW_OFFSET = constants.LX_CONFIG_KASAN_SHADOW_OFFSET - self.KASAN_SHADOW_END = (1 << (64 - self.KASAN_SHADOW_SCALE_SHIFT)) + self.KASAN_SHADOW_OFFSET + self.KASAN_SHADOW_END = self.KASAN_SHADOW_OFFSET self.PAGE_END = self.KASAN_SHADOW_END - (1 << (self.vabits_actual - self.KASAN_SHADOW_SCALE_SHIFT)) else: self.PAGE_END = self._PAGE_END(self.VA_BITS_MIN) -- 2.50.1