Received: by 2002:ab2:60d1:0:b0:1f7:5705:b850 with SMTP id i17csp20530lqm; Tue, 30 Apr 2024 11:23:16 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCUZLIbdl5B1rce7SX+GcdQhBAugoXVqUOfjTCJFjGSkQFg1nAtFIQ/w9MPtVdf7EamSFlnww3Q0qti2Bprrzu0tULAvCCxkIszPyLFMUw== X-Google-Smtp-Source: AGHT+IFF+W3B0rp0ax1yu2/tyIEpaY0NwTw8QX6RC2Os0IhGKMRUfLNH390BNVu2hge1y5UmMQms X-Received: by 2002:a05:6871:e006:b0:229:929a:b127 with SMTP id by6-20020a056871e00600b00229929ab127mr283148oac.37.1714501396120; Tue, 30 Apr 2024 11:23:16 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1714501396; cv=pass; d=google.com; s=arc-20160816; b=y0YUAO07aED91+2MEvQSUN2y/8dvkDLD0xJpZLvojrKveCwBXHZLt18MtURh4L86+5 hyrSE5zMeHvyP63ydBffvvDy+IPBBS+5V0/LiIaekFeu4yPiQ17mX7aik7+fE85lxNk6 cqZmNtCMFQ8RBApA+fdPQbDTRZ+q3LeBRr1Gq+BkgBkoe85rrLZ0P8kl3klnyENiCCvS +gEj8x9ZHjt7U/f7TvpL6leQKi8gdub7CpqwMTYtjcHYKDOCimds5oXF16R0xCBUedGm OI4yHWcINLwyHYyhqr62WdS0WrkyPp1QnRH/0l5vEJQ9MlXNO2xxP4Ddhjz0x4bBFNLx srEQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:message-id:subject:cc:to:from :date; bh=jMQSJNGMWiJI9z4M2FiCIBQPZ4YUiGmYvl40WlrYZvE=; fh=CcQ3vsJxw71PoqxOqCNHHxP2+FgPAXYD8t60EDs2t9w=; b=hPHbKc8/r+xatI/mc4V69w24Z1badT5qlhSjQl3MHpCYxQsa0WpoCThDNHp/rFyXDF 2dLmAdUauSe4VHiWOqcHPzkePraqtVrct00HHp6uNze2DDA5+E8cBX5k38FU89nBKX2n Cf5MHe4/0NMOehSVtLS90RuJPMJZwWWMep4Oqgk9tCws5DkVWl7IOzjOvlVAgyzuzG8w lXSDD5dYW7YlGzhsPLLahEh/rD4s1MEDFnfNZHLHU9XkvI1+z8yc5al0F7QTjw5RNIGI 0vWIleVZkG8KnxdNBYcQOQutNM3mlVYkneOtfjz7E0p7cW1rY8yks/0p0G1Orqj06q6h ERNQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; arc=pass (i=1); spf=pass (google.com: domain of linux-kernel+bounces-164583-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-164583-linux.lists.archive=gmail.com@vger.kernel.org" Return-Path: Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [2604:1380:40f1:3f00::1]) by mx.google.com with ESMTPS id y3-20020a634943000000b005dbcf612461si22613443pgk.416.2024.04.30.11.23.15 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Apr 2024 11:23:16 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-164583-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) client-ip=2604:1380:40f1:3f00::1; Authentication-Results: mx.google.com; arc=pass (i=1); spf=pass (google.com: domain of linux-kernel+bounces-164583-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-164583-linux.lists.archive=gmail.com@vger.kernel.org" Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id 98203B22F69 for ; Tue, 30 Apr 2024 18:22:57 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 7CB8B1836EB; Tue, 30 Apr 2024 18:22:47 +0000 (UTC) Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 003F51802DA; Tue, 30 Apr 2024 18:22:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714501367; cv=none; b=gVF8gWR21OxyLO6Kf2U2o1Xu7IN2WnS2eM/qMHd5Ck0aKieO9N+/UmcXmCYYrB/vmfuG1JdJcLnSLfFFxnSwYcoEYhBbRmQjEpYyuLfdUp1gl24KbZxMYKPSU2zy7iZZ2Y8PdQB7+RwVbSS4yjFzeQ71v3s947Xto2njYh7IsrU= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714501367; c=relaxed/simple; bh=XlTQNL+YhpK5nbJwkIGxGuNsLWfK2Atq2y8yIscclCg=; h=Date:From:To:Cc:Subject:Message-ID:MIME-Version:Content-Type; b=kClG8nZs8Hsjq4C8ZQ9mZpfnqUZNqzEp6V9p4k9mvlLIQoZ4pHKmsN6H/e0p/HwgJVDi3I6pHp7tMqQrjzEOaHCtepioNqS+5Q8kzWqcgNAtYPbBFtuG/yH5+F2z8PftV4P3+5cxcZdyZeT4zShAVG/vgXImc3c/CmvG3VGf3YQ= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id C72C5C2BBFC; Tue, 30 Apr 2024 18:22:45 +0000 (UTC) Date: Tue, 30 Apr 2024 14:23:27 -0400 From: Steven Rostedt To: LKML , Linux Trace Kernel Cc: Masami Hiramatsu , Mathieu Desnoyers , Tze-nan wu Subject: [PATCH] eventfs/tracing: Add callback for release of an eventfs_inode Message-ID: <20240430142327.7bff81ba@gandalf.local.home> X-Mailer: Claws Mail 3.19.1 (GTK+ 2.24.33; x86_64-pc-linux-gnu) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit From: "Steven Rostedt (Google)" Synthetic events create and destroy tracefs files when they are created and removed. The tracing subsystem has its own file descriptor representing the state of the events attached to the tracefs files. There's a race between the eventfs files and this file descriptor of the tracing system where the following can cause an issue: With two scripts 'A' and 'B' doing: Script 'A': echo "hello int aaa" > /sys/kernel/tracing/synthetic_events while : do echo 0 > /sys/kernel/tracing/events/synthetic/hello/enable done Script 'B': echo > /sys/kernel/tracing/synthetic_events Script 'A' creates a synthetic event "hello" and then just writes zero into its enable file. Script 'B' removes all synthetic events (including the newly created "hello" event). What happens is that the opening of the "enable" file has: { struct trace_event_file *file = inode->i_private; int ret; ret = tracing_check_open_get_tr(file->tr); [..] But deleting the events frees the "file" descriptor, and a "use after free" happens with the dereference at "file->tr". The file descriptor does have a reference counter, but there needs to be a way to decrement it from the eventfs when the eventfs_inode is removed that represents this file descriptor. Add an optional "release" callback to the eventfs_entry array structure, that gets called when the eventfs file is about to be removed. This allows for the creating on the eventfs file to increment the tracing file descriptor ref counter. When the eventfs file is deleted, it can call the release function that will call the put function for the tracing file descriptor. This will protect the tracing file from being freed while a eventfs file that references it is being opened. Link: https://lore.kernel.org/linux-trace-kernel/20240426073410.17154-1-Tze-nan.Wu@mediatek.com/ Cc: stable@vger.kernel.org Fixes: 5790b1fb3d672 ("eventfs: Remove eventfs_file and just use eventfs_inode") Reported-by: Tze-nan wu Signed-off-by: Steven Rostedt (Google) --- fs/tracefs/event_inode.c | 7 +++++++ include/linux/tracefs.h | 3 +++ kernel/trace/trace_events.c | 12 ++++++++++++ 3 files changed, 22 insertions(+) diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c index 894c6ca1e500..dc97c19f9e0a 100644 --- a/fs/tracefs/event_inode.c +++ b/fs/tracefs/event_inode.c @@ -84,10 +84,17 @@ enum { static void release_ei(struct kref *ref) { struct eventfs_inode *ei = container_of(ref, struct eventfs_inode, kref); + const struct eventfs_entry *entry; struct eventfs_root_inode *rei; WARN_ON_ONCE(!ei->is_freed); + for (int i = 0; i < ei->nr_entries; i++) { + entry = &ei->entries[i]; + if (entry->release) + entry->release(entry->name, ei->data); + } + kfree(ei->entry_attrs); kfree_const(ei->name); if (ei->is_events) { diff --git a/include/linux/tracefs.h b/include/linux/tracefs.h index 7a5fe17b6bf9..d03f74658716 100644 --- a/include/linux/tracefs.h +++ b/include/linux/tracefs.h @@ -62,6 +62,8 @@ struct eventfs_file; typedef int (*eventfs_callback)(const char *name, umode_t *mode, void **data, const struct file_operations **fops); +typedef void (*eventfs_release)(const char *name, void *data); + /** * struct eventfs_entry - dynamically created eventfs file call back handler * @name: Then name of the dynamic file in an eventfs directory @@ -72,6 +74,7 @@ typedef int (*eventfs_callback)(const char *name, umode_t *mode, void **data, struct eventfs_entry { const char *name; eventfs_callback callback; + eventfs_release release; }; struct eventfs_inode; diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 52f75c36bbca..6ef29eba90ce 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -2552,6 +2552,14 @@ static int event_callback(const char *name, umode_t *mode, void **data, return 0; } +/* The file is incremented on creation and freeing the enable file decrements it */ +static void event_release(const char *name, void *data) +{ + struct trace_event_file *file = data; + + event_file_put(file); +} + static int event_create_dir(struct eventfs_inode *parent, struct trace_event_file *file) { @@ -2566,6 +2574,7 @@ event_create_dir(struct eventfs_inode *parent, struct trace_event_file *file) { .name = "enable", .callback = event_callback, + .release = event_release, }, { .name = "filter", @@ -2634,6 +2643,9 @@ event_create_dir(struct eventfs_inode *parent, struct trace_event_file *file) return ret; } + /* Gets decremented on freeing of the "enable" file */ + event_file_get(file); + return 0; } -- 2.43.0