From: Johan Hovold <johan@kernel.org>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
"Rafael J. Wysocki" <rafael@kernel.org>,
Danilo Krummrich <dakr@kernel.org>,
Johan Hovold <johan@kernel.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
Daniel Scally <djrscally@gmail.com>,
Heikki Krogerus <heikki.krogerus@linux.intel.com>,
Sakari Ailus <sakari.ailus@linux.intel.com>,
Bartosz Golaszewski <brgl@kernel.org>,
Andi Shyti <andi.shyti@kernel.org>,
driver-core@lists.linux.dev, linux-acpi@vger.kernel.org,
linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v2 4/8] swnode: ignore primary nodes in device_remove_software_node()
Date: Tue, 10 Nov 2026 09:51:20 +0100 [thread overview]
Message-ID: <20261110085125.2535508-5-johan@kernel.org> (raw)
In-Reply-To: <20261110085125.2535508-1-johan@kernel.org>
device_remove_software_node() should only be used to remove secondary
firmware nodes added by device_add_software_node() but will currently
drop a reference also if a device has a primary software node.
Bail out early if device_remove_software_node() is called for a device
whose primary firmware node is a software node and fix up the two
callers that currently work around this themselves.
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/base/core.c | 3 ++-
drivers/base/platform.c | 9 ++++-----
drivers/base/swnode.c | 3 +++
drivers/i2c/i2c-core-base.c | 9 +++------
include/linux/device.h | 1 +
5 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/drivers/base/core.c b/drivers/base/core.c
index bf97b06337a1..460c7ad1eaeb 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -5212,10 +5212,11 @@ int dev_warn_probe(const struct device *dev, int err, const char *fmt, ...)
}
EXPORT_SYMBOL_GPL(dev_warn_probe);
-static inline bool fwnode_is_primary(struct fwnode_handle *fwnode)
+bool fwnode_is_primary(struct fwnode_handle *fwnode)
{
return fwnode && !IS_ERR(fwnode->secondary);
}
+EXPORT_SYMBOL_GPL(fwnode_is_primary);
/**
* set_primary_fwnode - Change the primary firmware node of a given device.
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index be5d2f315fdb..e0b38dbd5acf 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -598,15 +598,14 @@ static void platform_device_release(struct device *dev)
{
struct platform_object *pa = container_of(dev, struct platform_object,
pdev.dev);
- bool fwnode_is_software_node = is_software_node(dev_fwnode(dev));
device_remove_software_node(dev);
/*
- * If the firmware node is a software node, its reference count
- * was decremented by device_remove_software_node().
+ * Must be done after device_remove_software_node() which may have
+ * freed a secondary firmware node and cleared the fwnode pointer.
*/
- if (!fwnode_is_software_node)
- fwnode_handle_put(pa->pdev.dev.fwnode);
+ fwnode_handle_put(dev->fwnode);
+
kfree(pa->pdev.dev.platform_data);
kfree(pa->pdev.mfd_cell);
kfree(pa->pdev.resource);
diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
index 5dc2029f9a7b..a90c20cb84e6 100644
--- a/drivers/base/swnode.c
+++ b/drivers/base/swnode.c
@@ -1108,6 +1108,9 @@ void device_remove_software_node(struct device *dev)
if (!swnode)
return;
+ if (fwnode_is_primary(&swnode->fwnode))
+ return;
+
if (device_is_registered(dev))
software_node_notify_remove(dev);
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index c55ca14eaad9..af3ae2a83626 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -1056,7 +1056,6 @@ EXPORT_SYMBOL_GPL(i2c_new_client_device);
void i2c_unregister_device(struct i2c_client *client)
{
struct fwnode_handle *fwnode;
- bool fwnode_is_software_node;
if (IS_ERR_OR_NULL(client))
return;
@@ -1067,14 +1066,12 @@ void i2c_unregister_device(struct i2c_client *client)
else if (is_acpi_device_node(fwnode))
acpi_device_clear_enumerated(to_acpi_device_node(fwnode));
- fwnode_is_software_node = is_software_node(fwnode);
device_remove_software_node(&client->dev);
/*
- * If the firmware node is a software node, its reference count
- * was decremented by device_remove_software_node().
+ * Must be done after device_remove_software_node() which may have
+ * freed a secondary firmware node and cleared the fwnode pointer.
*/
- if (!fwnode_is_software_node)
- fwnode_handle_put(fwnode);
+ fwnode_handle_put(client->dev.fwnode);
device_unregister(&client->dev);
}
EXPORT_SYMBOL_GPL(i2c_unregister_device);
diff --git a/include/linux/device.h b/include/linux/device.h
index 6b082c638d45..229a15625766 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -1280,6 +1280,7 @@ int lock_device_hotplug_sysfs(void);
int device_offline(struct device *dev);
int device_online(struct device *dev);
+bool fwnode_is_primary(struct fwnode_handle *fwnode);
void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode);
void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode);
void device_set_node(struct device *dev, struct fwnode_handle *fwnode);
--
2.56.0
next prev parent reply other threads:[~2026-11-10 8:52 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-10 8:51 [PATCH v2 0/8] driver core: platform: fix swnode use-after-free on device release Johan Hovold
2026-11-10 8:51 ` [PATCH v2 1/8] " Johan Hovold
2026-11-10 8:51 ` [PATCH v2 2/8] i2c: core: fix swnode use-after-free on client deregistration Johan Hovold
2026-11-10 10:58 ` Andy Shevchenko
2026-11-10 11:15 ` Johan Hovold
2026-11-10 8:51 ` [PATCH v2 3/8] swnode: fix device_add_of_node() kernel doc Johan Hovold
2026-11-10 10:42 ` Johan Hovold
2026-11-10 11:00 ` Andy Shevchenko
2026-11-10 8:51 ` Johan Hovold [this message]
2026-11-10 11:05 ` [PATCH v2 4/8] swnode: ignore primary nodes in device_remove_software_node() Andy Shevchenko
2026-11-10 8:51 ` [PATCH v2 5/8] driver core: platform: warn on bad fwnode assignment Johan Hovold
2026-11-10 10:47 ` Johan Hovold
2026-11-10 8:51 ` [PATCH v2 6/8] driver core: platform: tests: fix swnode reuse test description Johan Hovold
2026-11-10 8:51 ` [PATCH v2 7/8] swnode: fix software_node_notify() primary node comment Johan Hovold
2026-11-10 8:51 ` [PATCH v2 8/8] device property: fix fwnode_get_next_child_node() comments Johan Hovold
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261110085125.2535508-5-johan@kernel.org \
--to=johan@kernel.org \
--cc=andi.shyti@kernel.org \
--cc=andriy.shevchenko@linux.intel.com \
--cc=brgl@kernel.org \
--cc=dakr@kernel.org \
--cc=djrscally@gmail.com \
--cc=driver-core@lists.linux.dev \
--cc=gregkh@linuxfoundation.org \
--cc=heikki.krogerus@linux.intel.com \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-i2c@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=rafael@kernel.org \
--cc=sakari.ailus@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.