From patchwork Fri Feb 10 21:16:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: andrey.konovalov@linux.dev X-Patchwork-Id: 13136464 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]) by smtp.lore.kernel.org (Postfix) with ESMTP id B6911C05027 for ; Fri, 10 Feb 2023 21:18:24 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id B66C56B019C; Fri, 10 Feb 2023 16:18:22 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id B18E66B019E; Fri, 10 Feb 2023 16:18:22 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 9DF636B019F; Fri, 10 Feb 2023 16:18:22 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0017.hostedemail.com [216.40.44.17]) by kanga.kvack.org (Postfix) with ESMTP id 8A6A96B019E for ; Fri, 10 Feb 2023 16:18:22 -0500 (EST) Received: from smtpin08.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id 6BFDB1C68B1 for ; Fri, 10 Feb 2023 21:18:22 +0000 (UTC) X-FDA: 80452645644.08.BB233CD Received: from out-184.mta1.migadu.com (out-184.mta1.migadu.com [95.215.58.184]) by imf02.hostedemail.com (Postfix) with ESMTP id 9A76380011 for ; Fri, 10 Feb 2023 21:18:20 +0000 (UTC) Authentication-Results: imf02.hostedemail.com; dkim=pass header.d=linux.dev header.s=key1 header.b=mZ77UXQw; spf=pass (imf02.hostedemail.com: domain of andrey.konovalov@linux.dev designates 95.215.58.184 as permitted sender) smtp.mailfrom=andrey.konovalov@linux.dev; dmarc=pass (policy=none) header.from=linux.dev ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1676063900; a=rsa-sha256; cv=none; b=Cq8b7XtZYwrmms5NebTt4NoXIsxSEYY5S9MhlYdXmHCfEd/UVxzyvNlKdBESammqofSMKo 1Ew2YTPO2UCGWYe+7jpDmdON/5b/2W+Ol677cUtRnp9CjE8Ja7dKDg2q90nHmIrHReMCKd aR32FbpJicBUAGK+Qdpqj/+DDux3Idg= ARC-Authentication-Results: i=1; imf02.hostedemail.com; dkim=pass header.d=linux.dev header.s=key1 header.b=mZ77UXQw; spf=pass (imf02.hostedemail.com: domain of andrey.konovalov@linux.dev designates 95.215.58.184 as permitted sender) smtp.mailfrom=andrey.konovalov@linux.dev; dmarc=pass (policy=none) header.from=linux.dev ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1676063900; 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=UVeF/wdyK+2zAJh1QGD4/79VjlNXyPEki9KG1Xr/HS8=; b=dMh14ktPxTHNZK/ShbAbq0Oa0hyTth5Qwp8fy2dZchy0vfWHjjQQTH2P6u517Io9CSwk7C XmS0kfR5+7PsWJKENWNIsJaJOIEB4OOr/hQxsl8sgVcqAdn5p4dHcr3B7JPp9PZg4WHJRR 8pV6oV0EkGH7fdwzJ5o+i+U85Ie3fFU= X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1676063899; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UVeF/wdyK+2zAJh1QGD4/79VjlNXyPEki9KG1Xr/HS8=; b=mZ77UXQw8ph3QwwxXcMEUBuXupMLlxGBtFsT/tvE3yPr1CWb80YBs30hTsFcDo2cxvMjfU fh5338Sdmtuz7SNFr7A8idY55ISDszradFlit9kl2SJREmvICU9yKZEh/SEEnh1I4YWVCb jOA+wNYeS/EARv0AleT+tvRG6/ySbBA= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Vlastimil Babka , kasan-dev@googlegroups.com, Evgenii Stepanov , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH v2 15/18] lib/stacktrace, kasan, kmsan: rework extra_bits interface Date: Fri, 10 Feb 2023 22:16:03 +0100 Message-Id: <317123b5c05e2f82854fc55d8b285e0869d3cb77.1676063693.git.andreyknvl@google.com> In-Reply-To: References: MIME-Version: 1.0 X-Migadu-Flow: FLOW_OUT X-Rspam-User: X-Rspamd-Queue-Id: 9A76380011 X-Rspamd-Server: rspam01 X-Stat-Signature: nphr1rhzb8ckycg374koq63e5u1iqdxt X-HE-Tag: 1676063900-69501 X-HE-Meta: U2FsdGVkX18nQ3YSBMoVcPfxlcMAZH7aeV/e+nIVMqwd5REXtyEg1Jt6Pq673T2aOBzFkb1d/SX/TVWnxPQFLIkVx/EXgAe0l5VVD1Q/cfV34yugd5jeBFp9WOcVugkHNXv0rqCHlm2Nq3XstXMalxBSFhiwJfVnENyJjbuqdi1r2ri4bAr+RhvS02OhDh9pjyNRpHZ44HV6XQt6Dug1lezY7os36eXXRoFz6CVPqZcbjoopawZlhXVivfA4mtr/qdJbiJ9e4GU+aYflxljRX6Oxizjm/jVACkarFiH9Z9ZHQXucDdaKdhfZsjMRYRYYnYGDM+W2/3yOmu1Zf0pim7UwDIwkLSUXbdjDq905H6eaBDIo+HS9iVhqg+VidhrrAiYJ3Bv/Qy99nCtEgSnKQDKzQsfn6nU3uIMy3T8PPDPmGhEpeQG7b/1Zg4trrKmvCWDk+ymX0AnKRdrYpbkPkJqXkbJeCZMtwyp0pXWcHDUoCNsWeAdGaRgJuZWpulYQc7xKPJT3KCjrGGLMhLIXRjDFjHNF6JWYYEyoS6gBEmLZE0ZzTJFoKflmrpnfAeaPWsRo30u0ctmmFuIJGAPgN50Oa1CprNcLDnHcQ3iYv2UgyY7pJ/JRv3MAIrxRCGD1eanAnf3uuwIKwKtPDq4CoPyNu+Fgwigdx0riEw+kv8GQI8+1k7MypZH3/8GkigZ0iZJuBH5RE6Hk3qLWOcLmnXJsGb+MKkOii2vqq7NVRD71zsbheSV1zgPV+FazVRd/kda0r4z0cmNxQ3JNiYelQhnROB+MNKfyeG/4QtYwHOAMUBaD14GApp4/o+/wGTLuQ1D7NcnQIjJLC2csrlxG6CRS8rkaJEtgJzmK/MFWiQdkym2YlhFn95sX7RW6EK0T0LDguwqrnm8kaec7+aWv2UVVpJ7534+eIBMkyt2artxQiE2Z66d4b2gBW5w2SnbVYz+MPRCNTjRrsUyiXjp btcCjhOk +1h7rA0y9ZNZZ15XVpoIFTF0RIQB8IrcBUX25SPNI2ySVaMK65l8sLF5+Ui4p2xPWa5gcpf50aLbxgEicRWAgN/Bgcr3HpaNys86Qg9J9DBwfDNrU8g4SZyFR0RVq1x2cDIpo1xzJ/X5FrVK7pESIid4HdA== 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: From: Andrey Konovalov The current implementation of the extra_bits interface is confusing: passing extra_bits to __stack_depot_save makes it seem that the extra bits are somehow stored in stack depot. In reality, they are only embedded into a stack depot handle and are not used within stack depot. Drop the extra_bits argument from __stack_depot_save and instead provide a new stack_depot_set_extra_bits function (similar to the exsiting stack_depot_get_extra_bits) that saves extra bits into a stack depot handle. Update the callers of __stack_depot_save to use the new interace. This change also fixes a minor issue in the old code: __stack_depot_save does not return NULL if saving stack trace fails and extra_bits is used. Signed-off-by: Andrey Konovalov Changes v1->v2: - Mark stack_depot_set_extra_bits as __must_check. - Only assign extra bits in stack_depot_set_extra_bits for non-empty handles. Reviewed-by: Alexander Potapenko --- include/linux/stackdepot.h | 4 +++- lib/stackdepot.c | 42 ++++++++++++++++++++++++++++++-------- mm/kasan/common.c | 2 +- mm/kmsan/core.c | 10 ++++++--- 4 files changed, 44 insertions(+), 14 deletions(-) diff --git a/include/linux/stackdepot.h b/include/linux/stackdepot.h index c4e3abc16b16..267f4b2634ee 100644 --- a/include/linux/stackdepot.h +++ b/include/linux/stackdepot.h @@ -57,7 +57,6 @@ static inline int stack_depot_early_init(void) { return 0; } depot_stack_handle_t __stack_depot_save(unsigned long *entries, unsigned int nr_entries, - unsigned int extra_bits, gfp_t gfp_flags, bool can_alloc); depot_stack_handle_t stack_depot_save(unsigned long *entries, @@ -71,6 +70,9 @@ void stack_depot_print(depot_stack_handle_t stack); int stack_depot_snprint(depot_stack_handle_t handle, char *buf, size_t size, int spaces); +depot_stack_handle_t __must_check stack_depot_set_extra_bits( + depot_stack_handle_t handle, unsigned int extra_bits); + unsigned int stack_depot_get_extra_bits(depot_stack_handle_t handle); #endif diff --git a/lib/stackdepot.c b/lib/stackdepot.c index 4df162a84bfe..8c6e4e9cb535 100644 --- a/lib/stackdepot.c +++ b/lib/stackdepot.c @@ -357,7 +357,6 @@ static inline struct stack_record *find_stack(struct stack_record *bucket, * * @entries: Pointer to storage array * @nr_entries: Size of the storage array - * @extra_bits: Flags to store in unused bits of depot_stack_handle_t * @alloc_flags: Allocation gfp flags * @can_alloc: Allocate stack pools (increased chance of failure if false) * @@ -369,10 +368,6 @@ static inline struct stack_record *find_stack(struct stack_record *bucket, * If the stack trace in @entries is from an interrupt, only the portion up to * interrupt entry is saved. * - * Additional opaque flags can be passed in @extra_bits, stored in the unused - * bits of the stack handle, and retrieved using stack_depot_get_extra_bits() - * without calling stack_depot_fetch(). - * * Context: Any context, but setting @can_alloc to %false is required if * alloc_pages() cannot be used from the current context. Currently * this is the case from contexts where neither %GFP_ATOMIC nor @@ -382,7 +377,6 @@ static inline struct stack_record *find_stack(struct stack_record *bucket, */ depot_stack_handle_t __stack_depot_save(unsigned long *entries, unsigned int nr_entries, - unsigned int extra_bits, gfp_t alloc_flags, bool can_alloc) { struct stack_record *found = NULL, **bucket; @@ -471,8 +465,6 @@ depot_stack_handle_t __stack_depot_save(unsigned long *entries, if (found) retval.handle = found->handle.handle; fast_exit: - retval.extra = extra_bits; - return retval.handle; } EXPORT_SYMBOL_GPL(__stack_depot_save); @@ -493,7 +485,7 @@ depot_stack_handle_t stack_depot_save(unsigned long *entries, unsigned int nr_entries, gfp_t alloc_flags) { - return __stack_depot_save(entries, nr_entries, 0, alloc_flags, true); + return __stack_depot_save(entries, nr_entries, alloc_flags, true); } EXPORT_SYMBOL_GPL(stack_depot_save); @@ -576,6 +568,38 @@ int stack_depot_snprint(depot_stack_handle_t handle, char *buf, size_t size, } EXPORT_SYMBOL_GPL(stack_depot_snprint); +/** + * stack_depot_set_extra_bits - Set extra bits in a stack depot handle + * + * @handle: Stack depot handle returned from stack_depot_save() + * @extra_bits: Value to set the extra bits + * + * Return: Stack depot handle with extra bits set + * + * Stack depot handles have a few unused bits, which can be used for storing + * user-specific information. These bits are transparent to the stack depot. + */ +depot_stack_handle_t __must_check stack_depot_set_extra_bits( + depot_stack_handle_t handle, unsigned int extra_bits) +{ + union handle_parts parts = { .handle = handle }; + + /* Don't set extra bits on empty handles. */ + if (!handle) + return 0; + + parts.extra = extra_bits; + return parts.handle; +} +EXPORT_SYMBOL(stack_depot_set_extra_bits); + +/** + * stack_depot_get_extra_bits - Retrieve extra bits from a stack depot handle + * + * @handle: Stack depot handle with extra bits saved + * + * Return: Extra bits retrieved from the stack depot handle + */ unsigned int stack_depot_get_extra_bits(depot_stack_handle_t handle) { union handle_parts parts = { .handle = handle }; diff --git a/mm/kasan/common.c b/mm/kasan/common.c index 833bf2cfd2a3..50f4338b477f 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -43,7 +43,7 @@ depot_stack_handle_t kasan_save_stack(gfp_t flags, bool can_alloc) unsigned int nr_entries; nr_entries = stack_trace_save(entries, ARRAY_SIZE(entries), 0); - return __stack_depot_save(entries, nr_entries, 0, flags, can_alloc); + return __stack_depot_save(entries, nr_entries, flags, can_alloc); } void kasan_set_track(struct kasan_track *track, gfp_t flags) diff --git a/mm/kmsan/core.c b/mm/kmsan/core.c index 112dce135c7f..f710257d6867 100644 --- a/mm/kmsan/core.c +++ b/mm/kmsan/core.c @@ -69,13 +69,15 @@ depot_stack_handle_t kmsan_save_stack_with_flags(gfp_t flags, { unsigned long entries[KMSAN_STACK_DEPTH]; unsigned int nr_entries; + depot_stack_handle_t handle; nr_entries = stack_trace_save(entries, KMSAN_STACK_DEPTH, 0); /* Don't sleep (see might_sleep_if() in __alloc_pages_nodemask()). */ flags &= ~__GFP_DIRECT_RECLAIM; - return __stack_depot_save(entries, nr_entries, extra, flags, true); + handle = __stack_depot_save(entries, nr_entries, flags, true); + return stack_depot_set_extra_bits(handle, extra); } /* Copy the metadata following the memmove() behavior. */ @@ -215,6 +217,7 @@ depot_stack_handle_t kmsan_internal_chain_origin(depot_stack_handle_t id) u32 extra_bits; int depth; bool uaf; + depot_stack_handle_t handle; if (!id) return id; @@ -250,8 +253,9 @@ depot_stack_handle_t kmsan_internal_chain_origin(depot_stack_handle_t id) * positives when __stack_depot_save() passes it to instrumented code. */ kmsan_internal_unpoison_memory(entries, sizeof(entries), false); - return __stack_depot_save(entries, ARRAY_SIZE(entries), extra_bits, - GFP_ATOMIC, true); + handle = __stack_depot_save(entries, ARRAY_SIZE(entries), GFP_ATOMIC, + true); + return stack_depot_set_extra_bits(handle, extra_bits); } void kmsan_internal_set_shadow_origin(void *addr, size_t size, int b,