From nobody Sat Jul 25 23:05:55 2026 Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.50]) (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 E397228CF5F for ; Sun, 12 Jul 2026 12:08:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783858132; cv=none; b=FFifhIHSarAmsdBEZkygPOhEbFqkPWBFLF5FJ7eC7o3cYZbTS5RINOy4iUW1Vr3Z2WgG8Uoo6HosebQkYcmEq2B3aXT6PLm3mM7oIAK69pc76/0S0SpHGuRusKggxeDkkC4OCOAMFbwWKlyr2RTG1iT8c82uAt7xAOMALh4JV2s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783858132; c=relaxed/simple; bh=pDQGgOI51v7B8IxzwR27wEG6G8cVPR5Hlaz/kQw4AtY=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=tInQvqUDWCpD5NneAX0f7vmThNEPfZWI06SdfD5ncS0N+e5yoRng2wVlAF1CvDEJs+yh5mFDFuIZduzhwGC/5i5srJeHOSG+5jW7/x2REMk3kSamq5mHlAxLh/kOFz2duTrS3vUsuLsDwIkJgGU1REhhapMaWFobY68uRcZMS9M= 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=c+waMipZ; arc=none smtp.client-ip=209.85.128.50 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="c+waMipZ" Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-493f60208a5so17851135e9.3 for ; Sun, 12 Jul 2026 05:08:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783858129; x=1784462929; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=fPDvzFIiqCdivNjWyVBd/1diSMnrRTpEbgxd7LdADq4=; b=c+waMipZLNnarzOPJ53LiIb6P8zb5KqZcuuc5bDVs5KVvAwNMJf9ErUWRTXDT3IvEA jw6R0C2O0V9Ub7M5RHtgpAll2TBD8fJfz7ldLunU0jSCPX7LY7xFQ6nKfB1+2l3ATVIc EMJhyVjs9fxPXs2WzFryJ9elCaW6YOEaC/SspH/afDPT8xuNsrNRJSQsdJmc4IC9L8yt xzPaDNOEmBP9wokXZ853bv2+JrTqWkOs02Xrg07T+SK2vhw64BmJcML961Qxl05+Ha3X HqSO7T63ppNAXCJTUvFXsS0pU3IY6sAlcdgs2TwT7xjr9nMZWDeKLifkPTJ41e94lvaS q2mg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783858129; x=1784462929; h=content-transfer-encoding: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=fPDvzFIiqCdivNjWyVBd/1diSMnrRTpEbgxd7LdADq4=; b=GyhgaImaIQPRThg6pDG51/QrUg5+vrytGc1snG6RTRCd1dHFo9Znnr4iYF7u6z+E/u 4EsL4WMIxpjYPhQhaVxMSeUJvNJoEcQ24r8C4rPxDKEPatwrlsW9bYa61rGpmMQWyh8C L+sXcVHF6j0kLIJdyWlCw8o2s8GasFcccvQ5qHeEoyn43sABFEw3ZrVqTtMKFrj4l9x4 jBtBdkHNTg24bc57kOw1L7WdJe7SxWOX9Ojg5OAIdHXr+pZEEO0fhzbj9FDYxxiTeIwI S9GCYzU8C/iUHSn2dY0Avi7E/jB4WoLf9r5WOyUX7EViv1vkRIEEDzKvmpPno5Hf+Zu1 FoKw== X-Forwarded-Encrypted: i=1; AHgh+Rqtj1NT7C406z+XlQkhhYYDyeIwNMOMQWHLg3dJDDnDYbgLBHI+2zyQQe8QkrmZD2qlT0Esr/bkUcLJxWk=@vger.kernel.org X-Gm-Message-State: AOJu0Yw2vQiErc0og1pkNLx7UfN1IIwiZpMexQ6aVBHn6xokzW79LtG8 +YVJgFMznhhk5arHCpV08xGZquLpbEKQ6mDLPFaRfvcANVA3icUTR7Jf X-Gm-Gg: AfdE7cmkPEeFEQ0rgO5nT/2ryA6r20A2qLsdYuVaX3Kus4pFcauuxV7/hynhr1wRQD5 omtXQoHPnB3A9LGXOulUZCVq5fkH4w6jQlKRk12Zx6zyYpnBrdBUJV4E85wSghJJFTuNGZGAZdA 5wexIlmN2WYe45y/8Lt+T0E4GRfcI0WhWMvLJmsc0EpgSGgyx1RdSpXXISy4oEuPYLZ+5zG3QmV h1APMhtlvp7WoCC0fI6DPpvegNByKKfcxmhvzmIUH+YPSkIoVgYPm5jy8nIybSg2shDOwTnJoBp pZqtdRv4Lzb7UqY1yRerPvR5xMxIzO4v8qD3R/GTMyAh+i7rd+4Q5yj93mlyE5blZ41yjwjCY0T AEW1OKBQz7AimvhVPDRrmM/s5w6g8NQgsY64J5/mdHJDKLolJvkNj30xmz/12SUuLThYKR533QC BXs6PAQtPqloamYf80k4mld6UDwECHvbsrn8xPq0CjeYsewi8S9n0K1SO8yv84YXYkUkJoc22xw eu2P8xJWrzG1jsocJ+4E7iUubM8VFvF6pq7+vtrhT8OVX9cm6cvjnOk X-Received: by 2002:a05:600c:4fca:b0:492:437a:a653 with SMTP id 5b1f17b1804b1-493f8826c59mr54375365e9.26.1783858128965; Sun, 12 Jul 2026 05:08:48 -0700 (PDT) Received: from localhost.localdomain (dynamic-095-117-112-249.95.117.pool.telefonica.de. [95.117.112.249]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-493eb742d0esm287633135e9.13.2026.07.12.05.08.47 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sun, 12 Jul 2026 05:08:48 -0700 (PDT) From: Karl Mehltretter To: Vlastimil Babka , Harry Yoo , Andrew Morton Cc: Rasmus Villemoes , Hao Li , Christoph Lameter , David Rientjes , Roman Gushchin , linux-mm@kvack.org, linux-kernel@vger.kernel.org, llvm@lists.linux.dev, Karl Mehltretter Subject: [RFC PATCH] slab: don't assume alignment on allocators that may return ZERO_SIZE_PTR Date: Sun, 12 Jul 2026 14:07:28 +0200 Message-Id: <20260712120728.96628-1-kmehltretter@gmail.com> X-Mailer: git-send-email 2.39.5 (Apple Git-154) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" __kmalloc_noprof(), __kmalloc_node_noprof(), and __kmalloc_flags_noprof() are annotated with __assume_kmalloc_alignment, which expands to __assume_aligned(ARCH_KMALLOC_MINALIGN). All three can return ZERO_SIZE_PTR, currently (void *)16, for zero-sized requests. When ARCH_KMALLOC_MINALIGN exceeds 16, this contradicts the annotation. Compilers may use this false assumption to reduce ZERO_OR_NULL_PTR() to a NULL check, losing recognition of ZERO_SIZE_PTR. Current GCC and Clang retain the existing range check through kmalloc's inline wrapper, so no functional miscompile was reproduced with the current source form. However, both eliminate an exact ZERO_SIZE_PTR comparison on the same return value. With Clang, UBSAN also reports the invalid alignment assumption at boot. Changing ZERO_SIZE_PTR to satisfy the annotation would make its value and the range accepted by ZERO_OR_NULL_PTR() architecture-dependent. Avoid that semantic change by dropping the annotation from the general kmalloc entry points. Retain it on the cache helpers, which cannot return the sentinel. Allocation behavior is unchanged. Kernels before v7.2 do not have __kmalloc_flags_noprof(). Backports to those kernels only need the include/linux/slab.h change. Fixes: 94a58c360a45 ("slab.h: sprinkle __assume_aligned attributes") Fixes: f6d50ab29afd ("mm/slab: introduce kmalloc_flags()") Cc: # needs adjustment before v7.2 Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Karl Mehltretter --- Notes: This is RFC because the alignment contract can be corrected in three wa= ys: =20 1. Remove the annotation from entry points that can return ZERO_SIZE_= PTR (this patch). On armv5 this increases .text by 1120 bytes (0.02%); no measurable change was seen on arm64. =20 2. Cap the assumed alignment at 16. This preserves some alignment information but couples the annotation to the current sentinel val= ue. =20 3. Change ZERO_SIZE_PTR to satisfy ARCH_KMALLOC_MINALIGN. This makes = the long-standing sentinel architecture-dependent and either expands t= he range accepted by ZERO_OR_NULL_PTR() or requires changing that mac= ro. =20 On armv5, Clang UBSAN reports the invalid alignment assumption during b= oot; the report disappears with this patch. =20 Clang 22 and GCC 13 retain ZERO_OR_NULL_PTR()'s existing range check th= rough _kmalloc_noprof(), so no functional miscompile was reproduced in current code. This is an optimizer limitation, not a guarantee. For a kmalloc r= eturn value, writing the check as "!p || p =3D=3D ZERO_SIZE_PTR" causes both = compilers to remove the ZERO_SIZE_PTR comparison. Built into an armv5 kernel with= that form, a zero-size allocation is then no longer recognised and is derefe= renced: =20 Unable to handle kernel NULL pointer dereference at virtual address 0= 0000010 Internal error: Oops: 805 [#1] ARM PC is at __fc_init+0x3c/0x60 Kernel panic - not syncing: Attempted to kill init! exitcode=3D0x0000= 000b =20 Without the annotation the comparison is retained and the kernel boots. =20 Would the slab maintainers prefer removing the annotation or retaining a weaker, valid alignment guarantee? include/linux/slab.h | 12 ++++++++---- mm/slab.h | 3 ++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index 51f03f18c9a7..1c63048f6467 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -632,8 +632,12 @@ static inline unsigned int arch_slab_minalign(void) =20 /* * kmem_cache_alloc and friends return pointers aligned to ARCH_SLAB_MINAL= IGN. - * kmalloc and friends return pointers aligned to both ARCH_KMALLOC_MINALI= GN - * and ARCH_SLAB_MINALIGN, but here we only assume the former alignment. + * Objects allocated by kmalloc and friends are aligned to both + * ARCH_KMALLOC_MINALIGN and ARCH_SLAB_MINALIGN, but here we only assume t= he + * former alignment. + * + * This guarantee does not apply to ZERO_SIZE_PTR, which is not an allocat= ed + * object. */ #define __assume_kmalloc_alignment __assume_aligned(ARCH_KMALLOC_MINALIGN) #define __assume_slab_alignment __assume_aligned(ARCH_SLAB_MINALIGN) @@ -939,10 +943,10 @@ unsigned int kmem_cache_sheaf_size(struct slab_sheaf = *sheaf); */ =20 void *__kmalloc_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t flags) - __assume_kmalloc_alignment __alloc_size(1); + __alloc_size(1); =20 void *__kmalloc_node_noprof(DECL_KMALLOC_PARAMS(size, b, token), gfp_t fla= gs, int node) - __assume_kmalloc_alignment __alloc_size(1); + __alloc_size(1); =20 void *__kmalloc_cache_noprof(struct kmem_cache *s, gfp_t flags, size_t siz= e) __assume_kmalloc_alignment __alloc_size(3); diff --git a/mm/slab.h b/mm/slab.h index 281a65233795..aea1373c7f83 100644 --- a/mm/slab.h +++ b/mm/slab.h @@ -28,9 +28,10 @@ static inline bool alloc_flags_allow_spinning(const unsi= gned int alloc_flags) return !(alloc_flags & SLAB_ALLOC_NOLOCK); } =20 +/* Can return ZERO_SIZE_PTR, so not tagged __assume_kmalloc_alignment. */ void *__kmalloc_flags_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t flags, unsigned int alloc_flags, int node) - __assume_kmalloc_alignment __alloc_size(1); + __alloc_size(1); =20 static __always_inline __alloc_size(1) void *_kmalloc_flags_noprof(size_t = size, gfp_t flags, unsigned int alloc_flags, int node, kmalloc_token_t token) --=20 2.39.5 (Apple Git-154)