From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 23CDD36EA98; Sat, 22 Aug 2026 09:22:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787390558; cv=none; b=BR3OWl7zp030gzub5J4jxrScGWMXsuWMsyR9rg9JdWG1olZ1SqKGGTSKskfCZQG0rO19JGi0RK94PNvfgzsnBGRtd0i9ekRYXDCFgihtvLe/m6tTKWbMaLXlA92BqfnvEbp68Ln36/KCcA20B2G1zPSBjZl0nH+D4FQ1a7mb+tc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787390558; c=relaxed/simple; bh=iNBqkjGw9boBKwGqswIgHukU35tiaVG/4H9oKlMlaBI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=geCWC9cml/ycrRkZt6TqnXvMfkkolvuySlrJcV8ow9jgbfKnfteEbiRdi0GUFlCZ5T3mIex2vOTw0/TVjrPl6p3xLzE+fkCd7el2z0hs26R5Rv/Ga2vYlljq7mBmb1sOoHRV7pIdXTSv/Ur9uxeZ21t1sXv8OetzNyJRZz2Povs= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mxysqClV; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="mxysqClV" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 39BAD1F000E9; Sat, 22 Aug 2026 09:22:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787390556; bh=He2O1Sn0+2lOx9gKR6SPUaj6ovVNGVeXwdkqK1WC+QY=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=mxysqClVUwg6mEDNbT05XJ6ot2xX4Vt2YVQmDggKDD560jKiNcKd02HidN6yLUvYm rVkrFjfand4Wr6SfVdAeCP9KhfjrHebSLo/9Cnh0jcLwjD2ht6nGRICi3nLIDBaLVe 5v+cgJCdopbiYOlieZlhllO8PCkh2QPvawS9/YuHR2pO24xP64R7wxmTHvqQRXHmot 0fNnGTSNTwP9bqvb5livqU8hTD1dxAy1jACTBxFTkhcI8tPOgLsqOY6VxwSzC+eTg3 HKn0cwoj07x3tHgMtTQdgeaSDrrb+Tf8SBdj5ChgovB6R9jro0f8pmsFrKBF6Yg9JC hUmX6t5/WlyGA== From: "Masami Hiramatsu (Google)" To: Steven Rostedt , Peter Zijlstra , Ingo Molnar , x86@kernel.org Cc: Jinchao Wang , Mathieu Desnoyers , Masami Hiramatsu , Thomas Gleixner , Borislav Petkov , Dave Hansen , "H . Peter Anvin" , Alexander Shishkin , Ian Rogers , linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-perf-users@vger.kernel.org Subject: [PATCH v13 01/12] kprobes: Protect kprobe_blacklist with RCU Date: Sat, 22 Aug 2026 18:22:31 +0900 Message-ID: <178739055104.1520941.17729343305722017231.stgit@devnote2> X-Mailer: git-send-email 2.43.0 In-Reply-To: <178739053919.1520941.17662338993878200834.stgit@devnote2> References: <178739053919.1520941.17662338993878200834.stgit@devnote2> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-trace-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 From: Masami Hiramatsu (Google) __within_kprobe_blacklist() traverses kprobe_blacklist without holding kprobe_mutex. When a module is unloaded, kprobe_remove_area_blacklist() removes blacklist entries and immediately frees them with kfree(). A concurrent call to within_kprobe_blacklist() can therefore dereference freed memory. Furthermore, within_kprobe_blacklist() can be called in atomic or non-preemptible contexts where the sleeping kprobe_mutex cannot be taken. Protect kprobe_blacklist with RCU. Use guard(rcu)() and list_for_each_entry_rcu() for traversal, list_add_tail_rcu() for insertions, list_del_rcu() for deletions, and kfree_rcu() to reclaim entries safely after a grace period. Assisted-by: Antigravity:gemini-3.7-flash Signed-off-by: Masami Hiramatsu (Google) --- Changes in v13: - Newly added. --- include/linux/kprobes.h | 1 + kernel/kprobes.c | 14 ++++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 8c4f3bb24429..e6de7ae55bda 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -181,6 +181,7 @@ struct kprobe_blacklist_entry { struct list_head list; unsigned long start_addr; unsigned long end_addr; + struct rcu_head rcu; }; #ifdef CONFIG_KPROBES diff --git a/kernel/kprobes.c b/kernel/kprobes.c index bfc89083daa9..6337da5cab9e 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1447,8 +1447,14 @@ static bool __within_kprobe_blacklist(unsigned long addr) /* * If 'kprobe_blacklist' is defined, check the address and * reject any probe registration in the prohibited area. + * Note: this can return true during transition period where + * (start_addr, end_addr) in the black list is shrinking + * but old entry has not been removed yet. This is acceptable + * because the worst case is that we reject more probes than + * we should. */ - list_for_each_entry(ent, &kprobe_blacklist, list) { + guard(rcu)(); + list_for_each_entry_rcu(ent, &kprobe_blacklist, list) { if (addr >= ent->start_addr && addr < ent->end_addr) return true; } @@ -2509,7 +2515,7 @@ int kprobe_add_ksym_blacklist(unsigned long entry) ent->start_addr = entry; ent->end_addr = entry + size; INIT_LIST_HEAD(&ent->list); - list_add_tail(&ent->list, &kprobe_blacklist); + list_add_tail_rcu(&ent->list, &kprobe_blacklist); return (int)size; } @@ -2603,8 +2609,8 @@ static void kprobe_remove_area_blacklist(unsigned long start, unsigned long end) list_for_each_entry_safe(ent, n, &kprobe_blacklist, list) { if (ent->start_addr < start || ent->start_addr >= end) continue; - list_del(&ent->list); - kfree(ent); + list_del_rcu(&ent->list); + kfree_rcu(ent, rcu); } }