From patchwork Mon Jan 30 20:49:39 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: 13121826 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 3EF72C636CD for ; Mon, 30 Jan 2023 20:52:02 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id E25266B007D; Mon, 30 Jan 2023 15:51:59 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id D72236B0080; Mon, 30 Jan 2023 15:51:59 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id BEC4A6B0085; Mon, 30 Jan 2023 15:51:59 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id 8C9586B007D for ; Mon, 30 Jan 2023 15:51:59 -0500 (EST) Received: from smtpin10.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay06.hostedemail.com (Postfix) with ESMTP id 629B5AAF94 for ; Mon, 30 Jan 2023 20:51:59 +0000 (UTC) X-FDA: 80412662358.10.1EAF362 Received: from out-187.mta0.migadu.com (out-187.mta0.migadu.com [91.218.175.187]) by imf12.hostedemail.com (Postfix) with ESMTP id 8EBE240023 for ; Mon, 30 Jan 2023 20:51:57 +0000 (UTC) Authentication-Results: imf12.hostedemail.com; dkim=pass header.d=linux.dev header.s=key1 header.b=TCrjIwKJ; spf=pass (imf12.hostedemail.com: domain of andrey.konovalov@linux.dev designates 91.218.175.187 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=1675111917; 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=GaiPOQJQg/3eaR9Q8OYjD4xHiibeiKzRxzXBSSG583E=; b=kxUlw0ODE+d0AzNiXDRsWBboiOr7FFQwTOwsDzIJvOHITMq7zZIsp46yW/+EpL7GYF9jPC /kf4lst/nZjJbZM+vffDWuXtNlYs6ujgF5Uha/wkRX9Z0UUl/LbqPccgKuUKDGbmb/LUQ8 dWw/zV/0/7zfuzZds/CuZwId5gMVZ1I= ARC-Authentication-Results: i=1; imf12.hostedemail.com; dkim=pass header.d=linux.dev header.s=key1 header.b=TCrjIwKJ; spf=pass (imf12.hostedemail.com: domain of andrey.konovalov@linux.dev designates 91.218.175.187 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=1675111917; a=rsa-sha256; cv=none; b=otu7ZnoxuKuoo36fteDFfW9nVs4RzGkSfIOmU+QQipwJGRWcFaqaQ0tRNVBSoUPcS59Jf3 WjMNKpcKyCtDM3TzdMwivwJIN3FQDKvy681YgraZS1NP6lLvwhatrySwQYYwqz0Ohae8g+ fhe7lvHVHtyYgEXtoELc6pMoeMGlNhs= 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=1675111916; 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=GaiPOQJQg/3eaR9Q8OYjD4xHiibeiKzRxzXBSSG583E=; b=TCrjIwKJC099LsLvlkSDhNlxLio8XBKvK6arn50U5Oq0wu2cv8MUDulFrm51KAee5EAjRV +8Pv4cs88SApX9F3qPDdGLCnq06UnlNLhh0BLPrRijp6pc7Uu5IQaz/tKz9173gWqPhMOZ 7S15Mtx6lM2aMb0WH+SSEAdvCLMs5J4= 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 15/18] lib/stacktrace, kasan, kmsan: rework extra_bits interface Date: Mon, 30 Jan 2023 21:49:39 +0100 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Migadu-Flow: FLOW_OUT X-Rspamd-Server: rspam05 X-Rspamd-Queue-Id: 8EBE240023 X-Stat-Signature: 6c8guxfwj4cxu6a5oqpgtj7u65bm5bz1 X-Rspam-User: X-HE-Tag: 1675111917-821325 X-HE-Meta: U2FsdGVkX189FPMG8AqF74KJKw0zfCQwBdcDidljYvqRqVYrcUTtXoJgHUnWehRca5MGBd0N7VsP2+/YOy2L9hOdGGrcREl/RP/0c35KjzdwUBk4ljEk9f1iU6uSPaADH4V066OmoTOfwPyApixomHtShlYYXDYGJL8vmCTgXfhpFoo8Kd/uxTOIv0a+MSrihRn5/TCowL7bodOzzrsJu9BGhd4i/sCh9iI574Oog6RMkJ3e2BHbA+xQ8ndBOIuqxheeRA819QCgKi13NqhMmxBNIgQt+JK/64pOIMovO5cMQFJSBhIwKSXd3jhSi3yIj8XqWxiihEmhm7ImW/oOEiGi37p3xKd4zbAV/x9syrr2srH91TPtKszp2Nv/Dr0te5fR8dXRycCNJUNbJE2yGvZ3A7l2/NYft31FLfVWTQfaQ13dm37C4sz4Dvo+F4zLHb/iIECVDhCs7STkj1C0KBisEXnKDoWgNZcqeb+sNVXMYeABTPNozO7c2DaaHEVCOTOKIKeJQy1mz0Ho2oDXO4Jld7BEEBYIJ24liHGNQcui2pxkwb1U6oACkEA5gNgcnFAw4ecKsTfyHQrgznZy6rm7U2YPGG3olC/zoYD21h937jF43ZnEnhkw8WSrPFHeLVfqngWeMt/qafQL8CqURx/0uVmPYwsnvz0mweFWxvt27U8h5YFkactzeLzX/wdqtCp1MXcMjA1nvIigtqwkGmhoyrS569l4nlgPKhzLY/TRwB3294SZ5MNAYPff0hEPAe8u4k0CJFsJZ59AUrW3xAt6N8r94ChTt3dupO8/kLTHM1+3Z+SD0fBbex+PKz6LJB8K/rWNxFPf8+fG7I7RsihYPkuXoUvRUF4/VdBbYtzrd8UdJ03E6paJgxoRQ3KNJM8tQEIccDrerp7t2TBa2ZfHu2HEfMUgGo+A3I3zuu+UbJwQwg6UYBUsyrMZnnv0k/9CYi5s4coDZqzMwua k5L4pAjd tBc0dH2inVQFYWrmizyDqJDhzjsHwnAgjgJpeAwzjXIvHchjKhJ6J1OtQinDOdPi8dGIHEVLApTtb9r9v6auY31pmxE36wdQvpaQPDZ9C/Kdu/h6FXb8KrpykE+NzjpVxwYgjj8eyRbSi2NSmiy+RVkmA/Q== 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 --- include/linux/stackdepot.h | 4 +++- lib/stackdepot.c | 38 +++++++++++++++++++++++++++++--------- mm/kasan/common.c | 2 +- mm/kmsan/core.c | 10 +++++++--- 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/include/linux/stackdepot.h b/include/linux/stackdepot.h index c4e3abc16b16..f999811c66d7 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 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 7282565722f2..f291ad6a4e72 100644 --- a/lib/stackdepot.c +++ b/lib/stackdepot.c @@ -346,7 +346,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 slabs (increased chance of failure if false) * @@ -358,10 +357,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 @@ -371,7 +366,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; @@ -461,8 +455,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); @@ -483,7 +475,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); @@ -566,6 +558,34 @@ 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 + * @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 stack_depot_set_extra_bits(depot_stack_handle_t handle, + unsigned int extra_bits) +{ + union handle_parts parts = { .handle = handle }; + + 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,