Thread (3 messages) read the whole thread 3 messages, 1 author, 1d ago
WARM1d

[PATCH net v2 1/2] nfc: reject SE I/O while a device is shutting down

From: Fan Wu <hidden>
Date: 2026-07-31 02:45:00
Also in: lkml, oe-linux-nfc, stable
Subsystem: networking [general], nfc subsystem, the rest · Maintainers: "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, David Heidelberg, Linus Torvalds

nfc_se_io() is the only secure-element entry point that does not check
dev->shutting_down: nfc_enable_se(), nfc_disable_se(), nfc_dev_up(),
nfc_dev_down() and nfc_start_poll() all reject new operations once
nfc_unregister_rfkill() has set the flag under the device lock.

An NFC_CMD_SE_IO request racing device removal can therefore still reach a
driver's se_io op after teardown has begun, arming driver state (for
example a timer) that the driver's later drain cannot account for.  Add
the same shutting_down check the other SE operations already perform; the
existing error path frees the freshly allocated se_io_ctx.

This also adds an optional nci_ops::pre_unregister hook, called in
nci_unregister_device() right after nfc_unregister_rfkill() (the admission
barrier is up, so new operations are rejected) and before
nci_close_device()/destroy_workqueue() (the NCI core and its workqueues
still exist).  An NCI driver whose teardown helper touches the NCI core can
use it to drain driver-owned state at the correct point.  The hook is
optional; nci_ops initialisers that leave it NULL are unaffected.

This follows the barrier-first teardown ordering from d2492688bb9f.

Cc: stable@vger.kernel.org # 6.6+
Signed-off-by: Fan Wu <redacted>
---

 include/net/nfc/nci_core.h | 1 +
 net/nfc/nci/core.c         | 3 +++
 net/nfc/netlink.c          | 5 +++++
 3 files changed, 9 insertions(+)
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index 664d5058e..754a67185 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -82,6 +82,7 @@ struct nci_ops {
 				    struct sk_buff *skb);
 	void  (*hci_cmd_received)(struct nci_dev *ndev, u8 pipe, u8 cmd,
 				  struct sk_buff *skb);
+	void  (*pre_unregister)(struct nci_dev *ndev);
 
 	const struct nci_driver_ops *prop_ops;
 	size_t n_prop_ops;
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 5f46c4b57..86286c076 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -1321,6 +1321,9 @@ void nci_unregister_device(struct nci_dev *ndev)
 
 	nfc_unregister_rfkill(ndev->nfc_dev);
 
+	if (ndev->ops->pre_unregister)
+		ndev->ops->pre_unregister(ndev);
+
 	/* This set_bit is not protected with specialized barrier,
 	 * However, it is fine because the mutex_lock(&ndev->req_lock);
 	 * in nci_close_device() will help to emit one.
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index 0c58824cb..3132f7a90 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -1426,6 +1426,11 @@ static int nfc_se_io(struct nfc_dev *dev, u32 se_idx,
 
 	device_lock(&dev->dev);
 
+	if (dev->shutting_down) {
+		rc = -ENODEV;
+		goto error;
+	}
+
 	if (!device_is_registered(&dev->dev)) {
 		rc = -ENODEV;
 		goto error;
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help