public inbox for stable@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5.15.y 1/3] driver: platform: Add helper for safer setting of driver_override
@ 2023-10-18 12:04 Lee Jones
  2023-10-18 12:04 ` [PATCH v5.15.y 2/3] rpmsg: Constify local variable in field store macro Lee Jones
  2023-10-18 12:04 ` [PATCH v5.15.y 3/3] rpmsg: Fix kfree() of static memory on setting driver_override Lee Jones
  0 siblings, 2 replies; 6+ messages in thread
From: Lee Jones @ 2023-10-18 12:04 UTC (permalink / raw)
  To: lee; +Cc: stable, Krzysztof Kozlowski, Rafael J . Wysocki,
	Greg Kroah-Hartman

From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

commit 6c2f421174273de8f83cde4286d1c076d43a2d35 upstream.

Several core drivers and buses expect that driver_override is a
dynamically allocated memory thus later they can kfree() it.

However such assumption is not documented, there were in the past and
there are already users setting it to a string literal. This leads to
kfree() of static memory during device release (e.g. in error paths or
during unbind):

    kernel BUG at ../mm/slub.c:3960!
    Internal error: Oops - BUG: 0 [#1] PREEMPT SMP ARM
    ...
    (kfree) from [<c058da50>] (platform_device_release+0x88/0xb4)
    (platform_device_release) from [<c0585be0>] (device_release+0x2c/0x90)
    (device_release) from [<c0a69050>] (kobject_put+0xec/0x20c)
    (kobject_put) from [<c0f2f120>] (exynos5_clk_probe+0x154/0x18c)
    (exynos5_clk_probe) from [<c058de70>] (platform_drv_probe+0x6c/0xa4)
    (platform_drv_probe) from [<c058b7ac>] (really_probe+0x280/0x414)
    (really_probe) from [<c058baf4>] (driver_probe_device+0x78/0x1c4)
    (driver_probe_device) from [<c0589854>] (bus_for_each_drv+0x74/0xb8)
    (bus_for_each_drv) from [<c058b48c>] (__device_attach+0xd4/0x16c)
    (__device_attach) from [<c058a638>] (bus_probe_device+0x88/0x90)
    (bus_probe_device) from [<c05871fc>] (device_add+0x3dc/0x62c)
    (device_add) from [<c075ff10>] (of_platform_device_create_pdata+0x94/0xbc)
    (of_platform_device_create_pdata) from [<c07600ec>] (of_platform_bus_create+0x1a8/0x4fc)
    (of_platform_bus_create) from [<c0760150>] (of_platform_bus_create+0x20c/0x4fc)
    (of_platform_bus_create) from [<c07605f0>] (of_platform_populate+0x84/0x118)
    (of_platform_populate) from [<c0f3c964>] (of_platform_default_populate_init+0xa0/0xb8)
    (of_platform_default_populate_init) from [<c01031f8>] (do_one_initcall+0x8c/0x404)

Provide a helper which clearly documents the usage of driver_override.
This will allow later to reuse the helper and reduce the amount of
duplicated code.

Convert the platform driver to use a new helper and make the
driver_override field const char (it is not modified by the core).

Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Link: https://lore.kernel.org/r/20220419113435.246203-2-krzysztof.kozlowski@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Lee Jones <lee@kernel.org>
---
 drivers/base/driver.c           | 69 +++++++++++++++++++++++++++++++++
 drivers/base/platform.c         | 28 ++-----------
 include/linux/device/driver.h   |  2 +
 include/linux/platform_device.h |  6 ++-
 4 files changed, 80 insertions(+), 25 deletions(-)

diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 8c0d33e182fd5..1b9d47b10bd0a 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -30,6 +30,75 @@ static struct device *next_device(struct klist_iter *i)
 	return dev;
 }
 
+/**
+ * driver_set_override() - Helper to set or clear driver override.
+ * @dev: Device to change
+ * @override: Address of string to change (e.g. &device->driver_override);
+ *            The contents will be freed and hold newly allocated override.
+ * @s: NUL-terminated string, new driver name to force a match, pass empty
+ *     string to clear it ("" or "\n", where the latter is only for sysfs
+ *     interface).
+ * @len: length of @s
+ *
+ * Helper to set or clear driver override in a device, intended for the cases
+ * when the driver_override field is allocated by driver/bus code.
+ *
+ * Returns: 0 on success or a negative error code on failure.
+ */
+int driver_set_override(struct device *dev, const char **override,
+			const char *s, size_t len)
+{
+	const char *new, *old;
+	char *cp;
+
+	if (!override || !s)
+		return -EINVAL;
+
+	/*
+	 * The stored value will be used in sysfs show callback (sysfs_emit()),
+	 * which has a length limit of PAGE_SIZE and adds a trailing newline.
+	 * Thus we can store one character less to avoid truncation during sysfs
+	 * show.
+	 */
+	if (len >= (PAGE_SIZE - 1))
+		return -EINVAL;
+
+	if (!len) {
+		/* Empty string passed - clear override */
+		device_lock(dev);
+		old = *override;
+		*override = NULL;
+		device_unlock(dev);
+		kfree(old);
+
+		return 0;
+	}
+
+	cp = strnchr(s, len, '\n');
+	if (cp)
+		len = cp - s;
+
+	new = kstrndup(s, len, GFP_KERNEL);
+	if (!new)
+		return -ENOMEM;
+
+	device_lock(dev);
+	old = *override;
+	if (cp != s) {
+		*override = new;
+	} else {
+		/* "\n" passed - clear override */
+		kfree(new);
+		*override = NULL;
+	}
+	device_unlock(dev);
+
+	kfree(old);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(driver_set_override);
+
 /**
  * driver_for_each_device - Iterator for devices bound to a driver.
  * @drv: Driver we're iterating.
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index ac5cf1a8d79ab..596fbe6b701a5 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -1270,31 +1270,11 @@ static ssize_t driver_override_store(struct device *dev,
 				     const char *buf, size_t count)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	char *driver_override, *old, *cp;
-
-	/* We need to keep extra room for a newline */
-	if (count >= (PAGE_SIZE - 1))
-		return -EINVAL;
-
-	driver_override = kstrndup(buf, count, GFP_KERNEL);
-	if (!driver_override)
-		return -ENOMEM;
-
-	cp = strchr(driver_override, '\n');
-	if (cp)
-		*cp = '\0';
-
-	device_lock(dev);
-	old = pdev->driver_override;
-	if (strlen(driver_override)) {
-		pdev->driver_override = driver_override;
-	} else {
-		kfree(driver_override);
-		pdev->driver_override = NULL;
-	}
-	device_unlock(dev);
+	int ret;
 
-	kfree(old);
+	ret = driver_set_override(dev, &pdev->driver_override, buf, count);
+	if (ret)
+		return ret;
 
 	return count;
 }
diff --git a/include/linux/device/driver.h b/include/linux/device/driver.h
index a498ebcf49933..abf948e102f5d 100644
--- a/include/linux/device/driver.h
+++ b/include/linux/device/driver.h
@@ -150,6 +150,8 @@ extern int __must_check driver_create_file(struct device_driver *driver,
 extern void driver_remove_file(struct device_driver *driver,
 			       const struct driver_attribute *attr);
 
+int driver_set_override(struct device *dev, const char **override,
+			const char *s, size_t len);
 extern int __must_check driver_for_each_device(struct device_driver *drv,
 					       struct device *start,
 					       void *data,
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 8aefdc0099c86..72cf70857b85f 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -31,7 +31,11 @@ struct platform_device {
 	struct resource	*resource;
 
 	const struct platform_device_id	*id_entry;
-	char *driver_override; /* Driver name to force a match */
+	/*
+	 * Driver name to force a match.  Do not set directly, because core
+	 * frees it.  Use driver_set_override() to set or clear it.
+	 */
+	const char *driver_override;
 
 	/* MFD cell pointer */
 	struct mfd_cell *mfd_cell;
-- 
2.42.0.655.g421f12c284-goog


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v5.15.y 2/3] rpmsg: Constify local variable in field store macro
  2023-10-18 12:04 [PATCH v5.15.y 1/3] driver: platform: Add helper for safer setting of driver_override Lee Jones
@ 2023-10-18 12:04 ` Lee Jones
  2023-10-18 12:04 ` [PATCH v5.15.y 3/3] rpmsg: Fix kfree() of static memory on setting driver_override Lee Jones
  1 sibling, 0 replies; 6+ messages in thread
From: Lee Jones @ 2023-10-18 12:04 UTC (permalink / raw)
  To: lee; +Cc: stable, Krzysztof Kozlowski, Greg Kroah-Hartman

From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

commit e5f89131a06142e91073b6959d91cea73861d40e upstream.

Memory pointed by variable 'old' in field store macro is not modified,
so it can be made a pointer to const.

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Link: https://lore.kernel.org/r/20220419113435.246203-12-krzysztof.kozlowski@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Lee Jones <lee@kernel.org>
---
 drivers/rpmsg/rpmsg_core.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index a71de08acc7b9..c544dee0b5dd9 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -376,7 +376,8 @@ field##_store(struct device *dev, struct device_attribute *attr,	\
 	      const char *buf, size_t sz)				\
 {									\
 	struct rpmsg_device *rpdev = to_rpmsg_device(dev);		\
-	char *new, *old;						\
+	const char *old;						\
+	char *new;							\
 									\
 	new = kstrndup(buf, sz, GFP_KERNEL);				\
 	if (!new)							\
-- 
2.42.0.655.g421f12c284-goog


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v5.15.y 3/3] rpmsg: Fix kfree() of static memory on setting driver_override
  2023-10-18 12:04 [PATCH v5.15.y 1/3] driver: platform: Add helper for safer setting of driver_override Lee Jones
  2023-10-18 12:04 ` [PATCH v5.15.y 2/3] rpmsg: Constify local variable in field store macro Lee Jones
@ 2023-10-18 12:04 ` Lee Jones
  2023-10-23  8:55   ` Greg Kroah-Hartman
  1 sibling, 1 reply; 6+ messages in thread
From: Lee Jones @ 2023-10-18 12:04 UTC (permalink / raw)
  To: lee; +Cc: stable, Krzysztof Kozlowski, Bjorn Andersson, Greg Kroah-Hartman

From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

commit 42cd402b8fd4672b692400fe5f9eecd55d2794ac upstream.

The driver_override field from platform driver should not be initialized
from static memory (string literal) because the core later kfree() it,
for example when driver_override is set via sysfs.

Use dedicated helper to set driver_override properly.

Fixes: 950a7388f02b ("rpmsg: Turn name service into a stand alone driver")
Fixes: c0cdc19f84a4 ("rpmsg: Driver for user space endpoint interface")
Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Link: https://lore.kernel.org/r/20220419113435.246203-13-krzysztof.kozlowski@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Lee Jones <lee@kernel.org>
---
 drivers/rpmsg/rpmsg_internal.h | 13 +++++++++++--
 include/linux/rpmsg.h          |  6 ++++--
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
index a76c344253bf5..5f4f3691bbf1e 100644
--- a/drivers/rpmsg/rpmsg_internal.h
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -90,10 +90,19 @@ int rpmsg_release_channel(struct rpmsg_device *rpdev,
  */
 static inline int rpmsg_chrdev_register_device(struct rpmsg_device *rpdev)
 {
+	int ret;
+
 	strcpy(rpdev->id.name, "rpmsg_chrdev");
-	rpdev->driver_override = "rpmsg_chrdev";
+	ret = driver_set_override(&rpdev->dev, &rpdev->driver_override,
+				  rpdev->id.name, strlen(rpdev->id.name));
+	if (ret)
+		return ret;
+
+	ret = rpmsg_register_device(rpdev);
+	if (ret)
+		kfree(rpdev->driver_override);
 
-	return rpmsg_register_device(rpdev);
+	return ret;
 }
 
 #endif
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index a8dcf8a9ae885..1b7294cefb807 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -41,7 +41,9 @@ struct rpmsg_channel_info {
  * rpmsg_device - device that belong to the rpmsg bus
  * @dev: the device struct
  * @id: device id (used to match between rpmsg drivers and devices)
- * @driver_override: driver name to force a match
+ * @driver_override: driver name to force a match; do not set directly,
+ *                   because core frees it; use driver_set_override() to
+ *                   set or clear it.
  * @src: local address
  * @dst: destination address
  * @ept: the rpmsg endpoint of this channel
@@ -51,7 +53,7 @@ struct rpmsg_channel_info {
 struct rpmsg_device {
 	struct device dev;
 	struct rpmsg_device_id id;
-	char *driver_override;
+	const char *driver_override;
 	u32 src;
 	u32 dst;
 	struct rpmsg_endpoint *ept;
-- 
2.42.0.655.g421f12c284-goog


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v5.15.y 3/3] rpmsg: Fix kfree() of static memory on setting driver_override
  2023-10-18 12:04 ` [PATCH v5.15.y 3/3] rpmsg: Fix kfree() of static memory on setting driver_override Lee Jones
@ 2023-10-23  8:55   ` Greg Kroah-Hartman
  2023-10-23  9:39     ` Lee Jones
  0 siblings, 1 reply; 6+ messages in thread
From: Greg Kroah-Hartman @ 2023-10-23  8:55 UTC (permalink / raw)
  To: Lee Jones; +Cc: stable, Krzysztof Kozlowski, Bjorn Andersson

On Wed, Oct 18, 2023 at 01:04:34PM +0100, Lee Jones wrote:
> From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> 
> commit 42cd402b8fd4672b692400fe5f9eecd55d2794ac upstream.
> 
> The driver_override field from platform driver should not be initialized
> from static memory (string literal) because the core later kfree() it,
> for example when driver_override is set via sysfs.
> 
> Use dedicated helper to set driver_override properly.
> 
> Fixes: 950a7388f02b ("rpmsg: Turn name service into a stand alone driver")
> Fixes: c0cdc19f84a4 ("rpmsg: Driver for user space endpoint interface")
> Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> Link: https://lore.kernel.org/r/20220419113435.246203-13-krzysztof.kozlowski@linaro.org
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Lee Jones <lee@kernel.org>
> ---
>  drivers/rpmsg/rpmsg_internal.h | 13 +++++++++++--
>  include/linux/rpmsg.h          |  6 ++++--
>  2 files changed, 15 insertions(+), 4 deletions(-)

Any specific reason why you missed the fixes for this commit as well?
Turned out to need some more things after this :(

Why are these needed at all for the stable kernels anyway?  It's good to
have in the tree, but who is using manual overrides for the rpmsg driver
in the first place?

I'm going to drop all of these from the stable queues now and wait for a
fixed up set of patches with a good reason to justify their existence in
the stable trees.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v5.15.y 3/3] rpmsg: Fix kfree() of static memory on setting driver_override
  2023-10-23  8:55   ` Greg Kroah-Hartman
@ 2023-10-23  9:39     ` Lee Jones
  2023-10-23  9:53       ` Greg Kroah-Hartman
  0 siblings, 1 reply; 6+ messages in thread
From: Lee Jones @ 2023-10-23  9:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: stable, Krzysztof Kozlowski, Bjorn Andersson

On Mon, 23 Oct 2023, Greg Kroah-Hartman wrote:

> On Wed, Oct 18, 2023 at 01:04:34PM +0100, Lee Jones wrote:
> > From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> > 
> > commit 42cd402b8fd4672b692400fe5f9eecd55d2794ac upstream.
> > 
> > The driver_override field from platform driver should not be initialized
> > from static memory (string literal) because the core later kfree() it,
> > for example when driver_override is set via sysfs.
> > 
> > Use dedicated helper to set driver_override properly.
> > 
> > Fixes: 950a7388f02b ("rpmsg: Turn name service into a stand alone driver")
> > Fixes: c0cdc19f84a4 ("rpmsg: Driver for user space endpoint interface")
> > Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> > Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> > Link: https://lore.kernel.org/r/20220419113435.246203-13-krzysztof.kozlowski@linaro.org
> > Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > Signed-off-by: Lee Jones <lee@kernel.org>
> > ---
> >  drivers/rpmsg/rpmsg_internal.h | 13 +++++++++++--
> >  include/linux/rpmsg.h          |  6 ++++--
> >  2 files changed, 15 insertions(+), 4 deletions(-)
> 
> Any specific reason why you missed the fixes for this commit as well?
> Turned out to need some more things after this :(

No reason not to.  I didn't notice them.

> Why are these needed at all for the stable kernels anyway?  It's good to
> have in the tree, but who is using manual overrides for the rpmsg driver
> in the first place?

UAF.

> I'm going to drop all of these from the stable queues now and wait for a
> fixed up set of patches with a good reason to justify their existence in
> the stable trees.

As per our SOP, I'd like to avoid spelling it out.

Ping me for details if you really want to know.

Which patches have you dropped?  Just these 3 or all branches?

-- 
Lee Jones [李琼斯]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v5.15.y 3/3] rpmsg: Fix kfree() of static memory on setting driver_override
  2023-10-23  9:39     ` Lee Jones
@ 2023-10-23  9:53       ` Greg Kroah-Hartman
  0 siblings, 0 replies; 6+ messages in thread
From: Greg Kroah-Hartman @ 2023-10-23  9:53 UTC (permalink / raw)
  To: Lee Jones; +Cc: stable, Krzysztof Kozlowski, Bjorn Andersson

On Mon, Oct 23, 2023 at 10:39:03AM +0100, Lee Jones wrote:
> On Mon, 23 Oct 2023, Greg Kroah-Hartman wrote:
> 
> > On Wed, Oct 18, 2023 at 01:04:34PM +0100, Lee Jones wrote:
> > > From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> > > 
> > > commit 42cd402b8fd4672b692400fe5f9eecd55d2794ac upstream.
> > > 
> > > The driver_override field from platform driver should not be initialized
> > > from static memory (string literal) because the core later kfree() it,
> > > for example when driver_override is set via sysfs.
> > > 
> > > Use dedicated helper to set driver_override properly.
> > > 
> > > Fixes: 950a7388f02b ("rpmsg: Turn name service into a stand alone driver")
> > > Fixes: c0cdc19f84a4 ("rpmsg: Driver for user space endpoint interface")
> > > Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> > > Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> > > Link: https://lore.kernel.org/r/20220419113435.246203-13-krzysztof.kozlowski@linaro.org
> > > Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > > Signed-off-by: Lee Jones <lee@kernel.org>
> > > ---
> > >  drivers/rpmsg/rpmsg_internal.h | 13 +++++++++++--
> > >  include/linux/rpmsg.h          |  6 ++++--
> > >  2 files changed, 15 insertions(+), 4 deletions(-)
> > 
> > Any specific reason why you missed the fixes for this commit as well?
> > Turned out to need some more things after this :(
> 
> No reason not to.  I didn't notice them.

fixes for fixes are important :)

> Which patches have you dropped?  Just these 3 or all branches?

All branches.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2023-10-23  9:53 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-10-18 12:04 [PATCH v5.15.y 1/3] driver: platform: Add helper for safer setting of driver_override Lee Jones
2023-10-18 12:04 ` [PATCH v5.15.y 2/3] rpmsg: Constify local variable in field store macro Lee Jones
2023-10-18 12:04 ` [PATCH v5.15.y 3/3] rpmsg: Fix kfree() of static memory on setting driver_override Lee Jones
2023-10-23  8:55   ` Greg Kroah-Hartman
2023-10-23  9:39     ` Lee Jones
2023-10-23  9:53       ` Greg Kroah-Hartman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox