--- /dev/null
+From stable-owner@vger.kernel.org Wed Oct 18 14:04:56 2023
+From: Lee Jones <lee@kernel.org>
+Date: Wed, 18 Oct 2023 13:04:32 +0100
+Subject: driver: platform: Add helper for safer setting of driver_override
+To: lee@kernel.org
+Cc: stable@vger.kernel.org, Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>, "Rafael J . Wysocki" <rafael.j.wysocki@intel.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Message-ID: <20231018120441.2110004-1-lee@kernel.org>
+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.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(-)
+
+--- a/drivers/base/driver.c
++++ b/drivers/base/driver.c
+@@ -31,6 +31,75 @@ static struct device *next_device(struct
+ }
+
+ /**
++ * 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.
+ * @start: Device to begin with
+--- a/drivers/base/platform.c
++++ b/drivers/base/platform.c
+@@ -1270,31 +1270,11 @@ static ssize_t driver_override_store(str
+ const char *buf, size_t count)
+ {
+ struct platform_device *pdev = to_platform_device(dev);
+- char *driver_override, *old, *cp;
++ int ret;
+
+- /* 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);
+-
+- kfree(old);
++ ret = driver_set_override(dev, &pdev->driver_override, buf, count);
++ if (ret)
++ return ret;
+
+ return count;
+ }
+--- a/include/linux/device/driver.h
++++ b/include/linux/device/driver.h
+@@ -150,6 +150,8 @@ extern int __must_check driver_create_fi
+ 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,
+--- 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;
--- /dev/null
+From stable-owner@vger.kernel.org Wed Oct 18 14:04:56 2023
+From: Lee Jones <lee@kernel.org>
+Date: Wed, 18 Oct 2023 13:04:33 +0100
+Subject: rpmsg: Constify local variable in field store macro
+To: lee@kernel.org
+Cc: stable@vger.kernel.org, Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Message-ID: <20231018120441.2110004-2-lee@kernel.org>
+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/rpmsg/rpmsg_core.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/rpmsg/rpmsg_core.c
++++ b/drivers/rpmsg/rpmsg_core.c
+@@ -376,7 +376,8 @@ field##_store(struct device *dev, struct
+ 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) \
--- /dev/null
+From stable-owner@vger.kernel.org Wed Oct 18 14:04:57 2023
+From: Lee Jones <lee@kernel.org>
+Date: Wed, 18 Oct 2023 13:04:34 +0100
+Subject: rpmsg: Fix kfree() of static memory on setting driver_override
+To: lee@kernel.org
+Cc: stable@vger.kernel.org, Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>, Bjorn Andersson <bjorn.andersson@linaro.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Message-ID: <20231018120441.2110004-3-lee@kernel.org>
+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/rpmsg/rpmsg_internal.h | 13 +++++++++++--
+ include/linux/rpmsg.h | 6 ++++--
+ 2 files changed, 15 insertions(+), 4 deletions(-)
+
+--- a/drivers/rpmsg/rpmsg_internal.h
++++ b/drivers/rpmsg/rpmsg_internal.h
+@@ -90,10 +90,19 @@ int rpmsg_release_channel(struct rpmsg_d
+ */
+ 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
+--- 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;
lib-kconfig.debug-do-not-enable-debug_preempt-by-default.patch
documentation-sysctl-align-cells-in-second-content-column.patch
+xfs-don-t-expose-internal-symlink-metadata-buffers-to-the-vfs.patch
+driver-platform-add-helper-for-safer-setting-of-driver_override.patch
+rpmsg-constify-local-variable-in-field-store-macro.patch
+rpmsg-fix-kfree-of-static-memory-on-setting-driver_override.patch
--- /dev/null
+From 7b7820b83f230036fc48c3e7fb280c48c58adebf Mon Sep 17 00:00:00 2001
+From: "Darrick J. Wong" <djwong@kernel.org>
+Date: Wed, 15 Dec 2021 12:07:41 -0800
+Subject: xfs: don't expose internal symlink metadata buffers to the vfs
+
+From: Darrick J. Wong <djwong@kernel.org>
+
+commit 7b7820b83f230036fc48c3e7fb280c48c58adebf upstream.
+
+Ian Kent reported that for inline symlinks, it's possible for
+vfs_readlink to hang on to the target buffer returned by
+_vn_get_link_inline long after it's been freed by xfs inode reclaim.
+This is a layering violation -- we should never expose XFS internals to
+the VFS.
+
+When the symlink has a remote target, we allocate a separate buffer,
+copy the internal information, and let the VFS manage the new buffer's
+lifetime. Let's adapt the inline code paths to do this too. It's
+less efficient, but fixes the layering violation and avoids the need to
+adapt the if_data lifetime to rcu rules. Clearly I don't care about
+readlink benchmarks.
+
+As a side note, this fixes the minor locking violation where we can
+access the inode data fork without taking any locks; proper locking (and
+eliminating the possibility of having to switch inode_operations on a
+live inode) is essential to online repair coordinating repairs
+correctly.
+
+Reported-by: Ian Kent <raven@themaw.net>
+Signed-off-by: Darrick J. Wong <djwong@kernel.org>
+Reviewed-by: Dave Chinner <dchinner@redhat.com>
+Tested-by: Chandan Babu R <chandanbabu@kernel.org>
+Acked-by: Leah Rumancik <leah.rumancik@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_iops.c | 34 +---------------------------------
+ fs/xfs/xfs_symlink.c | 29 +++++++++++++++++++----------
+ 2 files changed, 20 insertions(+), 43 deletions(-)
+
+--- a/fs/xfs/xfs_iops.c
++++ b/fs/xfs/xfs_iops.c
+@@ -511,27 +511,6 @@ xfs_vn_get_link(
+ return ERR_PTR(error);
+ }
+
+-STATIC const char *
+-xfs_vn_get_link_inline(
+- struct dentry *dentry,
+- struct inode *inode,
+- struct delayed_call *done)
+-{
+- struct xfs_inode *ip = XFS_I(inode);
+- char *link;
+-
+- ASSERT(ip->i_df.if_format == XFS_DINODE_FMT_LOCAL);
+-
+- /*
+- * The VFS crashes on a NULL pointer, so return -EFSCORRUPTED if
+- * if_data is junk.
+- */
+- link = ip->i_df.if_u1.if_data;
+- if (XFS_IS_CORRUPT(ip->i_mount, !link))
+- return ERR_PTR(-EFSCORRUPTED);
+- return link;
+-}
+-
+ static uint32_t
+ xfs_stat_blksize(
+ struct xfs_inode *ip)
+@@ -1200,14 +1179,6 @@ static const struct inode_operations xfs
+ .update_time = xfs_vn_update_time,
+ };
+
+-static const struct inode_operations xfs_inline_symlink_inode_operations = {
+- .get_link = xfs_vn_get_link_inline,
+- .getattr = xfs_vn_getattr,
+- .setattr = xfs_vn_setattr,
+- .listxattr = xfs_vn_listxattr,
+- .update_time = xfs_vn_update_time,
+-};
+-
+ /* Figure out if this file actually supports DAX. */
+ static bool
+ xfs_inode_supports_dax(
+@@ -1358,10 +1329,7 @@ xfs_setup_iops(
+ inode->i_fop = &xfs_dir_file_operations;
+ break;
+ case S_IFLNK:
+- if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL)
+- inode->i_op = &xfs_inline_symlink_inode_operations;
+- else
+- inode->i_op = &xfs_symlink_inode_operations;
++ inode->i_op = &xfs_symlink_inode_operations;
+ break;
+ default:
+ inode->i_op = &xfs_inode_operations;
+--- a/fs/xfs/xfs_symlink.c
++++ b/fs/xfs/xfs_symlink.c
+@@ -22,6 +22,7 @@
+ #include "xfs_trace.h"
+ #include "xfs_trans.h"
+ #include "xfs_ialloc.h"
++#include "xfs_error.h"
+
+ /* ----- Kernel only functions below ----- */
+ int
+@@ -96,17 +97,15 @@ xfs_readlink_bmap_ilocked(
+
+ int
+ xfs_readlink(
+- struct xfs_inode *ip,
+- char *link)
++ struct xfs_inode *ip,
++ char *link)
+ {
+- struct xfs_mount *mp = ip->i_mount;
+- xfs_fsize_t pathlen;
+- int error = 0;
++ struct xfs_mount *mp = ip->i_mount;
++ xfs_fsize_t pathlen;
++ int error = -EFSCORRUPTED;
+
+ trace_xfs_readlink(ip);
+
+- ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_LOCAL);
+-
+ if (xfs_is_shutdown(mp))
+ return -EIO;
+
+@@ -121,12 +120,22 @@ xfs_readlink(
+ __func__, (unsigned long long) ip->i_ino,
+ (long long) pathlen);
+ ASSERT(0);
+- error = -EFSCORRUPTED;
+ goto out;
+ }
+
+-
+- error = xfs_readlink_bmap_ilocked(ip, link);
++ if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
++ /*
++ * The VFS crashes on a NULL pointer, so return -EFSCORRUPTED
++ * if if_data is junk.
++ */
++ if (XFS_IS_CORRUPT(ip->i_mount, !ip->i_df.if_u1.if_data))
++ goto out;
++
++ memcpy(link, ip->i_df.if_u1.if_data, pathlen + 1);
++ error = 0;
++ } else {
++ error = xfs_readlink_bmap_ilocked(ip, link);
++ }
+
+ out:
+ xfs_iunlock(ip, XFS_ILOCK_SHARED);