From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-qk1-f178.google.com (mail-qk1-f178.google.com [209.85.222.178]) (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 A3E1F340A47 for ; Thu, 18 Jun 2026 22:28:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.178 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781821684; cv=none; b=o3U3u2+wuxxl+H+PSOp8vMFJtYh3IKsgnEPxm4bjmz0VsCxH8OOc90PQcWS/HobiIMnEQzPaZyxhwtZaBHQoOc+OKI8OfU1Ighd79+62+DSKw+3rtX74r5VjLIzpmpErvtChbRCDORLtCkYng6H1P4BjAIU76Ff676esOh2t91c= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781821684; c=relaxed/simple; bh=ukjsXcZv7riarW/xWZAYC0V9xN3/rjx1quN1mle8vxs=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=RoZkRUAdocr1dVxb/J/lt0A7/ZWXscjjpFMIBWIJdXoZpqdyMzB3MzvzIuqemdURqvydqwcve/Fc5fGo/5lmWh9ZOqRkkZqmSLlgJ6tNK1m4ixPuXqosEbsccLrngpcHSpVXpzKYSzFDjyo12mSdVoLNBqH3RwbuqGFpbOuj4kE= 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=G8VauR/o; arc=none smtp.client-ip=209.85.222.178 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="G8VauR/o" Received: by mail-qk1-f178.google.com with SMTP id af79cd13be357-9157b895c57so130216685a.3 for ; Thu, 18 Jun 2026 15:28:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1781821683; x=1782426483; 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; bh=YvWvGzURVdhpVRuCWjrVipteKdwDmCa/WOlEHoQ81l4=; b=G8VauR/opxjgJzpBuZI8PeHEnA62gEG2W6ZDJcLFxicx/Usum50gMyzShWYc+bB5Ot rGZNcwTljD1A+uk6kQBqYfqYif1mxTwqONQorcddHJppAMChZ9nMKIS4T3yNQixex7JJ daaLOLYjRnVOXnV4P4gSqRJ56I+CZJTKFD9qzDSXorSgJwsIhzTY7S25/nJcIE1S3ZMJ xxeGAJ+KkLVJuwxZLh3g2oDRrNNNQFi90jJuY2B2Cax/pwaotisVFhkglvD6sKB4vF20 +O4dMC3ULnMdAmB/G6k9IWycCH36CNGpWBFC+RnzfmqbnYzPRK6y+HUCJ/B0mvR7YKs5 AQvA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781821683; x=1782426483; 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; bh=YvWvGzURVdhpVRuCWjrVipteKdwDmCa/WOlEHoQ81l4=; b=tDjBzoCymNKPTzZUWuK7r12gCKv1tidaVMxHcy12IoEdVhgQ3NyIpX5KJIfOzkqfxY 9owg4cxAENuSx4pEBOj/ZIEmWU80dzH3Nu8Z1yGFGXSCOnHrHKiKV3XdHm06UamSRPC0 HkrjYpy+4wwFfCw7U4vtCRZOf8GNhsU4DaIFDvx5hUCg2zyqvQuZMEVDg4fJ87GnQ89U 5JDQ3u0NkNBumdTWj1JWSvaAB179d5ZySycYUy/IWxzbWlP9ONtWLxMml+LEgZBalWLl L35QXbBMWitZeOehz7UPnw7bseWo3fIi+g6fcbJoi8NW0+LsJihLeAM4MByvtpYlNRaI 81bw== X-Forwarded-Encrypted: i=1; AFNElJ8jL6QttunIYQxMFJsP/flAQ6McsWoX2E+SjFlJ+EWltltyS13DyslcBhCzuuqYw2kHhMZNNVRXQd+IUC0=@vger.kernel.org X-Gm-Message-State: AOJu0YxbB5fnXCYvBa+DRwLTTr5YSGAaXDjTCDh6xwsVUGX38TFflTJZ u0Z2v3mj/cR01lWkCVWUyPCM2ApcgqgFaQyeZCzQQi3y4XKlRlxF8n0q X-Gm-Gg: AfdE7cnpD9Lljm1xI8XxJNcUO0nRAclIlU0bcXbtrWTN1RjLyik9+G15uLwIoAa7e7M uHKUCK86JdM/zz0dITGbDry91n2oOOCx/BbhZ8GtuB99d45j6VwUWRLPuqsSy1pEGJuX5IV4E81 jid2+wCi3M1DHsn93qZK8hKxf4J5ZWNZBtkWZ39HQL9N7daehp94Myk+WkCU8r4pBBzGHebmjCY MJgYp4lhfO6U0U2nPh87/bo5UXYQxtvwpGTCksLV6Bf+N5Ekm+ctjS3KdupJYWCydqDm9T2EEUu 2SG0HfbUr7ov3GrnprLjuUF3RZKUuMvin7DhpT64Zy3E/Ro9mV2dmWh89RNbXCWVo0/UbOO4p+O kh3UbpaH6O0l6q+KaDQwdsWf20dJJsnHtlZpxA3rM/eB4B+5CybqF+dYjv5UjB7qdHmebjQ0FON HIbMB5iWRot4zggmcF+veXrtwr8/HDq4YOaJYD364SEnUJYRJjqxy/wlyJ7dMw46XsuKd6psYCz p9Ww7Ykdux82doWdVZQt1V0P49b143OGEASoDUMRrY= X-Received: by 2002:a05:620a:2845:b0:911:69a3:1653 with SMTP id af79cd13be357-920910a5da7mr160354085a.46.1781821682307; Thu, 18 Jun 2026 15:28:02 -0700 (PDT) Received: from server0.tail6e7dd.ts.net (c-68-48-65-54.hsd1.mi.comcast.net. [68.48.65.54]) by smtp.gmail.com with ESMTPSA id af79cd13be357-920a425448asm48643585a.23.2026.06.18.15.28.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 15:28:01 -0700 (PDT) From: Michael Bommarito To: Steven Rostedt , Masami Hiramatsu , Mathieu Desnoyers Cc: Beau Belgrave , linux-trace-kernel@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org Subject: [PATCH] tracing/user_events: fix use-after-free of enabler in user_event_mm_dup() Date: Thu, 18 Jun 2026 18:27:43 -0400 Message-ID: <20260618222743.538915-1-michael.bommarito@gmail.com> X-Mailer: git-send-email 2.53.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 7bit user_event_enabler_destroy() removes an enabler from the per-mm mm->enablers list with list_del_rcu() and then frees it immediately with kfree(). That list is walked locklessly by user_event_mm_dup() during fork(), under rcu_read_lock() only: rcu_read_lock(); list_for_each_entry_rcu(enabler, &old_mm->enablers, mm_enablers_link) ... user_event_mm_dup() does not take event_mutex. The per-enabler destroy path user_events_ioctl_unreg() (DIAG_IOCSUNREG) takes event_mutex but nothing that excludes the dup walk. Threads that share an mm share one user_event_mm and one enabler list, so an unregister on one thread can free an enabler while another thread is forking and user_event_mm_dup() is mid-walk. The walk then dereferences the freed enabler (for example enabler->event in user_event_enabler_dup()). This is reachable by an unprivileged task that can open user_events_data: a single multithreaded process that registers an enabler and then concurrently unregisters it and calls fork() triggers the race. KASAN reports a slab-use-after-free read in user_event_enabler_dup() called from user_event_mm_dup() and copy_process() during clone(); with kasan.fault=panic the kernel panics. Free the enabler after a grace period with kfree_rcu(), matching the list_del_rcu() removal and the rcu_read_lock() readers in user_event_mm_dup(). Add an rcu_head to struct user_event_enabler for this. The error path in user_event_enabler_create() keeps using kfree() because that enabler is freed before it is published to the RCU list. Cc: stable@vger.kernel.org Fixes: 7235759084a4 ("tracing/user_events: Use remote writes for event enablement") Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Michael Bommarito --- Notes: KASAN on the unpatched tree (v7.1, x86-64, CONFIG_KASAN=y, SMP): BUG: KASAN: slab-use-after-free in user_event_enabler_dup+0x50a/0x540 Read of size 8 (enabler->event, 16 bytes into a freed kmalloc-cg-64): user_event_enabler_dup user_event_mm_dup copy_process __do_sys_clone Allocated by the registering task; freed on another CPU via the DIAG_IOCSUNREG path. With kasan.fault=panic the access panics. After the patch the same reproducer runs cleanly (no splat, no panic) across the full window, and a serialized control (same paths, no concurrency) is clean on both stock and patched. Re-ran tools/testing/selftests/user_events on stock and patched, both clean: abi_test pass:6/6, dyn_test pass:4/4, ftrace_test pass:6/6. kernel/trace/trace_events_user.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/kernel/trace/trace_events_user.c b/kernel/trace/trace_events_user.c index c4ba484f7b38b..412ca1e3a40cf 100644 --- a/kernel/trace/trace_events_user.c +++ b/kernel/trace/trace_events_user.c @@ -109,6 +109,9 @@ struct user_event_enabler { /* Track enable bit, flags, etc. Aligned for bitops. */ unsigned long values; + + /* Defer free so RCU list readers (user_event_mm_dup) are safe. */ + struct rcu_head rcu; }; /* Bits 0-5 are for the bit to update upon enable/disable (0-63 allowed) */ @@ -404,7 +407,12 @@ static void user_event_enabler_destroy(struct user_event_enabler *enabler, /* No longer tracking the event via the enabler */ user_event_put(enabler->event, locked); - kfree(enabler); + /* + * The enabler is removed from an RCU-traversed list + * (user_event_mm_dup walks mm->enablers under rcu_read_lock only), + * so the backing memory must outlive a grace period. + */ + kfree_rcu(enabler, rcu); } static int user_event_mm_fault_in(struct user_event_mm *mm, unsigned long uaddr, -- 2.53.0