From patchwork Fri Nov 24 16:25:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 169498 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:ce62:0:b0:403:3b70:6f57 with SMTP id o2csp1352804vqx; Fri, 24 Nov 2023 08:35:40 -0800 (PST) X-Google-Smtp-Source: AGHT+IEC4qccd1AHs9Oqw5HfHuiluRGD6GPcaZwZcpuVZip22hJzsgy14GRfOBQYP91MMLLUfLnF X-Received: by 2002:a05:6a21:a599:b0:18b:23db:3dfd with SMTP id gd25-20020a056a21a59900b0018b23db3dfdmr4399804pzc.36.1700843739691; Fri, 24 Nov 2023 08:35:39 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1700843739; cv=none; d=google.com; s=arc-20160816; b=mlLGKSErmTCDXeifQR/Ir0HfqmSfKImBQilZis96EFPjuYuvWJULu7X6RZuKfr5q03 bcXICxjPGVxvs5SXUhDFxTx2AOXAqmdo43g5csdLqdYjDJ0zps/3Qsf1V0U4U5m4re8+ UCDQWVGNreN9vTwT8ufqjOEA6Iz/Viv/kOHeosaqFsXU190pmquJxEw7CvzS7AF00LEQ O3U8qILdxrIIkHCvUhhOPUNZUx9I6XVKXO3eu4mLeStSTU7wRojdqtTxnJghHVuGyYpe jPL5VNqlSUydJLTV9rEa/9HBTrnknZ0TJRsFkSED6LMq0MgG3jE7nk8WJFd3anDcw2bB gV8w== 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=0UN9GHGXC0XIxHJJM2egpSDSxRBo8sXF/uDuCd6FNTk=; fh=A9B0uqHrLOhV8lpdKrDO+2kao9UNQ/xn2a9tcpNN72M=; b=stdkYek9nOMvtw7kCHCIWHWlw7MQLi7LcXfRSRPkwifj+cx477f/i+n5PTROsl2C9x KfhcZU9vq/dzHXR/4dK7/FRGOy8SnJsICqH1plvDAn+6RlUhzXbuTSbVMO9T2LF9yRa6 1WAfOQ4ak8ffOSiSL/sIWbZaWM7GTA3TsNCcofVNo/I69E/EDpkPLiq7WxEl4Q8mul7z j8HE8ukh+OYGC6S+Ig9fdoqExfJUQo1gmiTkOwAp60vRCQObrm3w+CzYkXnc7slqrVLy qV228JBEpx/PAPI5Kt988y55M1pK8DPyoePQUDzxIJXdeb3vO4WZNWbj9PaA32Ywx+AQ Df7Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sipsolutions.net header.s=mail header.b=dEGBjhHq; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=sipsolutions.net Received: from fry.vger.email (fry.vger.email. [2620:137:e000::3:8]) by mx.google.com with ESMTPS id j6-20020a056a00130600b006cb4c6074c8si3825016pfu.311.2023.11.24.08.35.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Nov 2023 08:35:39 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) client-ip=2620:137:e000::3:8; Authentication-Results: mx.google.com; dkim=pass header.i=@sipsolutions.net header.s=mail header.b=dEGBjhHq; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=sipsolutions.net Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by fry.vger.email (Postfix) with ESMTP id 09CD0821148E; Fri, 24 Nov 2023 08:35:33 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at fry.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231266AbjKXQfQ (ORCPT + 99 others); Fri, 24 Nov 2023 11:35:16 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59902 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230354AbjKXQfM (ORCPT ); Fri, 24 Nov 2023 11:35:12 -0500 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:242:246e::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 632D919A9; Fri, 24 Nov 2023 08:35:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=0UN9GHGXC0XIxHJJM2egpSDSxRBo8sXF/uDuCd6FNTk=; t=1700843718; x=1702053318; b=dEGBjhHqJTsI3Lj/zIFvfVU7hpUSbW4Q9f/75tq8/BRq+gz d5a7ajw/fcQc+64/94LsyvdAiGny149/bB7Edf4HI3QcolFt8gwjbK+D/PQeF1xr/Uf6jb49bLaVb ErHwiI/9GmwQlGhDr2/QV9qDStvblr4682sGC3LEzQAoyUNsXj+l5FUPk48CaZO2APtXvFJKClZjF 98j1oCKAWshh7zmB5Iz9EotnmdZ/oHm28S2icUHnTD9JqjhIlpZEyR+Gi4R5jyfWQAd+menPV1qGb QqwD3qo3sLCw/7I5Aeix1ofhT6g98eSAQpAYy1CPu3Yh6hWEXuj3G0ImMewrRWIw==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.97) (envelope-from ) id 1r6Z99-00000002fA8-1aGJ; Fri, 24 Nov 2023 17:35:15 +0100 From: Johannes Berg To: linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , "Rafael J. Wysocki" , Johannes Berg Subject: [PATCH v2 1/6] debugfs: fix automount d_fsdata usage Date: Fri, 24 Nov 2023 17:25:24 +0100 Message-ID: <20231124172522.01928f127e73.I64fe5615568e87f9ae2d7fb2ac4e5fa96924cb50@changeid> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231124162522.16344-7-johannes@sipsolutions.net> References: <20231124162522.16344-7-johannes@sipsolutions.net> MIME-Version: 1.0 X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,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 fry.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 (fry.vger.email [0.0.0.0]); Fri, 24 Nov 2023 08:35:33 -0800 (PST) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1783463925527705848 X-GMAIL-MSGID: 1783463925527705848 From: Johannes Berg 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. Signed-off-by: Johannes Berg Acked-by: Greg Kroah-Hartman --- v2: add missing kfree() pointed out by smatch --- 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 87b3753aa4b1..e00189aebbf4 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 83e57e9f9fa0..dcde4199a625 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 92af8ae31313..f7c489b5a368 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; + }; + }; }; /* From patchwork Fri Nov 24 16:25:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 169499 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:ce62:0:b0:403:3b70:6f57 with SMTP id o2csp1352838vqx; Fri, 24 Nov 2023 08:35:43 -0800 (PST) X-Google-Smtp-Source: AGHT+IGLGQjKbgHWrJjsSROneZAY6bUPZYwV5sna91P+bQE3oRSn0lMIOwyK2zHMssAlrWAarl0G X-Received: by 2002:a17:90b:3c44:b0:285:9d3f:cca7 with SMTP id pm4-20020a17090b3c4400b002859d3fcca7mr801969pjb.25.1700843743020; Fri, 24 Nov 2023 08:35:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1700843743; cv=none; d=google.com; s=arc-20160816; b=yL8qxgbq1IFym5shZ2LNbEwi95KzhGl7Iep9uH/4fhP81hoavHpoUs0ZCMBnqrBD2S vlk/g0wZwAJHgX11di6RBVQtVgrxPWsLaDu71PI0gSe4HQHIMNj5zhzKH0p7rzlmWPP/ knydNMaUswwbmCnz5poJ8xl2e0IMjA8k6w+hQBITC0EwQyG1A80nEIHw1Qsm3gXU2Ynp S/AWmMGvuGXnuIm1d89YSCt6UPP9gVA5n1TCrz3KFC7h6nB1WRHhJG/b4qAl5nbM/dFS rXxmFkNKFCRe6gK4xSABGXNv+pJ2YM2i3ggqte5GpcyIbDPCYlmFjkprNcVNqSWAimLn 5Ryw== 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=eUQSivaM/C3sgIYV/55zPnV1kMbFsOGZiai+sGa+jDY=; fh=A9B0uqHrLOhV8lpdKrDO+2kao9UNQ/xn2a9tcpNN72M=; b=KsnS78TDmUwMYWwMkZeWL5bQWPlhqhteUqTiR1We1ZXZyh0m+JGWr9y5WAI+KxWhhE UQI6pwfVHUMwWrMFwkohhyBZrdYREeEkjlFryjJx4IIQC87WPmKT6hnx4ILfEKb5Pn/c A+eFjGHGmp4m9pPObetK0+Ur9gYl3DnEEuKroyZILAuTBBh10hrJ8SB4rh3FzRT10wGK 8Bia7mG5EOH4BeWJTQtmXwUZq/Y1oyf2gdO5L5ECeXoAqYBY1dtM9bBJkqmj2BuOuLMM CxWhkXKPzGyPpOMoKL6BUB0SNo4b3BPpGyV2/R5NFkt1m7LZ7I69Ngl3p920HWn+lPW5 Mb2Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sipsolutions.net header.s=mail header.b=eplHiX6Z; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:6 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=sipsolutions.net Received: from pete.vger.email (pete.vger.email. [2620:137:e000::3:6]) by mx.google.com with ESMTPS id ep2-20020a17090ae64200b00285259acbcesi3903067pjb.142.2023.11.24.08.35.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Nov 2023 08:35:43 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:6 as permitted sender) client-ip=2620:137:e000::3:6; Authentication-Results: mx.google.com; dkim=pass header.i=@sipsolutions.net header.s=mail header.b=eplHiX6Z; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:6 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=sipsolutions.net Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by pete.vger.email (Postfix) with ESMTP id CABE780C9A55; Fri, 24 Nov 2023 08:35:33 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at pete.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231268AbjKXQfT (ORCPT + 99 others); Fri, 24 Nov 2023 11:35:19 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59906 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229741AbjKXQfM (ORCPT ); Fri, 24 Nov 2023 11:35:12 -0500 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:242:246e::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AEB3D19A6; Fri, 24 Nov 2023 08:35:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=eUQSivaM/C3sgIYV/55zPnV1kMbFsOGZiai+sGa+jDY=; t=1700843718; x=1702053318; b=eplHiX6ZMYIt11LKuIlWEPvXql5NNzBtK2Qbe3nAL30vIGt FwyzxUPM43QQVDRpK5rOtubghhSH5orccxvy4bO30sNFYVr3FRo6gEh+RLgXqF+JmygXOabWp9aji GtNi+yykJNzgnhM3ysbd7YOcVdz1ANXHQNTPxQ91C5s934QrL7SKN6ezcaq+T/73gIJIiFx8dVrZQ ylpxnbTXDUpkSTYbqrkecDjd/p5AHJmS2flrv6a69kcyLKkvahc1e0p4m3l4XkNrqr/YroUpi2nil D/+u1vUE0e2O0twKy7C3KVmyXzAx3/kLvucZN02tB1jDypmrLFajK/96of2N1YZA==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.97) (envelope-from ) id 1r6Z9A-00000002fA8-0Xch; Fri, 24 Nov 2023 17:35:16 +0100 From: Johannes Berg To: linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , "Rafael J. Wysocki" , Johannes Berg Subject: [PATCH v2 2/6] debugfs: annotate debugfs handlers vs. removal with lockdep Date: Fri, 24 Nov 2023 17:25:25 +0100 Message-ID: <20231124172522.0442774abc66.Ia70a49792c448867fd61b0234e1da507b0f75086@changeid> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231124162522.16344-7-johannes@sipsolutions.net> References: <20231124162522.16344-7-johannes@sipsolutions.net> MIME-Version: 1.0 X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,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 pete.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 (pete.vger.email [0.0.0.0]); Fri, 24 Nov 2023 08:35:34 -0800 (PST) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1783463928854198657 X-GMAIL-MSGID: 1783463928854198657 From: Johannes Berg When you take a lock in a debugfs handler but also try to remove the debugfs file under that lock, things can deadlock since the removal has to wait for all users to finish. Add lockdep annotations in debugfs_file_get()/_put() to catch such issues. Signed-off-by: Johannes Berg Acked-by: Greg Kroah-Hartman --- fs/debugfs/file.c | 10 ++++++++++ fs/debugfs/inode.c | 12 ++++++++++++ fs/debugfs/internal.h | 6 ++++++ 3 files changed, 28 insertions(+) diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index e00189aebbf4..3eff92450fd5 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -108,6 +108,12 @@ int debugfs_file_get(struct dentry *dentry) kfree(fsd); fsd = READ_ONCE(dentry->d_fsdata); } +#ifdef CONFIG_LOCKDEP + fsd->lock_name = kasprintf(GFP_KERNEL, "debugfs:%pd", dentry); + lockdep_register_key(&fsd->key); + lockdep_init_map(&fsd->lockdep_map, fsd->lock_name ?: "debugfs", + &fsd->key, 0); +#endif } /* @@ -124,6 +130,8 @@ int debugfs_file_get(struct dentry *dentry) if (!refcount_inc_not_zero(&fsd->active_users)) return -EIO; + lock_map_acquire_read(&fsd->lockdep_map); + return 0; } EXPORT_SYMBOL_GPL(debugfs_file_get); @@ -141,6 +149,8 @@ void debugfs_file_put(struct dentry *dentry) { struct debugfs_fsdata *fsd = READ_ONCE(dentry->d_fsdata); + lock_map_release(&fsd->lockdep_map); + if (refcount_dec_and_test(&fsd->active_users)) complete(&fsd->active_users_drained); } diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index dcde4199a625..80f4f000dcc1 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -241,6 +241,14 @@ static void debugfs_release_dentry(struct dentry *dentry) if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT) return; + /* check it wasn't a dir (no fsdata) or automount (no real_fops) */ + if (fsd && fsd->real_fops) { +#ifdef CONFIG_LOCKDEP + lockdep_unregister_key(&fsd->key); + kfree(fsd->lock_name); +#endif + } + kfree(fsd); } @@ -744,6 +752,10 @@ static void __debugfs_file_removed(struct dentry *dentry) fsd = READ_ONCE(dentry->d_fsdata); if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT) return; + + lock_map_acquire(&fsd->lockdep_map); + lock_map_release(&fsd->lockdep_map); + if (!refcount_dec_and_test(&fsd->active_users)) wait_for_completion(&fsd->active_users_drained); } diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h index f7c489b5a368..c7d61cfc97d2 100644 --- a/fs/debugfs/internal.h +++ b/fs/debugfs/internal.h @@ -7,6 +7,7 @@ #ifndef _DEBUGFS_INTERNAL_H_ #define _DEBUGFS_INTERNAL_H_ +#include struct file_operations; @@ -23,6 +24,11 @@ struct debugfs_fsdata { struct { refcount_t active_users; struct completion active_users_drained; +#ifdef CONFIG_LOCKDEP + struct lockdep_map lockdep_map; + struct lock_class_key key; + char *lock_name; +#endif }; }; }; From patchwork Fri Nov 24 16:25:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 169500 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:ce62:0:b0:403:3b70:6f57 with SMTP id o2csp1352872vqx; Fri, 24 Nov 2023 08:35:46 -0800 (PST) X-Google-Smtp-Source: AGHT+IGRY0v4PrSWsDfrh4T5QDmM4gixM5NkC7AXwPGXxO97dTxrmH+M1TDEp4VoNmtyzFbothpY X-Received: by 2002:a05:6e02:174e:b0:35b:2908:a17b with SMTP id y14-20020a056e02174e00b0035b2908a17bmr4933035ill.31.1700843746092; Fri, 24 Nov 2023 08:35:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1700843746; cv=none; d=google.com; s=arc-20160816; b=n3EfaLquBOI85tqWPq2IndrnJBhGet4K6KPwbwaaWuvFSrVjT+2Tyh47kKSRe0chPl VznN9/7oDJvIiwgEwgIwKqN8X/xbtHYN1B0rOGbGd4GGSEQC9BhpnSYOkipKCVqqNUYp B8pQ0+pyop53ROb0BlzF2cuVVSluxv4PucUzBLCLqmS5TmcaETkGVdxUZAv/KTrC6OQZ Unnq4skQEbAkczyuI8+/G1VYN0feqtj3gkQwyDmIL2/0hd0iT0UAtCYPadJaY5C35tCR emU/zlLyMpLxISNCJAr4yQEs6Ip4MQGGFXXTEm8neoPCJIZTuzwjKy67o5pmA+CZGPzT TsFA== 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=lRmcKq7AIxSR6usOW5TWHREpkqLey1xNLAHUQ3oiplc=; fh=A9B0uqHrLOhV8lpdKrDO+2kao9UNQ/xn2a9tcpNN72M=; b=0oKd+ECCTPab+kxTw4l5GrMHKBbQUXp9xtjoMe8WuvMtJjHWoimjPHssdlDsDcP0FF rVLjhLkbo06UnyV0X9dIEWcDibvYLmAtbkI9oLQbhPTz90FYfzY2njk2SEI1jIevih3v JItlKaNwz783kYXbAgwVNfItmrc728L2n7VKeDTJzD1szqam30Qg6dqn39OeThU1Db0+ JK2n7TygM13e7v/Q9ZzrqoBqEIUG01fk7iUgu4QflvyvEKW1VvlEOK8dKN1NEp0/jJcG 2O+cAOvIvgpkO0Q9Y7mqx+4OzEBtOSZOBXMOsDvI8oQBAzomLD+jZeA7GWA15hKoCeYJ pKBg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sipsolutions.net header.s=mail header.b="wa+2OV/o"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:6 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=sipsolutions.net Received: from pete.vger.email (pete.vger.email. [2620:137:e000::3:6]) by mx.google.com with ESMTPS id d11-20020a631d4b000000b005c1ce3c9608si3594652pgm.756.2023.11.24.08.35.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Nov 2023 08:35:46 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:6 as permitted sender) client-ip=2620:137:e000::3:6; Authentication-Results: mx.google.com; dkim=pass header.i=@sipsolutions.net header.s=mail header.b="wa+2OV/o"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:6 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=sipsolutions.net Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by pete.vger.email (Postfix) with ESMTP id 55AFA80C9A51; Fri, 24 Nov 2023 08:35:37 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at pete.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1345407AbjKXQfW (ORCPT + 99 others); Fri, 24 Nov 2023 11:35:22 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59948 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231251AbjKXQfO (ORCPT ); Fri, 24 Nov 2023 11:35:14 -0500 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:242:246e::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E579710CF; Fri, 24 Nov 2023 08:35:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=lRmcKq7AIxSR6usOW5TWHREpkqLey1xNLAHUQ3oiplc=; t=1700843720; x=1702053320; b=wa+2OV/olec2UJOI4JBr78xUtZA+Ok2eKCz+qntJmqFVVx1 VkhlSBJMOwZOCHWZMjE2Ra0szNu7DWV1jr7v9HSEVevn83Kze8Q2wa7DFGaW9xkyNg3iTriUF6h2g 6QRQKXR6msqO3OvcEjVzoD4DD1XAf+OR19UGO1e6rwnLmSd/Bdnor2PTS0IdlnA8bhTl8NF4pzN1w n/xXm1wW6o1lrGe7JfxJRQ0EHsCxo3zgoFKjg7SD0otQJku34r1aHIk9jOMqeAo9sy5YPg5cog+Hb P2NuN5JYKZJDZ//7Ka+YfkT+9HAGXHf3c9+6DuLUOkemC6062/iHQG4jPoTc2bIA==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.97) (envelope-from ) id 1r6Z9A-00000002fA8-3co7; Fri, 24 Nov 2023 17:35:17 +0100 From: Johannes Berg To: linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , "Rafael J. Wysocki" , Johannes Berg Subject: [PATCH v2 3/6] debugfs: add API to allow debugfs operations cancellation Date: Fri, 24 Nov 2023 17:25:26 +0100 Message-ID: <20231124172522.8c5d739c69e7.If54cd017d5734024e7bee5e4a237e17244050480@changeid> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231124162522.16344-7-johannes@sipsolutions.net> References: <20231124162522.16344-7-johannes@sipsolutions.net> MIME-Version: 1.0 X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,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 pete.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 (pete.vger.email [0.0.0.0]); Fri, 24 Nov 2023 08:35:37 -0800 (PST) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1783463931776104390 X-GMAIL-MSGID: 1783463931776104390 From: Johannes Berg In some cases there might be longer-running hardware accesses in debugfs files, or attempts to acquire locks, and we want to still be able to quickly remove the files. Introduce a cancellations API to use inside the debugfs handler functions to be able to cancel such operations on a per-file basis. Signed-off-by: Johannes Berg Acked-by: Greg Kroah-Hartman --- v2: - use mutex to protect the cancellations and hold it around calling the cancel function so that cannot race with the handler finishing and leaving the cancellation. --- fs/debugfs/file.c | 82 +++++++++++++++++++++++++++++++++++++++++ fs/debugfs/inode.c | 32 +++++++++++++++- fs/debugfs/internal.h | 5 +++ include/linux/debugfs.h | 19 ++++++++++ 4 files changed, 137 insertions(+), 1 deletion(-) diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 3eff92450fd5..5568cdea3490 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -114,6 +114,8 @@ int debugfs_file_get(struct dentry *dentry) lockdep_init_map(&fsd->lockdep_map, fsd->lock_name ?: "debugfs", &fsd->key, 0); #endif + INIT_LIST_HEAD(&fsd->cancellations); + mutex_init(&fsd->cancellations_mtx); } /* @@ -156,6 +158,86 @@ void debugfs_file_put(struct dentry *dentry) } EXPORT_SYMBOL_GPL(debugfs_file_put); +/** + * debugfs_enter_cancellation - enter a debugfs cancellation + * @file: the file being accessed + * @cancellation: the cancellation object, the cancel callback + * inside of it must be initialized + * + * When a debugfs file is removed it needs to wait for all active + * operations to complete. However, the operation itself may need + * to wait for hardware or completion of some asynchronous process + * or similar. As such, it may need to be cancelled to avoid long + * waits or even deadlocks. + * + * This function can be used inside a debugfs handler that may + * need to be cancelled. As soon as this function is called, the + * cancellation's 'cancel' callback may be called, at which point + * the caller should proceed to call debugfs_leave_cancellation() + * and leave the debugfs handler function as soon as possible. + * Note that the 'cancel' callback is only ever called in the + * context of some kind of debugfs_remove(). + * + * This function must be paired with debugfs_leave_cancellation(). + */ +void debugfs_enter_cancellation(struct file *file, + struct debugfs_cancellation *cancellation) +{ + struct debugfs_fsdata *fsd; + struct dentry *dentry = F_DENTRY(file); + + INIT_LIST_HEAD(&cancellation->list); + + if (WARN_ON(!d_is_reg(dentry))) + return; + + if (WARN_ON(!cancellation->cancel)) + return; + + fsd = READ_ONCE(dentry->d_fsdata); + if (WARN_ON(!fsd || + ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT))) + return; + + mutex_lock(&fsd->cancellations_mtx); + list_add(&cancellation->list, &fsd->cancellations); + mutex_unlock(&fsd->cancellations_mtx); + + /* if we're already removing wake it up to cancel */ + if (d_unlinked(dentry)) + complete(&fsd->active_users_drained); +} +EXPORT_SYMBOL_GPL(debugfs_enter_cancellation); + +/** + * debugfs_leave_cancellation - leave cancellation section + * @file: the file being accessed + * @cancellation: the cancellation previously registered with + * debugfs_enter_cancellation() + * + * See the documentation of debugfs_enter_cancellation(). + */ +void debugfs_leave_cancellation(struct file *file, + struct debugfs_cancellation *cancellation) +{ + struct debugfs_fsdata *fsd; + struct dentry *dentry = F_DENTRY(file); + + if (WARN_ON(!d_is_reg(dentry))) + return; + + fsd = READ_ONCE(dentry->d_fsdata); + if (WARN_ON(!fsd || + ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT))) + return; + + mutex_lock(&fsd->cancellations_mtx); + if (!list_empty(&cancellation->list)) + list_del(&cancellation->list); + mutex_unlock(&fsd->cancellations_mtx); +} +EXPORT_SYMBOL_GPL(debugfs_leave_cancellation); + /* * Only permit access to world-readable files when the kernel is locked down. * We also need to exclude any file that has ways to write or alter it as root diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 80f4f000dcc1..d53c2860b03c 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -247,6 +247,8 @@ static void debugfs_release_dentry(struct dentry *dentry) lockdep_unregister_key(&fsd->key); kfree(fsd->lock_name); #endif + WARN_ON(!list_empty(&fsd->cancellations)); + mutex_destroy(&fsd->cancellations_mtx); } kfree(fsd); @@ -756,8 +758,36 @@ static void __debugfs_file_removed(struct dentry *dentry) lock_map_acquire(&fsd->lockdep_map); lock_map_release(&fsd->lockdep_map); - if (!refcount_dec_and_test(&fsd->active_users)) + /* if we hit zero, just wait for all to finish */ + if (!refcount_dec_and_test(&fsd->active_users)) { wait_for_completion(&fsd->active_users_drained); + return; + } + + /* if we didn't hit zero, try to cancel any we can */ + while (refcount_read(&fsd->active_users)) { + struct debugfs_cancellation *c; + + /* + * Lock the cancellations. Note that the cancellations + * structs are meant to be on the stack, so we need to + * ensure we either use them here or don't touch them, + * and debugfs_leave_cancellation() will wait for this + * to be finished processing before exiting one. It may + * of course win and remove the cancellation, but then + * chances are we never even got into this bit, we only + * do if the refcount isn't zero already. + */ + mutex_lock(&fsd->cancellations_mtx); + while ((c = list_first_entry_or_null(&fsd->cancellations, + typeof(*c), list))) { + list_del_init(&c->list); + c->cancel(dentry, c->cancel_data); + } + mutex_unlock(&fsd->cancellations_mtx); + + wait_for_completion(&fsd->active_users_drained); + } } static void remove_one(struct dentry *victim) diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h index c7d61cfc97d2..0c4c68cf161f 100644 --- a/fs/debugfs/internal.h +++ b/fs/debugfs/internal.h @@ -8,6 +8,7 @@ #ifndef _DEBUGFS_INTERNAL_H_ #define _DEBUGFS_INTERNAL_H_ #include +#include struct file_operations; @@ -29,6 +30,10 @@ struct debugfs_fsdata { struct lock_class_key key; char *lock_name; #endif + + /* protect cancellations */ + struct mutex cancellations_mtx; + struct list_head cancellations; }; }; }; diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index ea2d919fd9c7..c9c65b132c0f 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -171,6 +171,25 @@ ssize_t debugfs_write_file_bool(struct file *file, const char __user *user_buf, ssize_t debugfs_read_file_str(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); +/** + * struct debugfs_cancellation - cancellation data + * @list: internal, for keeping track + * @cancel: callback to call + * @cancel_data: extra data for the callback to call + */ +struct debugfs_cancellation { + struct list_head list; + void (*cancel)(struct dentry *, void *); + void *cancel_data; +}; + +void __acquires(cancellation) +debugfs_enter_cancellation(struct file *file, + struct debugfs_cancellation *cancellation); +void __releases(cancellation) +debugfs_leave_cancellation(struct file *file, + struct debugfs_cancellation *cancellation); + #else #include From patchwork Fri Nov 24 16:25:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 169501 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:ce62:0:b0:403:3b70:6f57 with SMTP id o2csp1353000vqx; Fri, 24 Nov 2023 08:35:55 -0800 (PST) X-Google-Smtp-Source: AGHT+IFGg/FPEynTtjSk6bdOXfvpd+qiPWpzF4TUEDCW1zixgLQZg0yB/6fg2sxFQC0XsntRdZV+ X-Received: by 2002:a17:90b:4b47:b0:27f:f260:ceaf with SMTP id mi7-20020a17090b4b4700b0027ff260ceafmr3453825pjb.10.1700843755646; Fri, 24 Nov 2023 08:35:55 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1700843755; cv=none; d=google.com; s=arc-20160816; b=IAOwnHUswL7kOfn6f7rQpRtB8O313fq4RJG0lOQ7N8Lu1J19o9US3L6Ha41RU735kT 8qelxWgIxNCaloAKxU4bRmrdu8SGxjSLGyYnIAxzOYMD7Eh4AvCc42owNjECPv+P/pmm 07nsUR3sh9BTCbNGIe82/1/o676oL5es+x4m2rXP6pdjW6zqYDyq0VBhlvMzmOduBCmL UD/kf6wPlZH4o0RXZAKQK7NNThdZN+0SG5lELFSu/IOKcKBnByLQf+Sr1OrB9lgkGljT cgpD1NzG3CB+rxrBfGXRpUdZtlgUuM/M+EO6r8cmfD2jajcnyfl5DhML512Hlypsm8YZ PpzQ== 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=liAhozg7Mw19h9BQg+C0TH1QJAs+IpxQtgvDIZ45qPY=; fh=A9B0uqHrLOhV8lpdKrDO+2kao9UNQ/xn2a9tcpNN72M=; b=0VBwNYGVajSXxWu3QzH0rbJULDdxnLeesau+DNkOBBhlWy1l8dBbVip/TbZNt/i/C+ MDH+CeMxYKKhmp3fCamW/LQunUmzXZ5DZvukCf8ZDQPKN2KrvskAcWYM9LwS1Dthi+FD GLOOdUSMv4W1PB8/BENkz/Y3oFmGrowpNQtUzP/w5jU8ihoL8C/9+YqYRVkFNIs4equM DHKb0Vu1DOkrgslXV+8bTaVvlPEMDtsyJZ9u+yyIuUmNKTlt7Iwd50Dmj/++kwE5KnbS gApQDbdfEBbzmPp9+wHzSVApDM2PFRFTwUElKEqIV9HlgK171QEJtfsxV2P8ghOuVNbD 1XUg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sipsolutions.net header.s=mail header.b=O0k0ulbt; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.36 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=sipsolutions.net Received: from pete.vger.email (pete.vger.email. [23.128.96.36]) by mx.google.com with ESMTPS id v7-20020a17090a898700b0028547582e74si4347806pjn.105.2023.11.24.08.35.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Nov 2023 08:35:55 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.36 as permitted sender) client-ip=23.128.96.36; Authentication-Results: mx.google.com; dkim=pass header.i=@sipsolutions.net header.s=mail header.b=O0k0ulbt; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.36 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=sipsolutions.net Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by pete.vger.email (Postfix) with ESMTP id 27BAC80C9A47; Fri, 24 Nov 2023 08:35:47 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at pete.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231332AbjKXQfZ (ORCPT + 99 others); Fri, 24 Nov 2023 11:35:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37528 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230159AbjKXQfO (ORCPT ); Fri, 24 Nov 2023 11:35:14 -0500 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:242:246e::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9043019A4; Fri, 24 Nov 2023 08:35:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=liAhozg7Mw19h9BQg+C0TH1QJAs+IpxQtgvDIZ45qPY=; t=1700843720; x=1702053320; b=O0k0ulbtJS8ygJhQrmxW7+kEchrVYQ6Xcz+cBuYRS+Vs+WT u++r4apCdiNEOI81+ivYE7/LWUU3XEanONBCiZRlwywwejyAetFPbXutAqeNIz4FbAh6RiY/2cIKM nKWa05FpEsAA5LDEQB698L+RDRLqJHP+RUvt5OGIbyZuMnlcYKxuZ44m3FP2QRGCKIkrD6/Mmpqih copzgWuvDTpVJ6336UNvyDTo8dO/PJzA+jHlgyWbRXMWJJpFQ1t44qp8PKeoSxMKJi5LynxscLKEm Lwsc/WopaEtOOr3IQvehOm3rsOmzRBsMlU/lzWcfLrCWS5oU9EMAKFEOtKHtJdFQ==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.97) (envelope-from ) id 1r6Z9B-00000002fA8-2i2H; Fri, 24 Nov 2023 17:35:18 +0100 From: Johannes Berg To: linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , "Rafael J. Wysocki" , Johannes Berg Subject: [PATCH v2 4/6] wifi: cfg80211: add locked debugfs wrappers Date: Fri, 24 Nov 2023 17:25:27 +0100 Message-ID: <20231124172522.e79351e3900f.I52daf6c4d8f70b5c5c2de7f0918c6748f11f1e8b@changeid> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231124162522.16344-7-johannes@sipsolutions.net> References: <20231124162522.16344-7-johannes@sipsolutions.net> MIME-Version: 1.0 X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,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 pete.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 (pete.vger.email [0.0.0.0]); Fri, 24 Nov 2023 08:35:47 -0800 (PST) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1783463942069807823 X-GMAIL-MSGID: 1783463942069807823 From: Johannes Berg Add wrappers for debugfs files that should be called with the wiphy mutex held, while the file is also to be removed under the wiphy mutex. This could otherwise deadlock when a file is trying to acquire the wiphy mutex while the code removing it holds the mutex but waits for the removal. This actually works by pushing the execution of the read or write handler to a wiphy work that can be cancelled using the debugfs cancellation API. Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 46 ++++++++++++ net/wireless/debugfs.c | 160 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index b137a33a1b68..4ecfb06c413d 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -9299,4 +9299,50 @@ bool cfg80211_valid_disable_subchannel_bitmap(u16 *bitmap, */ void cfg80211_links_removed(struct net_device *dev, u16 link_mask); +#ifdef CONFIG_CFG80211_DEBUGFS +/** + * wiphy_locked_debugfs_read - do a locked read in debugfs + * @wiphy: the wiphy to use + * @file: the file being read + * @buf: the buffer to fill and then read from + * @bufsize: size of the buffer + * @userbuf: the user buffer to copy to + * @count: read count + * @ppos: read position + * @handler: the read handler to call (under wiphy lock) + * @data: additional data to pass to the read handler + */ +ssize_t wiphy_locked_debugfs_read(struct wiphy *wiphy, struct file *file, + char *buf, size_t bufsize, + char __user *userbuf, size_t count, + loff_t *ppos, + ssize_t (*handler)(struct wiphy *wiphy, + struct file *file, + char *buf, + size_t bufsize, + void *data), + void *data); + +/** + * wiphy_locked_debugfs_write - do a locked write in debugfs + * @wiphy: the wiphy to use + * @file: the file being written to + * @buf: the buffer to copy the user data to + * @bufsize: size of the buffer + * @userbuf: the user buffer to copy from + * @count: read count + * @handler: the write handler to call (under wiphy lock) + * @data: additional data to pass to the write handler + */ +ssize_t wiphy_locked_debugfs_write(struct wiphy *wiphy, struct file *file, + char *buf, size_t bufsize, + const char __user *userbuf, size_t count, + ssize_t (*handler)(struct wiphy *wiphy, + struct file *file, + char *buf, + size_t count, + void *data), + void *data); +#endif + #endif /* __NET_CFG80211_H */ diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c index 0878b162890a..40e49074e2ee 100644 --- a/net/wireless/debugfs.c +++ b/net/wireless/debugfs.c @@ -4,6 +4,7 @@ * * Copyright 2009 Luis R. Rodriguez * Copyright 2007 Johannes Berg + * Copyright (C) 2023 Intel Corporation */ #include @@ -109,3 +110,162 @@ void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev) DEBUGFS_ADD(long_retry_limit); DEBUGFS_ADD(ht40allow_map); } + +struct debugfs_read_work { + struct wiphy_work work; + ssize_t (*handler)(struct wiphy *wiphy, + struct file *file, + char *buf, + size_t count, + void *data); + struct wiphy *wiphy; + struct file *file; + char *buf; + size_t bufsize; + void *data; + ssize_t ret; + struct completion completion; +}; + +static void wiphy_locked_debugfs_read_work(struct wiphy *wiphy, + struct wiphy_work *work) +{ + struct debugfs_read_work *w = container_of(work, typeof(*w), work); + + w->ret = w->handler(w->wiphy, w->file, w->buf, w->bufsize, w->data); + complete(&w->completion); +} + +static void wiphy_locked_debugfs_read_cancel(struct dentry *dentry, + void *data) +{ + struct debugfs_read_work *w = data; + + wiphy_work_cancel(w->wiphy, &w->work); + complete(&w->completion); +} + +ssize_t wiphy_locked_debugfs_read(struct wiphy *wiphy, struct file *file, + char *buf, size_t bufsize, + char __user *userbuf, size_t count, + loff_t *ppos, + ssize_t (*handler)(struct wiphy *wiphy, + struct file *file, + char *buf, + size_t bufsize, + void *data), + void *data) +{ + struct debugfs_read_work work = { + .handler = handler, + .wiphy = wiphy, + .file = file, + .buf = buf, + .bufsize = bufsize, + .data = data, + .ret = -ENODEV, + .completion = COMPLETION_INITIALIZER_ONSTACK(work.completion), + }; + struct debugfs_cancellation cancellation = { + .cancel = wiphy_locked_debugfs_read_cancel, + .cancel_data = &work, + }; + + /* don't leak stack data or whatever */ + memset(buf, 0, bufsize); + + wiphy_work_init(&work.work, wiphy_locked_debugfs_read_work); + wiphy_work_queue(wiphy, &work.work); + + debugfs_enter_cancellation(file, &cancellation); + wait_for_completion(&work.completion); + debugfs_leave_cancellation(file, &cancellation); + + if (work.ret < 0) + return work.ret; + + if (WARN_ON(work.ret > bufsize)) + return -EINVAL; + + return simple_read_from_buffer(userbuf, count, ppos, buf, work.ret); +} +EXPORT_SYMBOL_GPL(wiphy_locked_debugfs_read); + +struct debugfs_write_work { + struct wiphy_work work; + ssize_t (*handler)(struct wiphy *wiphy, + struct file *file, + char *buf, + size_t count, + void *data); + struct wiphy *wiphy; + struct file *file; + char *buf; + size_t count; + void *data; + ssize_t ret; + struct completion completion; +}; + +static void wiphy_locked_debugfs_write_work(struct wiphy *wiphy, + struct wiphy_work *work) +{ + struct debugfs_write_work *w = container_of(work, typeof(*w), work); + + w->ret = w->handler(w->wiphy, w->file, w->buf, w->count, w->data); + complete(&w->completion); +} + +static void wiphy_locked_debugfs_write_cancel(struct dentry *dentry, + void *data) +{ + struct debugfs_write_work *w = data; + + wiphy_work_cancel(w->wiphy, &w->work); + complete(&w->completion); +} + +ssize_t wiphy_locked_debugfs_write(struct wiphy *wiphy, + struct file *file, char *buf, size_t bufsize, + const char __user *userbuf, size_t count, + ssize_t (*handler)(struct wiphy *wiphy, + struct file *file, + char *buf, + size_t count, + void *data), + void *data) +{ + struct debugfs_write_work work = { + .handler = handler, + .wiphy = wiphy, + .file = file, + .buf = buf, + .count = count, + .data = data, + .ret = -ENODEV, + .completion = COMPLETION_INITIALIZER_ONSTACK(work.completion), + }; + struct debugfs_cancellation cancellation = { + .cancel = wiphy_locked_debugfs_write_cancel, + .cancel_data = &work, + }; + + /* mostly used for strings so enforce NUL-termination for safety */ + if (count >= bufsize) + return -EINVAL; + + memset(buf, 0, bufsize); + + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + + wiphy_work_init(&work.work, wiphy_locked_debugfs_write_work); + wiphy_work_queue(wiphy, &work.work); + + debugfs_enter_cancellation(file, &cancellation); + wait_for_completion(&work.completion); + debugfs_leave_cancellation(file, &cancellation); + + return work.ret; +} +EXPORT_SYMBOL_GPL(wiphy_locked_debugfs_write); From patchwork Fri Nov 24 16:25:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 169502 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:ce62:0:b0:403:3b70:6f57 with SMTP id o2csp1353497vqx; Fri, 24 Nov 2023 08:36:37 -0800 (PST) X-Google-Smtp-Source: AGHT+IEsBvVQig4x+g+hr4kpkGhQUKUiuBD+xNv5HLY0ViiX71Qdt7ByALNcEx6LBMqwt01CcvAM X-Received: by 2002:a17:902:ab5d:b0:1cf:9045:6058 with SMTP id ij29-20020a170902ab5d00b001cf90456058mr3545598plb.54.1700843797649; Fri, 24 Nov 2023 08:36:37 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1700843797; cv=none; d=google.com; s=arc-20160816; b=M/HeiMNM72C/7LJNZ8EV3KkkQrl2UUKcko0J+gMuH/53qAfjrtm2az8qZhlCcxvWR3 dtOLoEqOey7Kz/WwFe5+yOekDfZtpvc9U5IlHePxcByUJOZuN4ckY9+7ufCYg/5Uw9BV LaTgvV/fs/Cj5G8qmDVM69VsF+HEmoXR9wDTZ5FFxb1eI+5gr9NloI7XMsN0VNi+dabu GZ1Ae06cHG+5xMgUoTy4Q5f77WP9qHO6VJ8Su0PLmny3EkWQEX09wZIboCUjwok7s/qw W84Jy9nWsYBLhS3YHOB6L7CplW0x65Xs19IJoH/jsSeJSAmz/bY4QjMm0btaWaP851TQ Qeeg== 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=/IUf3uo2oD/a+xS0yZzjtqpayIwTZ7+Ecxpk1N2XlRA=; fh=A9B0uqHrLOhV8lpdKrDO+2kao9UNQ/xn2a9tcpNN72M=; b=n8QYieSxTWi8TThufcYsKTf3BMIrxByHlpasQbL47n539RKdWn7j8vkQk1hgiHbGZ8 9ntSbMTGrVSM8Sz9vxiVt9mGEJqaTpPw7+nDRr8uvLSQQGnNAxLytgdI7drBFjKxVSdc h1MOD/a8sM9pVGQQr+1AJ3O7juNDwT9jj2lNU7DEUQNXRspvl9k0zcSG7mYauUMJyewd vz9jBwHgE3D7TwfMhmQ/xAV5VmFPj/AdUPmN5ecwbHeWbByerim4K4MP3hJaMY3JNSz/ D9a8X8ji9lacbnsQhxq1q4A1Kv1g6tVnwDq1JtGuW5D1iBFvOeZltU1yL3WmONPiQGTM vyNA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sipsolutions.net header.s=mail header.b=Hui6ohvg; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:1 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=sipsolutions.net Received: from morse.vger.email (morse.vger.email. [2620:137:e000::3:1]) by mx.google.com with ESMTPS id x6-20020a170902ec8600b001ce5ba4754bsi3984558plg.141.2023.11.24.08.36.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Nov 2023 08:36:37 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:1 as permitted sender) client-ip=2620:137:e000::3:1; Authentication-Results: mx.google.com; dkim=pass header.i=@sipsolutions.net header.s=mail header.b=Hui6ohvg; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:1 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=sipsolutions.net Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by morse.vger.email (Postfix) with ESMTP id 9E5718095F7B; Fri, 24 Nov 2023 08:36:05 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at morse.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231173AbjKXQf3 (ORCPT + 99 others); Fri, 24 Nov 2023 11:35:29 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59964 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231259AbjKXQfP (ORCPT ); Fri, 24 Nov 2023 11:35:15 -0500 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:242:246e::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 64CB719AA; Fri, 24 Nov 2023 08:35:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=/IUf3uo2oD/a+xS0yZzjtqpayIwTZ7+Ecxpk1N2XlRA=; t=1700843721; x=1702053321; b=Hui6ohvg9kGiiEXql0YQ1U+qOGmEdE5cVpHBLFOapXGTRZ5 NX5qnKNgs/mo9r5DRavTUsNoOiN+xk3JsFN559kos522SgWpZmdQNxMT7jyl/A1CeZ83P/YU4aBAy 1NTVJBKIK3GTdF+cWbxeWQKD4ShD9mmB09vp2JuoHxafiIYNrVE840gTDMMwZBZbCLvl1Yp7yRBNI AJX6BI5zPsEK/+OYEkCWTfLz7XdTmv0dudXEuNeO7XRWKBjzacLiDeXn/AZSLAKJcekA8Ta6IPGKn jh18REJafmqu+Fo4NkLrzHNWrtE3vfsGHUzGzDDOYu5Vl2UheNjeWJiW4UMDUpxw==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.97) (envelope-from ) id 1r6Z9C-00000002fA8-32NO; Fri, 24 Nov 2023 17:35:18 +0100 From: Johannes Berg To: linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , "Rafael J. Wysocki" , Johannes Berg Subject: [PATCH v2 5/6] wifi: mac80211: use wiphy locked debugfs helpers for agg_status Date: Fri, 24 Nov 2023 17:25:28 +0100 Message-ID: <20231124172522.a5e8901f9976.Id4251db174cdd42519a5ef19cbb08d7ed8f65397@changeid> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231124162522.16344-7-johannes@sipsolutions.net> References: <20231124162522.16344-7-johannes@sipsolutions.net> MIME-Version: 1.0 X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,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 morse.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 (morse.vger.email [0.0.0.0]); Fri, 24 Nov 2023 08:36:05 -0800 (PST) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1783463986347247239 X-GMAIL-MSGID: 1783463986347247239 From: Johannes Berg The read is currently with RCU and the write can deadlock, convert both for the sake of illustration. Make mac80211 depend on cfg80211 debugfs to get the helpers, but mac80211 debugfs without it does nothing anyway. Signed-off-by: Johannes Berg --- v2: - make mac80211 debugfs depend on cfg80211 debugfs, it's anyway useless without it --- net/mac80211/Kconfig | 2 +- net/mac80211/debugfs_sta.c | 74 +++++++++++++++++++++----------------- 2 files changed, 43 insertions(+), 33 deletions(-) diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 037ab74f5ade..cb0291decf2e 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -88,7 +88,7 @@ config MAC80211_LEDS config MAC80211_DEBUGFS bool "Export mac80211 internals in DebugFS" - depends on MAC80211 && DEBUG_FS + depends on MAC80211 && CFG80211_DEBUGFS help Select this to see extensive information about the internal state of mac80211 in debugfs. diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 06e3613bf46b..5bf507ebb096 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -312,23 +312,14 @@ static ssize_t sta_aql_write(struct file *file, const char __user *userbuf, STA_OPS_RW(aql); -static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) +static ssize_t sta_agg_status_do_read(struct wiphy *wiphy, struct file *file, + char *buf, size_t bufsz, void *data) { - char *buf, *p; - ssize_t bufsz = 71 + IEEE80211_NUM_TIDS * 40; + struct sta_info *sta = data; + char *p = buf; int i; - struct sta_info *sta = file->private_data; struct tid_ampdu_rx *tid_rx; struct tid_ampdu_tx *tid_tx; - ssize_t ret; - - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) - return -ENOMEM; - p = buf; - - rcu_read_lock(); p += scnprintf(p, bufsz + buf - p, "next dialog_token: %#02x\n", sta->ampdu_mlme.dialog_token_allocator + 1); @@ -338,8 +329,8 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, for (i = 0; i < IEEE80211_NUM_TIDS; i++) { bool tid_rx_valid; - tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[i]); - tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[i]); + tid_rx = wiphy_dereference(wiphy, sta->ampdu_mlme.tid_rx[i]); + tid_tx = wiphy_dereference(wiphy, sta->ampdu_mlme.tid_tx[i]); tid_rx_valid = test_bit(i, sta->ampdu_mlme.agg_session_valid); p += scnprintf(p, bufsz + buf - p, "%02d", i); @@ -358,31 +349,39 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, tid_tx ? skb_queue_len(&tid_tx->pending) : 0); p += scnprintf(p, bufsz + buf - p, "\n"); } - rcu_read_unlock(); - ret = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); + return p - buf; +} + +static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct sta_info *sta = file->private_data; + struct wiphy *wiphy = sta->local->hw.wiphy; + size_t bufsz = 71 + IEEE80211_NUM_TIDS * 40; + char *buf = kmalloc(bufsz, GFP_KERNEL); + ssize_t ret; + + if (!buf) + return -ENOMEM; + + ret = wiphy_locked_debugfs_read(wiphy, file, buf, bufsz, + userbuf, count, ppos, + sta_agg_status_do_read, sta); kfree(buf); + return ret; } -static ssize_t sta_agg_status_write(struct file *file, const char __user *userbuf, - size_t count, loff_t *ppos) +static ssize_t sta_agg_status_do_write(struct wiphy *wiphy, struct file *file, + char *buf, size_t count, void *data) { - char _buf[25] = {}, *buf = _buf; - struct sta_info *sta = file->private_data; + struct sta_info *sta = data; bool start, tx; unsigned long tid; - char *pos; + char *pos = buf; int ret, timeout = 5000; - if (count > sizeof(_buf)) - return -EINVAL; - - if (copy_from_user(buf, userbuf, count)) - return -EFAULT; - - buf[sizeof(_buf) - 1] = '\0'; - pos = buf; buf = strsep(&pos, " "); if (!buf) return -EINVAL; @@ -420,7 +419,6 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu if (ret || tid >= IEEE80211_NUM_TIDS) return -EINVAL; - wiphy_lock(sta->local->hw.wiphy); if (tx) { if (start) ret = ieee80211_start_tx_ba_session(&sta->sta, tid, @@ -432,10 +430,22 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu 3, true); ret = 0; } - wiphy_unlock(sta->local->hw.wiphy); return ret ?: count; } + +static ssize_t sta_agg_status_write(struct file *file, + const char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct sta_info *sta = file->private_data; + struct wiphy *wiphy = sta->local->hw.wiphy; + char _buf[26]; + + return wiphy_locked_debugfs_write(wiphy, file, _buf, sizeof(_buf), + userbuf, count, + sta_agg_status_do_write, sta); +} STA_OPS_RW(agg_status); /* link sta attributes */ From patchwork Fri Nov 24 16:25:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 169503 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:ce62:0:b0:403:3b70:6f57 with SMTP id o2csp1354310vqx; Fri, 24 Nov 2023 08:37:43 -0800 (PST) X-Google-Smtp-Source: AGHT+IE2WJzWFzzjDuQBz1m8nch97Bu2qgutwPypGhN4y54Lh1N1oMvrXeduSpqQzHnjlKAairzS X-Received: by 2002:a05:6a20:c1aa:b0:188:2637:9242 with SMTP id bg42-20020a056a20c1aa00b0018826379242mr4839624pzb.47.1700843863653; Fri, 24 Nov 2023 08:37:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1700843863; cv=none; d=google.com; s=arc-20160816; b=KNukvT2wrfjA7dTKuDDJ6S5GuHYw4SfBuTTwjhR+VBmdxT8abkouna4dlAC+VflATn /OTNsRjzJoFepmw38R4el28sd8a9xlXrlRWUDkykcqV+o7G6cSu7R0fOQ3g1bHEYHAgV gcHnkWORvONBPMGIXX3FCw9hUG+CqVBjcgXrWWNUDZhsDGgr18+qAcv0xWQWc2b8YaR+ Vl5g6+Uc7NIH7AJBZvl6ArjDUpRSckcWfYcPjlc2SVkSzLuA/YGFqrmhA1UI/PVspCvF 7nX74I3hEzTM1lmn8MVbQKl/M3IpGWqzefrJdAkjwyyuVCNtGBR4r+xsf5Uxbax5KvGZ OEwA== 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=MUXidifnbmrT+lPICjftrAHoNPFMVQW1b1Sa6v/Ia/k=; fh=A9B0uqHrLOhV8lpdKrDO+2kao9UNQ/xn2a9tcpNN72M=; b=gvhlNK2LCG7Tq0n3lWNxmWpxMYnFOPNkulKxgCoFyi/G9QXVj0CJ7VcqsnVBQnJ/BM 6eJB32FZIsLXm2/m1r1o9Bsh6f3ZHY+SzldST+gryGRG8/OfiZucosTemZVVbiK7GR8i 78+SaK47J1xtuX01RSQvcYdFk6Ke3tJenrULHQqm0l4qL1cGmqi97QmZ8qJxgXXbwpAg z+QzJMKq6x/EYtxAzburQL8AoGglLiDbhjF+54s/oZ8wUCtPc2yJOjQtn5sLesed7U3A +lTivr318ys6URgbybz/99e0ndd8N+Zut4Qb9HK3F3BNr74SPLCA8FXzBXLCJ48vgXse Qmww== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sipsolutions.net header.s=mail header.b=rVyZeHaC; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=sipsolutions.net Received: from lipwig.vger.email (lipwig.vger.email. [23.128.96.33]) by mx.google.com with ESMTPS id h5-20020a654045000000b005b8f1c4aa49si3899624pgp.895.2023.11.24.08.37.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Nov 2023 08:37:43 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) client-ip=23.128.96.33; Authentication-Results: mx.google.com; dkim=pass header.i=@sipsolutions.net header.s=mail header.b=rVyZeHaC; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=sipsolutions.net Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by lipwig.vger.email (Postfix) with ESMTP id 558AF803C947; Fri, 24 Nov 2023 08:36:04 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at lipwig.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1345505AbjKXQfb (ORCPT + 99 others); Fri, 24 Nov 2023 11:35:31 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59986 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231258AbjKXQfQ (ORCPT ); Fri, 24 Nov 2023 11:35:16 -0500 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:242:246e::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4255C19A9; Fri, 24 Nov 2023 08:35:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=MUXidifnbmrT+lPICjftrAHoNPFMVQW1b1Sa6v/Ia/k=; t=1700843722; x=1702053322; b=rVyZeHaCbEZbZ/qU3M0JI/yJBcit7AjwfmuBpVQ/QywYqBU 7pdJrYkha5hv1CKNwS35NhFbYRdXInHXjyT5jF/hbcpyrm8LsWSXWArZc87cMW/BuKUcDRZX0GJoz jU1BymzxgmpUjJDLjKSfSoRCE4xlG7hVRrhXWDbUGiR5N+rf/YLvnSvEhyD02Tb0eW1w5OS5d3qf3 VBEo5vicYBFgAPZGkS9BRWP5AGToNPotZZPLnNV5rJPOCfpGwa+ECmJUgppDTqLXXuZ6VGUw9G8q6 ycvXPpCN8jPrYTtM52HXY+9stPrpWBiVxFojmTuRQZha78XJzzGRNu3Fl4k2d6Yw==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.97) (envelope-from ) id 1r6Z9D-00000002fA8-3DhM; Fri, 24 Nov 2023 17:35:20 +0100 From: Johannes Berg To: linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , "Rafael J. Wysocki" , Johannes Berg Subject: [PATCH v2 6/6] wifi: mac80211: use wiphy locked debugfs for sdata/link Date: Fri, 24 Nov 2023 17:25:29 +0100 Message-ID: <20231124172522.98baff0ebc5e.I99a21601e124f5ac4e161ad32b19949e7896e390@changeid> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231124162522.16344-7-johannes@sipsolutions.net> References: <20231124162522.16344-7-johannes@sipsolutions.net> MIME-Version: 1.0 X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,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 lipwig.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 (lipwig.vger.email [0.0.0.0]); Fri, 24 Nov 2023 08:36:04 -0800 (PST) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1783464055268111773 X-GMAIL-MSGID: 1783464055268111773 From: Johannes Berg The debugfs files for netdevs (sdata) and links are removed with the wiphy mutex held, which may deadlock. Use the new wiphy locked debugfs to avoid that. Signed-off-by: Johannes Berg --- net/mac80211/debugfs_netdev.c | 150 ++++++++++++++++++++++++---------- 1 file changed, 105 insertions(+), 45 deletions(-) diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index ec91e131b29e..80aeb25f1b68 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -22,88 +22,148 @@ #include "debugfs_netdev.h" #include "driver-ops.h" +struct ieee80211_if_read_sdata_data { + ssize_t (*format)(const struct ieee80211_sub_if_data *, char *, int); + struct ieee80211_sub_if_data *sdata; +}; + +static ssize_t ieee80211_if_read_sdata_handler(struct wiphy *wiphy, + struct file *file, + char *buf, + size_t bufsize, + void *data) +{ + struct ieee80211_if_read_sdata_data *d = data; + + return d->format(d->sdata, buf, bufsize); +} + static ssize_t ieee80211_if_read_sdata( - struct ieee80211_sub_if_data *sdata, + struct file *file, char __user *userbuf, size_t count, loff_t *ppos, ssize_t (*format)(const struct ieee80211_sub_if_data *sdata, char *, int)) { + struct ieee80211_sub_if_data *sdata = file->private_data; + struct ieee80211_if_read_sdata_data data = { + .format = format, + .sdata = sdata, + }; char buf[200]; - ssize_t ret = -EINVAL; - wiphy_lock(sdata->local->hw.wiphy); - ret = (*format)(sdata, buf, sizeof(buf)); - wiphy_unlock(sdata->local->hw.wiphy); + return wiphy_locked_debugfs_read(sdata->local->hw.wiphy, + file, buf, sizeof(buf), + userbuf, count, ppos, + ieee80211_if_read_sdata_handler, + &data); +} - if (ret >= 0) - ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret); +struct ieee80211_if_write_sdata_data { + ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int); + struct ieee80211_sub_if_data *sdata; +}; - return ret; +static ssize_t ieee80211_if_write_sdata_handler(struct wiphy *wiphy, + struct file *file, + char *buf, + size_t count, + void *data) +{ + struct ieee80211_if_write_sdata_data *d = data; + + return d->write(d->sdata, buf, count); } static ssize_t ieee80211_if_write_sdata( - struct ieee80211_sub_if_data *sdata, + struct file *file, const char __user *userbuf, size_t count, loff_t *ppos, ssize_t (*write)(struct ieee80211_sub_if_data *sdata, const char *, int)) { + struct ieee80211_sub_if_data *sdata = file->private_data; + struct ieee80211_if_write_sdata_data data = { + .write = write, + .sdata = sdata, + }; char buf[64]; - ssize_t ret; - if (count >= sizeof(buf)) - return -E2BIG; + return wiphy_locked_debugfs_write(sdata->local->hw.wiphy, + file, buf, sizeof(buf), + userbuf, count, + ieee80211_if_write_sdata_handler, + &data); +} - if (copy_from_user(buf, userbuf, count)) - return -EFAULT; - buf[count] = '\0'; +struct ieee80211_if_read_link_data { + ssize_t (*format)(const struct ieee80211_link_data *, char *, int); + struct ieee80211_link_data *link; +}; - wiphy_lock(sdata->local->hw.wiphy); - ret = (*write)(sdata, buf, count); - wiphy_unlock(sdata->local->hw.wiphy); +static ssize_t ieee80211_if_read_link_handler(struct wiphy *wiphy, + struct file *file, + char *buf, + size_t bufsize, + void *data) +{ + struct ieee80211_if_read_link_data *d = data; - return ret; + return d->format(d->link, buf, bufsize); } static ssize_t ieee80211_if_read_link( - struct ieee80211_link_data *link, + struct file *file, char __user *userbuf, size_t count, loff_t *ppos, ssize_t (*format)(const struct ieee80211_link_data *link, char *, int)) { + struct ieee80211_link_data *link = file->private_data; + struct ieee80211_if_read_link_data data = { + .format = format, + .link = link, + }; char buf[200]; - ssize_t ret = -EINVAL; - wiphy_lock(link->sdata->local->hw.wiphy); - ret = (*format)(link, buf, sizeof(buf)); - wiphy_unlock(link->sdata->local->hw.wiphy); + return wiphy_locked_debugfs_read(link->sdata->local->hw.wiphy, + file, buf, sizeof(buf), + userbuf, count, ppos, + ieee80211_if_read_link_handler, + &data); +} - if (ret >= 0) - ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret); +struct ieee80211_if_write_link_data { + ssize_t (*write)(struct ieee80211_link_data *, const char *, int); + struct ieee80211_link_data *link; +}; - return ret; +static ssize_t ieee80211_if_write_link_handler(struct wiphy *wiphy, + struct file *file, + char *buf, + size_t count, + void *data) +{ + struct ieee80211_if_write_sdata_data *d = data; + + return d->write(d->sdata, buf, count); } static ssize_t ieee80211_if_write_link( - struct ieee80211_link_data *link, + struct file *file, const char __user *userbuf, size_t count, loff_t *ppos, ssize_t (*write)(struct ieee80211_link_data *link, const char *, int)) { + struct ieee80211_link_data *link = file->private_data; + struct ieee80211_if_write_link_data data = { + .write = write, + .link = link, + }; char buf[64]; - ssize_t ret; - if (count >= sizeof(buf)) - return -E2BIG; - - if (copy_from_user(buf, userbuf, count)) - return -EFAULT; - buf[count] = '\0'; - - wiphy_lock(link->sdata->local->hw.wiphy); - ret = (*write)(link, buf, count); - wiphy_unlock(link->sdata->local->hw.wiphy); - - return ret; + return wiphy_locked_debugfs_write(link->sdata->local->hw.wiphy, + file, buf, sizeof(buf), + userbuf, count, + ieee80211_if_write_link_handler, + &data); } #define IEEE80211_IF_FMT(name, type, field, format_string) \ @@ -173,7 +233,7 @@ static ssize_t ieee80211_if_read_##name(struct file *file, \ char __user *userbuf, \ size_t count, loff_t *ppos) \ { \ - return ieee80211_if_read_sdata(file->private_data, \ + return ieee80211_if_read_sdata(file, \ userbuf, count, ppos, \ ieee80211_if_fmt_##name); \ } @@ -183,7 +243,7 @@ static ssize_t ieee80211_if_write_##name(struct file *file, \ const char __user *userbuf, \ size_t count, loff_t *ppos) \ { \ - return ieee80211_if_write_sdata(file->private_data, userbuf, \ + return ieee80211_if_write_sdata(file, userbuf, \ count, ppos, \ ieee80211_if_parse_##name); \ } @@ -211,7 +271,7 @@ static ssize_t ieee80211_if_read_##name(struct file *file, \ char __user *userbuf, \ size_t count, loff_t *ppos) \ { \ - return ieee80211_if_read_link(file->private_data, \ + return ieee80211_if_read_link(file, \ userbuf, count, ppos, \ ieee80211_if_fmt_##name); \ } @@ -221,7 +281,7 @@ static ssize_t ieee80211_if_write_##name(struct file *file, \ const char __user *userbuf, \ size_t count, loff_t *ppos) \ { \ - return ieee80211_if_write_link(file->private_data, userbuf, \ + return ieee80211_if_write_link(file, userbuf, \ count, ppos, \ ieee80211_if_parse_##name); \ }