Received: by 2002:a05:7412:b10a:b0:f3:1519:9f41 with SMTP id az10csp2969445rdb; Mon, 4 Dec 2023 12:35:18 -0800 (PST) X-Google-Smtp-Source: AGHT+IEOr12dlXuMsVF1CrS1UmF4UIi29lSuOXM/Set1Tz+KreIeIqJohxkgXpMdeXIbEQZQhtOt X-Received: by 2002:a05:6a20:4421:b0:18f:97c:8243 with SMTP id ce33-20020a056a20442100b0018f097c8243mr2556978pzb.77.1701722118126; Mon, 04 Dec 2023 12:35:18 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1701722118; cv=none; d=google.com; s=arc-20160816; b=reCUvE5w2Z9iyfQabl2h1O9pTyuDrPgDCybihP64LON9FPzmlm1sOie7ytQ0DMOSYE VQv2wO6+DwUBryokSzIpX76oBMl62L7OaUNNDxb1B37DCUeaMaW/UGk+FPsR8VThVa/b 8CHMRUZxaX0Tn7p3sp55C/TnoazKEYgDDHsvnSxCICM1/x8kRmMpGpfGwONLCflnfB+W LV4pnQIKpsc9RiM9kVA7HgOZ9leUtsGuzJhx+Nw3GiWhuveCZgeAKl7m5p2f+WhXFt2y NjJUcC/HJPh4MpFetc0AuRlqf3QTEcqwAo3rsLMRY9GhbTuXrd44P+0UUeLGMF7IG+sl BmPw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=J++VF4yFHYgUQQ2wlfhYPiXPnbL8lCOe4Im78U5OML4=; fh=O6f1As6qTdRDG4qMxG9MQ+/7HPm+rMmH0JY81zRf/Kw=; b=I96308v5EJptNrWDKBdZpBYWhC8PD5mHESvvIeK6HHqitHC0gCE4R7v31fyAqap3ZE nMGGksDBpu6n9sELVoWrB4ND4jKhPol/K3N70gt/ynLYB9jgk6QsRGtTFReDjv9/sd7D 7v6HiXnNwB+tUZfYTC1AylwGinRMp8CRbWL/JRPUzbF7Whh/e3w3Bh5Nr7DhZvW0TQpc IJNaOnyf66kMLKhTP7i7nO/X3OdwgiFHY2S/BqrpXAiv+xa85HIVlPxg9+sL8o84yVkf ik4uvHSI4bS011qSnLa06TFT7RPsC5fHrE2QbCMlVPMHGDdro/VHL78S80vKsx6BR+XS cIQg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b="UHU6ht/u"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:4 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from howler.vger.email (howler.vger.email. [2620:137:e000::3:4]) by mx.google.com with ESMTPS id q26-20020a63f95a000000b005be3c3748c7si7966375pgk.38.2023.12.04.12.35.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Dec 2023 12:35:18 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:4 as permitted sender) client-ip=2620:137:e000::3:4; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b="UHU6ht/u"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:4 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by howler.vger.email (Postfix) with ESMTP id C1F498043989; Mon, 4 Dec 2023 12:35:09 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at howler.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346127AbjLDUeb (ORCPT + 99 others); Mon, 4 Dec 2023 15:34:31 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36790 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346298AbjLDUeF (ORCPT ); Mon, 4 Dec 2023 15:34:05 -0500 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1A6F4113 for ; Mon, 4 Dec 2023 12:33:53 -0800 (PST) Received: by smtp.kernel.org (Postfix) with ESMTPSA id EA5A4C433C7; Mon, 4 Dec 2023 20:33:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1701722032; bh=oQZsZ4MZN5UxA81sG8wmKWKSLNwx9Tan/KFg+Ti7ghU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UHU6ht/uLXoxf0LwHMXtG3CW5wV9+vAVwE7qDTEU6gDaFPAA2Ms8M8BFCFUU3Egmv Tm9CYBEqGII1UP+70ElgfSa3vDJmYM++eTjvClqPA1zYvtYatINn4gG0URfl0gA937 wZ8YzY25MUL9WyYdcsbN9yrgj8H2KIQFID5w2FFJiaziH3yfFb4jCMsD0a6/rGJd5/ LUQvRFFjW4jy2/YtboAu5p+2jGBqKiSMA9ITpGLL+PXNSJCe9F15Grh7miRzEutn+o qzJVOOYIW01SE0Lu+fwz3m0f56SnNiJaXIvDBlLBnkC8ZFx0lB8wBPKBvE4+KWH19I UrL/kogOVogKw== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Johannes Berg , Greg Kroah-Hartman , Sasha Levin Subject: [PATCH AUTOSEL 6.6 14/32] debugfs: fix automount d_fsdata usage Date: Mon, 4 Dec 2023 15:32:34 -0500 Message-ID: <20231204203317.2092321-14-sashal@kernel.org> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231204203317.2092321-1-sashal@kernel.org> References: <20231204203317.2092321-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore X-stable-base: Linux 6.6.4 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-1.2 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on howler.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (howler.vger.email [0.0.0.0]); Mon, 04 Dec 2023 12:35:10 -0800 (PST) From: Johannes Berg [ Upstream commit 0ed04a1847a10297595ac24dc7d46b35fb35f90a ] debugfs_create_automount() stores a function pointer in d_fsdata, but since commit 7c8d469877b1 ("debugfs: add support for more elaborate ->d_fsdata") debugfs_release_dentry() will free it, now conditionally on DEBUGFS_FSDATA_IS_REAL_FOPS_BIT, but that's not set for the function pointer in automount. As a result, removing an automount dentry would attempt to free the function pointer. Luckily, the only user of this (tracing) never removes it. Nevertheless, it's safer if we just handle the fsdata in one way, namely either DEBUGFS_FSDATA_IS_REAL_FOPS_BIT or allocated. Thus, change the automount to allocate it, and use the real_fops in the data to indicate whether or not automount is filled, rather than adding a type tag. At least for now this isn't actually needed, but the next changes will require it. Also check in debugfs_file_get() that it gets only called on regular files, just to make things clearer. Acked-by: Greg Kroah-Hartman Signed-off-by: Johannes Berg Signed-off-by: Sasha Levin --- fs/debugfs/file.c | 8 ++++++++ fs/debugfs/inode.c | 27 ++++++++++++++++++++------- fs/debugfs/internal.h | 10 ++++++++-- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index c45e8c2d62e11..e40229c47fe58 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -84,6 +84,14 @@ int debugfs_file_get(struct dentry *dentry) struct debugfs_fsdata *fsd; void *d_fsd; + /* + * This could only happen if some debugfs user erroneously calls + * debugfs_file_get() on a dentry that isn't even a file, let + * them know about it. + */ + if (WARN_ON(!d_is_reg(dentry))) + return -EINVAL; + d_fsd = READ_ONCE(dentry->d_fsdata); if (!((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) { fsd = d_fsd; diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 83e57e9f9fa03..dcde4199a625d 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -236,17 +236,19 @@ static const struct super_operations debugfs_super_operations = { static void debugfs_release_dentry(struct dentry *dentry) { - void *fsd = dentry->d_fsdata; + struct debugfs_fsdata *fsd = dentry->d_fsdata; - if (!((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) - kfree(dentry->d_fsdata); + if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT) + return; + + kfree(fsd); } static struct vfsmount *debugfs_automount(struct path *path) { - debugfs_automount_t f; - f = (debugfs_automount_t)path->dentry->d_fsdata; - return f(path->dentry, d_inode(path->dentry)->i_private); + struct debugfs_fsdata *fsd = path->dentry->d_fsdata; + + return fsd->automount(path->dentry, d_inode(path->dentry)->i_private); } static const struct dentry_operations debugfs_dops = { @@ -634,13 +636,23 @@ struct dentry *debugfs_create_automount(const char *name, void *data) { struct dentry *dentry = start_creating(name, parent); + struct debugfs_fsdata *fsd; struct inode *inode; if (IS_ERR(dentry)) return dentry; + fsd = kzalloc(sizeof(*fsd), GFP_KERNEL); + if (!fsd) { + failed_creating(dentry); + return ERR_PTR(-ENOMEM); + } + + fsd->automount = f; + if (!(debugfs_allow & DEBUGFS_ALLOW_API)) { failed_creating(dentry); + kfree(fsd); return ERR_PTR(-EPERM); } @@ -648,13 +660,14 @@ struct dentry *debugfs_create_automount(const char *name, if (unlikely(!inode)) { pr_err("out of free dentries, can not create automount '%s'\n", name); + kfree(fsd); return failed_creating(dentry); } make_empty_dir_inode(inode); inode->i_flags |= S_AUTOMOUNT; inode->i_private = data; - dentry->d_fsdata = (void *)f; + dentry->d_fsdata = fsd; /* directory inodes start off with i_nlink == 2 (for "." entry) */ inc_nlink(inode); d_instantiate(dentry, inode); diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h index 92af8ae313134..f7c489b5a368c 100644 --- a/fs/debugfs/internal.h +++ b/fs/debugfs/internal.h @@ -17,8 +17,14 @@ extern const struct file_operations debugfs_full_proxy_file_operations; struct debugfs_fsdata { const struct file_operations *real_fops; - refcount_t active_users; - struct completion active_users_drained; + union { + /* automount_fn is used when real_fops is NULL */ + debugfs_automount_t automount; + struct { + refcount_t active_users; + struct completion active_users_drained; + }; + }; }; /* -- 2.42.0