5.10.270-rc1 review
Subsystems (2)
Greg Kroah-Hartman
maintainerPATCH 412/798 usb: gadget: configfs: fix out-of-bounds read of qw_sign
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
[ Upstream commit f63edb54d8f738f9c21e2068c777ae1c097df6b7 ]
os_desc_qw_sign_show() passes OS_STRING_QW_SIGN_LEN as the input length to utf16s_to_utf8s(), but that argument counts UTF-16 code units while OS_STRING_QW_SIGN_LEN (14) is the byte size of qw_sign[]. The array holds only OS_STRING_QW_SIGN_LEN / 2 (7) code units, so the conversion reads up to 7 units (14 bytes) past the end of qw_sign[] into the following members of struct gadget_info when the stored signature fills the array without a NUL terminator, exposing those bytes through the configfs attribute.
The store path halves the count for its input bound but passes the full byte count as the utf8s_to_utf16s() output limit; use the destination code-unit count in both directions.
--- drivers/usb/gadget/configfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/gadget/configfs.c +2 -2
@@ -842,7 +842,7 @@ static ssize_t os_desc_qw_sign_show(struct config_item *item, char *page)struct gadget_info *gi =os_desc_item_to_gadget_info (item);int res; - res =utf16s_to_utf8s ((wchar_t *) gi->qw_sign,OS_STRING_QW_SIGN_LEN , + res =utf16s_to_utf8s ((wchar_t *) gi->qw_sign,OS_STRING_QW_SIGN_LEN /2 ,UTF16_LITTLE_ENDIAN , page,PAGE_SIZE -1 ); page[res++] ='\n' ;
@@ -864,7 +864,7 @@ static ssize_t os_desc_qw_sign_store(struct config_item *item, const char *page,mutex_lock (&gi->lock); res =utf8s_to_utf16s (page, l,UTF16_LITTLE_ENDIAN , (wchar_t *) gi->qw_sign, -OS_STRING_QW_SIGN_LEN ); +OS_STRING_QW_SIGN_LEN /2 );if (res >0 ) res = len;mutex_unlock (&gi->lock);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 413/798 driver core: platform: reorder functions
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uwe Kleine-König <[email protected]>
[ Upstream commit e21d740a3fe5ad2db7b5f5c2331fe2b713b1edba ]
This way all callbacks and structures used to initialize platform_bus_type are defined just before platform_bus_type and in the same order. Also move platform_drv_probe_fail just before it's only user.
Stable-dep-of: 589b9e6f96be ("usb: renesas_usbhs: Fix power-off ordering on unbind")
--- drivers/base/platform.c | 293 ++++++++++++++++++++-------------------- 1 file changed, 147 insertions(+), 146 deletions(-)
drivers/base/platform.c +147 -146
@@ -772,11 +772,6 @@ static int platform_drv_probe(struct device *_dev)return ret; } -static int platform_drv_probe_fail (struct device *_dev) -{ -return -ENXIO ; -} -static int platform_drv_remove (struct device *_dev) {struct platform_driver *drv =to_platform_driver (_dev->driver);
@@ -827,6 +822,11 @@ void platform_driver_unregister(struct platform_driver *drv) }EXPORT_SYMBOL_GPL (platform_driver_unregister); +static int platform_drv_probe_fail (struct device *_dev) +{ +return -ENXIO ; +} +/** * __platform_driver_probe - register driver for non-hotpluggable device * @drv: platform driver structure
@@ -1017,109 +1017,6 @@ void platform_unregister_drivers(struct platform_driver * const *drivers, }EXPORT_SYMBOL_GPL (platform_unregister_drivers); -/* modalias support enables more hands-off userspace setup: -* (a) environment variable lets new-style hotplug events work once system is -* fully running: "modprobe $MODALIAS" -* (b) sysfs attribute lets new-style coldplug recover from hotplug events -* mishandled before system is fully running: "modprobe $(cat modalias)" -*/ -static ssize_t modalias_show (struct device *dev, -struct device_attribute *attr,char *buf) -{ -struct platform_device *pdev =to_platform_device (dev); -int len; - - len =of_device_modalias (dev, buf,PAGE_SIZE ); -if (len != -ENODEV ) -return len; - - len =acpi_device_modalias (dev, buf,PAGE_SIZE -1 ); -if (len != -ENODEV ) -return len; - -return sysfs_emit (buf,"platform:%s\n" , pdev->name); -} -static DEVICE_ATTR_RO (modalias); - -static ssize_t driver_override_store (struct device *dev, -struct device_attribute *attr, -const char *buf,size_t count) -{ -struct platform_device *pdev =to_platform_device (dev); -int ret; - - ret =driver_set_override (dev, &pdev->driver_override, buf, count); -if (ret) -return ret; - -return count; -} - -static ssize_t driver_override_show (struct device *dev, -struct device_attribute *attr,char *buf) -{ -struct platform_device *pdev =to_platform_device (dev); -ssize_t len; - -device_lock (dev); - len =sysfs_emit (buf,"%s\n" , pdev->driver_override); -device_unlock (dev); - -return len; -} -static DEVICE_ATTR_RW (driver_override); - -static ssize_t numa_node_show (struct device *dev, -struct device_attribute *attr,char *buf) -{ -return sysfs_emit (buf,"%d\n" ,dev_to_node (dev)); -} -static DEVICE_ATTR_RO (numa_node); - -static umode_t platform_dev_attrs_visible (struct kobject *kobj,struct attribute *a, -int n) -{ -struct device *dev =container_of (kobj,typeof (*dev), kobj); - -if (a == &dev_attr_numa_node.attr && -dev_to_node (dev) ==NUMA_NO_NODE ) -return 0 ; - -return a->mode; -} - -static struct attribute *platform_dev_attrs[] = { - &dev_attr_modalias.attr, - &dev_attr_numa_node.attr, - &dev_attr_driver_override.attr, -NULL , -}; - -static struct attribute_group platform_dev_group = { - .attrs = platform_dev_attrs, - .is_visible = platform_dev_attrs_visible, -}; -__ATTRIBUTE_GROUPS (platform_dev); - -static int platform_uevent (struct device *dev,struct kobj_uevent_env *env) -{ -struct platform_device *pdev =to_platform_device (dev); -int rc; - -/* Some devices have extra OF data and an OF-style MODALIAS */ - rc =of_device_uevent_modalias (dev, env); -if (rc != -ENODEV ) -return rc; - - rc =acpi_device_uevent_modalias (dev, env); -if (rc != -ENODEV ) -return rc; - -add_uevent_var (env,"MODALIAS=%s%s" ,PLATFORM_MODULE_PREFIX , - pdev->name); -return 0 ; -} -static const struct platform_device_id *platform_match_id (const struct platform_device_id *id,struct platform_device *pdev)
@@ -1134,44 +1031,6 @@ static const struct platform_device_id *platform_match_id(return NULL ; } -/** -* platform_match - bind platform device to platform driver. -* @dev: device. -* @drv: driver. -* -* Platform device IDs are assumed to be encoded like this: -* "<name><instance>", where <name> is a short description of the type of -* device, like "pci" or "floppy", and <instance> is the enumerated -* instance of the device, like '0' or '42'. Driver IDs are simply -* "<name>". So, extract the <name> from the platform_device structure, -* and compare it against the name of the driver. Return whether they match -* or not. -*/ -static int platform_match (struct device *dev,struct device_driver *drv) -{ -struct platform_device *pdev =to_platform_device (dev); -struct platform_driver *pdrv =to_platform_driver (drv); - -/* When driver_override is set, only bind to the matching driver */ -if (pdev->driver_override) -return !strcmp (pdev->driver_override, drv->name); - -/* Attempt an OF style match first */ -if (of_driver_match_device (dev, drv)) -return 1 ; - -/* Then try ACPI style match */ -if (acpi_driver_match_device (dev, drv)) -return 1 ; - -/* Then try to match against the id table */ -if (pdrv->id_table) -return platform_match_id (pdrv->id_table, pdev) !=NULL ; - -/* fall-back to driver name match */ -return (strcmp (pdev->name, drv->name) ==0 ); -} -#ifdef CONFIG_PM_SLEEP static int platform_legacy_suspend (struct device *dev,pm_message_t mesg)
@@ -1316,6 +1175,148 @@ int platform_pm_restore(struct device *dev)#endif /* CONFIG_HIBERNATE_CALLBACKS */ +/* modalias support enables more hands-off userspace setup: +* (a) environment variable lets new-style hotplug events work once system is +* fully running: "modprobe $MODALIAS" +* (b) sysfs attribute lets new-style coldplug recover from hotplug events +* mishandled before system is fully running: "modprobe $(cat modalias)" +*/ +static ssize_t modalias_show (struct device *dev, +struct device_attribute *attr,char *buf) +{ +struct platform_device *pdev =to_platform_device (dev); +int len; + + len =of_device_modalias (dev, buf,PAGE_SIZE ); +if (len != -ENODEV ) +return len; + + len =acpi_device_modalias (dev, buf,PAGE_SIZE -1 ); +if (len != -ENODEV ) +return len; + +return sysfs_emit (buf,"platform:%s\n" , pdev->name); +} +static DEVICE_ATTR_RO (modalias); + +static ssize_t numa_node_show (struct device *dev, +struct device_attribute *attr,char *buf) +{ +return sysfs_emit (buf,"%d\n" ,dev_to_node (dev)); +} +static DEVICE_ATTR_RO (numa_node); + +static ssize_t driver_override_show (struct device *dev, +struct device_attribute *attr,char *buf) +{ +struct platform_device *pdev =to_platform_device (dev); +ssize_t len; + +device_lock (dev); + len =sysfs_emit (buf,"%s\n" , pdev->driver_override); +device_unlock (dev); + +return len; +} + +static ssize_t driver_override_store (struct device *dev, +struct device_attribute *attr, +const char *buf,size_t count) +{ +struct platform_device *pdev =to_platform_device (dev); +int ret; + + ret =driver_set_override (dev, &pdev->driver_override, buf, count); +if (ret) +return ret; + +return count; +} +static DEVICE_ATTR_RW (driver_override); + +static struct attribute *platform_dev_attrs[] = { + &dev_attr_modalias.attr, + &dev_attr_numa_node.attr, + &dev_attr_driver_override.attr, +NULL , +}; + +static umode_t platform_dev_attrs_visible (struct kobject *kobj,struct attribute *a, +int n) +{ +struct device *dev =container_of (kobj,typeof (*dev), kobj); + +if (a == &dev_attr_numa_node.attr && +dev_to_node (dev) ==NUMA_NO_NODE ) +return 0 ; + +return a->mode; +} + +static struct attribute_group platform_dev_group = { + .attrs = platform_dev_attrs, + .is_visible = platform_dev_attrs_visible, +}; +__ATTRIBUTE_GROUPS (platform_dev); + + +/** +* platform_match - bind platform device to platform driver. +* @dev: device. +* @drv: driver. +* +* Platform device IDs are assumed to be encoded like this: +* "<name><instance>", where <name> is a short description of the type of +* device, like "pci" or "floppy", and <instance> is the enumerated +* instance of the device, like '0' or '42'. Driver IDs are simply +* "<name>". So, extract the <name> from the platform_device structure, +* and compare it against the name of the driver. Return whether they match +* or not. +*/ +static int platform_match (struct device *dev,struct device_driver *drv) +{ +struct platform_device *pdev =to_platform_device (dev); +struct platform_driver *pdrv =to_platform_driver (drv); + +/* When driver_override is set, only bind to the matching driver */ +if (pdev->driver_override) +return !strcmp (pdev->driver_override, drv->name); + +/* Attempt an OF style match first */ +if (of_driver_match_device (dev, drv)) +return 1 ; + +/* Then try ACPI style match */ +if (acpi_driver_match_device (dev, drv)) +return 1 ; + +/* Then try to match against the id table */ +if (pdrv->id_table) +return platform_match_id (pdrv->id_table, pdev) !=NULL ; + +/* fall-back to driver name match */ +return (strcmp (pdev->name, drv->name) ==0 ); +} + +static int platform_uevent (struct device *dev,struct kobj_uevent_env *env) +{ +struct platform_device *pdev =to_platform_device (dev); +int rc; + +/* Some devices have extra OF data and an OF-style MODALIAS */ + rc =of_device_uevent_modalias (dev, env); +if (rc != -ENODEV ) +return rc; + + rc =acpi_device_uevent_modalias (dev, env); +if (rc != -ENODEV ) +return rc; + +add_uevent_var (env,"MODALIAS=%s%s" ,PLATFORM_MODULE_PREFIX , + pdev->name); +return 0 ; +} +int platform_dma_configure (struct device *dev) {enum dev_dma_attr attr;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 414/798 driver core: platform: change logic implementing platform_driver_probe
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uwe Kleine-König <[email protected]>
[ Upstream commit 16085668eacdc56c46652d0f3bfef81ecace57de ]
Instead of overwriting the core driver's probe function handle probing devices for drivers loaded by platform_driver_probe() in the platform driver probe function.
The intended goal is to not have to change the probe function to simplify converting the platform bus to use bus functions.
Stable-dep-of: 589b9e6f96be ("usb: renesas_usbhs: Fix power-off ordering on unbind")
--- drivers/base/platform.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-)
drivers/base/platform.c +15 -3
@@ -743,12 +743,25 @@ struct platform_device *platform_device_register_full( }EXPORT_SYMBOL_GPL (platform_device_register_full); +static int platform_probe_fail (struct platform_device *pdev); +static int platform_drv_probe (struct device *_dev) {struct platform_driver *drv =to_platform_driver (_dev->driver);struct platform_device *dev =to_platform_device (_dev);int ret; +/* +* A driver registered using platform_driver_probe() cannot be bound +* again later because the probe function usually lives in __init code +* and so is gone. For these drivers .probe is set to +* platform_probe_fail in __platform_driver_probe(). Don't even +* prepare clocks and PM domains for these to match the traditional +* behaviour. +*/ +if (unlikely (drv->probe == platform_probe_fail)) +return -ENXIO ; + ret =of_clk_set_defaults (_dev->of_node, false);if (ret <0 )return ret;
@@ -822,7 +835,7 @@ void platform_driver_unregister(struct platform_driver *drv) }EXPORT_SYMBOL_GPL (platform_driver_unregister); -static int platform_drv_probe_fail (struct device *_dev) +static int platform_probe_fail (struct platform_device *pdev) {return -ENXIO ; }
@@ -887,10 +900,9 @@ int __init_or_module __platform_driver_probe(struct platform_driver *drv,* new devices fail. */ spin_lock (&drv->driver.bus->p->klist_drivers.k_lock); - drv->probe =NULL ; + drv->probe = platform_probe_fail;if (code ==0 &&list_empty (&drv->driver.p->klist_devices.k_list)) retval = -ENODEV ; - drv->driver.probe = platform_drv_probe_fail;spin_unlock (&drv->driver.bus->p->klist_drivers.k_lock);if (code != retval)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 415/798 driver core: platform: use bus_type functions
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uwe Kleine-König <[email protected]>
[ Upstream commit 9c30921fe7994907e0b3e0637b2c8c0fc4b5171f ]
This works towards the goal mentioned in 2006 in commit 594c8281f905 ("[PATCH] Add bus_type probe, remove, shutdown methods.").
The functions are moved to where the other bus_type functions are defined and renamed to match the already established naming scheme.
Stable-dep-of: 589b9e6f96be ("usb: renesas_usbhs: Fix power-off ordering on unbind")
--- drivers/base/platform.c | 132 ++++++++++++++++++++-------------------- 1 file changed, 65 insertions(+), 67 deletions(-)
drivers/base/platform.c +65 -67
@@ -743,70 +743,6 @@ struct platform_device *platform_device_register_full( }EXPORT_SYMBOL_GPL (platform_device_register_full); -static int platform_probe_fail (struct platform_device *pdev); - -static int platform_drv_probe (struct device *_dev) -{ -struct platform_driver *drv =to_platform_driver (_dev->driver); -struct platform_device *dev =to_platform_device (_dev); -int ret; - -/* -* A driver registered using platform_driver_probe() cannot be bound -* again later because the probe function usually lives in __init code -* and so is gone. For these drivers .probe is set to -* platform_probe_fail in __platform_driver_probe(). Don't even -* prepare clocks and PM domains for these to match the traditional -* behaviour. -*/ -if (unlikely (drv->probe == platform_probe_fail)) -return -ENXIO ; - - ret =of_clk_set_defaults (_dev->of_node, false); -if (ret <0 ) -return ret; - - ret =dev_pm_domain_attach (_dev, true); -if (ret) - goto out; - -if (drv->probe) { - ret = drv->probe (dev); -if (ret) -dev_pm_domain_detach (_dev, true); - } - -out: -if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER ) { -dev_warn (_dev,"probe deferral not supported\n" ); - ret = -ENXIO ; - } - -return ret; -} - -static int platform_drv_remove (struct device *_dev) -{ -struct platform_driver *drv =to_platform_driver (_dev->driver); -struct platform_device *dev =to_platform_device (_dev); -int ret =0 ; - -if (drv->remove) - ret = drv->remove (dev); -dev_pm_domain_detach (_dev, true); - -return ret; -} - -static void platform_drv_shutdown (struct device *_dev) -{ -struct platform_driver *drv =to_platform_driver (_dev->driver); -struct platform_device *dev =to_platform_device (_dev); - -if (drv->shutdown) - drv->shutdown (dev); -} -/** * __platform_driver_register - register a driver for platform-level devices * @drv: platform driver structure
@@ -817,9 +753,6 @@ int __platform_driver_register(struct platform_driver *drv, { drv->driver.owner = owner; drv->driver.bus = &platform_bus_type; - drv->driver.probe = platform_drv_probe; - drv->driver.remove = platform_drv_remove; - drv->driver.shutdown = platform_drv_shutdown;return driver_register (&drv->driver); }
@@ -1329,6 +1262,68 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)return 0 ; } +static int platform_probe (struct device *_dev) +{ +struct platform_driver *drv =to_platform_driver (_dev->driver); +struct platform_device *dev =to_platform_device (_dev); +int ret; + +/* +* A driver registered using platform_driver_probe() cannot be bound +* again later because the probe function usually lives in __init code +* and so is gone. For these drivers .probe is set to +* platform_probe_fail in __platform_driver_probe(). Don't even prepare +* clocks and PM domains for these to match the traditional behaviour. +*/ +if (unlikely (drv->probe == platform_probe_fail)) +return -ENXIO ; + + ret =of_clk_set_defaults (_dev->of_node, false); +if (ret <0 ) +return ret; + + ret =dev_pm_domain_attach (_dev, true); +if (ret) + goto out; + +if (drv->probe) { + ret = drv->probe (dev); +if (ret) +dev_pm_domain_detach (_dev, true); + } + +out: +if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER ) { +dev_warn (_dev,"probe deferral not supported\n" ); + ret = -ENXIO ; + } + +return ret; +} + +static int platform_remove (struct device *_dev) +{ +struct platform_driver *drv =to_platform_driver (_dev->driver); +struct platform_device *dev =to_platform_device (_dev); +int ret =0 ; + +if (drv->remove) + ret = drv->remove (dev); +dev_pm_domain_detach (_dev, true); + +return ret; +} + +static void platform_shutdown (struct device *_dev) +{ +struct platform_driver *drv =to_platform_driver (_dev->driver); +struct platform_device *dev =to_platform_device (_dev); + +if (drv->shutdown) + drv->shutdown (dev); +} + +int platform_dma_configure (struct device *dev) {enum dev_dma_attr attr;
@@ -1355,6 +1350,9 @@ struct bus_type platform_bus_type = { .dev_groups = platform_dev_groups, .match = platform_match, .uevent = platform_uevent, + .probe = platform_probe, + .remove = platform_remove, + .shutdown = platform_shutdown, .dma_configure = platform_dma_configure, .pm = &platform_dev_pm_ops, };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 416/798 driver core: platform: Emit a warning if a remove callback returned non-zero
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uwe Kleine-König <[email protected]>
[ Upstream commit e5e1c209788138f33ca6558bf9f572f6904f486d ]
The driver core ignores the return value of a bus' remove callback. However a driver returning an error code is a hint that there is a problem, probably a driver author who expects that returning e.g. -EBUSY has any effect.
The right thing to do would be to make struct platform_driver::remove() return void. With the immense number of platform drivers this is however a big quest and I hope to prevent at least a few new drivers that return an error code here.
Stable-dep-of: 589b9e6f96be ("usb: renesas_usbhs: Fix power-off ordering on unbind")
--- drivers/base/platform.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
drivers/base/platform.c +7 -4
@@ -1305,13 +1305,16 @@ static int platform_remove(struct device *_dev) {struct platform_driver *drv =to_platform_driver (_dev->driver);struct platform_device *dev =to_platform_device (_dev); -int ret =0 ; -if (drv->remove) - ret = drv->remove (dev); +if (drv->remove) { +int ret = drv->remove (dev); + +if (ret) +dev_warn (_dev,"remove callback returned a non-zero value. This will be ignored.\n" ); + }dev_pm_domain_detach (_dev, true); -return ret; +return 0 ; }static void platform_shutdown (struct device *_dev)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 417/798 platform: Provide a remove callback that returns no value
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uwe Kleine-König <[email protected]>
[ Upstream commit 5c5a7680e67ba6fbbb5f4d79fa41485450c1985c ]
struct platform_driver::remove returning an integer made driver authors expect that returning an error code was proper error handling. However the driver core ignores the error and continues to remove the device because there is nothing the core could do anyhow and reentering the remove callback again is only calling for trouble.
So this is an source for errors typically yielding resource leaks in the error path.
As there are too many platform drivers to neatly convert them all to return void in a single go, do it in several steps after this patch:
a) Convert all drivers to implement .remove_new() returning void instead
of .remove() returning int;
b) Change struct platform_driver::remove() to return void and so make
it identical to .remove_new(); c) Change all drivers back to .remove() now with the better prototype;
d) drop struct platform_driver::remove_new().
While this touches all drivers eventually twice, steps a) and c) can be done one driver after another and so reduces coordination efforts immensely and simplifies review.
Stable-dep-of: 589b9e6f96be ("usb: renesas_usbhs: Fix power-off ordering on unbind")
--- drivers/base/platform.c | 4 +++- include/linux/platform_device.h | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-)
drivers/base/platform.c +3 -1
@@ -1306,7 +1306,9 @@ static int platform_remove(struct device *_dev)struct platform_driver *drv =to_platform_driver (_dev->driver);struct platform_device *dev =to_platform_device (_dev); -if (drv->remove) { +if (drv->remove_new) { + drv->remove_new (dev); + }else if (drv->remove) {int ret = drv->remove (dev);if (ret)
include/linux/platform_device.h +11 -0
@@ -203,7 +203,18 @@ extern void platform_device_put(struct platform_device *pdev);struct platform_driver {int (*probe)(struct platform_device *); + +/* +* Traditionally the remove callback returned an int which however is +* ignored by the driver core. This led to wrong expectations by driver +* authors who thought returning an error code was a valid error +* handling strategy. To convert to a callback returning void, new +* drivers should implement .remove_new() until the conversion it done +* that eventually makes .remove() return void. +*/ int (*remove)(struct platform_device *); +void (*remove_new)(struct platform_device *); +void (*shutdown)(struct platform_device *);int (*suspend)(struct platform_device *,pm_message_t state);int (*resume)(struct platform_device *);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 418/798 usb: renesas_usbhs: Fix power-off ordering on unbind
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Biju Das <[email protected]>
[ Upstream commit 589b9e6f96be6bd8dd0d45fda8e948c31dc2fe94 ]
Move the usbhsc_power_ctrl() call to before hardware_exit() and reset_control_assert() in usbhs_remove(), so the PHY is powered off while priv->phy is still valid, rather than after hardware_exit() has already cleared it.
--- drivers/usb/renesas_usbhs/common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/usb/renesas_usbhs/common.c +3 -3
@@ -802,9 +802,6 @@ static int usbhs_remove(struct platform_device *pdev)flush_delayed_work (&priv->notify_hotplug_work); -usbhs_platform_call (priv, hardware_exit, pdev); -reset_control_assert (priv->rsts); -/* * Explicitly free the IRQ to ensure the interrupt handler is * disabled and synchronized before freeing resources.
@@ -821,6 +818,9 @@ static int usbhs_remove(struct platform_device *pdev)if (!usbhs_get_dparam (priv, runtime_pwctrl))usbhsc_power_ctrl (priv,0 ); +usbhs_platform_call (priv, hardware_exit, pdev); +reset_control_assert (priv->rsts); +usbhsc_clk_put (priv);pm_runtime_disable (&pdev->dev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 419/798 drm/panel: samsung-s6d16d0: Power off on prepare failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Laxman Acharya Padhya <[email protected]>
[ Upstream commit a9f950adfe2147318d75e7a6eab5e814851802ac ]
If enabling tearing mode or exiting sleep mode fails after the regulator is enabled, s6d16d0_prepare() returns without asserting reset or disabling the supply. Since the DRM panel core leaves the panel unprepared, a later unprepare call skips the driver callback and the supply remains enabled.
Assert reset and disable the supply before returning the DSI command error.
--- drivers/gpu/drm/panel/panel-samsung-s6d16d0.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
drivers/gpu/drm/panel/panel-samsung-s6d16d0.c +8 -2
@@ -89,16 +89,22 @@ static int s6d16d0_prepare(struct drm_panel *panel) MIPI_DSI_DCS_TEAR_MODE_VBLANK);if (ret) {dev_err (s6->dev,"failed to enable vblank TE (%d)\n" , ret); -return ret; + goto err_power_off; }/* Exit sleep mode and power on */ ret =mipi_dsi_dcs_exit_sleep_mode (dsi);if (ret) {dev_err (s6->dev,"failed to exit sleep mode (%d)\n" , ret); -return ret; + goto err_power_off; }return 0 ; + +err_power_off: +gpiod_set_value_cansleep (s6->reset_gpio,1 ); +regulator_disable (s6->supply); + +return ret; }static int s6d16d0_enable (struct drm_panel *panel)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 420/798 iio: accel: dmard09: Implement IIO_CHAN_INFO_SCALE
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mert Seftali <[email protected]>
[ Upstream commit aa58ecc73466d0cb8c418de98e2225490bf600e3 ]
Reading the in_accel_scale attribute on the DMARD09 has always returned -EINVAL: the channels advertise scale via info_mask_shared_by_type so the IIO core exposes the attribute, but dmard09_read_raw() only handles IIO_CHAN_INFO_RAW, so a SCALE read falls through to 'default: return -EINVAL':
$ cat .../iio:deviceX/in_accel_scale
cat: in_accel_scale: Invalid argumentleaving userspace with raw counts it cannot convert to m/s^2.
The driver was written from a vendor source [1] without a datasheet, and the scale was declared but never implemented. The vendor source carries the sensitivity: its conversion is
acc = raw * GRAVITY_EARTH_1000 / sensitivity (then / 1000 -> m/s^2)
with sensitivity = 32 and GRAVITY_EARTH_1000 = 9807 ("about (9.80665)*1000"), i.e. 32 counts correspond to 1 g.
That sensitivity applies to the value this driver already reports as raw:
the vendor reduces each 16-bit sample to a signed 9-bit value, and the preparation in dmard09_read_raw() yields the same value. It is
self-consistent: 256 counts / 32 = 8 g full scale, matching the +/-8g range.
Implement the scale derived from that sensitivity using standard gravity:
scale = 9.80665 / 32 = 0.3064578125 m/s^2 per LSB
--- drivers/iio/accel/dmard09.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/iio/accel/dmard09.c +7 -0
@@ -8,6 +8,7 @@#include <asm/unaligned.h> #include <linux/module.h> #include <linux/i2c.h> +#include <linux/units.h> #include <linux/iio/iio.h> #define DMARD09_DRV_NAME "dmard09"
@@ -79,6 +80,12 @@ static int dmard09_read_raw(struct iio_dev *indio_dev, *val = accel;return IIO_VAL_INT ; +case IIO_CHAN_INFO_SCALE : + *val =0 ; +/* 1 g / 32 LSB, in m/s^2 */ + *val2 =IIO_G_TO_M_S_2 (NANO /32 ); + +return IIO_VAL_INT_PLUS_NANO ;default :return -EINVAL ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 421/798 RDMA/core: Avoid flush_workqueue(system_unbound_wq) usage
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tetsuo Handa <[email protected]>
[ Upstream commit ff815a89398d8bbfdc14ced98252bdae92126225 ]
Flushing system-wide workqueues is dangerous and will be forbidden. Replace system_unbound_wq with local ib_unreg_wq.
Stable-dep-of: 7d75592114d1 ("RDMA/core: Wait for RCU callbacks before unloading ib_core")
--- drivers/infiniband/core/device.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-)
drivers/infiniband/core/device.c +14 -10
@@ -58,6 +58,7 @@ struct workqueue_struct *ib_comp_wq;struct workqueue_struct *ib_comp_unbound_wq;struct workqueue_struct *ib_wq;EXPORT_SYMBOL_GPL (ib_wq); +static struct workqueue_struct *ib_unreg_wq;/* * Each of the three rwsem locks (devices, clients, client_data) protects the
@@ -1563,7 +1564,7 @@ void ib_unregister_device_queued(struct ib_device *ib_dev)WARN_ON (!refcount_read (&ib_dev->refcount));WARN_ON (!ib_dev->ops.dealloc_driver);get_device (&ib_dev->dev); -if (!queue_work (system_unbound_wq, &ib_dev->unregistration_work)) +if (!queue_work (ib_unreg_wq, &ib_dev->unregistration_work))put_device (&ib_dev->dev); }EXPORT_SYMBOL (ib_unregister_device_queued);
@@ -2752,27 +2753,28 @@ static const struct rdma_nl_cbs ibnl_ls_cb_table[RDMA_NL_LS_NUM_OPS] = {static int __init ib_core_init (void ) { -int ret; +int ret = -ENOMEM ; ib_wq =alloc_workqueue ("infiniband" ,0 ,0 );if (!ib_wq)return -ENOMEM ; + ib_unreg_wq =alloc_workqueue ("ib-unreg-wq" ,WQ_UNBOUND , +WQ_UNBOUND_MAX_ACTIVE ); +if (!ib_unreg_wq) + goto err; + ib_comp_wq =alloc_workqueue ("ib-comp-wq" ,WQ_HIGHPRI |WQ_MEM_RECLAIM |WQ_SYSFS ,0 ); -if (!ib_comp_wq) { - ret = -ENOMEM ; - goto err; - } +if (!ib_comp_wq) + goto err_unbound; ib_comp_unbound_wq =alloc_workqueue ("ib-comp-unb-wq" ,WQ_UNBOUND |WQ_HIGHPRI |WQ_MEM_RECLAIM |WQ_SYSFS ,WQ_UNBOUND_MAX_ACTIVE ); -if (!ib_comp_unbound_wq) { - ret = -ENOMEM ; +if (!ib_comp_unbound_wq) goto err_comp; - } ret =class_register (&ib_class);if (ret) {
@@ -2840,6 +2842,8 @@ static int __init ib_core_init(void)destroy_workqueue (ib_comp_unbound_wq); err_comp:destroy_workqueue (ib_comp_wq); +err_unbound: +destroy_workqueue (ib_unreg_wq); err:destroy_workqueue (ib_wq);return ret;
@@ -2861,7 +2865,7 @@ static void __exit ib_core_cleanup(void)destroy_workqueue (ib_comp_wq);/* Make sure that any pending umem accounting work is done. */ destroy_workqueue (ib_wq); -flush_workqueue (system_unbound_wq); +destroy_workqueue (ib_unreg_wq);WARN_ON (!xa_empty (&clients));WARN_ON (!xa_empty (&devices)); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 422/798 RDMA/core: Wait for RCU callbacks before unloading ib_core
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit 7d75592114d1664623c8cf191a12b38052c04483 ]
put_gid_ndev() is queued with call_rcu() and implemented in ib_core. Stopping the workqueues does not drain callbacks already queued, so RCU could invoke it after the module code has been unloaded.
synchronize_rcu() does not wait for callbacks. Wait for them after all producers have stopped.
--- drivers/infiniband/core/device.c | 1 + 1 file changed, 1 insertion(+)
drivers/infiniband/core/device.c +1 -0
@@ -2866,6 +2866,7 @@ static void __exit ib_core_cleanup(void)/* Make sure that any pending umem accounting work is done. */ destroy_workqueue (ib_wq);destroy_workqueue (ib_unreg_wq); +rcu_barrier ();WARN_ON (!xa_empty (&clients));WARN_ON (!xa_empty (&devices)); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 423/798 RDMA/ipoib: Drain RCU callbacks during module teardown
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit 31b7c700670830a0e8a4cdcd451c88a13cc5dc48 ]
IPoIB reclamation completions can be signaled from inside an RCU callback. Teardown can wake before the callback returns and unload ib_ipoib while its code is still executing.
Client registration failure can also remove already-added devices and queue callbacks. Wait after client and workqueue teardown.
--- drivers/infiniband/ulp/ipoib/ipoib_main.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/infiniband/ulp/ipoib/ipoib_main.c +2 -0
@@ -2663,6 +2663,7 @@ static int __init ipoib_init_module(void) err_sa:ib_sa_unregister_client (&ipoib_sa_client);destroy_workqueue (ipoib_workqueue); +rcu_barrier (); err_fs:ipoib_unregister_debugfs ();
@@ -2680,6 +2681,7 @@ static void __exit ipoib_cleanup_module(void)ib_sa_unregister_client (&ipoib_sa_client);ipoib_unregister_debugfs ();destroy_workqueue (ipoib_workqueue); +rcu_barrier (); }module_init (ipoib_init_module);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 424/798 hwrng: ks-sa - access private data via struct hwrng
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Martin Kaiser <[email protected]>
[ Upstream commit b8f836cbe12bccf2beeadd638e1696f4acaa39c3 ]
This driver uses a struct ks_sa_rng for its private data. It contains a struct hwrng. Call container_of to get from hwrng to ks_sa_rng.
Stable-dep-of: 1c17b601fafb ("hwrng: ks-sa - Fix runtime PM cleanup on registration failure")
--- drivers/char/hw_random/ks-sa-rng.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-)
drivers/char/hw_random/ks-sa-rng.c +4 -11
@@ -113,8 +113,7 @@ static unsigned int refill_delay_ns(unsigned long clk_rate)static int ks_sa_rng_init (struct hwrng *rng) {u32 value; -struct device *dev = (struct device *)rng->priv; -struct ks_sa_rng *ks_sa_rng =dev_get_drvdata (dev); + struct ks_sa_rng *ks_sa_rng = container_of(rng, struct ks_sa_rng, rng);unsigned long clk_rate =clk_get_rate (ks_sa_rng->clk);/* Enable RNG module */
@@ -153,8 +152,7 @@ static int ks_sa_rng_init(struct hwrng *rng)static void ks_sa_rng_cleanup (struct hwrng *rng) { -struct device *dev = (struct device *)rng->priv; -struct ks_sa_rng *ks_sa_rng =dev_get_drvdata (dev); + struct ks_sa_rng *ks_sa_rng = container_of(rng, struct ks_sa_rng, rng);/* Disable RNG */ writel (0 , &ks_sa_rng->reg_rng->control);
@@ -164,8 +162,7 @@ static void ks_sa_rng_cleanup(struct hwrng *rng)static int ks_sa_rng_data_read (struct hwrng *rng,u32 *data) { -struct device *dev = (struct device *)rng->priv; -struct ks_sa_rng *ks_sa_rng =dev_get_drvdata (dev); + struct ks_sa_rng *ks_sa_rng = container_of(rng, struct ks_sa_rng, rng);/* Read random data */ data[0 ] =readl (&ks_sa_rng->reg_rng->output_l);
@@ -179,8 +176,7 @@ static int ks_sa_rng_data_read(struct hwrng *rng, u32 *data)static int ks_sa_rng_data_present (struct hwrng *rng,int wait) { -struct device *dev = (struct device *)rng->priv; -struct ks_sa_rng *ks_sa_rng =dev_get_drvdata (dev); + struct ks_sa_rng *ks_sa_rng = container_of(rng, struct ks_sa_rng, rng);u64 now =ktime_get_ns ();u32 ready;
@@ -225,7 +221,6 @@ static int ks_sa_rng_probe(struct platform_device *pdev) .data_present = ks_sa_rng_data_present, .cleanup = ks_sa_rng_cleanup, }; - ks_sa_rng->rng.priv = (unsigned long )dev; ks_sa_rng->reg_rng =devm_platform_ioremap_resource (pdev,0 );if (IS_ERR (ks_sa_rng->reg_rng))
@@ -253,8 +248,6 @@ static int ks_sa_rng_probe(struct platform_device *pdev)return ret; } -platform_set_drvdata (pdev, ks_sa_rng); -return devm_hwrng_register (&pdev->dev, &ks_sa_rng->rng); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 425/798 hwrng: ks-sa - Fix runtime PM cleanup on registration failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit 1c17b601fafb09c9ec074fd097737d20eafe7d63 ]
ks_sa_rng_probe() enables runtime PM and resumes the device before registering the hwrng. If devm_hwrng_register() fails, probe returns without dropping the runtime PM usage count or disabling runtime PM.
Unwind the runtime PM state on the registration failure path, matching the cleanup done by remove().
--- drivers/char/hw_random/ks-sa-rng.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/char/hw_random/ks-sa-rng.c +8 -1
@@ -248,7 +248,14 @@ static int ks_sa_rng_probe(struct platform_device *pdev)return ret; } -return devm_hwrng_register (&pdev->dev, &ks_sa_rng->rng); + ret =devm_hwrng_register (dev, &ks_sa_rng->rng); +if (ret) { +pm_runtime_put_sync (dev); +pm_runtime_disable (dev); +return ret; + } + +return 0 ; }static int ks_sa_rng_remove (struct platform_device *pdev)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 426/798 xfrm6: fix out-of-bounds write in xfrm6_input_addr() when secpath is full
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <[email protected]>
[ Upstream commit 5d9e3bf34fec9a5d237e4b7cef4a707bc2e091bc ]
The depth check in xfrm6_input_addr() is off by one:
if (1 + sp->len == XFRM_MAX_DEPTH)
goto drop;
...
sp->xvec[sp->len++] = x;xfrm_input() can leave sp->len == XFRM_MAX_DEPTH, and the transport-mode receive path re-enters IPv6 input via xfrm_trans_reinject() with that secpath preserved. If the inner packet carries a destination-options HAO option or a type-2 routing header, xfrm6_input_addr() is called with sp->len == XFRM_MAX_DEPTH; the check (1 + 6 == 6) is false, so sp->xvec[sp->len++] writes one slot past the 6-element xvec[]. The write stays within the sec_path allocation (invisible to KASAN); UBSAN_BOUNDS flags it and panics under panic_on_warn.
Use "sp->len >= XFRM_MAX_DEPTH", matching xfrm_input(). This also restores one chain level the old check rejected at sp->len == 5.
UBSAN: array-index-out-of-bounds in net/ipv6/xfrm6_input.c:309:10 index 6 is out of range for type 'xfrm_state *[6]'
--- net/ipv6/xfrm6_input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv6/xfrm6_input.c +1 -1
@@ -193,7 +193,7 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, goto drop; } -if (1 + sp->len ==XFRM_MAX_DEPTH ) { +if (sp->len >=XFRM_MAX_DEPTH ) {XFRM_INC_STATS (net,LINUX_MIB_XFRMINBUFFERERROR ); goto drop; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 427/798 ALSA: hpi: Check transport errors during HPI6000 adapter initialization
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Evgenii Burenchev <[email protected]>
[ Upstream commit cc15c329663e3ef1aeed0b68e49a5d5ce4ae0d5c ]
create_adapter_obj() retrieves adapter information by calling hpi6000_message_response_sequence(). This function reports transport-level errors through its return value and DSP-reported errors via hr0.error.
The current code only checks hr0.error, causing transport-level errors to be ignored. As a result, adapter initialization may continue with an invalid response.
Check the return value of hpi6000_message_response_sequence() before examining hr0.error.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- sound/pci/asihpi/hpi6000.c | 5 +++++ 1 file changed, 5 insertions(+)
sound/pci/asihpi/hpi6000.c +5 -0
@@ -537,6 +537,11 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao, hr1.size =sizeof (hr1); error =hpi6000_message_response_sequence (pao,0 , &hm, &hr0); +if (error) { +HPI_DEBUG_LOG (ERROR ,"message transport error %d\n" , + error); +return error; + }if (hr0.error) {HPI_DEBUG_LOG (DEBUG ,"message error %d\n" , hr0.error);return hr0.error;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 428/798 pmdomain: bcm: bcm2835: handle genpd provider registration errors
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
[ Upstream commit a1d9d3b958d69a13783613304f524f489fecdd1f ]
bcm2835_power_probe() initializes all power domains and then registers the onecell genpd provider, but ignores of_genpd_add_provider_onecell() failures. Probe can therefore return success even though no provider was published.
Check the provider registration return value and jump to the existing cleanup path on failure.
--- drivers/soc/bcm/bcm2835-power.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/soc/bcm/bcm2835-power.c +6 -1
@@ -657,7 +657,12 @@ static int bcm2835_power_probe(struct platform_device *pdev)if (ret) goto fail; -of_genpd_add_provider_onecell (dev->parent->of_node, &power->pd_xlate); + ret =of_genpd_add_provider_onecell (dev->parent->of_node, + &power->pd_xlate); +if (ret) { +dev_err_probe (dev, ret,"failed to add genpd provider\n" ); + goto fail; + }dev_info (dev,"Broadcom BCM2835 power domains driver" );return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 429/798 misc: rtsx_usb: avoid USB I/O in runtime autosuspend
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Rhodes <[email protected]>
[ Upstream commit 483c948324a3823871c004560a92545759d3253c ]
The runtime autosuspend callback currently queries card status and clears OCP by issuing USB register accesses. This can run from the USB runtime-PM path itself, which is the wrong place to start more device I/O.
Keep a cached copy of the card-status bits from normal status reads instead. During runtime autosuspend, use that cached value only to preserve the existing Memory Stick autosuspend deferral.
Do not treat raw SD_CD as an autosuspend blocker, because tray-based SD readers can assert SD_CD with an empty tray. A real SD card is protected by the SD/MMC child runtime-PM usage once powered.
Also stop clearing OCP from the runtime autosuspend callback, so the callback does not issue USB commands.
--- drivers/misc/cardreader/rtsx_usb.c | 23 ++++++++++++++++++++--- include/linux/rtsx_usb.h | 3 +++ 2 files changed, 23 insertions(+), 3 deletions(-)
drivers/misc/cardreader/rtsx_usb.c +20 -3
@@ -312,6 +312,9 @@ int rtsx_usb_get_card_status(struct rtsx_ucr *ucr, u16 *status)if (ret <0 )return ret; + ucr->card_status_cache = *status; + ucr->card_status_valid = true; +return 0 ; }EXPORT_SYMBOL_GPL (rtsx_usb_get_card_status);
@@ -619,6 +622,7 @@ static int rtsx_usb_probe(struct usb_interface *intf, {struct usb_device *usb_dev =interface_to_usbdev (intf);struct rtsx_ucr *ucr; +u16 status;int ret; dev_dbg(&intf->dev,
@@ -655,6 +659,9 @@ static int rtsx_usb_probe(struct usb_interface *intf,if (ret) goto out_init_fail; +/* Prime cached status for runtime autosuspend decisions. */ +rtsx_usb_get_card_status (ucr, &status); +/* initialize USB SG transfer timer */ timer_setup (&ucr->sg_timer, rtsx_usb_sg_timed_out,0 );
@@ -709,17 +716,27 @@ static int rtsx_usb_suspend(struct usb_interface *intf, pm_message_t message)struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata (intf);u16 val =0 ; +bool valid = false;dev_dbg (&intf->dev,"%s called with pm message 0x%04x\n" , __func__, message.event);if (PMSG_IS_AUTO (message)) {if (mutex_trylock (&ucr->dev_mutex)) { -rtsx_usb_get_card_status (ucr, &val); + valid = ucr->card_status_valid; +if (valid) + val = ucr->card_status_cache;mutex_unlock (&ucr->dev_mutex); -/* Defer the autosuspend if card exists */ -if (val & (SD_CD |MS_CD )) { +/* +* Do not issue USB commands from runtime autosuspend. +* Raw SD_CD is not authoritative on tray-based readers, +* while a real SD card is protected by the SD/MMC child +* runtime-PM reference once the card is powered. Keep +* the historical Memory Stick autosuspend deferral when +* the cached status says MS media is present. +*/ +if (valid && (val &MS_CD )) {device_for_each_child (&intf->dev,NULL , rtsx_usb_resume_child);return -EAGAIN ; }
include/linux/rtsx_usb.h +3 -0
@@ -57,6 +57,9 @@ struct rtsx_ucr {struct timer_list sg_timer;struct mutex dev_mutex; + +u16 card_status_cache; +bool card_status_valid; };/* buffer size */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 430/798 RDMA/hfi1: Preserve unit 0 on allocation failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit 2e3809ad8911f5d5581b3f046bd628417bface76 ]
hfi1_free_devdata() assumes that the device was inserted into the unit table and unconditionally erases dd->unit. If xa_alloc_irq() fails, the zero-initialized unit remains zero, so full cleanup can remove an unrelated device from index 0.
Release only the rdmavt allocation and return immediately while the unit table has not acquired the device.
--- drivers/infiniband/hw/hfi1/init.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/infiniband/hw/hfi1/init.c +3 -2
@@ -1269,8 +1269,9 @@ static struct hfi1_devdata *hfi1_alloc_devdata(struct pci_dev *pdev, GFP_KERNEL);if (ret <0 ) {dev_err (&pdev->dev, -"Could not allocate unit ID: error %d\n" , -ret); - goto bail; +"Could not allocate unit ID: error %pe\n" ,ERR_PTR (ret)); +rvt_dealloc_device (&dd->verbs_dev.rdi); +return ERR_PTR (ret); }rvt_set_ibdev_name (&dd->verbs_dev.rdi,"%s_%d" ,class_name (), dd->unit);/*
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 431/798 RDMA/hfi1: Remove redundant PCI device ID validation
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit af9117d02f50514c998714b23820de71d0aa5d24 ]
The PCI core calls init_one() only after pci_match_device() has selected an ID. For normal probing, hfi1_pci_tbl already restricts matches to the two supported Intel device IDs. Dynamic IDs and driver_override are explicit requests to attempt binding, so the probe should not second-guess the PCI core's decision.
Remove the redundant check.
Stable-dep-of: 9f674ba674a0 ("RDMA/hfi1: Allocate device data after PCI initialization")
--- drivers/infiniband/hw/hfi1/init.c | 9 --------- 1 file changed, 9 deletions(-)
drivers/infiniband/hw/hfi1/init.c +0 -9
@@ -1605,15 +1605,6 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)/* First, lock the non-writable module parameters */ HFI1_CAP_LOCK (); -/* Validate dev ids */ -if (!(ent->device ==PCI_DEVICE_ID_INTEL0 || - ent->device ==PCI_DEVICE_ID_INTEL1 )) { -dev_err (&pdev->dev,"Failing on unknown Intel deviceid 0x%x\n" , - ent->device); - ret = -ENODEV ; - goto bail; - } -/* Allocate the dd so we can get to work */ dd =hfi1_alloc_devdata (pdev,NUM_IB_PORTS *sizeof (struct hfi1_pportdata ));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 432/798 RDMA/hfi1: Create workqueues before device initialization
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit 0d5618c1b2fc9dd4fc086f0226acd8a077ab6c1b ]
create_workqueues() only needs fields set up by hfi1_alloc_devdata(). Call it before hfi1_init_dd() so a workqueue allocation failure happens before chip resources are initialized.
To keep the reordered error paths safe, make init_one() own hfi1_devdata. hfi1_init_dd() unwinds its partial setup but leaves the allocation for the caller to free. If device initialization fails, destroy the workqueues before freeing the device data.
Stable-dep-of: 9f674ba674a0 ("RDMA/hfi1: Allocate device data after PCI initialization")
--- drivers/infiniband/hw/hfi1/chip.c | 4 +--- drivers/infiniband/hw/hfi1/hfi.h | 2 -- drivers/infiniband/hw/hfi1/init.c | 19 ++++++++++--------- 3 files changed, 11 insertions(+), 14 deletions(-)
drivers/infiniband/hw/hfi1/chip.c +1 -3
@@ -15105,7 +15105,7 @@ int hfi1_init_dd(struct hfi1_devdata *dd)*/ ret =hfi1_pcie_ddinit (dd, pdev);if (ret <0 ) - goto bail_free; + goto bail;/* Save PCI space registers to rewrite after device reset */ ret =save_pci_variables (dd);
@@ -15360,8 +15360,6 @@ int hfi1_init_dd(struct hfi1_devdata *dd) bail_cleanup:hfi1_netdev_free (dd);hfi1_pcie_ddcleanup (dd); -bail_free: -hfi1_free_devdata (dd); bail:return ret; }
drivers/infiniband/hw/hfi1/hfi.h +0 -2
@@ -2096,9 +2096,7 @@ struct cc_state *get_cc_state_protected(struct hfi1_pportdata *ppd)/* waiting for an urgent packet to arrive */ #define HFI1_CTXT_WAITING_URG 4 -/* free up any allocated data at closes */ int hfi1_init_dd (struct hfi1_devdata *dd); -void hfi1_free_devdata (struct hfi1_devdata *dd);/* LED beaconing functions */ void hfi1_start_led_override(struct hfi1_pportdata *ppd, unsigned int timeon,
drivers/infiniband/hw/hfi1/init.c +10 -9
@@ -671,8 +671,6 @@ void hfi1_init_pportdata(struct pci_dev *pdev, struct hfi1_pportdata *ppd, ppd->sm_trap_qp =0x0 ; ppd->sa_qp =0x1 ; - ppd->hfi1_wq =NULL ; -spin_lock_init (&ppd->cca_timer_lock);for (i =0 ; i <OPA_MAX_SLS ; i++) {
@@ -1206,7 +1204,7 @@ static void finalize_asic_data(struct hfi1_devdata *dd,* It cleans up and frees all data structures set up by * by hfi1_alloc_devdata(). */ -void hfi1_free_devdata (struct hfi1_devdata *dd) +static void hfi1_free_devdata (struct hfi1_devdata *dd) {struct hfi1_asic_data *ad;unsigned long flags;
@@ -1658,17 +1656,17 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)if (ret) goto bail; + ret =create_workqueues (dd); +if (ret) + goto free_devdata; +/* * Do device-specific initialization, function table setup, dd * allocation, etc. */ ret =hfi1_init_dd (dd);if (ret) - goto clean_bail;/* error already printed */ - - ret =create_workqueues (dd); -if (ret) - goto clean_bail; + goto destroy_workqueues;/* error already printed */ /* do the generic initialization */ initfail =hfi1_init (dd,0 );
@@ -1721,7 +1719,10 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)return 0 ; -clean_bail: +destroy_workqueues: +destroy_workqueues (dd); +free_devdata: +hfi1_free_devdata (dd);hfi1_pcie_cleanup (pdev); bail:return ret;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 433/798 RDMA/hfi1: Stop flushing the global IB workqueue
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit d43b1c17f9e1b9d34a0d742f569c00d84147ebc0 ]
hfi1 does not queue work on ib_wq. QSFP and link work run on the per-port link_wq, while the remaining device work uses hfi1_wq or dedicated queues. The probe failure path destroys both per-port workqueues, and normal device removal flushes them in shutdown_device() before destroying them.
Remove the flushes of the core-owned global workqueue. Waiting for unrelated core or other device work is not part of hfi1 teardown.
--- drivers/infiniband/hw/hfi1/init.c | 4 ---- 1 file changed, 4 deletions(-)
drivers/infiniband/hw/hfi1/init.c +0 -4
@@ -1692,7 +1692,6 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)if (initfail || ret) {msix_clean_up_interrupts (dd);stop_timers (dd); -flush_workqueue (ib_wq);for (pidx =0 ; pidx < dd->num_pports; ++pidx) {hfi1_quiet_serdes (dd->pport + pidx); ppd = dd->pport + pidx;
@@ -1768,9 +1767,6 @@ static void remove_one(struct pci_dev *pdev)stop_timers (dd); -/* wait until all of our (qsfp) queue_work() calls complete */ -flush_workqueue (ib_wq); -postinit_cleanup (dd); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 434/798 RDMA/hfi1: Initialize debugfs after probe completes
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit bb18740b302f6f222ce3d5a7e5c45a52a90df805 ]
Commit ed6f653fe430 ("staging/rdma/hfi1: Fix debugfs access race") moved debugfs creation after device initialization and IB registration so users cannot access the files before the driver is ready. However, init_one() still creates them before character device creation and SDMA startup finish.
Move hfi1_dbg_ibdev_init() to the end of the successful probe path, matching hfi1_dbg_ibdev_exit() as the first action in remove_one().
--- drivers/infiniband/hw/hfi1/init.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/infiniband/hw/hfi1/init.c +2 -4
@@ -1679,11 +1679,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)* we still create devices, so diags, etc. can be used * to determine cause of problem. */ -if (!initfail && !ret) { +if (!initfail && !ret) dd->flags |=HFI1_INITTED ; -/* create debufs files after init and ib register */ -hfi1_dbg_ibdev_init (&dd->verbs_dev); - } j =hfi1_device_create (dd);if (j)
@@ -1715,6 +1712,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) }sdma_start (dd); +hfi1_dbg_ibdev_init (&dd->verbs_dev);return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 435/798 highmem: Provide generic variant of kmap_atomic*
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Gleixner <[email protected]>
[ Upstream commit 298fa1ad5571f59cb3ca5497a9455f36867f065e ]
The kmap_atomic* interfaces in all architectures are pretty much the same except for post map operations (flush) and pre- and post unmap operations.
Provide a generic variant for that.
Stable-dep-of: 68d4d3e78150 ("isofs: fix out-of-bounds page array access on empty zisofs block")
--- include/linux/highmem.h | 82 ++++++++++++++++++----- mm/Kconfig | 3 + mm/highmem.c | 144 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 211 insertions(+), 18 deletions(-)
include/linux/highmem.h +66 -16
@@ -31,9 +31,16 @@ static inline void invalidate_kernel_vmap_range(void *vaddr, int size)#include <asm/kmap_types.h> +/* +* Outside of CONFIG_HIGHMEM to support X86 32bit iomap_atomic() cruft. +*/ +#ifdef CONFIG_KMAP_LOCAL +void *__kmap_local_pfn_prot (unsigned long pfn,pgprot_t prot); +void *__kmap_local_page_prot (struct page *page,pgprot_t prot); +void kunmap_local_indexed (void *vaddr); +#endif +#ifdef CONFIG_HIGHMEM -extern void *kmap_atomic_high_prot (struct page *page,pgprot_t prot); -extern void kunmap_atomic_high (void *kvaddr);#include <asm/highmem.h> #ifndef ARCH_HAS_KMAP_FLUSH_TLB
@@ -81,6 +88,11 @@ static inline void kunmap(struct page *page)* be used in IRQ contexts, so in some (very limited) cases we need * it. */ + +#ifndef CONFIG_KMAP_LOCAL +void *kmap_atomic_high_prot (struct page *page,pgprot_t prot); +void kunmap_atomic_high (void *kvaddr); +static inline void *kmap_atomic_prot (struct page *page,pgprot_t prot) {preempt_disable ();
@@ -89,7 +101,38 @@ static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot)return page_address (page);return kmap_atomic_high_prot (page, prot); } -#define kmap_atomic (page) kmap_atomic_prot(page, kmap_prot) + +static inline void __kunmap_atomic (void *vaddr) +{ +kunmap_atomic_high (vaddr); +} +#else /* !CONFIG_KMAP_LOCAL */ + +static inline void *kmap_atomic_prot (struct page *page,pgprot_t prot) +{ +preempt_disable (); +pagefault_disable (); +return __kmap_local_page_prot (page, prot); +} + +static inline void *kmap_atomic_pfn (unsigned long pfn) +{ +preempt_disable (); +pagefault_disable (); +return __kmap_local_pfn_prot (pfn, kmap_prot); +} + +static inline void __kunmap_atomic (void *addr) +{ +kunmap_local_indexed (addr); +} + +#endif /* CONFIG_KMAP_LOCAL */ + +static inline void *kmap_atomic (struct page *page) +{ +return kmap_atomic_prot (page, kmap_prot); +}/* declarations for linux/mm/highmem.c */ unsigned int nr_free_highpages (void );
@@ -157,25 +200,33 @@ static inline void *kmap_atomic(struct page *page)pagefault_disable (); return page_address(page); } -#define kmap_atomic_prot (page, prot) kmap_atomic(page) -static inline void kunmap_atomic_high (void *addr) +static inline void *kmap_atomic_prot (struct page *page,pgprot_t prot) +{ +return kmap_atomic (page); +} + +static inline void *kmap_atomic_pfn (unsigned long pfn) +{ +return kmap_atomic (pfn_to_page (pfn)); +} + +static inline void __kunmap_atomic (void *addr) {/* * Mostly nothing to do in the CONFIG_HIGHMEM=n case as kunmap_atomic() -* handles re-enabling faults + preemption +* handles re-enabling faults and preemption */ #ifdef ARCH_HAS_FLUSH_ON_KUNMAP kunmap_flush_on_unmap (addr);#endif } -#define kmap_atomic_pfn (pfn) kmap_atomic(pfn_to_page(pfn)) -#define kmap_flush_unused () do {} while(0)#endif /* CONFIG_HIGHMEM */ +#if !defined(CONFIG_KMAP_LOCAL )#if defined(CONFIG_HIGHMEM ) || defined(CONFIG_X86_32 )DECLARE_PER_CPU (int, __kmap_atomic_idx);
@@ -206,22 +257,21 @@ static inline void kmap_atomic_idx_pop(void)__this_cpu_dec (__kmap_atomic_idx);#endif } - +#endif #endif /* * Prevent people trying to call kunmap_atomic() as if it were kunmap() * kunmap_atomic() should get the return value of kmap_atomic, not the page. */ -#define kunmap_atomic (addr) \ -do { \ - BUILD_BUG_ON(__same_type((addr), struct page *)); \ - kunmap_atomic_high(addr); \ - pagefault_enable(); \ - preempt_enable(); \ +#define kunmap_atomic (__addr) \ +do { \ + BUILD_BUG_ON(__same_type((__addr), struct page *)); \ + __kunmap_atomic(__addr); \ + pagefault_enable(); \ + preempt_enable(); \ } while (0) -/* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */ #ifndef clear_user_highpagestatic inline void clear_user_highpage (struct page *page,unsigned long vaddr)
mm/Kconfig +3 -0
@@ -859,4 +859,7 @@ config ARCH_HAS_HUGEPD config MAPPING_DIRTY_HELPERS bool +config KMAP_LOCAL + bool + endmenu
mm/highmem.c +142 -2
160 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 436/798 iov_iter: lift memzero_page() to highmem.h
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ira Weiny <[email protected]>
[ Upstream commit 28961998f858114e51d2ae862065b858afcfa2b2 ]
Patch series "btrfs: Convert kmap/memset/kunmap to memzero_user()".
Lifting memzero_user(), convert it to kmap_local_page() and then use it in btrfs.
This patch (of 3):
memzero_page() can replace the kmap/memset/kunmap pattern in other places in the code. While zero_user() has the same interface it is not the same call and its use should be limited and some of those calls may be better converted from zero_user() to memzero_page().[1] But that is not addressed in this series.
Lift memzero_page() to highmem.
[1] https://lore.kernel.org/lkml/CAHk-=wijdojzo56FzYqE5TOYw2Vws7ik3LEMGj9SPQaJJ+Z73Q@mail.gmail.com/
Stable-dep-of: 68d4d3e78150 ("isofs: fix out-of-bounds page array access on empty zisofs block")
--- include/linux/highmem.h | 7 +++++++ lib/iov_iter.c | 8 +------- 2 files changed, 8 insertions(+), 7 deletions(-)
include/linux/highmem.h +7 -0
@@ -413,4 +413,11 @@ static inline void memcpy_to_page(struct page *page, size_t offset, kunmap_atomic(to); } +static inline void memzero_page (struct page *page,size_t offset,size_t len) +{ +char *addr =kmap_atomic (page); +memset (addr + offset,0 , len); +kunmap_atomic (addr); +} +#endif /* _LINUX_HIGHMEM_H */
lib/iov_iter.c +1 -7
@@ -5,6 +5,7 @@#include <linux/fault-inject-usercopy.h> #include <linux/uio.h> #include <linux/pagemap.h> +#include <linux/highmem.h> #include <linux/slab.h> #include <linux/vmalloc.h> #include <linux/splice.h>
@@ -467,13 +468,6 @@ void iov_iter_init(struct iov_iter *i, unsigned int direction, }EXPORT_SYMBOL (iov_iter_init); -static void memzero_page (struct page *page,size_t offset,size_t len) -{ -char *addr =kmap_atomic (page); -memset (addr + offset,0 , len); -kunmap_atomic (addr); -} -static inline bool allocated (struct pipe_buffer *buf) {return buf->ops == &default_pipe_buf_ops;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 437/798 rpmsg: glink: Remove the rpmsg dev in close_ack
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arun Kumar Neelakantam <[email protected]>
[ Upstream commit c7c182d4447e172f87e37d6c04879b94b8635b37 ]
Un-register and register of rpmsg driver is sending invalid open_ack on closed channel.
To avoid sending invalid open_ack case unregister the rpmsg device after receiving the local_close_ack from remote side.
Stable-dep-of: 5a5a48e788e0 ("rpmsg: glink: fix deadlock in endpoint destroy during driver detach")
--- drivers/rpmsg/qcom_glink_native.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
drivers/rpmsg/qcom_glink_native.c +12 -0
@@ -1555,6 +1555,7 @@ static void qcom_glink_rx_close(struct qcom_glink *glink, unsigned int rcid)rpmsg_unregister_device (glink->dev, &chinfo); } + channel->rpdev =NULL ;qcom_glink_send_close_ack (glink, channel->rcid);
@@ -1568,6 +1569,7 @@ static void qcom_glink_rx_close(struct qcom_glink *glink, unsigned int rcid)static void qcom_glink_rx_close_ack (struct qcom_glink *glink,unsigned int lcid) { +struct rpmsg_channel_info chinfo;struct glink_channel *channel;unsigned long flags;
@@ -1585,6 +1587,16 @@ static void qcom_glink_rx_close_ack(struct qcom_glink *glink, unsigned int lcid) channel->lcid =0 ;spin_unlock_irqrestore (&glink->idr_lock, flags); +/* Decouple the potential rpdev from the channel */ +if (channel->rpdev) { +strscpy (chinfo.name, channel->name,sizeof (chinfo.name)); + chinfo.src =RPMSG_ADDR_ANY ; + chinfo.dst =RPMSG_ADDR_ANY ; + +rpmsg_unregister_device (glink->dev, &chinfo); + } + channel->rpdev =NULL ; +kref_put (&channel->refcount, qcom_glink_channel_release); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 438/798 rpmsg: glink: remove duplicate code for rpmsg device remove
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivas Kandagatla <[email protected]>
[ Upstream commit 112766cdf2e5ea0a0f72b0304d57a6f74c066670 ]
rpmsg device remove code is duplicated in at-least 2-3 places, add a helper function to remove this duplicated code.
Stable-dep-of: 5a5a48e788e0 ("rpmsg: glink: fix deadlock in endpoint destroy during driver detach")
--- drivers/rpmsg/qcom_glink_native.c | 43 ++++++++++++------------------- 1 file changed, 16 insertions(+), 27 deletions(-)
drivers/rpmsg/qcom_glink_native.c +16 -27
@@ -1240,11 +1240,23 @@ static int qcom_glink_announce_create(struct rpmsg_device *rpdev)return 0 ; } +static void qcom_glink_remove_rpmsg_device (struct qcom_glink *glink,struct glink_channel *channel) +{ +struct rpmsg_channel_info chinfo; + +if (channel->rpdev) { +strscpy_pad (chinfo.name, channel->name,sizeof (chinfo.name)); + chinfo.src =RPMSG_ADDR_ANY ; + chinfo.dst =RPMSG_ADDR_ANY ; +rpmsg_unregister_device (glink->dev, &chinfo); + } + channel->rpdev =NULL ; +} +static void qcom_glink_destroy_ept (struct rpmsg_endpoint *ept) {struct glink_channel *channel =to_glink_channel (ept);struct qcom_glink *glink = channel->glink; -struct rpmsg_channel_info chinfo;unsigned long flags;spin_lock_irqsave (&channel->recv_lock, flags);
@@ -1252,14 +1264,7 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint *ept)spin_unlock_irqrestore (&channel->recv_lock, flags);/* Decouple the potential rpdev from the channel */ -if (channel->rpdev) { -strscpy_pad (chinfo.name, channel->name,sizeof (chinfo.name)); - chinfo.src =RPMSG_ADDR_ANY ; - chinfo.dst =RPMSG_ADDR_ANY ; - -rpmsg_unregister_device (glink->dev, &chinfo); - } - channel->rpdev =NULL ; +qcom_glink_remove_rpmsg_device (glink, channel);qcom_glink_send_close_req (glink, channel); }
@@ -1535,7 +1540,6 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid,static void qcom_glink_rx_close (struct qcom_glink *glink,unsigned int rcid) { -struct rpmsg_channel_info chinfo;struct glink_channel *channel;unsigned long flags;
@@ -1548,14 +1552,7 @@ static void qcom_glink_rx_close(struct qcom_glink *glink, unsigned int rcid)/* cancel pending rx_done work */ cancel_work_sync (&channel->intent_work); -if (channel->rpdev) { -strscpy_pad (chinfo.name, channel->name,sizeof (chinfo.name)); - chinfo.src =RPMSG_ADDR_ANY ; - chinfo.dst =RPMSG_ADDR_ANY ; - -rpmsg_unregister_device (glink->dev, &chinfo); - } - channel->rpdev =NULL ; +qcom_glink_remove_rpmsg_device (glink, channel);qcom_glink_send_close_ack (glink, channel->rcid);
@@ -1569,7 +1566,6 @@ static void qcom_glink_rx_close(struct qcom_glink *glink, unsigned int rcid)static void qcom_glink_rx_close_ack (struct qcom_glink *glink,unsigned int lcid) { -struct rpmsg_channel_info chinfo;struct glink_channel *channel;unsigned long flags;
@@ -1588,14 +1584,7 @@ static void qcom_glink_rx_close_ack(struct qcom_glink *glink, unsigned int lcid)spin_unlock_irqrestore (&glink->idr_lock, flags);/* Decouple the potential rpdev from the channel */ -if (channel->rpdev) { -strscpy (chinfo.name, channel->name,sizeof (chinfo.name)); - chinfo.src =RPMSG_ADDR_ANY ; - chinfo.dst =RPMSG_ADDR_ANY ; - -rpmsg_unregister_device (glink->dev, &chinfo); - } - channel->rpdev =NULL ; +qcom_glink_remove_rpmsg_device (glink, channel);kref_put (&channel->refcount, qcom_glink_channel_release); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 439/798 rpmsg: glink: fix deadlock in endpoint destroy during driver detach
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vishnu Santhosh <[email protected]>
[ Upstream commit 5a5a48e788e02fd8a8eb7188ce440572d6c12418 ]
During driver detach, the device core holds the device mutex throughout the driver's remove callback chain. When the rpmsg endpoint is destroyed as part of that teardown, the GLINK endpoint destroy implementation attempts to unregister the underlying rpmsg device. That unregistration calls device_del(), which tries to re-acquire the same device mutex already held higher up the stack, causing rmmod to hang indefinitely.
The deadlock manifests with the following call chain:
[<0>] device_del+0x44/0x414 <- tries to acquire same mutex [<0>] device_unregister+0x18/0x34 [<0>] rpmsg_unregister_device+0x28/0x4c [<0>] qcom_glink_remove_rpmsg_device+0x70/0xc0 [<0>] qcom_glink_destroy_ept+0x58/0xbc [<0>] rpmsg_dev_remove+0x50/0x60 [<0>] device_remove+0x4c/0x80 [<0>] device_release_driver_internal+0x1cc/0x228 <- acquires device mutex [<0>] driver_detach+0x4c/0x98 [<0>] bus_remove_driver+0x6c/0xbc [<0>] driver_unregister+0x30/0x60 [<0>] unregister_rpmsg_driver+0x10/0x1c [<0>] fastrpc_exit+0x28/0x38 [fastrpc] [<0>] __arm64_sys_delete_module+0x1b8/0x294 [<0>] invoke_syscall+0x48/0x10c [<0>] el0_svc_common.constprop.0+0xc0/0xe0 [<0>] do_el0_svc+0x1c/0x28 [<0>] el0_svc+0x34/0x108 [<0>] el0t_64_sync_handler+0xa0/0xe4 [<0>] el0t_64_sync+0x198/0x19c
The rpmsg device unregistration inside endpoint destroy is redundant. In both contexts where endpoint destruction is triggered:
- Driver detach path: the driver core already tears down the rpmsg device.
- Channel close path: the rpmsg device is already unregistered before endpoint destruction is reached.
Remove the redundant unregistration to fix the deadlock.
--- drivers/rpmsg/qcom_glink_native.c | 3 --- 1 file changed, 3 deletions(-)
drivers/rpmsg/qcom_glink_native.c +0 -3
@@ -1263,9 +1263,6 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint *ept) channel->ept.cb =NULL ;spin_unlock_irqrestore (&channel->recv_lock, flags); -/* Decouple the potential rpdev from the channel */ -qcom_glink_remove_rpmsg_device (glink, channel); -qcom_glink_send_close_req (glink, channel); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 440/798 hfsplus: validate thread record before delete key rebuild
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kyle Zeng <[email protected]>
[ Upstream commit e2ea5cac61acfc11dad22f1d2d4bc71d56c52a20 ]
hfsplus_delete_cat() is called with str == NULL when the last open reference to an unlinked HFS+ hardlink backing inode is closed. In that case, the function finds the catalog thread by CNID and rebuilds the catalog key from thread.nodeName.
That reconstruction path reads thread.nodeName.length directly from the catalog B-tree into fd.search_key and then copies length * 2 bytes into fd.search_key->cat.name.unicode. It does not first check that the found record is a thread record or that its size matches the thread name.
A corrupted image can therefore provide an oversized thread name length and make hfs_bnode_read() write past the catalog search-key allocation.
Read the CNID record through hfsplus_brec_read_cat(), which bounds the record read to sizeof(hfsplus_cat_entry) and verifies that a thread record's size exactly matches nodeName.length. Together, these checks ensure an accepted thread name fits HFSPLUS_MAX_STRLEN. Reject non-thread records before building the delete key from the validated thread name.
Share the thread-record-type helper between hfsplus_find_cat() and hfsplus_delete_cat().
--- fs/hfsplus/catalog.c | 25 ++++++++++++------------- fs/hfsplus/hfsplus_fs.h | 6 ++++++ 2 files changed, 18 insertions(+), 13 deletions(-)
fs/hfsplus/catalog.c +12 -13
@@ -204,7 +204,7 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid,return err; type =be16_to_cpu (tmp.type); -if (type !=HFSPLUS_FOLDER_THREAD && type !=HFSPLUS_FILE_THREAD ) { +if (!is_hfs_thread_record_type (type)) {pr_err ("found bad thread record in catalog\n" );return -EIO ; }
@@ -350,23 +350,22 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, const struct qstr *str) goto out;if (!str) { -int len; +hfsplus_cat_entry entry = {0 };hfsplus_cat_build_key_with_cnid (sb, fd.search_key, cnid); - err =hfs_brec_find (&fd, hfs_find_rec_by_key); + err =hfsplus_brec_read_cat (&fd, &entry);if (err) goto out; - off = fd.entryoffset + - offsetof(struct hfsplus_cat_thread , nodeName); - fd.search_key->cat.parent =cpu_to_be32 (dir->i_ino); -hfs_bnode_read (fd.bnode, - &fd.search_key->cat.name.length, off,2 ); - len =be16_to_cpu (fd.search_key->cat.name.length) *2 ; -hfs_bnode_read (fd.bnode, - &fd.search_key->cat.name.unicode, - off +2 , len); - fd.search_key->key_len =cpu_to_be16 (6 + len); + type =be16_to_cpu (entry.type); +if (!is_hfs_thread_record_type (type)) { +pr_err ("found bad thread record in catalog\n" ); + err = -EIO ; + goto out; + } + +hfsplus_cat_build_key_uni (fd.search_key, dir->i_ino, + &entry.thread.nodeName); }else { err =hfsplus_cat_build_key (sb, fd.search_key, dir->i_ino, str);if (unlikely (err))
fs/hfsplus/hfsplus_fs.h +6 -0
@@ -543,6 +543,12 @@ static inline u32 hfsplus_cat_thread_size(const struct hfsplus_cat_thread *threabe16_to_cpu (thread->nodeName.length) *sizeof (hfsplus_unichr); } +static inline +bool is_hfs_thread_record_type (u16 type) +{ +return type ==HFSPLUS_FOLDER_THREAD || type ==HFSPLUS_FILE_THREAD ; +} +int hfsplus_brec_read_cat (struct hfs_find_data *fd,hfsplus_cat_entry *entry);/*
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 441/798 wifi: ath11k: cap out-of-range rx MCS instead of leaving bogus rate
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baochen Qiang <[email protected]>
[ Upstream commit 12b09e478aa7459b7893a695ef77682202f2da83 ]
ath11k can receive HT/VHT/HE frames whose reported MCS is above the maximum that can be expressed in the corresponding mac80211 rate space (e.g. an HE frame reported with MCS 12, while HE tops out at MCS 11).
The frame itself is valid and decodes correctly, but for such a frame ath11k_dp_rx_h_rate() leaves rx_status->rate_idx set to the out-of-range value and never assigns rx_status->encoding, so it stays RX_ENC_LEGACY from the ath11k_dp_rx_h_ppdu() initialization. Once that frame reaches mac80211 it trips the rate sanity check and the frame is dropped with a splat:
ath11k_pci 0000:03:00.0: Received with invalid mcs in HE mode 12
WARNING: CPU: 0 PID: 0 at net/mac80211/rx.c:5433 ieee80211_rx_list+0xb0a/0xe90 [mac80211]
Dropping the frame would discard otherwise valid data, so instead cap the reported MCS to the maximum the rate space can express and deliver the frame. Set rx_status->encoding before the range check and assign rate_idx from the capped value, so a frame with an out-of-range MCS no longer leaves partial or bogus rate metadata behind. Also downgrade the logging level since they are not treated as invalid frames now. The only loss is that such a frame is reported as the capped MCS in the rx rate statistics.
Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.41
--- drivers/net/wireless/ath/ath11k/dp_rx.c | 30 ++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-)
drivers/net/wireless/ath/ath11k/dp_rx.c +15 -15
@@ -2272,10 +2272,10 @@ static void ath11k_dp_rx_h_rate(struct ath11k *ar, struct hal_rx_desc *rx_desc,case RX_MSDU_START_PKT_TYPE_11N : rx_status->encoding =RX_ENC_HT ;if (rate_mcs >ATH11K_HT_MCS_MAX ) { -ath11k_warn (ar->ab, -"Received with invalid mcs in HT mode %d\n" , - rate_mcs); -break ; +ath11k_dbg (ar->ab,ATH11K_DBG_DP_RX , +"Received HT frame with out-of-range mcs %d, capping to %d\n" , + rate_mcs,ATH11K_HT_MCS_MAX ); + rate_mcs =ATH11K_HT_MCS_MAX ; } rx_status->rate_idx = rate_mcs + (8 * (nss -1 ));if (sgi)
@@ -2284,27 +2284,27 @@ static void ath11k_dp_rx_h_rate(struct ath11k *ar, struct hal_rx_desc *rx_desc,break ;case RX_MSDU_START_PKT_TYPE_11AC : rx_status->encoding =RX_ENC_VHT ; - rx_status->rate_idx = rate_mcs;if (rate_mcs >ATH11K_VHT_MCS_MAX ) { -ath11k_warn (ar->ab, -"Received with invalid mcs in VHT mode %d\n" , - rate_mcs); -break ; +ath11k_dbg (ar->ab,ATH11K_DBG_DP_RX , +"Received VHT frame with out-of-range mcs %d, capping to %d\n" , + rate_mcs,ATH11K_VHT_MCS_MAX ); + rate_mcs =ATH11K_VHT_MCS_MAX ; } + rx_status->rate_idx = rate_mcs; rx_status->nss = nss;if (sgi) rx_status->enc_flags |=RX_ENC_FLAG_SHORT_GI ; rx_status->bw =ath11k_mac_bw_to_mac80211_bw (bw);break ;case RX_MSDU_START_PKT_TYPE_11AX : - rx_status->rate_idx = rate_mcs; + rx_status->encoding =RX_ENC_HE ;if (rate_mcs >ATH11K_HE_MCS_MAX ) { -ath11k_warn (ar->ab, -"Received with invalid mcs in HE mode %d\n" , - rate_mcs); -break ; +ath11k_dbg (ar->ab,ATH11K_DBG_DP_RX , +"Received HE frame with out-of-range mcs %d, capping to %d\n" , + rate_mcs,ATH11K_HE_MCS_MAX ); + rate_mcs =ATH11K_HE_MCS_MAX ; } - rx_status->encoding =RX_ENC_HE ; + rx_status->rate_idx = rate_mcs; rx_status->nss = nss; rx_status->he_gi =ath11k_he_gi_to_nl80211_he_gi (sgi); rx_status->bw =ath11k_mac_bw_to_mac80211_bw (bw);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 442/798 libnvdimm/labels: Bound the on-media label size before the shift
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
[ Upstream commit 18f9124248ed7a9da1c31973b629dceef76a9b0c ]
For a v1.2+ index, __nd_label_validate() computes the label size as 1 << (7 + nsindex[i]->labelsize), where labelsize is a u8 read from the label storage medium. A value of 25 or more makes the shift count reach or exceed the width of int -- undefined behavior -- and 24 already shifts into the sign bit. Only 0 (128-byte) and 1 (256-byte) are valid.
Reject a labelsize above 1 before the shift. The result was rejected by the following size comparison anyway, so this only removes the undefined shift on a crafted or corrupted medium; conforming labels are unaffected.
--- drivers/nvdimm/label.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
drivers/nvdimm/label.c +13 -2
@@ -137,10 +137,21 @@ static int __nd_label_validate(struct nvdimm_drvdata *ndd)/* label sizes larger than 128 arrived with v1.2 */ version =__le16_to_cpu (nsindex[i]->major) *100 +__le16_to_cpu (nsindex[i]->minor); -if (version >=102 ) +if (version >=102 ) { +/* +* labelsize feeds the shift below; only 0 (128-byte) +* and 1 (256-byte) are valid -- a larger value would +* overflow or exceed the width of int. +*/ +if (nsindex[i]->labelsize >1 ) { +dev_dbg (dev,"nsindex%d labelsize: %d invalid\n" , + i, nsindex[i]->labelsize); +continue ; + } labelsize =1 << (7 + nsindex[i]->labelsize); -else + }else { labelsize =128 ; + }if (labelsize !=sizeof_namespace_label (ndd)) { dev_dbg(dev, "nsindex%d labelsize %d invalid\n",
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 443/798 cpufreq: spear: Fix an IS_ERR() vs NULL bug in spear1340_set_cpu_rate()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit 6a9e0e0f7592313ace66303cf5eca68e04c10f30 ]
The clk_get_parent() function doesn't return error pointers, it returns NULL on error. Update the error checking to match.
--- drivers/cpufreq/spear-cpufreq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/cpufreq/spear-cpufreq.c +2 -2
@@ -79,9 +79,9 @@ static int spear1340_set_cpu_rate(struct clk *sys_pclk, unsigned long newfreq)int ret =0 ; sys_clk =clk_get_parent (spear_cpufreq.clk); -if (IS_ERR (sys_clk)) { +if (!sys_clk) {pr_err ("failed to get cpu's parent (sys) clock\n" ); -return PTR_ERR (sys_clk); +return -EINVAL ; }/* Set the rate of the source clock before changing the parent */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 444/798 irqdomain: Introduce irq_domain_instantiate()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Herve Codina <[email protected]>
[ Upstream commit 299d623f5c9ab48e53255cf6b510627f1ef26dfe ]
The existing irq_domain_add_*() functions used to instantiate an IRQ domain are wrappers built on top of __irq_domain_add() and describe the domain properties using a bunch of parameters.
Adding more parameters and wrappers to hide new parameters in the existing code lead to more and more code without any relevant value and without any flexibility.
Introduce irq_domain_instantiate() where the interrupt domain properties are given using a irq_domain_info structure instead of the bunch of parameters to allow flexibility and easy evolution.
irq_domain_instantiate() performs the same operation as the one done by __irq_domain_add(). For compatibility reason with existing code, keep __irq_domain_add() but convert it to irq_domain_instantiate().
[ tglx: Fixed up struct initializer coding style ]
Stable-dep-of: 616dd89d81ad ("irqchip/renesas-irqc: Fix generic interrupt chip leak on remove")
--- include/linux/irqdomain.h | 21 +++++++++++++++++++++ kernel/irq/irqdomain.c | 39 ++++++++++++++++++++++++++++++++------- 2 files changed, 53 insertions(+), 7 deletions(-)
include/linux/irqdomain.h +21 -0
@@ -266,6 +266,27 @@ static inline struct fwnode_handle *irq_domain_alloc_fwnode(phys_addr_t *pa) }void irq_domain_free_fwnode (struct fwnode_handle *fwnode); +/** +* struct irq_domain_info - Domain information structure +* @fwnode: firmware node for the interrupt controller +* @size: Size of linear map; 0 for radix mapping only +* @hwirq_max: Maximum number of interrupts supported by controller +* @direct_max: Maximum value of direct maps; +* Use ~0 for no limit; 0 for no direct mapping +* @ops: Domain operation callbacks +* @host_data: Controller private data pointer +*/ +struct irq_domain_info { +struct fwnode_handle *fwnode; +unsigned int size; +irq_hw_number_t hwirq_max; +int direct_max; +const struct irq_domain_ops *ops; +void *host_data; +}; + +struct irq_domain *irq_domain_instantiate (const struct irq_domain_info *info); + struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, unsigned int size, irq_hw_number_t hwirq_max, int direct_max, const struct irq_domain_ops *ops,
kernel/irq/irqdomain.c +32 -7
@@ -212,6 +212,27 @@ static void __irq_domain_publish(struct irq_domain *domain)pr_debug ("Added domain %s\n" , domain->name); } +/** +* irq_domain_instantiate() - Instantiate a new irq domain data structure +* @info: Domain information pointer pointing to the information for this domain +* +* Return: A pointer to the instantiated irq domain or an ERR_PTR value. +*/ +struct irq_domain *irq_domain_instantiate (const struct irq_domain_info *info) +{ +struct irq_domain *domain; + + domain =__irq_domain_create (info->fwnode, info->size, info->hwirq_max, + info->direct_max, info->ops, info->host_data); +if (!domain) +return ERR_PTR (-ENOMEM ); + +__irq_domain_publish (domain); + +return domain; +} +EXPORT_SYMBOL_GPL (irq_domain_instantiate); +/** * __irq_domain_add() - Allocate a new irq_domain data structure * @fwnode: firmware node for the interrupt controller
@@ -230,14 +251,18 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, unsigned int sconst struct irq_domain_ops *ops, void *host_data) { - struct irq_domain *domain; - - domain =__irq_domain_create (fwnode, size, hwirq_max, direct_max, - ops, host_data); -if (domain) -__irq_domain_publish (domain); + struct irq_domain_info info = { + .fwnode = fwnode, + .size = size, + .hwirq_max = hwirq_max, + .direct_max = direct_max, + .ops = ops, + .host_data = host_data, + }; +struct irq_domain *d; -return domain; + d =irq_domain_instantiate (&info); +return IS_ERR (d) ?NULL : d; }EXPORT_SYMBOL_GPL (__irq_domain_add);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 445/798 irqdomain: Handle additional domain flags in irq_domain_instantiate()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Herve Codina <[email protected]>
[ Upstream commit 757398541c30a5e898169763b43f08dab71ea3bd ]
In order to use irq_domain_instantiate() from several places such as irq_domain_create_hierarchy(), irq_domain_instantiate() needs to handle additional domain flags.
Add the required infrastructure.
Stable-dep-of: 616dd89d81ad ("irqchip/renesas-irqc: Fix generic interrupt chip leak on remove")
--- include/linux/irqdomain.h | 2 ++ kernel/irq/irqdomain.c | 2 ++ 2 files changed, 4 insertions(+)
include/linux/irqdomain.h +2 -0
@@ -269,6 +269,7 @@ void irq_domain_free_fwnode(struct fwnode_handle *fwnode);/** * struct irq_domain_info - Domain information structure * @fwnode: firmware node for the interrupt controller +* @domain_flags: Additional flags to add to the domain flags * @size: Size of linear map; 0 for radix mapping only * @hwirq_max: Maximum number of interrupts supported by controller * @direct_max: Maximum value of direct maps;
@@ -278,6 +279,7 @@ void irq_domain_free_fwnode(struct fwnode_handle *fwnode);*/ struct irq_domain_info {struct fwnode_handle *fwnode; +unsigned int domain_flags;unsigned int size;irq_hw_number_t hwirq_max;int direct_max;
kernel/irq/irqdomain.c +2 -0
@@ -227,6 +227,8 @@ struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info)if (!domain)return ERR_PTR (-ENOMEM ); + domain->flags |= info->domain_flags; +__irq_domain_publish (domain);return domain;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 446/798 cpufreq: intel_pstate: Simplify intel_cpufreq_update_pstate()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
[ Upstream commit 2554c32f0b84df1f506546125c9d15c8044a2ec2 ]
Avoid doing the same assignment in both branches of a conditional, do it after the whole conditional instead.
Stable-dep-of: db53c573d31d ("cpufreq: intel_pstate: Fix setting minimum P-state at init time")
--- drivers/cpufreq/intel_pstate.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/cpufreq/intel_pstate.c +4 -5
@@ -2572,14 +2572,13 @@ static int intel_cpufreq_update_pstate(struct cpufreq_policy *policy,int old_pstate = cpu->pstate.current_pstate; target_pstate =intel_pstate_prepare_request (cpu, target_pstate); -if (hwp_active) { +if (hwp_active)intel_cpufreq_adjust_hwp (cpu, target_pstate, policy->strict_target, fast_switch); - cpu->pstate.current_pstate = target_pstate; - }else if (target_pstate != old_pstate) { +else if (target_pstate != old_pstate)intel_cpufreq_adjust_perf_ctl (cpu, target_pstate, fast_switch); - cpu->pstate.current_pstate = target_pstate; - } + + cpu->pstate.current_pstate = target_pstate;intel_cpufreq_trace (cpu, fast_switch ?INTEL_PSTATE_TRACE_FAST_SWITCH :INTEL_PSTATE_TRACE_TARGET , old_pstate);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 447/798 cpufreq: schedutil: Add util to struct sg_cpu
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
[ Upstream commit ca6827de4b67367e73fdf43d2ea0a0064423edfb ]
Instead of passing util and max between functions while computing the utilization and capacity, store the former in struct sg_cpu (along with the latter and bw_dl).
This will allow the current utilization value to be compared with the one obtained previously (which is requisite for some code changes to follow this one), but also it causes the code to look slightly more consistent and cleaner.
Stable-dep-of: db53c573d31d ("cpufreq: intel_pstate: Fix setting minimum P-state at init time")
--- kernel/sched/cpufreq_schedutil.c | 42 +++++++++++++++----------------- 1 file changed, 20 insertions(+), 22 deletions(-)
kernel/sched/cpufreq_schedutil.c +20 -22
@@ -53,6 +53,7 @@ struct sugov_cpu {unsigned int iowait_boost;u64 last_update; +unsigned long util;unsigned long bw_dl;unsigned long max;
@@ -310,16 +311,15 @@ unsigned long schedutil_cpu_util(int cpu, unsigned long util_cfs,return min (max, util); } -static unsigned long sugov_get_util (struct sugov_cpu *sg_cpu) +static void sugov_get_util (struct sugov_cpu *sg_cpu) {struct rq *rq =cpu_rq (sg_cpu->cpu); -unsigned long util =cpu_util_cfs (rq);unsigned long max =arch_scale_cpu_capacity (sg_cpu->cpu); sg_cpu->max = max; sg_cpu->bw_dl =cpu_bw_dl (rq); - -return schedutil_cpu_util (sg_cpu->cpu, util, max,FREQUENCY_UTIL ,NULL ); + sg_cpu->util =schedutil_cpu_util (sg_cpu->cpu,cpu_util_cfs (rq), max, +FREQUENCY_UTIL ,NULL ); }/**
@@ -396,8 +396,6 @@ static void sugov_iowait_boost(struct sugov_cpu *sg_cpu, u64 time,* sugov_iowait_apply() - Apply the IO boost to a CPU. * @sg_cpu: the sugov data for the cpu to boost * @time: the update time from the caller -* @util: the utilization to (eventually) boost -* @max: the maximum value the utilization can be boosted to * * A CPU running a task which woken up after an IO operation can have its * utilization boosted to speed up the completion of those IO operations.
@@ -411,18 +409,17 @@ static void sugov_iowait_boost(struct sugov_cpu *sg_cpu, u64 time,* This mechanism is designed to boost high frequently IO waiting tasks, while * being more conservative on tasks which does sporadic IO operations. */ -static unsigned long sugov_iowait_apply (struct sugov_cpu *sg_cpu,u64 time, -unsigned long util,unsigned long max) +static void sugov_iowait_apply (struct sugov_cpu *sg_cpu,u64 time) {unsigned long boost;/* No boost currently required */ if (!sg_cpu->iowait_boost) -return util; +return ;/* Reset boost if the CPU appears to have been idle enough */ if (sugov_iowait_reset (sg_cpu, time, false)) -return util; +return ;if (!sg_cpu->iowait_boost_pending) {/*
@@ -431,18 +428,19 @@ static unsigned long sugov_iowait_apply(struct sugov_cpu *sg_cpu, u64 time, sg_cpu->iowait_boost >>=1 ;if (sg_cpu->iowait_boost <IOWAIT_BOOST_MIN ) { sg_cpu->iowait_boost =0 ; -return util; +return ; } } sg_cpu->iowait_boost_pending = false;/* -* @util is already in capacity scale; convert iowait_boost +* sg_cpu->util is already in capacity scale; convert iowait_boost * into the same scale so we can compare. */ - boost = (sg_cpu->iowait_boost * max) >>SCHED_CAPACITY_SHIFT ; -return max (boost, util); + boost = (sg_cpu->iowait_boost * sg_cpu->max) >>SCHED_CAPACITY_SHIFT ; +if (sg_cpu->util < boost) + sg_cpu->util = boost; }#ifdef CONFIG_NO_HZ_COMMON
@@ -473,9 +471,8 @@ static void sugov_update_single(struct update_util_data *hook, u64 time, { struct sugov_cpu *sg_cpu = container_of(hook, struct sugov_cpu, update_util);struct sugov_policy *sg_policy = sg_cpu->sg_policy; -unsigned long util, max; -unsigned int next_f;unsigned int cached_freq = sg_policy->cached_raw_freq; +unsigned int next_f;sugov_iowait_boost (sg_cpu, time, flags); sg_cpu->last_update = time;
@@ -485,10 +482,10 @@ static void sugov_update_single(struct update_util_data *hook, u64 time,if (!sugov_should_update_freq (sg_policy, time))return ; - util =sugov_get_util (sg_cpu); - max = sg_cpu->max; - util =sugov_iowait_apply (sg_cpu, time, util, max); - next_f =get_next_freq (sg_policy, util, max); +sugov_get_util (sg_cpu); +sugov_iowait_apply (sg_cpu, time); + + next_f =get_next_freq (sg_policy, sg_cpu->util, sg_cpu->max);/* * Do not reduce the frequency if the CPU has not been idle * recently, as the reduction is likely to be premature then.
@@ -525,9 +522,10 @@ static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu, u64 time)struct sugov_cpu *j_sg_cpu = &per_cpu (sugov_cpu, j);unsigned long j_util, j_max; - j_util =sugov_get_util (j_sg_cpu); +sugov_get_util (j_sg_cpu); +sugov_iowait_apply (j_sg_cpu, time); + j_util = j_sg_cpu->util; j_max = j_sg_cpu->max; - j_util =sugov_iowait_apply (j_sg_cpu, time, j_util, j_max);if (j_util * max > j_max * util) { util = j_util;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 448/798 cpufreq: schedutil: Fix self-contradictory comment in sugov_iowait_apply()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhongqiu Han <[email protected]>
[ Upstream commit db6a017c91b774c15b1b890db45981eacfff540e ]
The kerneldoc of sugov_iowait_apply() says the IO boost value is increased in sugov_iowait_apply() and, in the same sentence, that it is decreased by the same function. That is self-contradictory, and the first part is wrong:sugov_iowait_apply() only decreases the boost.
The boost is actually increased in sugov_iowait_boost(). Fix the comment to name sugov_iowait_boost() as the place where the boost is increased, so it matches the code.
No functional change.
--- kernel/sched/cpufreq_schedutil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/sched/cpufreq_schedutil.c +1 -1
@@ -400,7 +400,7 @@ static void sugov_iowait_boost(struct sugov_cpu *sg_cpu, u64 time,* A CPU running a task which woken up after an IO operation can have its * utilization boosted to speed up the completion of those IO operations. * The IO boost value is increased each time a task wakes up from IO, in -* sugov_iowait_apply(), and it's instead decreased by this function, +* sugov_iowait_boost(), and it's instead decreased by this function, * each time an increase has not been requested (!iowait_boost_pending). * * A CPU which also appears to have been idle for at least one tick has also
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 449/798 remoteproc: qcom: Fix glink->node reference leak in qcom_add_glink_subdev
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uday Khare <[email protected]>
[ Upstream commit 44f4911ab8e6f4d69afad5f2571bbd2da421c918 ]
In qcom_add_glink_subdev(), the device node reference acquired via of_get_child_by_name() is stored in glink->node. If the subsequent kstrdup_const() allocation for glink->ssr_name fails, the function returns early without calling of_node_put() on glink->node, leaking the reference count.
Fix this by adding of_node_put(glink->node) on the error path before returning.
--- drivers/remoteproc/qcom_common.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/remoteproc/qcom_common.c +3 -1
@@ -74,8 +74,10 @@ void qcom_add_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink,return ; glink->ssr_name =kstrdup_const (ssr_name,GFP_KERNEL ); -if (!glink->ssr_name) +if (!glink->ssr_name) { +of_node_put (glink->node);return ; + } glink->dev = dev; glink->subdev.start = glink_subdev_start;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 450/798 drm/bridge: tc358767: clamp the reported AUX read size to the request
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maoyi Xie <[email protected]>
[ Upstream commit ec6444a00c49e6c2b5e9a507272a28126677f9ee ]
tc_aux_transfer() clamps an AUX read to the payload limit:
size_t size = min_t(size_t, DP_AUX_MAX_PAYLOAD_BYTES - 1, msg->size);
After the transfer it replaces size with the byte count the controller reports in AUX_BYTES:
if (size) size = FIELD_GET(AUX_BYTES, auxstatus);
AUX_BYTES is GENMASK(15, 8), so it can be up to 255. Nothing clamps it back to the request. tc_aux_read_data() reads that many bytes into the 16-byte auxrdata stack buffer, then copies them into the caller buffer. A reported count of 255 makes the read run to 256 bytes and overruns both.
The controller should never report more than it was asked to transfer, so this is defense in depth rather than a live hole. The reported count is only lightly trusted, and the check is cheap. Clamp it back to the request, the same way ti-sn65dsi86 does in commit aca58eac52b8 ("drm/bridge:
ti-sn65dsi86: Never store more than msg->size bytes in AUX xfer").
--- drivers/gpu/drm/bridge/tc358767.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/bridge/tc358767.c +1 -1
@@ -395,7 +395,7 @@ static ssize_t tc_aux_transfer(struct drm_dp_aux *aux,* address-only transfer */ if (size) - size =FIELD_GET (AUX_BYTES , auxstatus); + size =min_t (size_t, size,FIELD_GET (AUX_BYTES , auxstatus)); msg->reply =FIELD_GET (AUX_STATUS , auxstatus);switch (request) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 451/798 gpu: host1x: Fix offset calculation in trace_write_gather
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikko Perttunen <[email protected]>
[ Upstream commit eb896850964d3dfce291b4fdff9c2d42d85e564b ]
When a gather longer than 2*TRACE_MAX_LENGTH (256) words is traced through host1x_cdma_push_gather, the reported BO offset drifts from the third iteration onward.
Fix the calculation by properly calculating the value on each loop rather than accumulating.
In reality, gathers tend to be pretty short so this is unlikely to ever have been observed.
--- drivers/gpu/host1x/hw/channel_hw.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/gpu/host1x/hw/channel_hw.c +2 -3
@@ -36,10 +36,9 @@ static void trace_write_gather(struct host1x_cdma *cdma, struct host1x_bo *bo,for (i =0 ; i < words; i +=TRACE_MAX_LENGTH ) {u32 num_words =min (words - i,TRACE_MAX_LENGTH ); - offset += i *sizeof (u32); -trace_host1x_cdma_push_gather (dev_name (dev), bo, - num_words, offset, + num_words, + offset + i *sizeof (u32), mem); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 452/798 gpu: host1x: Avoid stack over-read in debug output helpers
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikko Perttunen <[email protected]>
[ Upstream commit bc17ac285fb708f22a8fa2c0ed32eceb1d37e6d6 ]
host1x_debug_output() and host1x_debug_cont() used vsnprintf(), which returns the length the formatted string would have reached with an unbounded buffer. That return value was passed straight to o->fn as the number of bytes to emit.
This could cause a read past end of the output buffer if a call to host1x_debug_* produced a string longer than 256 bytes. This only affected the debugfs files as the printk debug sink ignores the number of bytes. In practice, this is very unlikely to occur.
Fix by switching to vscnprintf(), which returns the number of bytes actually written.
--- drivers/gpu/host1x/debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/host1x/debug.c +2 -2
@@ -30,7 +30,7 @@ void host1x_debug_output(struct output *o, const char *fmt, ...)int len;va_start (args, fmt); - len =vsnprintf (o->buf,sizeof (o->buf), fmt, args); + len =vscnprintf (o->buf,sizeof (o->buf), fmt, args);va_end (args); o->fn (o->ctx, o->buf, len, false);
@@ -42,7 +42,7 @@ void host1x_debug_cont(struct output *o, const char *fmt, ...)int len;va_start (args, fmt); - len =vsnprintf (o->buf,sizeof (o->buf), fmt, args); + len =vscnprintf (o->buf,sizeof (o->buf), fmt, args);va_end (args); o->fn (o->ctx, o->buf, len, true);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 453/798 media: ACPI / bus: Add acpi_dev_get_next_match_dev() and helper macro
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Scally <[email protected]>
[ Upstream commit bf263f64e804a74ace9bd37f49341d68a653e5e6 ]
To ensure we handle situations in which multiple sensors of the same model (and therefore _HID) are present in a system, we need to be able to iterate over devices matching a known _HID but unknown _UID and _HRV
- add acpi_dev_get_next_match_dev() to accommodate that possibility and
change acpi_dev_get_first_match_dev() to simply call the new function with a NULL starting point. Add an iterator macro for convenience.
Stable-dep-of: d5c13047a132 ("ACPI: processor: idle: Expand _LPI package sanity checks")
--- drivers/acpi/utils.c | 30 ++++++++++++++++++++++++++---- include/acpi/acpi_bus.h | 7 +++++++ 2 files changed, 33 insertions(+), 4 deletions(-)
drivers/acpi/utils.c +26 -4
@@ -843,12 +843,13 @@ bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)EXPORT_SYMBOL (acpi_dev_present);/** -* acpi_dev_get_first_match_dev - Return the first match of ACPI device +* acpi_dev_get_next_match_dev - Return the next match of ACPI device +* @adev: Pointer to the previous acpi_device matching this @hid, @uid and @hrv * @hid: Hardware ID of the device. * @uid: Unique ID of the device, pass NULL to not check _UID * @hrv: Hardware Revision of the device, pass -1 to not check _HRV * -* Return the first match of ACPI device if a matching device was present +* Return the next match of ACPI device if another matching device was present * at the moment of invocation, or NULL otherwise. * * The caller is responsible to call put_device() on the returned device.
@@ -856,8 +857,9 @@ EXPORT_SYMBOL(acpi_dev_present);* See additional information in acpi_dev_present() as well. */ struct acpi_device * -acpi_dev_get_first_match_dev (const char *hid,const char *uid,s64 hrv) +acpi_dev_get_next_match_dev (struct acpi_device *adev,const char *hid,const char *uid,s64 hrv) { +struct device *start = adev ? &adev->dev :NULL ;struct acpi_dev_match_info match = {};struct device *dev;
@@ -865,9 +867,29 @@ acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv) match.uid = uid; match.hrv = hrv; - dev =bus_find_device (&acpi_bus_type,NULL , &match, acpi_dev_match_cb); + dev =bus_find_device (&acpi_bus_type, start, &match, acpi_dev_match_cb);return dev ?to_acpi_device (dev) :NULL ; } +EXPORT_SYMBOL (acpi_dev_get_next_match_dev); + +/** +* acpi_dev_get_first_match_dev - Return the first match of ACPI device +* @hid: Hardware ID of the device. +* @uid: Unique ID of the device, pass NULL to not check _UID +* @hrv: Hardware Revision of the device, pass -1 to not check _HRV +* +* Return the first match of ACPI device if a matching device was present +* at the moment of invocation, or NULL otherwise. +* +* The caller is responsible to call put_device() on the returned device. +* +* See additional information in acpi_dev_present() as well. +*/ +struct acpi_device * +acpi_dev_get_first_match_dev (const char *hid,const char *uid,s64 hrv) +{ +return acpi_dev_get_next_match_dev (NULL , hid, uid, hrv); +}EXPORT_SYMBOL (acpi_dev_get_first_match_dev);/*
include/acpi/acpi_bus.h +7 -0
@@ -685,9 +685,16 @@ static inline bool acpi_device_can_poweroff(struct acpi_device *adev)bool acpi_dev_hid_uid_match (struct acpi_device *adev,const char *hid2,const char *uid2); +struct acpi_device * +acpi_dev_get_next_match_dev (struct acpi_device *adev,const char *hid,const char *uid,s64 hrv);struct acpi_device *acpi_dev_get_first_match_dev (const char *hid,const char *uid,s64 hrv); +#define for_each_acpi_dev_match (adev, hid, uid, hrv) \ + for (adev = acpi_dev_get_first_match_dev(hid, uid, hrv); \ + adev; \ + adev = acpi_dev_get_next_match_dev(adev, hid, uid, hrv)) +static inline void acpi_dev_put (struct acpi_device *adev) {if (adev)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 454/798 ACPI: move from strlcpy() with unused retval to strscpy()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wolfram Sang <[email protected]>
[ Upstream commit b75d2cd06b33956b7ec35c6316e717c25a196ee5 ]
Follow the advice of the below link and prefer 'strscpy' in this subsystem. Conversion is 1:1 because the return value is not used. Generated by a coccinelle script.
Stable-dep-of: d5c13047a132 ("ACPI: processor: idle: Expand _LPI package sanity checks")
--- drivers/acpi/bus.c | 4 ++-- drivers/acpi/processor_idle.c | 8 ++++---- drivers/acpi/utils.c | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-)
drivers/acpi/bus.c +2 -2
@@ -681,7 +681,7 @@ static bool acpi_of_modalias(struct acpi_device *adev, str = obj->string.pointer; chr =strchr (str,',' ); -strlcpy (modalias, chr ? chr +1 : str, len); +strscpy (modalias, chr ? chr +1 : str, len);return true; }
@@ -701,7 +701,7 @@ void acpi_set_modalias(struct acpi_device *adev, const char *default_id, char *modalias, size_t len) {if (!acpi_of_modalias (adev, modalias, len)) -strlcpy (modalias, default_id, len); +strscpy (modalias, default_id, len); }EXPORT_SYMBOL_GPL (acpi_set_modalias);
drivers/acpi/processor_idle.c +4 -4
@@ -801,7 +801,7 @@ static int acpi_processor_setup_cstates(struct acpi_processor *pr) state = &drv->states[count];snprintf (state->name,CPUIDLE_NAME_LEN ,"C%d" , i); -strlcpy (state->desc, cx->desc,CPUIDLE_DESC_LEN ); +strscpy (state->desc, cx->desc,CPUIDLE_DESC_LEN ); state->exit_latency = cx->latency; state->target_residency = cx->latency * latency_factor; state->enter = acpi_idle_enter;
@@ -968,7 +968,7 @@ static int acpi_processor_evaluate_lpi(acpi_handle handle, obj = pkg_elem +9 ;if (obj->type ==ACPI_TYPE_STRING ) -strlcpy (lpi_state->desc, obj->string.pointer, +strscpy (lpi_state->desc, obj->string.pointer,ACPI_CX_DESC_LEN ); lpi_state->index = state_idx;
@@ -1034,7 +1034,7 @@ static bool combine_lpi_states(struct acpi_lpi_state *local, result->arch_flags = parent->arch_flags; result->index = parent->index; -strlcpy (result->desc, local->desc,ACPI_CX_DESC_LEN ); +strscpy (result->desc, local->desc,ACPI_CX_DESC_LEN );strlcat (result->desc,"+" ,ACPI_CX_DESC_LEN );strlcat (result->desc, parent->desc,ACPI_CX_DESC_LEN );return true;
@@ -1210,7 +1210,7 @@ static int acpi_processor_setup_lpi_states(struct acpi_processor *pr) state = &drv->states[i];snprintf (state->name,CPUIDLE_NAME_LEN ,"LPI-%d" , i); -strlcpy (state->desc, lpi->desc,CPUIDLE_DESC_LEN ); +strscpy (state->desc, lpi->desc,CPUIDLE_DESC_LEN ); state->exit_latency = lpi->wake_latency; state->target_residency = lpi->min_residency;if (lpi->arch_flags)
drivers/acpi/utils.c +3 -3
@@ -832,7 +832,7 @@ bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)struct acpi_dev_match_info match = {};struct device *dev; -strlcpy (match.hid[0 ].id, hid,sizeof (match.hid[0 ].id)); +strscpy (match.hid[0 ].id, hid,sizeof (match.hid[0 ].id)); match.uid = uid; match.hrv = hrv;
@@ -863,7 +863,7 @@ acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const chastruct acpi_dev_match_info match = {};struct device *dev; -strlcpy (match.hid[0 ].id, hid,sizeof (match.hid[0 ].id)); +strscpy (match.hid[0 ].id, hid,sizeof (match.hid[0 ].id)); match.uid = uid; match.hrv = hrv;
@@ -901,7 +901,7 @@ EXPORT_SYMBOL(acpi_video_backlight_string);static int __init acpi_backlight (char *str) { -strlcpy (acpi_video_backlight_string, str, +strscpy (acpi_video_backlight_string, str,sizeof (acpi_video_backlight_string));return 1 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 455/798 ACPI: processor: idle: Expand _LPI package sanity checks
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
[ Upstream commit d5c13047a132162d2649be876906ead691d12948 ]
The _LPI package sanity checks in acpi_processor_evaluate_lpi() miss a couple of things, so expand them by adding a buffer size check before retrieving a struct acpi_power_register from it (and skip the given state if the buffer is not large enough to hold a register structure) and making the function avoid copying the state description from the ACPI table if there are too few elements in the package supposed to hold it.
While at it, relocate and rephrase a comment about skipping _LPI state package elements [7-8].
--- drivers/acpi/processor_idle.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-)
drivers/acpi/processor_idle.c +21 -7
@@ -948,6 +948,13 @@ static int acpi_processor_evaluate_lpi(acpi_handle handle,if (obj->type ==ACPI_TYPE_BUFFER ) {struct acpi_power_register *reg; +if (obj->buffer.length <sizeof (*reg)) { +acpi_handle_debug (handle, +"Invalid register data for _LPI state %d\n" , + state_idx); +continue ; + } + reg = (struct acpi_power_register *)obj->buffer.pointer;if (reg->space_id !=ACPI_ADR_SPACE_SYSTEM_IO && reg->space_id !=ACPI_ADR_SPACE_FIXED_HARDWARE )
@@ -964,13 +971,6 @@ static int acpi_processor_evaluate_lpi(acpi_handle handle,continue ; } -/* elements[7,8] skipped for now i.e. Residency/Usage counter*/ - - obj = pkg_elem +9 ; -if (obj->type ==ACPI_TYPE_STRING ) -strscpy (lpi_state->desc, obj->string.pointer, -ACPI_CX_DESC_LEN ); - lpi_state->index = state_idx;if (obj_get_integer (pkg_elem +0 , &lpi_state->min_residency)) {pr_debug ("No min. residency found, assuming 10 us\n" );
@@ -993,6 +993,20 @@ static int acpi_processor_evaluate_lpi(acpi_handle handle,if (obj_get_integer (pkg_elem +5 , &lpi_state->enable_parent_state)) lpi_state->enable_parent_state =0 ; + +/* Skip elements [7-8] i.e. Residency/Usage counters. */ + +/* +* Avoid out-of-bounds access if the size of the package is less +* than expected. +*/ +if (element->package.count <10 ) +continue ; + + obj = pkg_elem +9 ; +if (obj->type ==ACPI_TYPE_STRING ) +strscpy (lpi_state->desc, obj->string.pointer, +ACPI_CX_DESC_LEN ); }acpi_handle_debug (handle,"Found %d power states\n" , state_idx);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 456/798 usb: gadget: f_uac1_legacy: remove broken string configfs attributes
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xu Yang <[email protected]>
[ Upstream commit 590d74ec8f488e06b9f1c0f8f0941f45531f3a55 ]
The UAC1_STR_ATTRIBUTE macro defines configfs show/store handlers for the fn_play, fn_cap, and fn_cntl string options. The store function contains an inverted null check on the kstrndup() return value.
This means every write attempt returns -ENOMEM on success and dereferences a NULL pointer on allocation failure. The attributes have been broken and unused for many years.
Remove the UAC1_STR_ATTRIBUTE macro and the three attributes it generated. The internal defaults (FILE_PCM_PLAYBACK, FILE_PCM_CAPTURE, FILE_CONTROL) set in f_audio_alloc_inst() are unaffected.
--- .../testing/configfs-usb-gadget-uac1_legacy | 3 - Documentation/usb/gadget-testing.rst | 3 - drivers/usb/gadget/function/f_uac1_legacy.c | 56 ------------------- drivers/usb/gadget/function/u_uac1_legacy.h | 3 - 4 files changed, 65 deletions(-)
Documentation/ABI/testing/configfs-usb-gadget-uac1_legacy +0 -3
@@ -5,8 +5,5 @@ Description: The attributes: audio_buf_size - audio buffer size - fn_cap - capture pcm device file name - fn_cntl - control device file name - fn_play - playback pcm device file name req_buf_size - ISO OUT endpoint request buffer size req_count - ISO OUT endpoint request count
Documentation/usb/gadget-testing.rst +0 -3
@@ -695,9 +695,6 @@ The uac1 function provides these attributes in its function directory: =============== ==================================== audio_buf_size audio buffer size - fn_cap capture pcm device file name - fn_cntl control device file name - fn_play playback pcm device file name req_buf_size ISO OUT endpoint request buffer size req_count ISO OUT endpoint request count =============== ====================================
drivers/usb/gadget/function/f_uac1_legacy.c +0 -56
72 lines not on this page · raw message
drivers/usb/gadget/function/u_uac1_legacy.h +0 -3
@@ -62,9 +62,6 @@ struct f_uac1_legacy_opts {char *fn_cap;char *fn_cntl; unsigned bound:1; - unsigned fn_play_alloc:1; - unsigned fn_cap_alloc:1; - unsigned fn_cntl_alloc:1;struct mutex lock;int refcnt; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 457/798 tty: hvc: restrict HVC_DCC to ARMv6+ and ARM64
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Karl Mehltretter <[email protected]>
[ Upstream commit 782f4dbd1794b4f30dc116a7ca42c5962c409be8 ]
hvc_dcc drives the JTAG DCC via the ARMv6/v7 CP14 debug registers (mrc/mcr p14, 0, rX, c0, c1/c5, 0 in asm/dcc.h). That encoding is undefined on older ARM cores, and also on ARMv7-M, but HVC_DCC only depends on ARM, so it can be enabled on e.g. ARM926 (ARCH_MULTI_V5), where hvc_dcc_console_init() runs __dcc_putchar() at boot and takes an undefined-instruction trap before the console is up:
Internal error: Oops - undefined instruction: 0 [#1] ARM PC is at hvc_dcc_check+0x50/0x8c hvc_dcc_check from hvc_dcc_console_init+0x18/0x48 hvc_dcc_console_init from console_init+0x58/0x170 Kernel panic - not syncing: Fatal exception
Restrict HVC_DCC to the CPUs where that encoding is valid: the CPU_V6 || CPU_V6K || CPU_V7 set that arch/arm/include/debug/icedcc.S guards it with, plus ARM64.
--- drivers/tty/hvc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/tty/hvc/Kconfig +1 -1
@@ -79,7 +79,7 @@ config HVC_UDBG config HVC_DCC bool "ARM JTAG DCC console" - depends on ARM || ARM64 + depends on (ARM && (CPU_V6 || CPU_V6K || CPU_V7)) || ARM64 select HVC_DRIVER select SERIAL_CORE_CONSOLE help
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 458/798 UDF symlink pathComponent header OOB read
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lee <[email protected]>
[ Upstream commit d23eb7380d1594cda31a5dc8487dd2a5c8def8c7 ]
udf_symlink_filler() can enter udf_pc_to_char() with a partial pathComponent header.
Validate that enough input remains for a complete pathComponent header before accessing it. Reject malformed symlink data that would otherwise make udf_pc_to_char() perform an out-of-bounds read.
--- fs/udf/symlink.c | 2 ++ 1 file changed, 2 insertions(+)
fs/udf/symlink.c +2 -0
@@ -40,6 +40,8 @@ static int udf_pc_to_char(struct super_block *sb, unsigned char *from,/* Reserve one byte for terminating \0 */ tolen--;while (elen < fromlen) { +if (fromlen - elen <sizeof (struct pathComponent )) +return -EIO ; pc = (struct pathComponent *)(from + elen); elen +=sizeof (struct pathComponent );switch (pc->componentType) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 459/798 uio: Fix stale info pointer in failed registration path
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit 67b6fc084b034a91c3ec7907a3fed89a2450f30b ]
After device_add(), the UIO device is visible to userspace and /dev/uioX can be opened. If a later setup step fails, __uio_register_device() unwinds the device but leaves idev->info pointing at the caller-owned struct uio_info.
That is unsafe when an opener races with the failed registration path. The open file keeps a reference to the uio_device, while the caller sees registration failure and may free its struct uio_info. Later file operations can then follow idev->info and dereference freed memory.
Handle post-device_add() failures like unregister: remove UIO attributes while the info pointer is still valid, then clear idev->info under info_lock and wake existing waiters/async users before removing the device and minor. This makes already-open file descriptors observe the same "device gone" state as normal uio_unregister_device().
--- drivers/uio/uio.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/uio/uio.c +5 -0
@@ -988,6 +988,11 @@ int __uio_register_device(struct module *owner, err_request_irq:uio_dev_del_attributes (idev); err_uio_dev_add_attributes: +mutex_lock (&idev->info_lock); + idev->info =NULL ; +mutex_unlock (&idev->info_lock); +wake_up_interruptible (&idev->wait); +kill_fasync (&idev->async_queue,SIGIO ,POLL_HUP );device_del (&idev->dev); err_device_create:uio_free_minor (idev->minor);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 460/798 accessibility: speakup: Fix incorrect string length computation in report_char_chartab_status()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christophe JAILLET <[email protected]>
[ Upstream commit bce0e640623372520d9d90c42f33ddbfb576ce69 ]
snprintf() returns the "number of characters which *would* be generated for the given input", not the size *really* generated.
In order to avoid too large values for 'len' (and potential negative values for "sizeof(buf) - (len - 1)") use scnprintf() instead of snprintf().
--- drivers/accessibility/speakup/kobjects.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/accessibility/speakup/kobjects.c +3 -3
@@ -92,9 +92,9 @@ static void report_char_chartab_status(int reset, int received, int used,if (reset) {pr_info ("%s reset to defaults\n" , object_type[do_characters]); }else if (received) { - len =snprintf (buf,sizeof (buf), -" updated %d of %d %s\n" , - used, received, object_type[do_characters]); + len =scnprintf (buf,sizeof (buf), +" updated %d of %d %s\n" , + used, received, object_type[do_characters]);if (rejected) snprintf(buf + (len - 1), sizeof(buf) - (len - 1), " with %d reject%s\n",
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 461/798 speakup: keyhelp: guard letter_offsets possible out-of-range indexing
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pavel Zhigulin <[email protected]>
[ Upstream commit 6a19ad4d68c95185308cd9e5d169b10a2cf236c8 ]
help_init() builds letter_offsets[] by using the first byte of each function name as an index via (start & 31) - 1. If function_names are overridden from sysfs (root) with a name starting outside [a–z], the index underflows or exceeds the array, leading to OOB write.
Function names can be overridden with the following commands as root:
modprobe speakup_soft
echo "0 _bad" > /sys/accessibility/speakup/i18n/function_names # then press Insert+2 on /dev/tty
This fix checks the first letter in help_init(), and if it is not in the [a–z] range the function returns an error to the caller. Eventually this error is propagated to drivers/accessibility/speakup/main.c:2217, which causes a bleep sound.
--- drivers/accessibility/speakup/keyhelp.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
drivers/accessibility/speakup/keyhelp.c +12 -5
@@ -8,6 +8,7 @@*/ #include <linux/keyboard.h> +#include <linux/ctype.h> #include "spk_priv.h" #include "speakup.h"
@@ -111,7 +112,7 @@ static void say_key(int key) spk_msg_get(MSG_KEYNAMES_START + (key - 1))); } -static int help_init (void ) +static void help_init (void ) {char start =SPACE ;int i;
@@ -120,13 +121,19 @@ static int help_init(void) state_tbl = spk_our_keys[0 ] +SHIFT_TBL_SIZE +2 ;for (i =0 ; i < num_funcs; i++) {char *cur_funcname =spk_msg_get (MSG_FUNCNAMES_START + i); +char first_letter; -if (start == *cur_funcname) + first_letter =tolower (*cur_funcname); + +/* Accept only 'a'..'z' to index letter_offsets[] safely */ +if (first_letter <'a' || first_letter >'z' ) +continue ; + +if (start == first_letter)continue ; - start = *cur_funcname; + start = first_letter; letter_offsets[(start &31 ) -1 ] = i; } -return 0 ; }int spk_handle_help (struct vc_data *vc,u_char type,u_char ch,u_short key)
@@ -144,7 +151,7 @@ int spk_handle_help(struct vc_data *vc, u_char type, u_char ch, u_short key)synth_printf ("%s\n" ,spk_msg_get (MSG_LEAVING_HELP ));return 1 ; } - ch |=32 ;/* lower case */ + ch =tolower (ch);if (ch <'a' || ch >'z' )return -1 ;if (letter_offsets[ch -'a' ] ==-1 ) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 462/798 misc: rtsx: add missing write register handling
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gleb Markov <[email protected]>
[ Upstream commit 655faba1ccf195e22a7a83146ef6015e3271233c ]
If an error occurs at the stage of working with registers in conjunction with MCU_Block, it will not be processed.
The occurrence of errors at this stage may signal an impact on writes to the device's PCI registers and is a more global problem than a driver-level security problem, but adding a handler would be a good practice.
Add a missing error handling.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/misc/cardreader/rtsx_pcr.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/misc/cardreader/rtsx_pcr.c +2 -0
@@ -1277,6 +1277,8 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)/* Gating real mcu clock */ err =rtsx_pci_write_register (pcr,RTS5261_FW_CFG1 ,RTS5261_MCU_CLOCK_GATING ,0 ); +if (err <0 ) +return err; err =rtsx_pci_write_register (pcr,RTS5261_REG_FPDCTL ,SSC_POWER_DOWN ,0 ); }else {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 463/798 misc: ad525x_dpot: Make ad_dpot_remove() return void
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uwe Kleine-König <[email protected]>
[ Upstream commit 85385a51ceadfe79ae3b1eb5848fab6c3b917ea8 ]
Up to now ad_dpot_remove() returns zero unconditionally. Make it return void instead which makes it easier to see in the callers that there is no error to handle.
Also the return value of i2c and spi remove callbacks is ignored anyway.
Stable-dep-of: e3a8557e88eb ("misc: ad525x_dpot: use driver core groups for sysfs files")
--- drivers/misc/ad525x_dpot-i2c.c | 3 ++- drivers/misc/ad525x_dpot-spi.c | 3 ++- drivers/misc/ad525x_dpot.c | 4 +--- drivers/misc/ad525x_dpot.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-)
drivers/misc/ad525x_dpot-i2c.c +2 -1
@@ -69,7 +69,8 @@ static int ad_dpot_i2c_probe(struct i2c_client *client,static int ad_dpot_i2c_remove (struct i2c_client *client) { -return ad_dpot_remove (&client->dev); +ad_dpot_remove (&client->dev); +return 0 ; }static const struct i2c_device_id ad_dpot_id[] = {
drivers/misc/ad525x_dpot-spi.c +2 -1
@@ -92,7 +92,8 @@ static int ad_dpot_spi_probe(struct spi_device *spi)static int ad_dpot_spi_remove (struct spi_device *spi) { -return ad_dpot_remove (&spi->dev); +ad_dpot_remove (&spi->dev); +return 0 ; }static const struct spi_device_id ad_dpot_spi_id[] = {
drivers/misc/ad525x_dpot.c +1 -3
@@ -740,7 +740,7 @@ int ad_dpot_probe(struct device *dev, }EXPORT_SYMBOL (ad_dpot_probe); -int ad_dpot_remove (struct device *dev) +void ad_dpot_remove (struct device *dev) {struct dpot_data *data =dev_get_drvdata (dev);int i;
@@ -750,8 +750,6 @@ int ad_dpot_remove(struct device *dev)ad_dpot_remove_files (dev, data->feat, i);kfree (data); - -return 0 ; }EXPORT_SYMBOL (ad_dpot_remove);
drivers/misc/ad525x_dpot.h +1 -1
@@ -209,6 +209,6 @@ struct ad_dpot_bus_data {int ad_dpot_probe (struct device *dev,struct ad_dpot_bus_data *bdata,unsigned long devid,const char *name); -int ad_dpot_remove (struct device *dev); +void ad_dpot_remove (struct device *dev);#endif
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 464/798 misc: ad525x_dpot: use driver core groups for sysfs files
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
[ Upstream commit e3a8557e88eb26278eda60bf64f2ef33ce7de8bf ]
ad_dpot_probe() creates per-RDAC sysfs files manually and then optionally creates the command sysfs group. This leaves probe responsible for rolling back partial sysfs state and makes remove responsible for matching every file that probe created.
Move the device attributes into driver core dev_groups for the I2C and SPI drivers and use an is_visible() callback to expose only the attributes supported by the probed device. With this shape, the driver core creates the sysfs files only after probe succeeds and removes them before the remove callback frees the driver data.
--- drivers/misc/ad525x_dpot-i2c.c | 1 + drivers/misc/ad525x_dpot-spi.c | 1 + drivers/misc/ad525x_dpot.c | 177 ++++++++++++++++++++------------- drivers/misc/ad525x_dpot.h | 3 + 4 files changed, 112 insertions(+), 70 deletions(-)
drivers/misc/ad525x_dpot-i2c.c +1 -0
@@ -106,6 +106,7 @@ MODULE_DEVICE_TABLE(i2c, ad_dpot_id);static struct i2c_driver ad_dpot_i2c_driver = { .driver = { .name ="ad_dpot" , + .dev_groups = ad_dpot_groups, }, .probe = ad_dpot_i2c_probe, .remove = ad_dpot_i2c_remove,
drivers/misc/ad525x_dpot-spi.c +1 -0
@@ -132,6 +132,7 @@ MODULE_DEVICE_TABLE(spi, ad_dpot_spi_id);static struct spi_driver ad_dpot_spi_driver = { .driver = { .name ="ad_dpot" , + .dev_groups = ad_dpot_groups, }, .probe = ad_dpot_spi_probe, .remove = ad_dpot_spi_remove,
drivers/misc/ad525x_dpot.c +107 -70
224 lines not on this page · raw message
drivers/misc/ad525x_dpot.h +3 -0
@@ -10,6 +10,8 @@#include <linux/types.h> +struct attribute_group ; +#define DPOT_CONF (features, wipers, max_pos, uid) \ (((features) << 18) | (((wipers) & 0xFF) << 10) | \ ((max_pos & 0xF) << 6) | (uid & 0x3F))
@@ -210,5 +212,6 @@ struct ad_dpot_bus_data {int ad_dpot_probe (struct device *dev,struct ad_dpot_bus_data *bdata,unsigned long devid,const char *name);void ad_dpot_remove (struct device *dev); +extern const struct attribute_group *ad_dpot_groups[];#endif
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 465/798 ppdev: prevent overflow when setting port timeout
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linmao Li <[email protected]>
[ Upstream commit 3c0cf801ea2fa40daa5e7d1e6d32adca5ff75ad9 ]
PPSETTIME64 supplies the timeval fields as s64 values, but pp_set_timeout() narrows tv_usec to int and calculates tv_sec * HZ in a signed long. Large positive values can therefore be truncated or overflow and install an unintended timeout.
Keep both fields as s64, reject a non-canonical microsecond value, and use timespec64_to_jiffies() to cap excessively large timeouts at MAX_JIFFY_OFFSET. This is a behavior change because both PPSETTIME ioctls could previously accept values with tv_usec >= USEC_PER_SEC. The validation follows the precedent set by sock_set_timeout().
--- drivers/char/ppdev.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/char/ppdev.c +6 -4
@@ -340,15 +340,17 @@ static enum ieee1284_phase init_phase(int mode)return IEEE1284_PH_FWD_IDLE ; } -static int pp_set_timeout (struct pardevice *pdev,long tv_sec,int tv_usec) +static int pp_set_timeout (struct pardevice *pdev,s64 tv_sec,s64 tv_usec) { +struct timespec64 ts;long to_jiffies; -if ((tv_sec <0 ) || (tv_usec <0 )) +if (tv_sec <0 || tv_usec <0 || tv_usec >=USEC_PER_SEC )return -EINVAL ; - to_jiffies =usecs_to_jiffies (tv_usec); - to_jiffies += tv_sec *HZ ; + ts.tv_sec = tv_sec; + ts.tv_nsec = tv_usec *NSEC_PER_USEC ; + to_jiffies =timespec64_to_jiffies (&ts);if (to_jiffies <=0 )return -EINVAL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 466/798 char: xilinx_hwicap: unregister class on init errors
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Myeonghun Pak <[email protected]>
[ Upstream commit e7e12b4cc0f0c3a2782aea084d4215e23f5512b3 ]
hwicap_module_init() registers icap_class before reserving the character-device region and registering the platform driver. If either of those later steps fails, the init path must undo the successful class registration before returning an error.
Route the chrdev registration failure through a class unwind label, and let the platform-driver registration failure fall through the existing chrdev unwind before unregistering the class. The normal module exit path is unchanged.
This issue was identified during our ongoing static-analysis research while reviewing kernel code.
--- drivers/char/xilinx_hwicap/xilinx_hwicap.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/char/xilinx_hwicap/xilinx_hwicap.c +4 -1
@@ -864,7 +864,7 @@ static int __init hwicap_module_init(void)HWICAP_DEVICES , DRIVER_NAME);if (retval <0 ) -return retval; + goto failed_class; retval =platform_driver_register (&hwicap_platform_driver);if (retval)
@@ -875,6 +875,9 @@ static int __init hwicap_module_init(void) failed:unregister_chrdev_region (devt,HWICAP_DEVICES ); + failed_class: +class_unregister (&icap_class); +return retval; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 467/798 vfio/pci: clear vdev->msi_perm after freeing it on init failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <[email protected]>
[ Upstream commit dc77acfeb979dded39b247b60fef0399536bfa77 ]
vfio_msi_cap_len() lazily allocates the per-device MSI permission table:
vdev->msi_perm = kmalloc_obj(struct perm_bits, GFP_KERNEL_ACCOUNT);
if (!vdev->msi_perm)
return -ENOMEM;
ret = init_pci_cap_msi_perm(vdev->msi_perm, len, flags);
if (ret) {
kfree(vdev->msi_perm);
return ret; /* vdev->msi_perm left dangling */
}When init_pci_cap_msi_perm() -> alloc_perm_bits() fails with -ENOMEM, the error path frees vdev->msi_perm but leaves the freed pointer stored in it. vdev->msi_perm is not re-zeroed later because struct vfio_pci_core_device is per-device and persists across open/close cycles, and the vfio_config_init() error path returns without calling vfio_config_free(). So the dangling pointer outlives the failed open.
That leads to two use-after-frees on the same device:
1. Reuse. The next vfio_config_init() sees the stale pointer at "if (vdev->msi_perm) return len;" and reuses the freed object. MSI config accesses in vfio_pci_config_rw_single() then dereference and call the freed perm->readfn / perm->writefn function pointers.
2. Double free. A later vfio_config_free() runs free_perm_bits() and kfree() on the already-freed object.
Fix it by NULLing vdev->msi_perm after the kfree(), matching the NULL-after-free discipline already used in free_perm_bits() and vfio_config_free().
BUG: KASAN: slab-use-after-free in vfio_pci_config_rw_single (drivers/vfio/pci/vfio_pci_config.c:1961) Read of size 8 at addr ffff88800fcc88d0 by task exploit/143 Call Trace: ... kasan_report (mm/kasan/report.c:595) vfio_pci_config_rw_single (drivers/vfio/pci/vfio_pci_config.c:1961) vfio_pci_config_rw (drivers/vfio/pci/vfio_pci_config.c:1986) vfio_pci_rw (drivers/vfio/pci/vfio_pci_core.c:1599) vfs_read (fs/read_write.c:572) __x64_sys_pread64 (fs/read_write.c:764) do_syscall_64 (arch/x86/entry/syscall_64.c:94) ...
Followed on device close by a double free of the same object:
Oops: general protection fault, probably for non-canonical address
0x1f63e0e8000008: 0000 [#1] SMP KASAN NOPTI
RIP: 0010:kfree (mm/slub.c:6711)
Call Trace:
vfio_config_free (drivers/vfio/pci/vfio_pci_config.c:1861)
vfio_pci_core_disable (drivers/vfio/pci/vfio_pci_core.c:685)
vfio_pci_core_close_device (drivers/vfio/pci/vfio_pci_core.c:777)
vfio_df_close (drivers/vfio/vfio_main.c:602)
vfio_device_fops_release (drivers/vfio/vfio_main.c:648)
__fput (fs/file_table.c:512)
__x64_sys_close (fs/open.c:1496)
do_syscall_64 (arch/x86/entry/syscall_64.c:94)
...
Kernel panic - not syncing: Fatal exception--- drivers/vfio/pci/vfio_pci_config.c | 1 + 1 file changed, 1 insertion(+)
drivers/vfio/pci/vfio_pci_config.c +1 -0
@@ -1219,6 +1219,7 @@ static int vfio_msi_cap_len(struct vfio_pci_device *vdev, u8 pos) ret =init_pci_cap_msi_perm (vdev->msi_perm, len, flags);if (ret) {kfree (vdev->msi_perm); + vdev->msi_perm =NULL ;return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 468/798 soc: ti: knav_qmss_queue: Implement resource cleanup in remove()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Md Shofiqul Islam <[email protected]>
[ Upstream commit 10a1969353b20caa50c320717e054601631c0d3e ]
Implement the TODO in knav_queue_remove() by stopping PDSPs and freeing queue regions and queue ranges before disabling runtime PM, mirroring the cleanup performed in the probe error path.
Set device_ready to false before cleanup to prevent any further use of the device during teardown.
This ensures resources are released on driver unbind and avoids leaking queue/region state.
Stable-dep-of: 3c8178627599 ("soc: ti: knav_qmss: Remove debugfs file on teardown")
--- drivers/soc/ti/knav_qmss_queue.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/soc/ti/knav_qmss_queue.c +6 -1
@@ -1885,7 +1885,12 @@ static int knav_queue_probe(struct platform_device *pdev)static int knav_queue_remove (struct platform_device *pdev) { -/* TODO: Free resources */ +struct knav_device *kdev =platform_get_drvdata (pdev); + + device_ready = false; +knav_queue_stop_pdsps (kdev); +knav_queue_free_regions (kdev); +knav_free_queue_ranges (kdev);pm_runtime_put_sync (&pdev->dev);pm_runtime_disable (&pdev->dev);return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 469/798 soc: ti: knav_qmss: Remove debugfs file on teardown
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
[ Upstream commit 3c817862759913097f11467ed4ed2bbf974dabaf ]
knav_queue_probe() creates the global qmss debugfs file whose show callback reads the global knav_qdev state. knav_queue_remove() tears down the queue manager resources but leaves the debugfs file published.
Save the debugfs dentry in struct knav_device and remove it during teardown before the resources used by the show callback are released. While touching the debugfs_create_file() call, spell the unchanged read- only file mode as 0444.
--- drivers/soc/ti/knav_qmss.h | 1 + drivers/soc/ti/knav_qmss_queue.c | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-)
drivers/soc/ti/knav_qmss.h +1 -0
@@ -304,6 +304,7 @@ struct knav_device {struct list_head pools;struct list_head pdsps;struct list_head qmgrs; +struct dentry *debugfs_file;enum qmss_version version; };
drivers/soc/ti/knav_qmss_queue.c +5 -2
@@ -1869,8 +1869,9 @@ static int knav_queue_probe(struct platform_device *pdev) goto err; } -debugfs_create_file ("qmss" ,S_IFREG |S_IRUGO ,NULL ,NULL , - &knav_queue_debug_fops); + knav_qdev->debugfs_file = +debugfs_create_file ("qmss" ,0444 ,NULL ,NULL , + &knav_queue_debug_fops); device_ready = true;return 0 ;
@@ -1888,6 +1889,8 @@ static int knav_queue_remove(struct platform_device *pdev)struct knav_device *kdev =platform_get_drvdata (pdev); device_ready = false; +debugfs_remove (kdev->debugfs_file); + kdev->debugfs_file =NULL ;knav_queue_stop_pdsps (kdev);knav_queue_free_regions (kdev);knav_free_queue_ranges (kdev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 470/798 mtd: mtdswap: Avoid freeing registered blktrans device twice
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <[email protected]>
[ Upstream commit 779aa4c66a96bf43d2d62982ea1a9096a9128d87 ]
In mtdswap_add_mtd(), debugfs setup failure after successful blktrans registration can free mbd_dev twice.
add_mtd_blktrans_dev() initializes the blktrans device reference and publishes the disk. Once that succeeds, del_mtd_blktrans_dev() tears the disk down and drops the blktrans reference; when that reference reaches zero, blktrans_dev_release() frees the mtd_blktrans_dev.
The debugfs failure path called del_mtd_blktrans_dev(mbd_dev), then fell through the common cleanup label and called kfree(mbd_dev) again. Clear the local pointer after deregistration so the common cleanup can still release the mtdswap state without freeing the blktrans object twice.
This issue was found by a static analysis checker and confirmed by manual source review.
--- drivers/mtd/mtdswap.c | 1 + 1 file changed, 1 insertion(+)
drivers/mtd/mtdswap.c +1 -0
@@ -1454,6 +1454,7 @@ static void mtdswap_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) debugfs_failed:del_mtd_blktrans_dev (mbd_dev); + mbd_dev =NULL ; cleanup:mtdswap_cleanup (d);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 471/798 mtd: part: reject MTDPART_OFS_RETAIN in mtd_add_partition()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: zhouminqiang <[email protected]>
[ Upstream commit b759d5bb6265419344ee9729fd0dc07ad85719d8 ]
mtd_add_partition() does not reject the special offset value MTDPART_OFS_RETAIN (-3), which leads to a WARN_ON in add_mtd_device() when called through the BLKPG ioctl on NAND devices. The RETAIN value depends on cur_offset being the end of the previous partition, but in the dynamic partition path cur_offset equals the offset argument itself, causing undefined behavior.
Commit 5daa7b21496a ("mtd: prepare partition add and del functions for ioctl requests") introduced mtd_add_partition() and correctly rejected MTDPART_OFS_APPEND (-1) and MTDPART_OFS_NXTBLK (-2), since those special offsets rely on cur_offset tracking the previous partition's end. However, commit 1a31368bf92e ("mtd: add a flags for partitions which should just leave smth. after them") later added MTDPART_OFS_RETAIN (-3) for the static
partition table path without updating mtd_add_partition() to also reject this value.
With offset=-3 passed via BLKPG, the RETAIN size calculation in allocate_partition() underflows (parent_size - 0xFFFFFFFFFFFFFFFD = parent_size + 3). If the underflow result does not appear to leave enough space, allocate_partition() jumps to out_register via goto, skipping erasesize initialization. This results in erasesize=0, which triggers:
WARN_ON((!mtd->erasesize || !master->_erase) &&
!(mtd->flags & MTD_NO_ERASE))
in add_mtd_device(). If the underflow result appears to leave enough space, a bogus partition size is calculated, but the "out of reach" sanity check catches the invalid offset and creates a disabled empty partition (offset=0, size=0) instead of returning an error.
Fix this by adding MTDPART_OFS_RETAIN to the rejection list in mtd_add_partition(), consistent with the existing handling of APPEND and NXTBLK.
--- drivers/mtd/mtdpart.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/mtd/mtdpart.c +2 -1
@@ -248,7 +248,8 @@ int mtd_add_partition(struct mtd_info *parent, const char *name,/* the direct offset is expected */ if (offset ==MTDPART_OFS_APPEND || - offset ==MTDPART_OFS_NXTBLK ) + offset ==MTDPART_OFS_NXTBLK || + offset ==MTDPART_OFS_RETAIN )return -EINVAL ;if (length ==MTDPART_SIZ_FULL )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 472/798 perf ui hists: Fix uninitialized stack memory free on pstack allocation failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Rogers <[email protected]>
[ Upstream commit d5fdde1c426922efabe86a515f0782b3eba40577 ]
Fixes heap corruption by initializing the options and actions arrays before the pstack allocation check, preventing an uninitialized stack pointer from being passed to free_popup_options() if the allocation fails.
--- tools/perf/ui/browsers/hists.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
tools/perf/ui/browsers/hists.c +3 -3
@@ -3008,15 +3008,15 @@ static int perf_evsel__hists_browse(struct evsel *evsel, int nr_events, browser->min_pcnt = min_pcnt;hist_browser__update_nr_entries (browser); +memset (options,0 ,sizeof (options)); +memset (actions,0 ,sizeof (actions)); + browser->pstack =pstack__new (3 );if (browser->pstack ==NULL ) goto out;ui_helpline__push (helpline); -memset (options,0 ,sizeof (options)); -memset (actions,0 ,sizeof (actions)); -if (symbol_conf.col_width_list_str)perf_hpp__set_user_width (symbol_conf.col_width_list_str);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 473/798 software node: Fix software_node_get_reference_args() with index -1
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alban Bedel <[email protected]>
[ Upstream commit ba3dedcf3bd47017307595a7e54924198f018246 ]
The bounds check for the index passed to software_node_get_reference_args() was failing when passed UINT_MAX, this in turn would lead to an out of bound access in the property array. Fix the bound check to also cover the UINT_MAX case.
--- drivers/base/swnode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/base/swnode.c +1 -1
@@ -508,7 +508,7 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,if (prop->is_inline)return -EINVAL ; -if ((index +1 ) *sizeof (*ref) > prop->length) +if (index >= prop->length /sizeof (*ref))return -ENOENT ; ref_array = prop->pointer;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 474/798 driver core: soc: remove layering violation for the soc_bus
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Greg Kroah-Hartman <[email protected]>
[ Upstream commit 90be1f15c39858a4f0f4346c39fa150697d231c1 ]
The soc_bus code pokes around in the internal bus structures assuming that it "knows" if a field is not set that it has not been registered yet. That isn't a safe assumption, so just remove the layering violation entirely and keep track if the bus has been registered or not ourselves.
Stable-dep-of: 45dfa004893d ("driver core: soc: Unregister bus on early device registration failure")
--- drivers/base/soc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/base/soc.c +3 -1
@@ -30,6 +30,7 @@ struct soc_device {static struct bus_type soc_bus_type = { .name ="soc" , }; +static bool soc_bus_registered; static DEVICE_ATTR(machine, 0444, soc_info_show, NULL); static DEVICE_ATTR(family, 0444, soc_info_show, NULL);
@@ -117,7 +118,7 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attrconst struct attribute_group **soc_attr_groups;int ret; -if (!soc_bus_type.p) { +if (!soc_bus_registered) {if (early_soc_dev_attr)return ERR_PTR (-EBUSY ); early_soc_dev_attr = soc_dev_attr;
@@ -183,6 +184,7 @@ static int __init soc_bus_register(void) ret =bus_register (&soc_bus_type);if (ret)return ret; + soc_bus_registered = true;if (early_soc_dev_attr)return PTR_ERR (soc_device_register (early_soc_dev_attr));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 475/798 driver core: soc: Unregister bus on early device registration failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit 45dfa004893dfeae182ec27eddbd153c6d4ddbf9 ]
soc_bus_register() registers the SoC bus before registering a deferred early SoC device. If soc_device_register() fails in that path, the function returns the error directly and leaves the bus registered.
Store the returned SoC device pointer explicitly so the success and error cases are handled separately. On failure, clear soc_bus_registered and unregister the bus before returning the error.
--- drivers/base/soc.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
drivers/base/soc.c +13 -2
@@ -179,6 +179,7 @@ EXPORT_SYMBOL_GPL(soc_device_unregister);static int __init soc_bus_register (void ) { +struct soc_device *soc_dev;int ret; ret =bus_register (&soc_bus_type);
@@ -186,10 +187,20 @@ static int __init soc_bus_register(void)return ret; soc_bus_registered = true; -if (early_soc_dev_attr) -return PTR_ERR (soc_device_register (early_soc_dev_attr)); +if (early_soc_dev_attr) { + soc_dev =soc_device_register (early_soc_dev_attr); +if (IS_ERR (soc_dev)) { + ret =PTR_ERR (soc_dev); + goto err_unregister_bus; + } + }return 0 ; + +err_unregister_bus: + soc_bus_registered = false; +bus_unregister (&soc_bus_type); +return ret; }core_initcall (soc_bus_register);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 476/798 dmaengine: dw-edma: Serialize abort state updates
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Koichiro Den <[email protected]>
[ Upstream commit dd80e259f65d932634e26d366570d71669ef6654 ]
dw_edma_abort_interrupt() drops vc.lock before changing request and status. issue_pending() can acquire the lock in that small window, observe the old busy state, and skip starting queued descriptors. Then the abort handler overwrites the channel status as idle, leaving the new descriptors stranded for good.
Keep descriptor completion and the state transition in the same critical section.
--- drivers/dma/dw-edma/dw-edma-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/dma/dw-edma/dw-edma-core.c +1 -1
@@ -579,9 +579,9 @@ static void dw_edma_abort_interrupt(struct dw_edma_chan *chan)list_del (&vd->node);vchan_cookie_complete (vd); } -spin_unlock_irqrestore (&chan->vc.lock, flags); chan->request =EDMA_REQ_NONE ; chan->status =EDMA_ST_IDLE ; +spin_unlock_irqrestore (&chan->vc.lock, flags); }static irqreturn_t dw_edma_interrupt (int irq,void *data,bool write)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 477/798 dmaengine: dw-edma: Serialize channel state checks
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Koichiro Den <[email protected]>
[ Upstream commit f7d1619f3e10c619b62c6cd6d95371b5c526c85a ]
pause() and resume() read and update channel state without holding vc.lock, while the interrupt handlers update the same state under it. Take the same lock around those state checks so that request, status, and configured stay consistent.
For example, pause() can observe EDMA_ST_BUSY right before the interrupt handler completes the final descriptor and moves the channel to EDMA_ST_IDLE, and then record EDMA_REQ_PAUSE on an already idle channel. No further interrupt will acknowledge the request, and since issue_pending() requires EDMA_REQ_NONE, the channel is wedged for good: terminate_all() leaves the stale request behind, so even reconfiguring the channel does not recover it.
issue_pending() already runs under vc.lock, but it tests configured before taking it. Move that test under the lock as well, so configured, request, and status are evaluated as one channel-state snapshot.
--- drivers/dma/dw-edma/dw-edma-core.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/dma/dw-edma/dw-edma-core.c +6 -4
@@ -216,6 +216,8 @@ static int dw_edma_device_pause(struct dma_chan *dchan)struct dw_edma_chan *chan =dchan2dw_edma_chan (dchan);int err =0 ; +guard (spinlock_irqsave)(&chan->vc.lock); +if (!chan->configured) err = -EPERM ;else if (chan->status !=EDMA_ST_BUSY )
@@ -233,6 +235,8 @@ static int dw_edma_device_resume(struct dma_chan *dchan)struct dw_edma_chan *chan =dchan2dw_edma_chan (dchan);int err =0 ; +guard (spinlock_irqsave)(&chan->vc.lock); +if (!chan->configured) { err = -EPERM ; }else if (chan->status !=EDMA_ST_PAUSE ) {
@@ -282,11 +286,9 @@ static void dw_edma_device_issue_pending(struct dma_chan *dchan)struct dw_edma_chan *chan =dchan2dw_edma_chan (dchan);unsigned long flags; -if (!chan->configured) -return ; -spin_lock_irqsave (&chan->vc.lock, flags); -if (vchan_issue_pending (&chan->vc) && chan->request ==EDMA_REQ_NONE && +if (chan->configured &&vchan_issue_pending (&chan->vc) && + chan->request ==EDMA_REQ_NONE && chan->status ==EDMA_ST_IDLE ) { chan->status =EDMA_ST_BUSY ;dw_edma_start_transfer (chan);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 478/798 dmaengine: dw-edma: Clear stale requests on termination
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Koichiro Den <[email protected]>
[ Upstream commit c0d9c6275adcca7c0ca5f4270bf88026f9864bd1 ]
terminate_all() can finish immediately when the channel is unconfigured, paused, idle, or already stopped in hardware. A pending PAUSE request can survive these paths and block issue_pending() even after termination.
Clear the request whenever termination leaves the channel idle. A running channel keeps its STOP request until the interrupt handler consumes it.
--- drivers/dma/dw-edma/dw-edma-core.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/dma/dw-edma/dw-edma-core.c +2 -0
@@ -277,6 +277,8 @@ static int dw_edma_device_terminate_all(struct dma_chan *dchan) }else { chan->request =EDMA_REQ_STOP ; } +if (chan->status ==EDMA_ST_IDLE ) + chan->request =EDMA_REQ_NONE ;return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 479/798 ASoC: meson: Keep link pointers valid on realloc failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linmao Li <[email protected]>
[ Upstream commit 2aaa41cf974f83a6fb105422bac4e2f107150774 ]
meson_card_reallocate_links() grows the DAI link and private data arrays with two consecutive krealloc() calls and updates the owner pointers only after both calls have succeeded.
A successful krealloc() may move the data: it frees the old block and returns a new one. When that happens for the link array and the second krealloc() then fails, card->dai_link still points to the block that krealloc() already freed, and the error path frees the new block too. The probe error path then calls meson_card_clean_references(), which dereferences card->dai_link and kfree()s it again, resulting in a use-after-free and a double free.
Commit card->dai_link and card->num_links right after the first krealloc() succeeds, so the pointer always refers to a valid allocation that meson_card_clean_references() can walk and free. krealloc() with __GFP_ZERO zero-initializes the added entries, so walking them on the error path is safe. With both failure paths reduced to a plain return, drop the goto labels and the error message.
--- sound/soc/meson/meson-card-utils.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-)
sound/soc/meson/meson-card-utils.c +6 -11
@@ -50,25 +50,20 @@ int meson_card_reallocate_links(struct snd_soc_card *card, num_links *sizeof (*priv->card.dai_link), GFP_KERNEL | __GFP_ZERO);if (!links) - goto err_links; +return -ENOMEM ; + + priv->card.dai_link = links; + priv->card.num_links = num_links; ldata =krealloc (priv->link_data, num_links *sizeof (*priv->link_data),GFP_KERNEL | __GFP_ZERO); +/* meson_card_clean_references() will free the links on this error path */ if (!ldata) - goto err_ldata; +return -ENOMEM ; - priv->card.dai_link = links; priv->link_data = ldata; - priv->card.num_links = num_links;return 0 ; - -err_ldata: -kfree (links); -err_links: -dev_err (priv->card.dev,"failed to allocate links\n" ); -return -ENOMEM ; - }EXPORT_SYMBOL_GPL (meson_card_reallocate_links);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 480/798 RDMA/hfi1: Propagate sdma_txinit_ahg() errors
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Danila Chernetsov <[email protected]>
[ Upstream commit 091c6162c022cbdfb64219708a71728cfd1d4600 ]
set_txreq_header_ahg() ignores the return value of sdma_txinit_ahg().
If sdma_txinit_ahg() fails, it returns before initializing tx->txreq. However, set_txreq_header_ahg() ignores the error and returns the AHG change count, causing the caller to continue processing the request as though initialization had succeeded.
Propagate sdma_txinit_ahg() failures to the caller and abort request processing when initialization fails.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/infiniband/hw/hfi1/user_sdma.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/infiniband/hw/hfi1/user_sdma.c +8 -5
@@ -1100,6 +1100,7 @@ static int set_txreq_header_ahg(struct user_sdma_request *req, struct user_sdma_txreq *tx, u32 datalen) {u32 ahg[AHG_KDETH_ARRAY_SIZE ]; +int ret;int idx =0 ;u8 omfactor;/* KDETH.OM */ struct hfi1_user_sdma_pkt_q *pq = req->pq;
@@ -1204,11 +1205,13 @@ static int set_txreq_header_ahg(struct user_sdma_request *req,trace_hfi1_sdma_user_header_ahg (pq->dd, pq->ctxt, pq->subctxt, req->info.comp_idx, req->sde->this_idx, req->ahg_idx, ahg, idx, tidval); -sdma_txinit_ahg (&tx->txreq, -SDMA_TXREQ_F_USE_AHG , - datalen, req->ahg_idx, idx, - ahg,sizeof (req->hdr), - user_sdma_txreq_cb); + ret =sdma_txinit_ahg (&tx->txreq, +SDMA_TXREQ_F_USE_AHG , + datalen, req->ahg_idx, idx, + ahg,sizeof (req->hdr), + user_sdma_txreq_cb); +if (ret) +return ret;return idx; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 481/798 RDMA/srpt: Fix srpt_alloc_rw_ctxs() unwind counters
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: TanZheng <[email protected]>
[ Upstream commit b38f98e176050850f41bb6415f3a71400056623e ]
When srpt_alloc_rw_ctxs() fails partway through a multi-buffer indirect descriptor, the unwind path destroys RDMA contexts but leaves stale n_rw_ctx and n_rdma values (and a dangling rw_ctxs pointer). Later sq_wr_avail accounting in srpt_queue_response() or srpt_write_pending() can then subtract the wrong number of send queue credits.
Reset the counters and clear rw_ctxs after freeing the heap allocation before returning an error.
--- drivers/infiniband/ulp/srpt/ib_srpt.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/infiniband/ulp/srpt/ib_srpt.c +7 -0
@@ -900,6 +900,7 @@ static int srpt_alloc_rw_ctxs(struct srpt_send_ioctx *ioctx,struct srpt_rdma_ch *ch = ioctx->ch;struct scatterlist *prev =NULL ;unsigned prev_nents; +u8 n_rdma, n_rw_ctx;int ret, i;if (nbufs ==1 ) {
@@ -911,6 +912,9 @@ static int srpt_alloc_rw_ctxs(struct srpt_send_ioctx *ioctx,return -ENOMEM ; } + n_rw_ctx = ioctx->n_rw_ctx; + n_rdma = ioctx->n_rdma; +for (i = ioctx->n_rw_ctx; i < nbufs; i++, db++) {struct srpt_rw_ctx *ctx = &ioctx->rw_ctxs[i];u64 remote_addr =be64_to_cpu (db->va);
@@ -957,6 +961,9 @@ static int srpt_alloc_rw_ctxs(struct srpt_send_ioctx *ioctx, }if (ioctx->rw_ctxs != &ioctx->s_rw_ctx)kfree (ioctx->rw_ctxs); + ioctx->rw_ctxs =NULL ; + ioctx->n_rw_ctx = n_rw_ctx; + ioctx->n_rdma = n_rdma;return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 482/798 irqchip/gic-v3-its: Prevent leak in its_vpe_irq_domain_alloc()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kemeng Shi <[email protected]>
[ Upstream commit 325ff3e78c64cd619d52b99f7c8b09a3f31e1495 ]
When its_irq_gic_domain_alloc() fails, the following its_vpe_irq_domain_free() fails to invoke its_vep_teardown() for the corresponding interrupt, which leaks the resource.
Invoke its_vpe_teardown() in the error handling path to avoid the leak.
[ tglx: Massaged change log ]
--- drivers/irqchip/irq-gic-v3-its.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/irqchip/irq-gic-v3-its.c +10 -1
@@ -4444,6 +4444,13 @@ static int its_vpe_init(struct its_vpe *vpe)static void its_vpe_teardown (struct its_vpe *vpe) { +/* +* If vpt_page is NULL, then its_vpe_init() has failed, and +* there is nothing to do as no resource has been allocated. +*/ +if (vpe->vpt_page ==NULL ) +return ; +its_vpe_db_proxy_unmap (vpe);its_vpe_id_free (vpe->vpe_id);its_free_pending_table (vpe->vpt_page);
@@ -4522,8 +4529,10 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virqset_bit (i, bitmap); } -if (err) +if (err) { +its_vpe_teardown (vm->vpes[i]);its_vpe_irq_domain_free (domain, virq, i); + }return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 483/798 ACPI: processor: validate MADT IOAPIC entry bounds
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
[ Upstream commit 2c50ffdc73f3a70d745d249f509fc290754121e6 ]
The IOAPIC hotplug lookup parses both MADT and _MAT records directly. The MADT walk previously used a subtable's declared length to advance the cursor after only locating a generic header. The _MAT path likewise passed a generic header to the IOAPIC helper.
Validate that a current record has a complete generic header, that its declared length is contained in the available record range, and that a typed IOAPIC record contains the full fixed IOAPIC body before reading its fields. Use the same relation for both MADT and _MAT provider paths.
--- drivers/acpi/processor_core.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-)
drivers/acpi/processor_core.c +25 -6
@@ -262,11 +262,26 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)EXPORT_SYMBOL_GPL (acpi_get_cpuid);#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC -static int get_ioapic_id (struct acpi_subtable_header *entry,u32 gsi_base, +static bool madt_entry_is_valid (struct acpi_subtable_header *entry, +unsigned long end) +{ +unsigned long start = (unsigned long )entry; + +if (start >= end || end - start <sizeof (*entry)) +return false; + +return entry->length >=sizeof (*entry) && entry->length <= end - start; +} + +static int get_ioapic_id (struct acpi_subtable_header *entry, +const unsigned long end,u32 gsi_base,u64 *phys_addr,int *ioapic_id) {struct acpi_madt_io_apic *ioapic = (struct acpi_madt_io_apic *)entry; +if (!madt_entry_is_valid (entry, end) ||BAD_MADT_ENTRY (ioapic, end)) +return 0 ; +if (ioapic->global_irq_base != gsi_base)return 0 ;
@@ -287,17 +302,19 @@ static int parse_madt_ioapic_entry(u32 gsi_base, u64 *phys_addr)return apic_id; entry = (unsigned long )madt; +if (madt->header.length <sizeof (*madt)) +return apic_id; madt_end = entry + madt->header.length;/* Parse all entries looking for a match. */ entry +=sizeof (struct acpi_table_madt ); -while (entry +sizeof (struct acpi_subtable_header ) < madt_end) { +while (madt_entry_is_valid ((struct acpi_subtable_header *)entry, + madt_end)) { hdr = (struct acpi_subtable_header *)entry;if (hdr->type ==ACPI_MADT_TYPE_IO_APIC && -get_ioapic_id (hdr, gsi_base, phys_addr, &apic_id)) +get_ioapic_id (hdr, madt_end, gsi_base, phys_addr, &apic_id))break ; -else - entry += hdr->length; + entry += hdr->length; }return apic_id;
@@ -324,7 +341,9 @@ static int parse_mat_ioapic_entry(acpi_handle handle, u32 gsi_base, header = (struct acpi_subtable_header *)obj->buffer.pointer;if (header->type ==ACPI_MADT_TYPE_IO_APIC ) -get_ioapic_id (header, gsi_base, phys_addr, &apic_id); +get_ioapic_id (header, + (unsigned long )header + obj->buffer.length, + gsi_base, phys_addr, &apic_id); exit:kfree (buffer.pointer);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 484/798 ACPI: PCI: Clear driver_data on all paths that free the acpi_pci_root
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen Pei <[email protected]>
[ Upstream commit 8a742141f7ab84975aa758b775567ef4740ef0cf ]
acpi_pci_root_add() assigns the freshly allocated root to device->driver_data before dmar_device_add() and pci_acpi_scan_root(). Both failure paths reach the end: label where root is kfree()'d, but only the pci_acpi_scan_root() path clears driver_data first.
When dmar_device_add() fails during a hot-add, root is freed while device->driver_data still points at it. The ACPI core does not clear driver_data on attach failure, so a later acpi_pci_find_root() call may dereference this dangling pointer.
acpi_pci_root_remove() has the same problem: it frees root without clearing device->driver_data, leaving a dangling pointer behind after the root bridge is removed.
Move the NULL assignment to the shared end: label so every error path in acpi_pci_root_add() clears driver_data before freeing root, and clear it in acpi_pci_root_remove() as well, so the object is never left reachable through driver_data after being freed.
--- drivers/acpi/pci_root.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/acpi/pci_root.c +2 -1
@@ -609,7 +609,6 @@ static int acpi_pci_root_add(struct acpi_device *device,dev_err (&device->dev,"Bus %04x:%02x not present in PCI namespace\n" , root->segment, (unsigned int )root->secondary.start); - device->driver_data =NULL ; result = -ENODEV ; goto remove_dmar; }
@@ -645,6 +644,7 @@ static int acpi_pci_root_add(struct acpi_device *device,if (hotadd)dmar_device_remove (handle); end: + device->driver_data =NULL ;kfree (root);return result; }
@@ -668,6 +668,7 @@ static void acpi_pci_root_remove(struct acpi_device *device)pci_unlock_rescan_remove (); + device->driver_data =NULL ;kfree (root); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 485/798 ext4: skip extra isize expansion during mount to prevent deadlock
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yun Zhou <[email protected]>
[ Upstream commit 7461c60b9c6a839b13ad4c3490681a0cf5aa0637 ]
ext4_try_to_expand_extra_isize() is called from __ext4_mark_inode_dirty() while holding an active jbd2 handle. During mount (!SB_ACTIVE), the expand path may move xattrs to external blocks and release ea_inodes via iput(). When !SB_ACTIVE, iput() calls write_inode_now() which acquires s_writepages_rwsem, creating a circular lock dependency:
s_writepages_rwsem --> jbd2_handle --> xattr_sem --> s_writepages_rwsem
This can be triggered via:
ext4_process_orphan() -> ext4_truncate() -> ext4_mark_inode_dirty()
-> ext4_try_to_expand_extra_isize()
or:
ext4_evict_inode() -> ext4_mark_inode_dirty()
-> ext4_try_to_expand_extra_isize()
Skip expansion when !SB_ACTIVE. This is a minor loss of functionality (extra isize won't grow for these inodes during mount), which e2fsck can resolve later if needed.
--- fs/ext4/inode.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
fs/ext4/inode.c +10 -0
@@ -6015,6 +6015,16 @@ static int ext4_try_to_expand_extra_isize(struct inode *inode,if (ext4_test_inode_state (inode,EXT4_STATE_NO_EXPAND ))return -EOVERFLOW ; +/* +* Skip expansion during mount (!SB_ACTIVE). Expanding extra isize +* may move xattrs to external blocks and release ea_inodes via iput. +* When !SB_ACTIVE, iput triggers write_inode_now() which acquires +* s_writepages_rwsem, causing a deadlock with the caller's active +* jbd2 handle (lock order: s_writepages_rwsem -> jbd2_handle). +*/ +if (unlikely (!(inode->i_sb->s_flags &SB_ACTIVE ))) +return -EBUSY ; +/* * In nojournal mode, we can immediately attempt to expand * the inode. When journaled, we first need to obtain extra
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 486/798 scsi: qla2xxx: Drop TARGET_SCF_LOOKUP_LUN_FROM_TAG
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Christie <[email protected]>
[ Upstream commit 8f394da36a361cbe0e1e8b1d4213e5598c8095ac ]
Only the __qlt_24xx_handle_abts() code path does not know the LUN for an abort and it uses the TARGET_SCF_LOOKUP_LUN_FROM_TAG flag to have LIO core look it up. LIO uses target_lookup_lun_from_tag to go from cmd tag to LUN for the driver. However, qla2xxx has a tcm_qla2xxx_find_cmd_by_tag() which does almost the same thing as the LIO helper (it finds the cmd but does not return the LUN). This patch has qla2xxx use its internal helper.
Stable-dep-of: ef63cc441703 ("RDMA/srpt: Pass the mapped task attribute to target_init_cmd()")
--- drivers/scsi/qla2xxx/qla_target.c | 21 +++++++++++---------- drivers/scsi/qla2xxx/tcm_qla2xxx.c | 4 +--- 2 files changed, 12 insertions(+), 13 deletions(-)
drivers/scsi/qla2xxx/qla_target.c +11 -10
@@ -2095,6 +2095,7 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha,struct qla_hw_data *ha = vha->hw;struct qla_tgt_mgmt_cmd *mcmd;struct qla_qpair_hint *h = &vha->vha_tgt.qla_tgt->qphints[0 ]; +struct qla_tgt_cmd *abort_cmd; ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00f, "qla_target(%d): task abort (tag=%d)\n",
@@ -2122,17 +2123,17 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha,*/ mcmd->se_cmd.cpuid = h->cpuid; -if (ha->tgt.tgt_ops->find_cmd_by_tag) { -struct qla_tgt_cmd *abort_cmd; - - abort_cmd = ha->tgt.tgt_ops->find_cmd_by_tag (sess, + abort_cmd = ha->tgt.tgt_ops->find_cmd_by_tag (sess,le32_to_cpu (abts->exchange_addr_to_abort)); -if (abort_cmd && abort_cmd->qpair) { - mcmd->qpair = abort_cmd->qpair; - mcmd->se_cmd.cpuid = abort_cmd->se_cmd.cpuid; - mcmd->abort_io_attr = abort_cmd->atio.u.isp24.attr; - mcmd->flags =QLA24XX_MGMT_ABORT_IO_ATTR_VALID ; - } +if (!abort_cmd) +return -EIO ; + mcmd->unpacked_lun = abort_cmd->se_cmd.orig_fe_lun; + +if (abort_cmd->qpair) { + mcmd->qpair = abort_cmd->qpair; + mcmd->se_cmd.cpuid = abort_cmd->se_cmd.cpuid; + mcmd->abort_io_attr = abort_cmd->atio.u.isp24.attr; + mcmd->flags =QLA24XX_MGMT_ABORT_IO_ATTR_VALID ; }INIT_WORK (&mcmd->work, qlt_do_tmr_work);
drivers/scsi/qla2xxx/tcm_qla2xxx.c +1 -3
@@ -574,13 +574,11 @@ static int tcm_qla2xxx_handle_tmr(struct qla_tgt_mgmt_cmd *mcmd, u64 lun,struct fc_port *sess = mcmd->sess;struct se_cmd *se_cmd = &mcmd->se_cmd;int transl_tmr_func =0 ; -int flags =TARGET_SCF_ACK_KREF ;switch (tmr_func) {case QLA_TGT_ABTS :pr_debug ("%ld: ABTS received\n" , sess->vha->host_no); transl_tmr_func =TMR_ABORT_TASK ; - flags |=TARGET_SCF_LOOKUP_LUN_FROM_TAG ;break ;case QLA_TGT_2G_ABORT_TASK :pr_debug ("%ld: 2G Abort Task received\n" , sess->vha->host_no);
@@ -613,7 +611,7 @@ static int tcm_qla2xxx_handle_tmr(struct qla_tgt_mgmt_cmd *mcmd, u64 lun, }return target_submit_tmr (se_cmd, sess->se_sess,NULL , lun, mcmd, - transl_tmr_func,GFP_ATOMIC , tag, flags); + transl_tmr_func,GFP_ATOMIC , tag,TARGET_SCF_ACK_KREF ); } static struct qla_tgt_cmd *tcm_qla2xxx_find_cmd_by_tag(struct fc_port *sess,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 487/798 scsi: target: Remove TARGET_SCF_LOOKUP_LUN_FROM_TAG
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Christie <[email protected]>
[ Upstream commit 27b0efd15d5247ada0c2ed9cbc77fd3fb3b1f26d ]
TARGET_SCF_LOOKUP_LUN_FROM_TAG is no longer used so remove it.
Stable-dep-of: ef63cc441703 ("RDMA/srpt: Pass the mapped task attribute to target_init_cmd()")
--- drivers/target/target_core_transport.c | 33 -------------------------- include/target/target_core_base.h | 1 - 2 files changed, 34 deletions(-)
drivers/target/target_core_transport.c +0 -33
@@ -1771,29 +1771,6 @@ static void target_complete_tmr_failure(struct work_struct *work)transport_cmd_check_stop_to_fabric (se_cmd); } -static bool target_lookup_lun_from_tag (struct se_session *se_sess,u64 tag, -u64 *unpacked_lun) -{ -struct se_cmd *se_cmd; -unsigned long flags; -bool ret = false; - -spin_lock_irqsave (&se_sess->sess_cmd_lock, flags); -list_for_each_entry (se_cmd, &se_sess->sess_cmd_list, se_cmd_list) { -if (se_cmd->se_cmd_flags &SCF_SCSI_TMR_CDB ) -continue ; - -if (se_cmd->tag == tag) { - *unpacked_lun = se_cmd->orig_fe_lun; - ret = true; -break ; - } - } -spin_unlock_irqrestore (&se_sess->sess_cmd_lock, flags); - -return ret; -} -/** * target_submit_tmr - lookup unpacked lun and submit uninitialized se_cmd * for TMR CDBs
@@ -1841,16 +1818,6 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,core_tmr_release_req (se_cmd->se_tmr_req);return ret; } -/* -* If this is ABORT_TASK with no explicit fabric provided LUN, -* go ahead and search active session tags for a match to figure -* out unpacked_lun for the original se_cmd. -*/ -if (tm_type ==TMR_ABORT_TASK && (flags &TARGET_SCF_LOOKUP_LUN_FROM_TAG )) { -if (!target_lookup_lun_from_tag (se_sess, tag, - &se_cmd->orig_fe_lun)) - goto failure; - } ret =transport_lookup_tmr_lun (se_cmd);if (ret)
include/target/target_core_base.h +0 -1
@@ -195,7 +195,6 @@ enum target_sc_flags_table {TARGET_SCF_ACK_KREF =0x02 ,TARGET_SCF_UNKNOWN_SIZE =0x04 , TARGET_SCF_USE_CPUID = 0x08, - TARGET_SCF_LOOKUP_LUN_FROM_TAG = 0x10, };/* fabric independent task management function values */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 488/798 scsi: qla2xxx: Move sess cmd list/lock to driver
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Christie <[email protected]>
[ Upstream commit 605e74025f953b995a3a241ead43bde71c1c99b5 ]
Except for debug output in the shutdown path, tcm_qla2xxx is the only driver using the se_session sess_cmd_list. Move the list to that driver to facilitate removing the sess_cmd_lock from the main I/O path for the rest of the drivers.
Stable-dep-of: ef63cc441703 ("RDMA/srpt: Pass the mapped task attribute to target_init_cmd()")
--- drivers/scsi/qla2xxx/qla_def.h | 2 ++ drivers/scsi/qla2xxx/qla_init.c | 3 ++ drivers/scsi/qla2xxx/qla_target.c | 1 + drivers/scsi/qla2xxx/qla_target.h | 1 + drivers/scsi/qla2xxx/tcm_qla2xxx.c | 57 ++++++++++++++++++------------ 5 files changed, 42 insertions(+), 22 deletions(-)
drivers/scsi/qla2xxx/qla_def.h +2 -0
@@ -2493,6 +2493,8 @@ typedef struct fc_port {int generation;struct se_session *se_sess; +struct list_head sess_cmd_list; +spinlock_t sess_cmd_lock;struct kref sess_kref;struct qla_tgt *tgt;unsigned long expires;
drivers/scsi/qla2xxx/qla_init.c +3 -0
@@ -5164,6 +5164,9 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)INIT_LIST_HEAD (&fcport->gnl_entry);INIT_LIST_HEAD (&fcport->list); +INIT_LIST_HEAD (&fcport->sess_cmd_list); +spin_lock_init (&fcport->sess_cmd_lock); +return fcport; }
drivers/scsi/qla2xxx/qla_target.c +1 -0
@@ -4301,6 +4301,7 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha, cmd->cmd_type =TYPE_TGT_CMD ;memcpy (&cmd->atio, atio,sizeof (*atio)); +INIT_LIST_HEAD (&cmd->sess_cmd_list); cmd->state =QLA_TGT_STATE_NEW ; cmd->tgt = vha->vha_tgt.qla_tgt;qlt_incr_num_pend_cmds (vha);
drivers/scsi/qla2xxx/qla_target.h +1 -0
@@ -856,6 +856,7 @@ struct qla_tgt_cmd {uint8_t cmd_type;uint8_t pad[7 ];struct se_cmd se_cmd; +struct list_head sess_cmd_list;struct fc_port *sess;struct qla_qpair *qpair;uint32_t reset_count;
drivers/scsi/qla2xxx/tcm_qla2xxx.c +35 -22
107 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 489/798 scsi: target: core: Replace in_interrupt() usage in target_submit_cmd_map_sgls()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sebastian Andrzej Siewior <[email protected]>
[ Upstream commit 513e29946ab22f66cd14670024f6c98b5b913462 ]
target_submit_cmd_map_sgls() uses in_interrupt() to crash if it returns true.
The usage of in_interrupt() in drivers is phased out and Linus clearly requested that code which changes behaviour depending on context should either be separated or the context be conveyed in an argument passed by the caller, which usually knows the context.
The usage of in_interrupt() is clearly for debugging. might_sleep() is better at this because it also detects other contexts in which it is not allowed to sleep, like preempt-disabled section.
Replace BUG_ON(in_interrupt) with might_sleep().
Stable-dep-of: ef63cc441703 ("RDMA/srpt: Pass the mapped task attribute to target_init_cmd()")
--- drivers/target/target_core_transport.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/target/target_core_transport.c +2 -1
@@ -1612,10 +1612,11 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sesssense_reason_t rc;int ret; +might_sleep (); + se_tpg = se_sess->se_tpg;BUG_ON (!se_tpg);BUG_ON (se_cmd->se_tfo || se_cmd->se_sess); -BUG_ON (in_interrupt ());if (flags &TARGET_SCF_USE_CPUID ) se_cmd->se_cmd_flags |=SCF_USE_CPUID ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 490/798 scsi: target: core: Rename transport_init_se_cmd()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Christie <[email protected]>
[ Upstream commit a78b713618c02752310b2be7da465a34fb660ed9 ]
Rename transport_init_se_cmd() to __target_init_cmd() to reflect that it is more of an internal function that drivers should normally not use and because we are going to add a new init function in the next patches.
Stable-dep-of: ef63cc441703 ("RDMA/srpt: Pass the mapped task attribute to target_init_cmd()")
--- drivers/target/iscsi/iscsi_target.c | 16 ++++++++-------- drivers/target/target_core_transport.c | 16 ++++++++-------- drivers/target/target_core_xcopy.c | 8 ++++---- drivers/usb/gadget/function/f_tcm.c | 20 ++++++++++---------- include/target/target_core_fabric.h | 2 +- 5 files changed, 31 insertions(+), 31 deletions(-)
drivers/target/iscsi/iscsi_target.c +8 -8
@@ -1154,10 +1154,10 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,/* * Initialize struct se_cmd descriptor from target_core_mod infrastructure */ -transport_init_se_cmd (&cmd->se_cmd, &iscsi_ops, - conn->sess->se_sess,be32_to_cpu (hdr->data_length), - cmd->data_direction, sam_task_attr, - cmd->sense_buffer +2 ,scsilun_to_int (&hdr->lun)); +__target_init_cmd (&cmd->se_cmd, &iscsi_ops, + conn->sess->se_sess,be32_to_cpu (hdr->data_length), + cmd->data_direction, sam_task_attr, + cmd->sense_buffer +2 ,scsilun_to_int (&hdr->lun)); pr_debug("Got SCSI Command, ITT: 0x%08x, CmdSN: 0x%08x," " ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt,
@@ -2012,10 +2012,10 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, buf); } -transport_init_se_cmd (&cmd->se_cmd, &iscsi_ops, - conn->sess->se_sess,0 ,DMA_NONE , -TCM_SIMPLE_TAG , cmd->sense_buffer +2 , -scsilun_to_int (&hdr->lun)); +__target_init_cmd (&cmd->se_cmd, &iscsi_ops, + conn->sess->se_sess,0 ,DMA_NONE , +TCM_SIMPLE_TAG , cmd->sense_buffer +2 , +scsilun_to_int (&hdr->lun));target_get_sess_cmd (&cmd->se_cmd, true);
drivers/target/target_core_transport.c +8 -8
@@ -1295,7 +1295,7 @@ target_check_max_data_sg_nents(struct se_cmd *cmd, struct se_device *dev,* Compare the data buffer size from the CDB with the data buffer limit from the transport * header. Set @cmd->residual_count and SCF_OVERFLOW_BIT or SCF_UNDERFLOW_BIT if necessary. * -* Note: target drivers set @cmd->data_length by calling transport_init_se_cmd(). +* Note: target drivers set @cmd->data_length by calling __target_init_cmd(). * * Return: TCM_NO_SENSE */
@@ -1367,7 +1367,7 @@ target_cmd_size_check(struct se_cmd *cmd, unsigned int size)* * Preserves the value of @cmd->tag. */ -void transport_init_se_cmd( +void __target_init_cmd( struct se_cmd *cmd, const struct target_core_fabric_ops *tfo, struct se_session *se_sess,
@@ -1400,7 +1400,7 @@ void transport_init_se_cmd( cmd->state_active = false; } -EXPORT_SYMBOL (transport_init_se_cmd); +EXPORT_SYMBOL (__target_init_cmd);static sense_reason_t transport_check_alloc_task_attr (struct se_cmd *cmd)
@@ -1625,9 +1625,9 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess* exceptions are handled by sending exception status via * target_core_fabric_ops->queue_status() callback */ -transport_init_se_cmd (se_cmd, se_tpg->se_tpg_tfo, se_sess, - data_length, data_dir, task_attr, sense, - unpacked_lun); +__target_init_cmd (se_cmd, se_tpg->se_tpg_tfo, se_sess, + data_length, data_dir, task_attr, sense, + unpacked_lun);if (flags &TARGET_SCF_UNKNOWN_SIZE ) se_cmd->unknown_data_length =1 ;
@@ -1800,8 +1800,8 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess, se_tpg = se_sess->se_tpg;BUG_ON (!se_tpg); -transport_init_se_cmd (se_cmd, se_tpg->se_tpg_tfo, se_sess, -0 ,DMA_NONE ,TCM_SIMPLE_TAG , sense, unpacked_lun); +__target_init_cmd (se_cmd, se_tpg->se_tpg_tfo, se_sess, +0 ,DMA_NONE ,TCM_SIMPLE_TAG , sense, unpacked_lun);/* * FIXME: Currently expect caller to handle se_cmd->se_tmr_req * allocation failure.
drivers/target/target_core_xcopy.c +4 -4
@@ -615,8 +615,8 @@ static int target_xcopy_read_source(pr_debug ("XCOPY: Built READ_16: LBA: %llu Sectors: %u Length: %u\n" , (unsigned long long )src_lba, src_sectors, length); -transport_init_se_cmd (se_cmd, &xcopy_pt_tfo, &xcopy_pt_sess, length, -DMA_FROM_DEVICE ,0 , &xpt_cmd.sense_buffer[0 ],0 ); +__target_init_cmd (se_cmd, &xcopy_pt_tfo, &xcopy_pt_sess, length, +DMA_FROM_DEVICE ,0 , &xpt_cmd.sense_buffer[0 ],0 ); rc =target_xcopy_setup_pt_cmd (&xpt_cmd, xop, src_dev, &cdb[0 ], remote_port);
@@ -660,8 +660,8 @@ static int target_xcopy_write_destination(pr_debug ("XCOPY: Built WRITE_16: LBA: %llu Sectors: %u Length: %u\n" , (unsigned long long )dst_lba, dst_sectors, length); -transport_init_se_cmd (se_cmd, &xcopy_pt_tfo, &xcopy_pt_sess, length, -DMA_TO_DEVICE ,0 , &xpt_cmd.sense_buffer[0 ],0 ); +__target_init_cmd (se_cmd, &xcopy_pt_tfo, &xcopy_pt_sess, length, +DMA_TO_DEVICE ,0 , &xpt_cmd.sense_buffer[0 ],0 ); rc =target_xcopy_setup_pt_cmd (&xpt_cmd, xop, dst_dev, &cdb[0 ], remote_port);
drivers/usb/gadget/function/f_tcm.c +10 -10
@@ -1041,11 +1041,11 @@ static void usbg_cmd_work(struct work_struct *work) dir =get_cmd_dir (cmd->cmd_buf);if (dir <0 ) { -transport_init_se_cmd (se_cmd, - tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo, - tv_nexus->tvn_se_sess, cmd->data_len,DMA_NONE , - cmd->prio_attr, cmd->sense_iu.sense, - cmd->unpacked_lun); +__target_init_cmd (se_cmd, + tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo, + tv_nexus->tvn_se_sess, cmd->data_len,DMA_NONE , + cmd->prio_attr, cmd->sense_iu.sense, + cmd->unpacked_lun); goto out; }
@@ -1178,11 +1178,11 @@ static void bot_cmd_work(struct work_struct *work) dir =get_cmd_dir (cmd->cmd_buf);if (dir <0 ) { -transport_init_se_cmd (se_cmd, - tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo, - tv_nexus->tvn_se_sess, cmd->data_len,DMA_NONE , - cmd->prio_attr, cmd->sense_iu.sense, - cmd->unpacked_lun); +__target_init_cmd (se_cmd, + tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo, + tv_nexus->tvn_se_sess, cmd->data_len,DMA_NONE , + cmd->prio_attr, cmd->sense_iu.sense, + cmd->unpacked_lun); goto out; }
include/target/target_core_fabric.h +1 -1
@@ -150,7 +150,7 @@ void transport_deregister_session_configfs(struct se_session *);void transport_deregister_session (struct se_session *); -void transport_init_se_cmd (struct se_cmd *, +void __target_init_cmd (struct se_cmd *,const struct target_core_fabric_ops *,struct se_session *,u32 ,int ,int ,unsigned char *,u64 );sense_reason_t transport_lookup_cmd_lun (struct se_cmd *);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 491/798 scsi: target: core: Break up target_submit_cmd_map_sgls()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Christie <[email protected]>
[ Upstream commit 750a1d93f90583a270eb62f36e6d32ebbb6af779 ]
This breaks up target_submit_cmd_map_sgls() into 3 helpers:
- target_init_cmd(): Do the basic general setup and get a refcount to the session to make sure the caller can execute the cmd.
- target_submit_prep(): Do the mapping, cdb processing and get a ref to the LUN.
- target_submit(): Pass the cmd to LIO core for execution.
The above functions must be used by drivers that either:
1. Rely on LIO for session shutdown synchronization by calling target_stop_session().
2. Need to map sgls.
When the next patches are applied then simple drivers that do not need the extra functionality above can use target_submit_cmd() and not worry about failures being returned and how to handle them, since many drivers were getting this wrong and would have hit refcount bugs.
Also, by breaking target_submit_cmd_map_sgls() up into these 3 helper functions, we can allow the later patches to do the init/prep from interrupt context and then do the submission from a workqueue.
Stable-dep-of: ef63cc441703 ("RDMA/srpt: Pass the mapped task attribute to target_init_cmd()")
--- drivers/target/target_core_transport.c | 201 +++++++++++++++++-------- include/target/target_core_fabric.h | 8 + 2 files changed, 148 insertions(+), 61 deletions(-)
drivers/target/target_core_transport.c +140 -61
@@ -1573,46 +1573,31 @@ transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *sgl, }/** -* target_submit_cmd_map_sgls - lookup unpacked lun and submit uninitialized -* se_cmd + use pre-allocated SGL memory. -* -* @se_cmd: command descriptor to submit +* target_init_cmd - initialize se_cmd +* @se_cmd: command descriptor to init * @se_sess: associated se_sess for endpoint -* @cdb: pointer to SCSI CDB * @sense: pointer to SCSI sense buffer * @unpacked_lun: unpacked LUN to reference for struct se_lun * @data_length: fabric expected data transfer length * @task_attr: SAM task attribute * @data_dir: DMA data direction * @flags: flags for command submission from target_sc_flags_tables -* @sgl: struct scatterlist memory for unidirectional mapping -* @sgl_count: scatterlist count for unidirectional mapping -* @sgl_bidi: struct scatterlist memory for bidirectional READ mapping -* @sgl_bidi_count: scatterlist count for bidirectional READ mapping -* @sgl_prot: struct scatterlist memory protection information -* @sgl_prot_count: scatterlist count for protection information * * Task tags are supported if the caller has set @se_cmd->tag. * -* Returns non zero to signal active I/O shutdown failure. All other -* setup exceptions will be returned as a SCSI CHECK_CONDITION response, -* but still return zero here. +* Returns: +* - less than zero to signal active I/O shutdown failure. +* - zero on success. * -* This may only be called from process context, and also currently -* assumes internal allocation of fabric payload buffer by target-core. +* If the fabric driver calls target_stop_session, then it must check the +* return code and handle failures. This will never fail for other drivers, +* and the return code can be ignored. */ -int target_submit_cmd_map_sgls (struct se_cmd *se_cmd,struct se_session *se_sess, -unsigned char *cdb,unsigned char *sense,u64 unpacked_lun, -u32 data_length,int task_attr,int data_dir,int flags, -struct scatterlist *sgl,u32 sgl_count, -struct scatterlist *sgl_bidi,u32 sgl_bidi_count, -struct scatterlist *sgl_prot,u32 sgl_prot_count) +int target_init_cmd (struct se_cmd *se_cmd,struct se_session *se_sess, +unsigned char *sense,u64 unpacked_lun, +u32 data_length,int task_attr,int data_dir,int flags) {struct se_portal_group *se_tpg; -sense_reason_t rc; -int ret; - -might_sleep (); se_tpg = se_sess->se_tpg;BUG_ON (!se_tpg);
@@ -1620,54 +1605,70 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sessif (flags &TARGET_SCF_USE_CPUID ) se_cmd->se_cmd_flags |=SCF_USE_CPUID ; +/* +* Signal bidirectional data payloads to target-core +*/ +if (flags &TARGET_SCF_BIDI_OP ) + se_cmd->se_cmd_flags |=SCF_BIDI ; + +if (flags &TARGET_SCF_UNKNOWN_SIZE ) + se_cmd->unknown_data_length =1 ;/* * Initialize se_cmd for target operation. From this point * exceptions are handled by sending exception status via * target_core_fabric_ops->queue_status() callback */ -__target_init_cmd (se_cmd, se_tpg->se_tpg_tfo, se_sess, - data_length, data_dir, task_attr, sense, - unpacked_lun); +__target_init_cmd (se_cmd, se_tpg->se_tpg_tfo, se_sess, data_length, + data_dir, task_attr, sense, unpacked_lun); -if (flags &TARGET_SCF_UNKNOWN_SIZE ) - se_cmd->unknown_data_length =1 ;/* * Obtain struct se_cmd->cmd_kref reference and add new cmd to * se_sess->sess_cmd_list. A second kref_get here is necessary * for fabrics using TARGET_SCF_ACK_KREF that expect a second * kref_put() to happen during fabric packet acknowledgement. */ - ret =target_get_sess_cmd (se_cmd, flags &TARGET_SCF_ACK_KREF ); -if (ret) -return ret; -/* -* Signal bidirectional data payloads to target-core -*/ -if (flags &TARGET_SCF_BIDI_OP ) - se_cmd->se_cmd_flags |=SCF_BIDI ; +return target_get_sess_cmd (se_cmd, flags &TARGET_SCF_ACK_KREF ); +} +EXPORT_SYMBOL_GPL (target_init_cmd); + +/** +* target_submit_prep - prepare cmd for submission +* @se_cmd: command descriptor to prep +* @cdb: pointer to SCSI CDB +* @sgl: struct scatterlist memory for unidirectional mapping +* @sgl_count: scatterlist count for unidirectional mapping +* @sgl_bidi: struct scatterlist memory for bidirectional READ mapping +* @sgl_bidi_count: scatterlist count for bidirectional READ mapping +* @sgl_prot: struct scatterlist memory protection information +* @sgl_prot_count: scatterlist count for protection information +* +* Returns: +* - less than zero to signal failure. +* - zero on success. +* If failure is returned, lio will the callers queue_status to complete +* the cmd. +*/ +int target_submit_prep (struct se_cmd *se_cmd,unsigned char *cdb, +struct scatterlist *sgl,u32 sgl_count, +struct scatterlist *sgl_bidi,u32 sgl_bidi_count, +struct scatterlist *sgl_prot,u32 sgl_prot_count) +{ +sense_reason_t rc; rc =target_cmd_init_cdb (se_cmd, cdb); -if (rc) { -transport_send_check_condition_and_sense (se_cmd, rc,0 ); -target_put_sess_cmd (se_cmd); -return 0 ; - } +if (rc) + goto send_cc_direct;/* * Locate se_lun pointer and attach it to struct se_cmd */ rc =transport_lookup_cmd_lun (se_cmd); -if (rc) { -transport_send_check_condition_and_sense (se_cmd, rc,0 ); -target_put_sess_cmd (se_cmd); -return 0 ; - } +if (rc) + goto send_cc_direct; rc =target_cmd_parse_cdb (se_cmd); -if (rc !=0 ) { -transport_generic_request_failure (se_cmd, rc); -return 0 ; - } +if (rc !=0 ) + goto generic_fail;/* * Save pointers for SGLs containing protection information,
@@ -1687,6 +1688,41 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sessif (sgl_count !=0 ) {BUG_ON (!sgl); + rc =transport_generic_map_mem_to_cmd (se_cmd, sgl, sgl_count, + sgl_bidi, sgl_bidi_count); +if (rc !=0 ) + goto generic_fail; + } + +return 0 ; + +send_cc_direct: +transport_send_check_condition_and_sense (se_cmd, rc,0 ); +target_put_sess_cmd (se_cmd); +return -EIO ; + +generic_fail: +transport_generic_request_failure (se_cmd, rc); +return -EIO ; +} +EXPORT_SYMBOL_GPL (target_submit_prep); + +/** +* target_submit - perform final initialization and submit cmd to LIO core +* @se_cmd: command descriptor to submit +* +* target_submit_prep must have been called on the cmd, and this must be +* called from process context. +*/ +void target_submit (struct se_cmd *se_cmd) +{ +struct scatterlist *sgl = se_cmd->t_data_sg; +unsigned char *buf =NULL ; + +might_sleep (); + +if (se_cmd->t_data_nents !=0 ) { +BUG_ON (!sgl);/* * A work-around for tcm_loop as some userspace code via * scsi-generic do not memset their associated read buffers,
@@ -1697,8 +1733,6 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess*/ if (!(se_cmd->se_cmd_flags &SCF_SCSI_DATA_CDB ) && se_cmd->data_direction ==DMA_FROM_DEVICE ) { -unsigned char *buf =NULL ; -if (sgl) buf =kmap (sg_page (sgl)) + sgl->offset;
@@ -1708,12 +1742,6 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess } } - rc =transport_generic_map_mem_to_cmd (se_cmd, sgl, sgl_count, - sgl_bidi, sgl_bidi_count); -if (rc !=0 ) { -transport_generic_request_failure (se_cmd, rc); -return 0 ; - } }/*
@@ -1723,6 +1751,57 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sesscore_alua_check_nonop_delay (se_cmd);transport_handle_cdb_direct (se_cmd); +} +EXPORT_SYMBOL_GPL (target_submit); + +/** +* target_submit_cmd_map_sgls - lookup unpacked lun and submit uninitialized +* se_cmd + use pre-allocated SGL memory. +* +* @se_cmd: command descriptor to submit +* @se_sess: associated se_sess for endpoint +* @cdb: pointer to SCSI CDB +* @sense: pointer to SCSI sense buffer +* @unpacked_lun: unpacked LUN to reference for struct se_lun +* @data_length: fabric expected data transfer length +* @task_attr: SAM task attribute +* @data_dir: DMA data direction +* @flags: flags for command submission from target_sc_flags_tables +* @sgl: struct scatterlist memory for unidirectional mapping +* @sgl_count: scatterlist count for unidirectional mapping +* @sgl_bidi: struct scatterlist memory for bidirectional READ mapping +* @sgl_bidi_count: scatterlist count for bidirectional READ mapping +* @sgl_prot: struct scatterlist memory protection information +* @sgl_prot_count: scatterlist count for protection information +* +* Task tags are supported if the caller has set @se_cmd->tag. +* +* Returns non zero to signal active I/O shutdown failure. All other +* setup exceptions will be returned as a SCSI CHECK_CONDITION response, +* but still return zero here. +* +* This may only be called from process context, and also currently +* assumes internal allocation of fabric payload buffer by target-core. +*/ +int target_submit_cmd_map_sgls (struct se_cmd *se_cmd,struct se_session *se_sess, +unsigned char *cdb,unsigned char *sense,u64 unpacked_lun, +u32 data_length,int task_attr,int data_dir,int flags, +struct scatterlist *sgl,u32 sgl_count, +struct scatterlist *sgl_bidi,u32 sgl_bidi_count, +struct scatterlist *sgl_prot,u32 sgl_prot_count) +{ +int rc; + + rc =target_init_cmd (se_cmd, se_sess, sense, unpacked_lun, + data_length, task_attr, data_dir, flags); +if (rc <0 ) +return rc; + +if (target_submit_prep (se_cmd, cdb, sgl, sgl_count, sgl_bidi, + sgl_bidi_count, sgl_prot, sgl_prot_count)) +return 0 ; + +target_submit (se_cmd);return 0 ; }EXPORT_SYMBOL (target_submit_cmd_map_sgls);
include/target/target_core_fabric.h +8 -0
@@ -153,6 +153,14 @@ void transport_deregister_session(struct se_session *);void __target_init_cmd (struct se_cmd *,const struct target_core_fabric_ops *,struct se_session *,u32 ,int ,int ,unsigned char *,u64 ); +int target_init_cmd (struct se_cmd *se_cmd,struct se_session *se_sess, +unsigned char *sense,u64 unpacked_lun,u32 data_length, +int task_attr,int data_dir,int flags); +int target_submit_prep (struct se_cmd *se_cmd,unsigned char *cdb, +struct scatterlist *sgl,u32 sgl_count, +struct scatterlist *sgl_bidi,u32 sgl_bidi_count, +struct scatterlist *sgl_prot,u32 sgl_prot_count); +void target_submit (struct se_cmd *se_cmd);sense_reason_t transport_lookup_cmd_lun (struct se_cmd *);sense_reason_t target_cmd_init_cdb (struct se_cmd *,unsigned char *);sense_reason_t target_cmd_parse_cdb (struct se_cmd *);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 492/798 scsi: target: srpt: Convert to new submission API
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Christie <[email protected]>
[ Upstream commit 50ab9c47f51dbe3419e414ac6880273f58ac2849 ]
target_submit_cmd_map_sgls() is being removed, so convert srpt to the new submission API.
srpt uses target_stop_session() to sync session shutdown with LIO core, so we use target_init_cmd()/target_submit_prep()/target_submit(), because target_init_cmd() will detect the target_stop_session() call and return an error.
Stable-dep-of: ef63cc441703 ("RDMA/srpt: Pass the mapped task attribute to target_init_cmd()")
--- drivers/infiniband/ulp/srpt/ib_srpt.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/infiniband/ulp/srpt/ib_srpt.c +8 -5
@@ -1542,16 +1542,19 @@ static void srpt_handle_cmd(struct srpt_rdma_ch *ch, goto busy; } - rc =target_submit_cmd_map_sgls (cmd, ch->sess, srp_cmd->cdb, - &send_ioctx->sense_data[0 ], -scsilun_to_int (&srp_cmd->lun), data_len, -TCM_SIMPLE_TAG , dir,TARGET_SCF_ACK_KREF , - sg, sg_cnt,NULL ,0 ,NULL ,0 ); + rc =target_init_cmd (cmd, ch->sess, &send_ioctx->sense_data[0 ], +scsilun_to_int (&srp_cmd->lun), data_len, +TCM_SIMPLE_TAG , dir,TARGET_SCF_ACK_KREF );if (rc !=0 ) {pr_debug ("target_submit_cmd() returned %d for tag %#llx\n" , rc, srp_cmd->tag); goto busy; } + +if (target_submit_prep (cmd, srp_cmd->cdb, sg, sg_cnt,NULL ,0 ,NULL ,0 )) +return ; + +target_submit (cmd);return ; busy:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 493/798 RDMA/srpt: Pass the mapped task attribute to target_init_cmd()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit ef63cc441703412628a517dda354f3e51fe2dc92 ]
srpt_handle_cmd() maps the initiator-supplied srp_cmd->task_attr into cmd->sam_task_attr, but then hands a hardcoded TCM_SIMPLE_TAG to target_init_cmd().
Pass the already mapped cmd->sam_task_attr instead, so target core sees the attribute the initiator requested.
--- drivers/infiniband/ulp/srpt/ib_srpt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/ulp/srpt/ib_srpt.c +1 -1
@@ -1544,7 +1544,7 @@ static void srpt_handle_cmd(struct srpt_rdma_ch *ch, rc =target_init_cmd (cmd, ch->sess, &send_ioctx->sense_data[0 ],scsilun_to_int (&srp_cmd->lun), data_len, -TCM_SIMPLE_TAG , dir,TARGET_SCF_ACK_KREF ); + cmd->sam_task_attr, dir,TARGET_SCF_ACK_KREF );if (rc !=0 ) {pr_debug ("target_submit_cmd() returned %d for tag %#llx\n" , rc, srp_cmd->tag);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 494/798 RDMA/restrack: Fix typos in the comments
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kalesh AP <[email protected]>
[ Upstream commit d43358cda7c4696e08880aaa58a7df82e471fa7c ]
Fix couple of occurrences of the misspelled word "reource" in the comments with the correct spelling "resource".
Stable-dep-of: 3481bec4dfc4 ("RDMA/core: Fix potential use after free in ib_destroy_cq_user()")
--- drivers/infiniband/core/restrack.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/infiniband/core/restrack.c +2 -2
@@ -214,7 +214,7 @@ void rdma_restrack_new(struct rdma_restrack_entry *res,EXPORT_SYMBOL (rdma_restrack_new);/** -* rdma_restrack_add() - add object to the reource tracking database +* rdma_restrack_add() - add object to the resource tracking database * @res: resource entry */ void rdma_restrack_add (struct rdma_restrack_entry *res)
@@ -302,7 +302,7 @@ int rdma_restrack_put(struct rdma_restrack_entry *res)EXPORT_SYMBOL (rdma_restrack_put);/** -* rdma_restrack_del() - delete object from the reource tracking database +* rdma_restrack_del() - delete object from the resource tracking database * @res: resource entry */ void rdma_restrack_del (struct rdma_restrack_entry *res)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 495/798 iommu/arm-smmu: Add missing pm_runtime_disable() in qcom_iommu_device_probe
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miaoqian Lin <[email protected]>
[ Upstream commit 93665e0275a2e2badfcfca5ada3b78b22df4a01a ]
If the probe fails, we should use pm_runtime_disable() to balance pm_runtime_enable().
Add missing pm_runtime_disable() for error handling.
Stable-dep-of: c579f18e7959 ("iommu/qcom: Remove sysfs device on probe failure path")
--- drivers/iommu/arm/arm-smmu/qcom_iommu.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/iommu/arm/arm-smmu/qcom_iommu.c +7 -3
@@ -853,14 +853,14 @@ static int qcom_iommu_device_probe(struct platform_device *pdev) ret =devm_of_platform_populate (dev);if (ret) {dev_err (dev,"Failed to populate iommu contexts\n" ); -return ret; + goto err_pm_disable; } ret =iommu_device_sysfs_add (&qcom_iommu->iommu, dev,NULL ,dev_name (dev));if (ret) {dev_err (dev,"Failed to register iommu in sysfs\n" ); -return ret; + goto err_pm_disable; }iommu_device_set_ops (&qcom_iommu->iommu, &qcom_iommu_ops);
@@ -869,7 +869,7 @@ static int qcom_iommu_device_probe(struct platform_device *pdev) ret =iommu_device_register (&qcom_iommu->iommu);if (ret) {dev_err (dev,"Failed to register iommu\n" ); -return ret; + goto err_pm_disable; }bus_set_iommu (&platform_bus_type, &qcom_iommu_ops);
@@ -881,6 +881,10 @@ static int qcom_iommu_device_probe(struct platform_device *pdev) }return 0 ; + +err_pm_disable: +pm_runtime_disable (dev); +return ret; }static int qcom_iommu_device_remove (struct platform_device *pdev)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 496/798 iommu/qcom: Remove sysfs device on probe failure path
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoxiang Li <[email protected]>
[ Upstream commit c579f18e79599c16168925cb149e1db3f29eea5f ]
In qcom_iommu_device_probe(), if iommu_device_register() fails, the sysfs device created by iommu_device_sysfs_add() is not released. Add a goto label to do the cleanup.
--- drivers/iommu/arm/arm-smmu/qcom_iommu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/iommu/arm/arm-smmu/qcom_iommu.c +3 -1
@@ -869,7 +869,7 @@ static int qcom_iommu_device_probe(struct platform_device *pdev) ret =iommu_device_register (&qcom_iommu->iommu);if (ret) {dev_err (dev,"Failed to register iommu\n" ); - goto err_pm_disable; + goto err_sysfs_remove; }bus_set_iommu (&platform_bus_type, &qcom_iommu_ops);
@@ -882,6 +882,8 @@ static int qcom_iommu_device_probe(struct platform_device *pdev)return 0 ; +err_sysfs_remove: +iommu_device_sysfs_remove (&qcom_iommu->iommu); err_pm_disable:pm_runtime_disable (dev);return ret;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 497/798 iommu/qcom: Fix inverted fault report check in qcom_iommu_fault()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mukesh Ojha <[email protected]>
[ Upstream commit 1f33b8208a1978b0c0d6ad60a47fe4bb7a235e58 ]
report_iommu_fault() returns 0 when a fault handler successfully handles the fault, and -ENOSYS when no handler is installed. The condition '!report_iommu_fault()' evaluates to true (printing "Unhandled context fault") precisely when the fault *was* handled, and stays silent when no handler is present — the opposite of what is intended.
Remove the '!' so the driver logs unhandled faults correctly.
--- drivers/iommu/arm/arm-smmu/qcom_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iommu/arm/arm-smmu/qcom_iommu.c +1 -1
@@ -220,7 +220,7 @@ static irqreturn_t qcom_iommu_fault(int irq, void *dev) fsynr =iommu_readl (ctx,ARM_SMMU_CB_FSYNR0 ); iova =iommu_readq (ctx,ARM_SMMU_CB_FAR ); -if (!report_iommu_fault (ctx->domain, ctx->dev, iova,0 )) { +if (report_iommu_fault (ctx->domain, ctx->dev, iova,0 )) { dev_err_ratelimited(ctx->dev, "Unhandled context fault: fsr=0x%x, " "iova=0x%016llx, fsynr=0x%x, cb=%d\n",
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 498/798 thermal: int340x_thermal: Consolidate priv->data_vault checks
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
[ Upstream commit e9a7c526c29b0ae60c888b335bd6cf6e2ee80154 ]
It is sufficient to check priv->data_vault once in the error code path of int3400_thermal_probe(), so do that.
Stable-dep-of: d83dc9ce57a7 ("thermal: intel: int3400: clean up ODVP on probe failures")
--- drivers/thermal/intel/int340x_thermal/int3400_thermal.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/thermal/intel/int340x_thermal/int3400_thermal.c +2 -3
@@ -548,9 +548,8 @@ static int int3400_thermal_probe(struct platform_device *pdev) free_sysfs:cleanup_odvp (priv); -if (priv->data_vault) { -if (!ZERO_OR_NULL_PTR (priv->data_vault)) -sysfs_remove_group (&pdev->dev.kobj, &data_attribute_group); +if (!ZERO_OR_NULL_PTR (priv->data_vault)) { +sysfs_remove_group (&pdev->dev.kobj, &data_attribute_group);kfree (priv->data_vault); } free_uuid:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 499/798 thermal: intel: int3400: clean up ODVP on probe failures
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
[ Upstream commit d83dc9ce57a746a6dca28439bcc0575d26fa6986 ]
evaluate_odvp() creates per-ODVP sysfs files before the thermal zone and later probe resources are registered. The current unwind path only calls cleanup_odvp() from the late sysfs failure path, so failures after evaluate_odvp() but before that label, including thermal_tripless_zone_device_register() failures, leave the ODVP files and storage behind.
Move the ODVP cleanup to the common ART/TRT unwind path so every failure after evaluate_odvp() releases the ODVP state. Also clear the cached ODVP pointers in cleanup_odvp(), because evaluate_odvp() can already call it for partial setup failures while probe continues.
--- drivers/thermal/intel/int340x_thermal/int3400_thermal.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/thermal/intel/int340x_thermal/int3400_thermal.c +3 -1
@@ -290,8 +290,10 @@ static void cleanup_odvp(struct int3400_thermal_priv *priv)kfree (priv->odvp_attrs[i].attr.attr.name); }kfree (priv->odvp_attrs); + priv->odvp_attrs =NULL ; }kfree (priv->odvp); + priv->odvp =NULL ; priv->odvp_count =0 ; }
@@ -547,7 +549,6 @@ static int int3400_thermal_probe(struct platform_device *pdev)return 0 ; free_sysfs: -cleanup_odvp (priv);if (!ZERO_OR_NULL_PTR (priv->data_vault)) {sysfs_remove_group (&pdev->dev.kobj, &data_attribute_group);kfree (priv->data_vault);
@@ -559,6 +560,7 @@ static int int3400_thermal_probe(struct platform_device *pdev)acpi_thermal_rel_misc_device_remove (priv->adev->handle);thermal_zone_device_unregister (priv->thermal); free_art_trt: +cleanup_odvp (priv);kfree (priv->trts);kfree (priv->arts); free_priv:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 500/798 ext4: drain in-flight DIO before buffered write fallback
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baokun Li <[email protected]>
[ Upstream commit 15cdefd0c0522f9d5e12d947fa04f4c11649b699 ]
generic/746 started failing intermittently on ext3 (no-extent inodes). The test triggers 'Page cache invalidation failure on direct I/O' warnings and subsequent fsync returns -EIO. Adding a 50ms delay between ext4_buffered_write_iter() and filemap_write_and_wait_range() in ext4_dio_write_iter() makes the race almost always reproducible.
On no-extent inodes, DIO writes to holes cannot use unwritten extents, so ext4_iomap_alloc() leaves m_flags=0 and ext4_map_blocks() returns 0. The iomap layer then returns -ENOTBLK, causing fallback to buffered I/O.
The fallback path in ext4_dio_write_iter() calls ext4_buffered_write_iter() which dirties pages, then does flush and invalidate. However, there's an unprotected window between ext4_buffered_write_iter() returning (with inode lock released) and the subsequent flush+invalidate.
Concurrent async DIO completions from other threads can run kiocb_invalidate_post_direct_write() during this window. If pages have been re-dirtied, post-invalidation finds dirty pages and triggers the warning, setting -EIO in the error sequence.
Consider a file with two 4k extents: [hole][written]. Thread A does DIO to the written extent, while thread B does DIO spanning both:
kworker A (4k DIO, allocated block) kworker B (8k DIO, fallback)
----------------------------------- ----------------------------
inode_lock_shared() inode_lock_shared()
iomap_dio_rw(): iomap_dio_rw():
kiocb_invalidate_pages -> clean iomap_begin -> -ENOTBLK
submit_bio (async) dio->size = 0 inode_unlock_shared() inode_unlock_shared()
[bio pending in block layer] /* fallback: lock released */
ext4_buffered_write_iter()
inode_lock(exclusive)
generic_perform_write()
-> dirty pages [0, 8k]
inode_unlock(exclusive)
/* pages dirty, no lock */
[bio completes] filemap_write_and_wait_range()
iomap_dio_complete() -> flush dirty pages
kiocb_invalidate_post_direct_write() invalidate_mapping_pages()
invalidate_inode_pages2_range()
-> finds dirty page!
-> dio_warn_stale_pagecache()
-> errseq_set(-EIO)This issue can be triggered through normal I/O paths, not just intentionally overlapping DIO writes from userspace. For example, generic/746 uses a loop device where multiple kworkers issue concurrent I/O to the backing file. Additionally, when block_size < folio_size, non-overlapping DIO writes that share a large folio can also trigger the race.
Add inode_dio_wait() in ext4_buffered_write_iter() before ext4_write_checks() to drain all in-flight DIO. This ensures that all DIO clears existing pages before submitting IO (via kiocb_invalidate_pages()), all BIO waits for all DIO to complete (via inode_dio_wait()), and ext4_write_checks() observes the inode size after all completed DIO so that ext4_block_zero_eof() does not race with in-flight DIO, thus eliminating the race.
--- fs/ext4/file.c | 7 +++++++ 1 file changed, 7 insertions(+)
fs/ext4/file.c +7 -0
@@ -261,6 +261,13 @@ static ssize_t ext4_buffered_write_iter(struct kiocb *iocb,return -EOPNOTSUPP ;inode_lock (inode); + +/* +* Prevent concurrent direct I/O and buffered I/O to the same file +* range. Wait for in-flight DIO to finish before dirtying pages. +*/ +inode_dio_wait (inode); + ret =ext4_write_checks (iocb, from);if (ret <=0 ) goto out;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 501/798 wifi: ath6kl: avoid buffer overreads in WMI event handlers
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Johnson <[email protected]>
[ Upstream commit f57314aade9d74d30f3360ec5ef85a83654748be ]
The following WMI event handlers currently read from the event buffer without first verifying that the message was large enough to hold the expected event:ath6kl_wmi_scan_complete_rx() ath6kl_wmi_addba_req_event_rx() ath6kl_wmi_delba_req_event_rx()
Add length checks to prevent overread.
--- drivers/net/wireless/ath/ath6kl/wmi.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
drivers/net/wireless/ath/ath6kl/wmi.c +15 -2
@@ -1296,6 +1296,9 @@ static int ath6kl_wmi_scan_complete_rx(struct wmi *wmi, u8 *datap, int len, {struct wmi_scan_complete_event *ev; +if (len <sizeof (*ev)) +return -EINVAL ; + ev = (struct wmi_scan_complete_event *) datap;ath6kl_scan_complete_evt (vif,a_sle32_to_cpu (ev->status));
@@ -3386,7 +3389,12 @@ static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap,static int ath6kl_wmi_addba_req_event_rx (struct wmi *wmi,u8 *datap,int len,struct ath6kl_vif *vif) { -struct wmi_addba_req_event *cmd = (struct wmi_addba_req_event *) datap; +struct wmi_addba_req_event *cmd; + +if (len <sizeof (*cmd)) +return -EINVAL ; + + cmd = (struct wmi_addba_req_event *)datap;aggr_recv_addba_req_evt (vif, cmd->tid,le16_to_cpu (cmd->st_seq_no), cmd->win_sz);
@@ -3397,7 +3405,12 @@ static int ath6kl_wmi_addba_req_event_rx(struct wmi *wmi, u8 *datap, int len,static int ath6kl_wmi_delba_req_event_rx (struct wmi *wmi,u8 *datap,int len,struct ath6kl_vif *vif) { -struct wmi_delba_event *cmd = (struct wmi_delba_event *) datap; +struct wmi_delba_event *cmd; + +if (len <sizeof (*cmd)) +return -EINVAL ; + + cmd = (struct wmi_delba_event *)datap;aggr_recv_delba_req_evt (vif, cmd->tid);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 502/798 wifi: ath11k: Correctly copy the hint BSSID in WMI scan request
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Johnson <[email protected]>
[ Upstream commit 6fe2dddf59bbb2a96be0fcf23a205807b25ac173 ]
Currently, in ath11k_wmi_send_scan_start_cmd(), the logic to populate the hint_bssid copies the BSSID in the wrong direction, from the firmware message to the argument buffer. Swap the parameters so that the BSSID is correctly populated in the firmware message from the argument buffer.
This issue was reported on ath12k, but exists in ath11k as well.
Compile tested only.
--- drivers/net/wireless/ath/ath11k/wmi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/ath/ath11k/wmi.c +2 -2
@@ -2194,8 +2194,8 @@ int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar,for (i =0 ; i < params->num_hint_bssid; ++i) { hint_bssid->freq_flags = params->hint_bssid[i].freq_flags; -ether_addr_copy (¶ms->hint_bssid[i].bssid.addr[0 ], - &hint_bssid->bssid.addr[0 ]); +ether_addr_copy (&hint_bssid->bssid.addr[0 ], + ¶ms->hint_bssid[i].bssid.addr[0 ]); hint_bssid++; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 503/798 ath11k: add trace log support
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Venkateswara Naralasetty <[email protected]>
[ Upstream commit fb12305aff12e735e599c79514dde5dac40f5a59 ]
This change is to add trace log support for,
* WMI events
* WMI commands
* ath11k_dbg messages
* ath11k_dbg_dump messages
* ath11k_log_info messages
* ath11k_log_warn messages
* ath11k_log_err messages
Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.5.0.1-00652-QCAHKSWPL_SILICONZ-1
Stable-dep-of: 9ef9dd30058c ("wifi: ath11k: Avoid buffer overread in ath11k_wmi_tlv_op_rx()")
--- drivers/net/wireless/ath/ath11k/debug.c | 12 +- drivers/net/wireless/ath/ath11k/debug.h | 3 +- drivers/net/wireless/ath/ath11k/trace.c | 1 + drivers/net/wireless/ath/ath11k/trace.h | 172 ++++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/wmi.c | 4 + 5 files changed, 187 insertions(+), 5 deletions(-)
drivers/net/wireless/ath/ath11k/debug.c +8 -4
@@ -17,7 +17,7 @@ void ath11k_info(struct ath11k_base *ab, const char *fmt, ...)va_start (args, fmt); vaf.va = &args;dev_info (ab->dev,"%pV" , &vaf); -/* TODO: Trace the log */ +trace_ath11k_log_info (ab, &vaf);va_end (args); }EXPORT_SYMBOL (ath11k_info);
@@ -32,7 +32,7 @@ void ath11k_err(struct ath11k_base *ab, const char *fmt, ...)va_start (args, fmt); vaf.va = &args;dev_err (ab->dev,"%pV" , &vaf); -/* TODO: Trace the log */ +trace_ath11k_log_err (ab, &vaf);va_end (args); }EXPORT_SYMBOL (ath11k_err);
@@ -47,7 +47,7 @@ void ath11k_warn(struct ath11k_base *ab, const char *fmt, ...)va_start (args, fmt); vaf.va = &args;dev_warn_ratelimited (ab->dev,"%pV" , &vaf); -/* TODO: Trace the log */ +trace_ath11k_log_warn (ab, &vaf);va_end (args); }EXPORT_SYMBOL (ath11k_warn);
@@ -68,7 +68,7 @@ void __ath11k_dbg(struct ath11k_base *ab, enum ath11k_debug_mask mask,if (ath11k_debug_mask & mask)dev_printk (KERN_DEBUG , ab->dev,"%pV" , &vaf); -/* TODO: trace log */ +trace_ath11k_log_dbg (ab, mask, &vaf);va_end (args); }
@@ -100,6 +100,10 @@ void ath11k_dbg_dump(struct ath11k_base *ab,dev_printk (KERN_DEBUG , ab->dev,"%s\n" , linebuf); } } + +/* tracing code doesn't like null strings */ +trace_ath11k_log_dbg_dump (ab, msg ? msg :"" , prefix ? prefix :"" , + buf, len); }EXPORT_SYMBOL (ath11k_dbg_dump);
drivers/net/wireless/ath/ath11k/debug.h +2 -1
@@ -60,7 +60,8 @@ static inline void ath11k_dbg_dump(struct ath11k_base *ab,#define ath11k_dbg (ar, dbg_mask, fmt, ...) \ do { \ - if (ath11k_debug_mask & dbg_mask) \ + if ((ath11k_debug_mask & dbg_mask) || \ + trace_ath11k_log_dbg_enabled()) \ __ath11k_dbg(ar, dbg_mask, fmt, ##__VA_ARGS__); \ } while (0)
drivers/net/wireless/ath/ath11k/trace.c +1 -0
@@ -7,3 +7,4 @@#define CREATE_TRACE_POINTS #include "trace.h" +EXPORT_SYMBOL (__tracepoint_ath11k_log_dbg);
drivers/net/wireless/ath/ath11k/trace.h +172 -0
190 lines not on this page · raw message
drivers/net/wireless/ath/ath11k/wmi.c +4 -0
@@ -243,6 +243,8 @@ static int ath11k_wmi_cmd_send_nowait(struct ath11k_pdev_wmi *wmi, struct sk_buf cmd_hdr = (struct wmi_cmd_hdr *)skb->data; cmd_hdr->cmd_id = cmd; +trace_ath11k_wmi_cmd (ab, cmd_id, skb->data, skb->len); +memset (skb_cb,0 ,sizeof (*skb_cb)); ret =ath11k_htc_send (&ab->htc, wmi->eid, skb);
@@ -6429,6 +6431,8 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb) cmd_hdr = (struct wmi_cmd_hdr *)skb->data; id =FIELD_GET (WMI_CMD_HDR_CMD_ID , (cmd_hdr->cmd_id)); +trace_ath11k_wmi_event (ab, id, skb->data, skb->len); +if (skb_pull (skb,sizeof (struct wmi_cmd_hdr )) ==NULL ) goto out;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 504/798 wifi: ath11k: Avoid buffer overread in ath11k_wmi_tlv_op_rx()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Johnson <[email protected]>
[ Upstream commit 9ef9dd30058cc9223c72f711dca1a28a5947d0c5 ]
Currently, in ath11k_wmi_tlv_op_rx(), the firmware buffer is read without first verifying that the buffer has enough data to hold a header. This could result in a buffer overread.
Add an upfront length check before dereferencing skb->data as a wmi_cmd_hdr. The check is placed before the trace_ath11k_wmi_event() call to preserve the existing trace semantics (tracing the full raw WMI event including the header), unlike the analogous ath12k fix which could use skb_pull_data() directly.
Compile tested only.
--- drivers/net/wireless/ath/ath11k/wmi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/wireless/ath/ath11k/wmi.c +4 -2
@@ -6428,13 +6428,15 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)struct wmi_cmd_hdr *cmd_hdr;enum wmi_tlv_event_id id; +if (skb->len <sizeof (*cmd_hdr)) + goto out; + cmd_hdr = (struct wmi_cmd_hdr *)skb->data; id =FIELD_GET (WMI_CMD_HDR_CMD_ID , (cmd_hdr->cmd_id));trace_ath11k_wmi_event (ab, id, skb->data, skb->len); -if (skb_pull (skb,sizeof (struct wmi_cmd_hdr )) ==NULL ) - goto out; +skb_pull (skb,sizeof (*cmd_hdr));switch (id) {/* Process all the WMI events here */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 505/798 ARM: dts: allwinner: a10: Fix PMU interrupt
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andre Przywara <[email protected]>
[ Upstream commit eb7051f756460d7b951e94d9656e31ebb631ba28 ]
The Performance Monitoring Unit of the Cortex-A8 cores in the Allwinner A10 SoC is connected to interrupt line 66, not 3. This is shown in the manual (where interrupt 3 is assigned to UART2, also in our .dtsi), but has also been confirmed by triggering an PMU overflow interrupt and inspecting the IRQ controller status registers (from U-Boot). Please note that "perf stat" does not use interrupts, this might explain why this evaded the initial testing.
--- arch/arm/boot/dts/sun4i-a10.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/boot/dts/sun4i-a10.dtsi +1 -1
@@ -186,7 +186,7 @@ de: display-engine { pmu { compatible = "arm,cortex-a8-pmu"; - interrupts = <3>; + interrupts = <66>; }; reserved-memory {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 506/798 perf cs-etm: Flush thread stacks after decoder reset
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leo Yan <[email protected]>
[ Upstream commit ea5075e3776846d4941dddf1549426ebd3feb81f ]
Perf resets the CoreSight decoder when moving to a new AUX trace buffer, this causes trace discontinunity globally.
For callchain synthesis, keeping thread-stack state after decoder reset can leave stale call/return history attached to threads that are decoded later, producing incorrect synthesized callchains.
Flush all host thread stacks after a decoder reset. When virtualization is present, flush the guest thread stacks as well.
Stable-dep-of: ec99be8a31db ("perf cs-etm: Avoid truncating AUX buffer sizes to int")
--- tools/perf/util/cs-etm.c | 45 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
tools/perf/util/cs-etm.c +45 -0
@@ -1609,6 +1609,45 @@ static int cs_etm__end_block(struct cs_etm_queue *etmq,return 0 ; } + +static int cs_etm__flush_stack_cb (struct thread *thread, +void *data__maybe_unused ) +{ +thread_stack__flush (thread); +return 0 ; +} + +static void cs_etm__flush_machine_stack (struct cs_etm_queue *etmq,pid_t pid) +{ +struct machine *machine; + + machine =machines__find (&etmq->etm->session->machines, pid); +if (machine) +machine__for_each_thread (machine, cs_etm__flush_stack_cb,NULL ); +} + +static void cs_etm__flush_all_stack (struct cs_etm_queue *etmq) +{ +enum cs_etm_pid_fmt pid_fmt =cs_etm__get_pid_fmt (etmq); + +if (!etmq->etm->synth_opts.last_branch) +return ; + +switch (pid_fmt) { +case CS_ETM_PIDFMT_CTXTID2 : +/* Clear the guest stack if virtualization is supported */ +cs_etm__flush_machine_stack (etmq,DEFAULT_GUEST_KERNEL_ID ); + fallthrough; +case CS_ETM_PIDFMT_CTXTID : +cs_etm__flush_machine_stack (etmq,HOST_KERNEL_ID ); +break ; +case CS_ETM_PIDFMT_NONE : +default : +break ; + + } +} +/* * cs_etm__get_data_block: Fetch a block from the auxtrace_buffer queue * if need be.
@@ -1631,6 +1670,12 @@ static int cs_etm__get_data_block(struct cs_etm_queue *etmq) ret =cs_etm_decoder__reset (etmq->decoder);if (ret)return ret; + +/* +* Since the decoder is reset, this causes a global trace +* discontinuity. Flush all thread stacks. +*/ +cs_etm__flush_all_stack (etmq); }return etmq->buf_len;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 507/798 perf cs-etm: Avoid truncating AUX buffer sizes to int
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leo Yan <[email protected]>
[ Upstream commit ec99be8a31db999a4f866be74ea7db61dbb19f24 ]
cs_etm__get_trace() returns an int, but it used to return etmq->buf_len on success. That value comes from auxtrace_buffer::size, which is a size_t. For a large AUX trace block, returning the byte count through an int can overflow and make a valid buffer look like a negative error.
The callers do not need the actual byte count from cs_etm__get_trace(). The buffer length is already stored in the etmq->buf_len. The callers only need to distinguish three states:
< 0: error
= 0: no more AUX buffers
Quoted 1 line
0: data is available
Make cs_etm__get_trace() return 0 for all non-error cases and use etmq->buf_len to indicate whether a new buffer was found. Then make cs_etm__get_data_block() return 1 whenever data is available, instead of returning the buffer length.
Also refactor cs_etm__get_data_block() to make its return value semantics clearer.
--- tools/perf/util/cs-etm.c | 46 +++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 20 deletions(-)
tools/perf/util/cs-etm.c +26 -20
@@ -1065,8 +1065,7 @@ cs_etm__get_trace(struct cs_etm_queue *etmq) etmq->buf_used =0 ; etmq->buf_len = aux_buffer->size; etmq->buf = aux_buffer->data; - -return etmq->buf_len; +return 0 ; } static void cs_etm__set_pid_tid_cpu(struct cs_etm_auxtrace *etm,
@@ -1659,26 +1658,33 @@ static int cs_etm__get_data_block(struct cs_etm_queue *etmq) {int ret; -if (!etmq->buf_len) { - ret =cs_etm__get_trace (etmq); -if (ret <=0 ) -return ret; -/* -* We cannot assume consecutive blocks in the data file -* are contiguous, reset the decoder to force re-sync. -*/ - ret =cs_etm_decoder__reset (etmq->decoder); -if (ret) -return ret; +/* The current block is not finished */ +if (etmq->buf_len) +return 1 ; -/* -* Since the decoder is reset, this causes a global trace -* discontinuity. Flush all thread stacks. -*/ -cs_etm__flush_all_stack (etmq); - } + ret =cs_etm__get_trace (etmq); +if (ret <0 ) +return ret; + +/* No more buffer to read */ +if (!etmq->buf_len) +return 0 ; + +/* +* We cannot assume consecutive blocks in the data file +* are contiguous, reset the decoder to force re-sync. +*/ + ret =cs_etm_decoder__reset (etmq->decoder); +if (ret) +return ret; + +/* +* Since the decoder is reset, this causes a global trace +* discontinuity. Flush all thread stacks. +*/ +cs_etm__flush_all_stack (etmq); -return etmq->buf_len; +return 1 ; } static bool cs_etm__is_svc_instr(struct cs_etm_queue *etmq, u8 trace_chan_id,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 508/798 leds: pca9532: Fix phantom device registration on missing hardware
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cosmo Chou <[email protected]>
[ Upstream commit 8d6b6c05b8e33d11e3fb3203309385e1a9cceecd ]
The initial PWM and PSC register writes in pca9532_configure() do not check the return values of i2c_smbus_write_byte_data(). If the I2C device is physically absent from the bus, the write fails with -ENXIO. However, the driver ignores this error and allows probe() to complete successfully.
This results in the registration of phantom LED class devices and gpiochips backed by non-existent hardware. Subsequent GPIO reads from these phantom chips return bogus values (due to -ENXIO being truncated to an unsigned char in pca9532_gpio_get_value()), silently corrupting hardware state tracking in userspace.
Propagate the I2C write failures back to probe() so the driver core can gracefully abort binding and release devres-managed resources.
--- drivers/leds/leds-pca9532.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/leds/leds-pca9532.c +8 -4
@@ -360,10 +360,14 @@ static int pca9532_configure(struct i2c_client *client,for (i =0 ; i <2 ; i++) { data->pwm[i] = pdata->pwm[i]; data->psc[i] = pdata->psc[i]; -i2c_smbus_write_byte_data (client,PCA9532_REG_PWM (maxleds, i), - data->pwm[i]); -i2c_smbus_write_byte_data (client,PCA9532_REG_PSC (maxleds, i), - data->psc[i]); + err =i2c_smbus_write_byte_data (client,PCA9532_REG_PWM (maxleds, i), + data->pwm[i]); +if (err <0 ) +return err; + err =i2c_smbus_write_byte_data (client,PCA9532_REG_PSC (maxleds, i), + data->psc[i]); +if (err <0 ) +return err; }for (i =0 ; i < data->chip_info->num_leds; i++) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 509/798 drm/tve200: add OF module alias for autoloading
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Can Peng <[email protected]>
[ Upstream commit b6c3585f2058e0fbfa8cb403458f5cc6cf5c5e06 ]
The TVE200 DRM driver can be built as a module and uses tve200_of_match as its OF match table, but the table is not exported for module alias generation.
Add the MODULE_DEVICE_TABLE(of, ...) entry so modpost can generate OF module aliases for OF based module autoloading.
--- drivers/gpu/drm/tve200/tve200_drv.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/tve200/tve200_drv.c +1 -0
@@ -258,6 +258,7 @@ static const struct of_device_id tve200_of_match[] = { }, {}, }; +MODULE_DEVICE_TABLE (of, tve200_of_match);static struct platform_driver tve200_driver = { .driver = {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 510/798 netfilter: nf_nat_sip: rewind offset when NAT shrinks the packet
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit 16aecbe3036f6097c26b51b12e4c1cf207769690 ]
sashiko says:
If map_addr() changes the packet length, such as when the public NAT IP string is shorter or longer than the internal IP, coff will still point to the offset relative to the pre-mangled packet.
If the packet shrinks, coff could overshoot the correct position, potentially causing the next ct_sip_parse_header_uri() call to silently skip bytes and miss subsequent Contact headers. Could this lead to a failure to NAT those subsequent headers and leak internal network details?
--- net/netfilter/nf_nat_sip.c | 5 +++++ 1 file changed, 5 insertions(+)
net/netfilter/nf_nat_sip.c +5 -0
@@ -267,12 +267,17 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff, SIP_HDR_CONTACT, &in_header, &matchoff, &matchlen, &addr, &port) > 0) { +int old_len = skb->len, delta; +if (!map_addr (skb, protoff, dataoff, dptr, datalen, matchoff, matchlen, &addr, port)) {nf_ct_helper_log (skb, ct,"cannot mangle contact" );return NF_DROP ; } + + delta = (int )skb->len - old_len; + coff += delta; } if (!map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_FROM) ||
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 511/798 arm64: dts: rockchip: Add gru-scarlet-dumo board
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen-Yu Tsai <[email protected]>
[ Upstream commit 5707e34166f546bf1fcdfd3da600e8187d04d937 ]
Dumo is another variant of Scarlet, also known as the ASUS Chromebook Tablet CT100. This is almost the same as Scarlet-Innolux, but uses a board-specific calibration variant for the WiFi module.
Add a new device tree for it.
Stable-dep-of: a761818d9ee1 ("arm64: dts: rockchip: Fix Gru WLAN sideband interrupt")
--- arch/arm64/boot/dts/rockchip/Makefile | 1 + .../dts/rockchip/rk3399-gru-scarlet-dumo.dts | 41 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet-dumo.dts
arch/arm64/boot/dts/rockchip/Makefile +1 -0
@@ -20,6 +20,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-ficus.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-firefly.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-gru-bob.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-gru-kevin.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-gru-scarlet-dumo.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-gru-scarlet-inx.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-gru-scarlet-kd.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-hugsun-x99.dtb
arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet-dumo.dts new file +41 -0
41 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 512/798 arm64: dts: rockchip: Fix PCI node addresses on rk3399-gru
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rob Herring <[email protected]>
[ Upstream commit c13c823a78b77ea0e5f1f73112d910e259911101 ]
The rk3399-gru PCI node addresses are wrong.
In rk3399-gru-scarlet, the bus number in the address should be 0. This is because bus number assignment is dynamic and not known up front. For FDT, the bus number is simply ignored.
In rk3399-gru-chromebook, the addresses are simply invalid. The first "reg" entry must be the configuration space for the device. The entry should be all 0s except for device/slot and function numbers. The existing 64-bit memory space (0x83000000) entries are not valid because they must have the BAR address in the lower byte of the first cell.
Warnings for these are enabled by adding the missing 'device_type = "pci"' for the root port node.
Stable-dep-of: a761818d9ee1 ("arm64: dts: rockchip: Fix Gru WLAN sideband interrupt")
--- arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi | 3 +-- arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet-dumo.dts | 4 ++-- arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi | 1 + 3 files changed, 4 insertions(+), 4 deletions(-)
arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi +1 -2
@@ -327,8 +327,7 @@ wacky_spi_audio: spi2@0 { &pci_rootport { mvl_wifi: wifi@0,0 { compatible = "pci1b4b,2b42"; - reg = <0x83010000 0x0 0x00000000 0x0 0x00100000 - 0x83010000 0x0 0x00100000 0x0 0x00100000>; + reg = <0x0000 0x0 0x0 0x0 0x0>; interrupt-parent = <&gpio0>; interrupts = <8 IRQ_TYPE_LEVEL_LOW>; pinctrl-names = "default";
arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet-dumo.dts +2 -2
@@ -34,8 +34,8 @@ &mipi_panel { &pci_rootport { wifi@0,0 { compatible = "qcom,ath10k"; - reg = <0x00010000 0x0 0x00000000 0x0 0x00000000>, - <0x03010010 0x0 0x00000000 0x0 0x00200000>; + reg = <0x00000000 0x0 0x00000000 0x0 0x00000000>, + <0x03000010 0x0 0x00000000 0x0 0x00200000>; qcom,ath10k-calibration-variant = "GO_DUMO"; }; };
arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +1 -0
@@ -456,6 +456,7 @@ pci_rootport: pcie@0,0 { #address-cells = <3>; #size-cells = <2>; ranges; + device_type = "pci"; }; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 513/798 arm64: dts: rockchip: Fix Gru WLAN sideband interrupt
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fabio Estevam <[email protected]>
[ Upstream commit a761818d9ee11183df0aefd16bf9fe46cc1c4c6d ]
The Marvell WLAN host wake interrupt is wired to GPIO0 8 and is not one of the PCI INTx interrupts. The PCI device schema therefore interprets the two-cell GPIO interrupt specifier as an invalid PCI interrupt and reports dtbs_check warnings:
pcie@0,0: wifi@0,0:interrupts:0:0: 8 is not one of [1, 2, 3, 4] pcie@0,0: wifi@0,0:interrupts:0: [8, 8] is too long
Describe the sideband interrupt with interrupts-extended, which explicitly carries the interrupt controller and removes the ambiguity.
--- arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi +1 -2
@@ -328,8 +328,7 @@ &pci_rootport { mvl_wifi: wifi@0,0 { compatible = "pci1b4b,2b42"; reg = <0x0000 0x0 0x0 0x0 0x0>; - interrupt-parent = <&gpio0>; - interrupts = <8 IRQ_TYPE_LEVEL_LOW>; + interrupts-extended = <&gpio0 8 IRQ_TYPE_LEVEL_LOW>; pinctrl-names = "default"; pinctrl-0 = <&wlan_host_wake_l>; wakeup-source;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 514/798 ARM: lpc32xx: only run SoC init on LPC32xx hardware
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Karl Mehltretter <[email protected]>
[ Upstream commit 717ea4000867e6dffee5e1ed92150a9704ae9f68 ]
lpc32xx_check_uid() and lpc32xx_pm_init() are arch_initcalls that poke LPC32xx-only registers. Since the multiplatform conversion they also run on other ARCH_MULTI_V5 boards where access faults e.g. on versatile:
Unable to handle kernel paging request at virtual address f4004130 PC is at lpc32xx_check_uid+0x2c/0x9c
Drop the arch_initcall() registrations and call both functions directly from lpc3250_machine_init(), the machine's .init_machine hook. The calls are placed in link order (common.c, pm.c, phy3250.c) to keep their previous relative ordering.
--- arch/arm/mach-lpc32xx/common.c | 5 +---- arch/arm/mach-lpc32xx/common.h | 2 ++ arch/arm/mach-lpc32xx/phy3250.c | 2 ++ arch/arm/mach-lpc32xx/pm.c | 5 +---- 4 files changed, 6 insertions(+), 8 deletions(-)
arch/arm/mach-lpc32xx/common.c +1 -4
@@ -106,7 +106,7 @@ void __init lpc32xx_map_io(void)iotable_init (lpc32xx_io_desc,ARRAY_SIZE (lpc32xx_io_desc)); } -static int __init lpc32xx_check_uid (void ) +void __init lpc32xx_check_uid (void ) {u32 uid[4 ];
@@ -119,7 +119,4 @@ static int __init lpc32xx_check_uid(void) system_serial_low = uid[0 ]; system_serial_high = uid[1 ]; } - -return 1 ; } -arch_initcall (lpc32xx_check_uid);
arch/arm/mach-lpc32xx/common.h +2 -0
@@ -16,6 +16,8 @@* Other arch specific structures and functions */ extern void __init lpc32xx_map_io (void ); +extern void __init lpc32xx_check_uid (void ); +extern void __init lpc32xx_pm_init (void );extern void __init lpc32xx_serial_init (void );/*
arch/arm/mach-lpc32xx/phy3250.c +2 -0
@@ -71,6 +71,8 @@ static const struct of_dev_auxdata lpc32xx_auxdata_lookup[] __initconst = {static void __init lpc3250_machine_init (void ) { +lpc32xx_check_uid (); +lpc32xx_pm_init ();lpc32xx_serial_init ();of_platform_default_populate (NULL , lpc32xx_auxdata_lookup,NULL );
arch/arm/mach-lpc32xx/pm.c +1 -4
@@ -122,7 +122,7 @@ static const struct platform_suspend_ops lpc32xx_pm_ops = {#define EMC_DYN_MEM_CTRL_OFS 0x20#define EMC_SRMMC (1 << 3)#define EMC_CTRL_REG io_p2v(LPC32XX_EMC_BASE + EMC_DYN_MEM_CTRL_OFS) -static int __init lpc32xx_pm_init (void ) +void __init lpc32xx_pm_init (void ) {/* * Setup SDRAM self-refresh clock to automatically disable o
@@ -131,7 +131,4 @@ static int __init lpc32xx_pm_init(void)__raw_writel (__raw_readl (EMC_CTRL_REG ) |EMC_SRMMC ,EMC_CTRL_REG );suspend_set_ops (&lpc32xx_pm_ops); - -return 0 ; } -arch_initcall (lpc32xx_pm_init);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 515/798 power: supply: sbs-battery: cache constant string properties
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ikjoon Jang <[email protected]>
[ Upstream commit b49a81d0fd021a1f0c8660fa40ad9984d9d1f5b7 ]
Currently sbs-battery supports three string properties - manufacturer, model_name, and chemistry. Buffers for those properties are currently defined as global variables.
This patch moves those global variables into struct sbs_info and cache/reuse them as they are all constant values.
Stable-dep-of: 6027892925b8 ("power: supply: sbs-battery: Use a per-device serial number buffer")
--- drivers/power/supply/sbs-battery.c | 153 ++++++++++++++++++----------- 1 file changed, 95 insertions(+), 58 deletions(-)
drivers/power/supply/sbs-battery.c +95 -58
@@ -188,6 +188,14 @@ static const enum power_supply_property sbs_properties[] = {/* Supports special manufacturer commands from TI BQ20Z65 and BQ20Z75 IC. */ #define SBS_FLAGS_TI_BQ20ZX5 BIT(0) +static const enum power_supply_property string_properties[] = { +POWER_SUPPLY_PROP_TECHNOLOGY , +POWER_SUPPLY_PROP_MANUFACTURER , +POWER_SUPPLY_PROP_MODEL_NAME , +}; + +#define NR_STRING_BUFFERS ARRAY_SIZE(string_properties) +struct sbs_info {struct i2c_client *client;struct power_supply *power_supply;
@@ -201,11 +209,32 @@ struct sbs_info {struct delayed_work work;struct mutex mode_lock;u32 flags; +int technology; +char strings[NR_STRING_BUFFERS ][I2C_SMBUS_BLOCK_MAX +1 ]; }; -static char model_name[I2C_SMBUS_BLOCK_MAX +1 ]; -static char manufacturer[I2C_SMBUS_BLOCK_MAX +1 ]; -static char chemistry[I2C_SMBUS_BLOCK_MAX +1 ]; +static char *sbs_get_string_buf (struct sbs_info *chip, +enum power_supply_property psp) +{ +int i =0 ; + +for (i =0 ; i <NR_STRING_BUFFERS ; i++) +if (string_properties[i] == psp) +return chip->strings[i]; + +return ERR_PTR (-EINVAL ); +} + +static void sbs_invalidate_cached_props (struct sbs_info *chip) +{ +int i =0 ; + + chip->technology =-1 ; + +for (i =0 ; i <NR_STRING_BUFFERS ; i++) + chip->strings[i][0 ] =0 ; +} +static bool force_load;static int sbs_read_word_data (struct i2c_client *client,u8 address);
@@ -243,6 +272,7 @@ static int sbs_update_presence(struct sbs_info *chip, bool is_present) chip->is_present = false;/* Disable PEC when no device is present */ client->flags &= ~I2C_CLIENT_PEC ; +sbs_invalidate_cached_props (chip);return 0 ; }
@@ -639,17 +669,45 @@ static int sbs_get_battery_property(struct i2c_client *client,return 0 ; } -static int sbs_get_battery_string_property (struct i2c_client *client, -int reg_offset,enum power_supply_property psp,char *val) +static int sbs_get_property_index (struct i2c_client *client, +enum power_supply_property psp) { -s32 ret; +int count; - ret =sbs_read_string_data (client, sbs_data[reg_offset].addr, val); +for (count =0 ; count <ARRAY_SIZE (sbs_data); count++) +if (psp == sbs_data[count].psp) +return count; -if (ret <0 ) -return ret; +dev_warn (&client->dev, +"%s: Invalid Property - %d\n" , __func__, psp); -return 0 ; +return -EINVAL ; +} + +static const char *sbs_get_constant_string (struct sbs_info *chip, +enum power_supply_property psp) +{ +int ret; +char *buf; +u8 addr; + + buf =sbs_get_string_buf (chip, psp); +if (IS_ERR (buf)) +return buf; + +if (!buf[0 ]) { + ret =sbs_get_property_index (chip->client, psp); +if (ret <0 ) +return ERR_PTR (ret); + + addr = sbs_data[ret].addr; + + ret =sbs_read_string_data (chip->client, addr, buf); +if (ret <0 ) +return ERR_PTR (ret); + } + +return buf; } static void sbs_unit_adjustment(struct i2c_client *client,
@@ -772,48 +830,36 @@ static int sbs_get_battery_serial_number(struct i2c_client *client,return 0 ; } -static int sbs_get_property_index (struct i2c_client *client, -enum power_supply_property psp) -{ -int count; -for (count =0 ; count <ARRAY_SIZE (sbs_data); count++) -if (psp == sbs_data[count].psp) -return count; - -dev_warn (&client->dev, -"%s: Invalid Property - %d\n" , __func__, psp); - -return -EINVAL ; -} - -static int sbs_get_chemistry (struct i2c_client *client, +static int sbs_get_chemistry (struct sbs_info *chip,union power_supply_propval *val) { -enum power_supply_property psp =POWER_SUPPLY_PROP_TECHNOLOGY ; -int ret; +const char *chemistry; - ret =sbs_get_property_index (client, psp); -if (ret <0 ) -return ret; +if (chip->technology !=-1 ) { + val->intval = chip->technology; +return 0 ; + } - ret =sbs_get_battery_string_property (client, ret, psp, - chemistry); -if (ret <0 ) -return ret; + chemistry =sbs_get_constant_string (chip,POWER_SUPPLY_PROP_TECHNOLOGY ); + +if (IS_ERR (chemistry)) +return PTR_ERR (chemistry);if (!strncasecmp (chemistry,"LION" ,4 )) - val->intval =POWER_SUPPLY_TECHNOLOGY_LION ; + chip->technology =POWER_SUPPLY_TECHNOLOGY_LION ;else if (!strncasecmp (chemistry,"LiP" ,3 )) - val->intval =POWER_SUPPLY_TECHNOLOGY_LIPO ; + chip->technology =POWER_SUPPLY_TECHNOLOGY_LIPO ;else if (!strncasecmp (chemistry,"NiCd" ,4 )) - val->intval = POWER_SUPPLY_TECHNOLOGY_NiCd; + chip->technology = POWER_SUPPLY_TECHNOLOGY_NiCd;else if (!strncasecmp (chemistry,"NiMH" ,4 )) - val->intval = POWER_SUPPLY_TECHNOLOGY_NiMH; + chip->technology = POWER_SUPPLY_TECHNOLOGY_NiMH;else - val->intval =POWER_SUPPLY_TECHNOLOGY_UNKNOWN ; + chip->technology =POWER_SUPPLY_TECHNOLOGY_UNKNOWN ; + +if (chip->technology ==POWER_SUPPLY_TECHNOLOGY_UNKNOWN ) +dev_warn (&chip->client->dev,"Unknown chemistry: %s\n" , chemistry); -if (val->intval ==POWER_SUPPLY_TECHNOLOGY_UNKNOWN ) -dev_warn (&client->dev,"Unknown chemistry: %s\n" , chemistry); + val->intval = chip->technology;return 0 ; }
@@ -857,6 +903,7 @@ static int sbs_get_property(struct power_supply *psy,int ret =0 ;struct sbs_info *chip =power_supply_get_drvdata (psy);struct i2c_client *client = chip->client; +const char *str;if (chip->gpio_detect) { ret =gpiod_get_value_cansleep (chip->gpio_detect);
@@ -882,7 +929,7 @@ static int sbs_get_property(struct power_supply *psy,break ;case POWER_SUPPLY_PROP_TECHNOLOGY : - ret =sbs_get_chemistry (client, val); + ret =sbs_get_chemistry (chip, val);if (ret <0 )break ;
@@ -934,23 +981,12 @@ static int sbs_get_property(struct power_supply *psy,break ;case POWER_SUPPLY_PROP_MODEL_NAME : - ret =sbs_get_property_index (client, psp); -if (ret <0 ) -break ; - - ret =sbs_get_battery_string_property (client, ret, psp, - model_name); - val->strval = model_name; -break ; -case POWER_SUPPLY_PROP_MANUFACTURER : - ret =sbs_get_property_index (client, psp); -if (ret <0 ) -break ; - - ret =sbs_get_battery_string_property (client, ret, psp, - manufacturer); - val->strval = manufacturer; + str =sbs_get_constant_string (chip, psp); +if (IS_ERR (str)) + ret =PTR_ERR (str); +else + val->strval = str;break ;case POWER_SUPPLY_PROP_MANUFACTURE_YEAR :
@@ -1097,6 +1133,7 @@ static int sbs_probe(struct i2c_client *client) psy_cfg.of_node = client->dev.of_node; psy_cfg.drv_data = chip; chip->last_state =POWER_SUPPLY_STATUS_UNKNOWN ; +sbs_invalidate_cached_props (chip);mutex_init (&chip->mode_lock);/* use pdata if available, fall back to DT properties,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 516/798 power: supply: sbs-battery: Use a per-device serial number buffer
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Babanpreet Singh <[email protected]>
[ Upstream commit 6027892925b8d19d2245c2d077e2ae35b49cc2b1 ]
sbs_get_battery_serial_number() formats the battery serial number into sbs_serial[], a single file-scope buffer shared by every sbs-battery instance, and points val->strval at it.
Nothing restricts this driver to one instance. It binds per I2C client, and sbs-manager registers one muxed I2C channel per supported battery specifically so that the smart battery driver can be bound to each of them, so several sbs-battery instances on one system is a supported configuration.
The power supply core reads strval after the driver's get_property() callback has returned: power_supply_show_property() fills a local union power_supply_propval, then formats it with sysfs_emit(). Two concurrent POWER_SUPPLY_PROP_SERIAL_NUMBER reads on different batteries therefore race for the shared buffer - battery B's sprintf() can land between battery A filling the buffer and the core reading it, and battery A then reports battery B's serial number.
Move the buffer into struct sbs_info so that each battery formats into its own storage. It is deliberately not added to the chip->strings[]
array: those entries hold the cached constant strings that sbs_invalidate_cached_props() clears on presence changes, whereas the serial number is re-read from its word register on every access.
--- drivers/power/supply/sbs-battery.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/power/supply/sbs-battery.c +4 -3
@@ -211,6 +211,7 @@ struct sbs_info {u32 flags;int technology;char strings[NR_STRING_BUFFERS ][I2C_SMBUS_BLOCK_MAX +1 ]; +char serial[5 ]; }; static char *sbs_get_string_buf(struct sbs_info *chip,
@@ -814,18 +815,18 @@ static int sbs_get_battery_capacity(struct i2c_client *client,return 0 ; } -static char sbs_serial[5 ];static int sbs_get_battery_serial_number (struct i2c_client *client,union power_supply_propval *val) { +struct sbs_info *chip =i2c_get_clientdata (client);int ret; ret =sbs_read_word_data (client, sbs_data[REG_SERIAL_NUMBER ].addr);if (ret <0 )return ret; -sprintf (sbs_serial,"%04x" , ret); - val->strval = sbs_serial; +sprintf (chip->serial,"%04x" , ret); + val->strval = chip->serial;return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 517/798 RDMA/mlx5: Fix integer overflow of user QP buffer size
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maher Sanalla <[email protected]>
[ Upstream commit dec47e4b0fe34afdf38caa72b4408ba95502e5de ]
set_user_buf_size() computes the QP buffer size by left-shifting the user-supplied rq.wqe_cnt and rq.wqe_shift values as signed integers. A sufficiently large rq.wqe_cnt causes signed integer overflow, which is undefined behavior, and yields a small or negative buf_size, causing ib_umem_get() to map a buffer smaller than the hardware will actually write into.
Replace the shifts and addition with check_shl_overflow() and check_add_overflow(), rejecting invalid user inputs.
Moreover, guard the identical shift computing qp->sq.offset in _create_user_qp() before set_user_buf_size() is reached.
--- drivers/infiniband/hw/mlx5/qp.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-)
drivers/infiniband/hw/mlx5/qp.c +20 -5
@@ -555,6 +555,7 @@ static int set_user_buf_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr) {int desc_sz =1 << qp->sq.wqe_shift; +int rq_buf_size, sq_buf_size;if (desc_sz >MLX5_CAP_GEN (dev->mdev, max_wqe_sz_sq)) { mlx5_ib_warn(dev, "desc_sz %d, max_sq_desc_sz %d\n",
@@ -579,11 +580,21 @@ static int set_user_buf_size(struct mlx5_ib_dev *dev,if (attr->qp_type ==IB_QPT_RAW_PACKET || qp->flags &IB_QP_CREATE_SOURCE_QPN ) { - base->ubuffer.buf_size = qp->rq.wqe_cnt << qp->rq.wqe_shift; - qp->raw_packet_qp.sq.ubuffer.buf_size = qp->sq.wqe_cnt <<6 ; +if (check_shl_overflow (qp->rq.wqe_cnt, qp->rq.wqe_shift, + &base->ubuffer.buf_size)) +return -EINVAL ; +if (check_shl_overflow (qp->sq.wqe_cnt,6 , + &qp->raw_packet_qp.sq.ubuffer.buf_size)) +return -EINVAL ; }else { - base->ubuffer.buf_size = (qp->rq.wqe_cnt << qp->rq.wqe_shift) + - (qp->sq.wqe_cnt <<6 ); +if (check_shl_overflow (qp->rq.wqe_cnt, qp->rq.wqe_shift, + &rq_buf_size)) +return -EINVAL ; +if (check_shl_overflow (qp->sq.wqe_cnt,6 , &sq_buf_size)) +return -EINVAL ; +if (check_add_overflow (rq_buf_size, sq_buf_size, + &base->ubuffer.buf_size)) +return -EINVAL ; }return 0 ;
@@ -939,7 +950,11 @@ static int _create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd, qp->rq.offset =0 ; qp->sq.wqe_shift =ilog2 (MLX5_SEND_WQE_BB ); - qp->sq.offset = qp->rq.wqe_cnt << qp->rq.wqe_shift; +if (check_shl_overflow (qp->rq.wqe_cnt, qp->rq.wqe_shift, + &qp->sq.offset)) { + err = -EINVAL ; + goto err_bfreg; + } err =set_user_buf_size (dev, qp, ucmd, base, attr);if (err)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 518/798 isofs: release zisofs block pointer buffer head
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yichong Chen <[email protected]>
[ Upstream commit 2f7dd9b86fe4076059e6a4a2a2c5d565afd76b9e ]
zisofs_fill_pages() reads the compressed block pointer table. The error paths release the current buffer_head, the loop also releases the old buffer_head when it advances. However, the success path leaves the last buffer_head referenced. Release it before returning success.
--- fs/isofs/compress.c | 1 + 1 file changed, 1 insertion(+)
fs/isofs/compress.c +1 -0
@@ -288,6 +288,7 @@ static int zisofs_fill_pages(struct inode *inode, int full_page, int pcount,flush_dcache_page (*pages);SetPageUptodate (*pages); } +brelse (bh);return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 519/798 w1: ds2482: Fix signedness bug in ds2482_w1_triplet()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Babanpreet Singh <[email protected]>
[ Upstream commit 4d3721b204f961e905714954ff95633337b768e3 ]
ds2482_wait_1wire_idle() returns the status register value (0..255) on success, or a negative value on I2C failure: -1 when selecting the status register fails, or a negative errno from i2c_smbus_read_byte().
ds2482_w1_triplet() feeds that result into "return (status >> 5);" without checking for errors, and the function returns u8. For a negative status the arithmetic shift keeps the sign and the u8 truncation fabricates a triplet result whose meaning depends on the errno value: -1 and -EIO happen to become 0xff, whose set low bits make w1_search() abort, but -ETIMEDOUT (-110 >> 5 = -4) becomes 0xfc - "devices responded on both branches, wrote 1" - and -EOPNOTSUPP (-95 >> 5 = -3) becomes 0xfd - "only the zero branch responded". w1_search() then continues the ROM search with a fabricated direction bit instead of aborting, and the corrupted id is either rejected by the ROM CRC (existing device missed) or registers a phantom slave.
The function already defines an in-band error value: status is initialized to (3 << 5), which decodes to 3 (both branch bits set, "no device responded") and makes w1_search() terminate the search when sending the triplet command fails. Decode a negative status to the same value.
Found by smatch:drivers/w1/masters/ds2482.c:314 ds2482_w1_triplet() warn: signedness bug returning '(-67108864)'
--- drivers/w1/masters/ds2482.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/w1/masters/ds2482.c +4 -0
@@ -312,6 +312,10 @@ static u8 ds2482_w1_triplet(void *data, u8 dbit)mutex_unlock (&pdev->access_lock); +/* On bus error, decode to 3 (no device responded) to abort the search */ +if (status <0 ) + status =3 <<5 ; +/* Decode the status */ return (status >>5 ); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 520/798 remoteproc: Remove useless check in rproc_del()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mathieu Poirier <[email protected]>
[ Upstream commit 16324fc8def1c08a92261089aaf503aca3381aa6 ]
Whether started at probe() time or thereafter from the command line, a remote processor needs to be shut down before the final cleanup phases can happen. Otherwise the system may be left in an unpredictable state where the remote processor is expecting the remoteproc core to be providing services when in fact it no longer exist.
Invariably calling rproc_shutdown() is fine since it will return immediately if the remote processor has already been switched off.
Stable-dep-of: 74ee3b2f5767 ("remoteproc: Prevent crash handling to race with rproc_del()")
--- drivers/remoteproc/remoteproc_core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/remoteproc/remoteproc_core.c +1 -3
@@ -2321,10 +2321,8 @@ int rproc_del(struct rproc *rproc)if (!rproc)return -EINVAL ; -/* if rproc is marked always-on, rproc_add() booted it */ /* TODO: make sure this works with rproc->power > 1 */ -if (rproc->auto_boot) -rproc_shutdown (rproc); +rproc_shutdown (rproc);mutex_lock (&rproc->lock); rproc->state =RPROC_DELETED ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 521/798 remoteproc: Add new RPROC_ATTACHED state
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mathieu Poirier <[email protected]>
[ Upstream commit 4196d18903f94090f0a223d65de25e3bf50a3d13 ]
Add a new RPROC_ATTACHED state to take into account scenarios where the remoteproc core needs to attach to a remote processor that is booted by another entity.
Stable-dep-of: 74ee3b2f5767 ("remoteproc: Prevent crash handling to race with rproc_del()")
--- drivers/remoteproc/remoteproc_sysfs.c | 1 + include/linux/remoteproc.h | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-)
drivers/remoteproc/remoteproc_sysfs.c +1 -0
@@ -201,6 +201,7 @@ static const char * const rproc_state_string[] = { [RPROC_RUNNING] = "running", [RPROC_CRASHED] = "crashed", [RPROC_DELETED] = "deleted", + [RPROC_ATTACHED] = "attached", [RPROC_DETACHED] = "detached", [RPROC_LAST] = "invalid", };
include/linux/remoteproc.h +5 -2
@@ -407,6 +407,8 @@ struct rproc_ops {* @RPROC_RUNNING: device is up and running * @RPROC_CRASHED: device has crashed; need to start recovery * @RPROC_DELETED: device is deleted +* @RPROC_ATTACHED: device has been booted by another entity and the core +* has attached to it * @RPROC_DETACHED: device has been booted by another entity and waiting * for the core to attach to it * @RPROC_LAST: just keep this one at the end
@@ -423,8 +425,9 @@ enum rproc_state {RPROC_RUNNING =2 ,RPROC_CRASHED =3 ,RPROC_DELETED =4 , -RPROC_DETACHED =5 , - RPROC_LAST = 6, +RPROC_ATTACHED =5 , +RPROC_DETACHED =6 , + RPROC_LAST = 7, };/**
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 522/798 remoteproc: use freezable workqueue for crash notifications
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
[ Upstream commit 3ad51c1743ebd23ec3b5ebc6195dafe867eaebb1 ]
When a remoteproc has crashed, rproc_report_crash() is called to handle whatever recovery is desired. This can happen at almost any time, often triggered by an interrupt, though it can also be initiated by a write to debugfs file remoteproc/remoteproc*/crash.
When a crash is reported, the crash handler worker is scheduled to run (rproc_crash_handler_work()). One thing that worker does is call rproc_trigger_recovery(), which calls rproc_stop(). That calls the ->stop method for any remoteproc subdevices before making the remote processor go offline.
The Q6V5 modem remoteproc driver implements an SSR subdevice that notifies registered drivers when the modem changes operational state (prepare, started, stop/crash, unprepared). The IPA driver registers to receive these notifications.
With that as context, I'll now describe the problem.
There was a situation in which buggy modem firmware led to a modem crash very soon after system (AP) resume had begun. The crash caused a remoteproc SSR crash notification to be sent to the IPA driver. The problem was that, although system resume had begun, it had not yet completed, and the IPA driver was still in a suspended state.
This scenario could happen to any driver that registers for these SSR notifications, because they are delivered without knowledge of the (suspend) state of registered recipient drivers.
This patch offers a simple fix for this, by having the crash handling worker function run on the system freezable workqueue. This workqueue does not operate if user space is frozen (for suspend). As a result, the SSR subdevice only delivers its crash notification when the system is fully operational (i.e., neither suspended nor in suspend/resume transition).
Stable-dep-of: 74ee3b2f5767 ("remoteproc: Prevent crash handling to race with rproc_del()")
--- drivers/remoteproc/remoteproc_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/remoteproc/remoteproc_core.c +2 -2
@@ -2450,8 +2450,8 @@ void rproc_report_crash(struct rproc *rproc, enum rproc_crash_type type)dev_err (&rproc->dev,"crash detected in %s: type %s\n" , rproc->name,rproc_crash_to_string (type)); -/* create a new task to handle the error */ -schedule_work (&rproc->crash_handler); +/* Have a worker handle the error; ensure system is not suspended */ +queue_work (system_freezable_wq, &rproc->crash_handler); }EXPORT_SYMBOL (rproc_report_crash);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 523/798 remoteproc: Use unbounded workqueue for recovery work
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mukesh Ojha <[email protected]>
[ Upstream commit cab8300b5621a54aa25306ff800c27fa5a4632d7 ]
There could be a scenario when there is too much load on a core (n number of tasks which is affined) or in a case when multiple rproc subsystem is going for recovery, they queue their recovery work to one core so even though subsystem are independent their recovery will be delayed if one of the subsystem recovery work is taking more time in completing.
If we make this queue unbounded, the recovery work could be picked on any cpu. This patch is trying to address this.
Stable-dep-of: 74ee3b2f5767 ("remoteproc: Prevent crash handling to race with rproc_del()")
--- drivers/remoteproc/remoteproc_core.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
drivers/remoteproc/remoteproc_core.c +13 -2
@@ -58,6 +58,7 @@ static int rproc_release_carveout(struct rproc *rproc,/* Unique indices for remoteproc devices */ static DEFINE_IDA (rproc_dev_index); +static struct workqueue_struct *rproc_recovery_wq;static const char *const rproc_crash_names[] = { [RPROC_MMUFAULT ] ="mmufault" ,
@@ -2450,8 +2451,7 @@ void rproc_report_crash(struct rproc *rproc, enum rproc_crash_type type)dev_err (&rproc->dev,"crash detected in %s: type %s\n" , rproc->name,rproc_crash_to_string (type)); -/* Have a worker handle the error; ensure system is not suspended */ -queue_work (system_freezable_wq, &rproc->crash_handler); +queue_work (rproc_recovery_wq, &rproc->crash_handler); }EXPORT_SYMBOL (rproc_report_crash);
@@ -2496,6 +2496,13 @@ static void __exit rproc_exit_panic(void)static int __init remoteproc_init (void ) { + rproc_recovery_wq =alloc_workqueue ("rproc_recovery_wq" , +WQ_UNBOUND |WQ_FREEZABLE ,0 ); +if (!rproc_recovery_wq) { +pr_err ("remoteproc: creation of rproc_recovery_wq failed\n" ); +return -ENOMEM ; + } +rproc_init_sysfs ();rproc_init_debugfs ();rproc_init_cdev ();
@@ -2509,9 +2516,13 @@ static void __exit remoteproc_exit(void) {ida_destroy (&rproc_dev_index); +if (!rproc_recovery_wq) +return ; +rproc_exit_panic ();rproc_exit_debugfs ();rproc_exit_sysfs (); +destroy_workqueue (rproc_recovery_wq); }module_exit (remoteproc_exit);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 524/798 remoteproc: core: Attach rproc asynchronously in rproc_add() path via schedule_work()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jingyi Wang <[email protected]>
[ Upstream commit 026a3fada43261e403c6c4d9bda9501547e3f108 ]
Unlike the remoteproc firmware load path where rproc_add() call rproc_auto_boot_callback() asynchronously and ignores the return value of rproc_boot(), the attach path calls rproc_boot() synchronously and propagates its return value back to rproc_add(). This means a failure during rproc_attach() causes rproc_add() to fail and triggers resource release, removing the remoteproc from sysfs and making it unavailable for recovery or further boot attempts.
Align the remoteproc attach path with the firmware load path by introducing attach_work and scheduling rproc_boot() asynchronously via schedule_work(). This keeps the remoteproc registered and available in sysfs even if the initial attach attempt fails, and avoids blocking rproc_add() on the attach result.
Stable-dep-of: 74ee3b2f5767 ("remoteproc: Prevent crash handling to race with rproc_del()")
--- drivers/remoteproc/remoteproc_core.c | 20 ++++++++++++-------- include/linux/remoteproc.h | 2 ++ 2 files changed, 14 insertions(+), 8 deletions(-)
drivers/remoteproc/remoteproc_core.c +12 -8
@@ -1646,18 +1646,21 @@ static void rproc_auto_boot_callback(const struct firmware *fw, void *context)release_firmware (fw); } +static void rproc_attach_work (struct work_struct *work) +{ + struct rproc *rproc = container_of(work, struct rproc, attach_work); + +rproc_boot (rproc); +} +static int rproc_trigger_auto_boot (struct rproc *rproc) {int ret; -/* -* Since the remote processor is in a detached state, it has already -* been booted by another entity. As such there is no point in waiting -* for a firmware image to be loaded, we can simply initiate the process -* of attaching to it immediately. -*/ -if (rproc->state ==RPROC_DETACHED ) -return rproc_boot (rproc); +if (rproc->state ==RPROC_DETACHED ) { +schedule_work (&rproc->attach_work); +return 0 ; + }/* * We're initiating an asynchronous firmware loading, so we can
@@ -2260,6 +2263,7 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,INIT_LIST_HEAD (&rproc->dump_segments);INIT_WORK (&rproc->crash_handler, rproc_crash_handler_work); +INIT_WORK (&rproc->attach_work, rproc_attach_work); rproc->state =RPROC_OFFLINE ;
include/linux/remoteproc.h +2 -0
@@ -505,6 +505,7 @@ struct rproc_dump_segment {* @subdevs: list of subdevices, to following the running state * @notifyids: idr for dynamically assigning rproc-wide unique notify ids * @index: index of this rproc device +* @attach_work: workqueue for attaching rproc * @crash_handler: workqueue for handling a crash * @crash_cnt: crash counter * @recovery_disabled: flag that state if recovery was disabled
@@ -542,6 +543,7 @@ struct rproc {struct list_head subdevs;struct idr notifyids;int index; +struct work_struct attach_work;struct work_struct crash_handler;unsigned int crash_cnt;bool recovery_disabled;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 525/798 remoteproc: Prevent crash handling to race with rproc_del()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bjorn Andersson <[email protected]>
[ Upstream commit 74ee3b2f5767447c57959994341e5b95f1079977 ]
There's no synchronization between rproc_crash_handler_work() and rproc_del(), as such it's possible for a driver to be removed while crash-handler work is scheduled, or even executing - resulting in use-after-free issues.
To avoid this the scheduled work need to be cancelled and synchronized against before the removal proceeds.
In order to ensure that this doesn't race with the reporting, and thereby scheduling new work, a "deleting" flag is introduced. This is similar to the RPROC_DELETE state that was introduced to ensure that "start" didn't race with rproc_del(), but the existing mechanism can not be used as it's valid to call rproc_report_crash() in atomic context - and the "state" is protected by a mutex.
In the event that work is cancelled the pm_stay_awake() is left unbalanced and need to be unrolled.
The blocking and cancelling of crash-handler work prior to the actual rproc_shutdown() call does have the explicit side-effect that crashes resulting from the shutdown process will not enter the crash-handling path, and as such will not generate devcoredumps etc. Due to the existing mutual exclusion between these code paths there's no concrete reduction in functionality, but further work would be needed to handle this case.
--- drivers/remoteproc/remoteproc_core.c | 42 +++++++++++++++++++++------ drivers/remoteproc/remoteproc_sysfs.c | 1 - include/linux/remoteproc.h | 13 +++++---- 3 files changed, 41 insertions(+), 15 deletions(-)
drivers/remoteproc/remoteproc_core.c +33 -9
@@ -1731,6 +1731,11 @@ int rproc_trigger_recovery(struct rproc *rproc)if (ret)return ret; +if (READ_ONCE (rproc->deleting)) { + ret = -ENODEV ; + goto unlock_mutex; + } +/* State could have changed before we got the mutex */ if (rproc->state !=RPROC_CRASHED ) goto unlock_mutex;
@@ -1777,6 +1782,11 @@ static void rproc_crash_handler_work(struct work_struct *work)mutex_lock (&rproc->lock); +if (READ_ONCE (rproc->deleting)) { +mutex_unlock (&rproc->lock); + goto out; + } +if (rproc->state ==RPROC_CRASHED ) {/* handle only the first crash detected */ mutex_unlock (&rproc->lock);
@@ -1832,9 +1842,9 @@ int rproc_boot(struct rproc *rproc)return ret; } -if (rproc->state ==RPROC_DELETED ) { +if (READ_ONCE (rproc->deleting)) { ret = -ENODEV ; -dev_err (dev,"can't boot deleted rproc %s\n" , rproc->name); +dev_err (dev,"can't boot deleting rproc %s\n" , rproc->name); goto unlock_mutex; }
@@ -2262,8 +2272,9 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,INIT_LIST_HEAD (&rproc->subdevs);INIT_LIST_HEAD (&rproc->dump_segments); -INIT_WORK (&rproc->crash_handler, rproc_crash_handler_work);INIT_WORK (&rproc->attach_work, rproc_attach_work); +INIT_WORK (&rproc->crash_handler, rproc_crash_handler_work); +spin_lock_init (&rproc->crash_handler_lock); rproc->state =RPROC_OFFLINE ;
@@ -2323,16 +2334,21 @@ EXPORT_SYMBOL(rproc_put);*/ int rproc_del (struct rproc *rproc) { +unsigned long flags; +if (!rproc)return -EINVAL ; +spin_lock_irqsave (&rproc->crash_handler_lock, flags); +WRITE_ONCE (rproc->deleting, true); +spin_unlock_irqrestore (&rproc->crash_handler_lock, flags); + +if (cancel_work_sync (&rproc->crash_handler)) +pm_relax (rproc->dev.parent); +/* TODO: make sure this works with rproc->power > 1 */ rproc_shutdown (rproc); -mutex_lock (&rproc->lock); - rproc->state =RPROC_DELETED ; -mutex_unlock (&rproc->lock); -rproc_delete_debug_dir (rproc);/* the rproc is downref'ed as soon as it's removed from the klist */
@@ -2444,18 +2460,26 @@ EXPORT_SYMBOL(rproc_get_by_child);*/ void rproc_report_crash (struct rproc *rproc,enum rproc_crash_type type) { +unsigned long flags; +if (!rproc) {pr_err ("NULL rproc pointer\n" );return ; } +spin_lock_irqsave (&rproc->crash_handler_lock, flags); +if (READ_ONCE (rproc->deleting)) { +spin_unlock_irqrestore (&rproc->crash_handler_lock, flags); +return ; + } +/* Prevent suspend while the remoteproc is being recovered */ pm_stay_awake (rproc->dev.parent); +queue_work (rproc_recovery_wq, &rproc->crash_handler); +spin_unlock_irqrestore (&rproc->crash_handler_lock, flags);dev_err (&rproc->dev,"crash detected in %s: type %s\n" , rproc->name,rproc_crash_to_string (type)); - -queue_work (rproc_recovery_wq, &rproc->crash_handler); }EXPORT_SYMBOL (rproc_report_crash);
drivers/remoteproc/remoteproc_sysfs.c +0 -1
@@ -200,7 +200,6 @@ static const char * const rproc_state_string[] = { [RPROC_SUSPENDED] = "suspended", [RPROC_RUNNING] = "running", [RPROC_CRASHED] = "crashed", - [RPROC_DELETED] = "deleted", [RPROC_ATTACHED] = "attached", [RPROC_DETACHED] = "detached", [RPROC_LAST] = "invalid",
include/linux/remoteproc.h +8 -5
@@ -37,6 +37,7 @@#include <linux/types.h> #include <linux/mutex.h> +#include <linux/spinlock.h> #include <linux/virtio.h> #include <linux/cdev.h> #include <linux/completion.h>
@@ -406,7 +407,6 @@ struct rproc_ops {* a message. * @RPROC_RUNNING: device is up and running * @RPROC_CRASHED: device has crashed; need to start recovery -* @RPROC_DELETED: device is deleted * @RPROC_ATTACHED: device has been booted by another entity and the core * has attached to it * @RPROC_DETACHED: device has been booted by another entity and waiting
@@ -424,10 +424,9 @@ enum rproc_state {RPROC_SUSPENDED =1 ,RPROC_RUNNING =2 ,RPROC_CRASHED =3 , -RPROC_DELETED =4 , -RPROC_ATTACHED =5 , -RPROC_DETACHED =6 , - RPROC_LAST = 7, +RPROC_ATTACHED =4 , +RPROC_DETACHED =5 , + RPROC_LAST = 6, };/**
@@ -507,6 +506,8 @@ struct rproc_dump_segment {* @index: index of this rproc device * @attach_work: workqueue for attaching rproc * @crash_handler: workqueue for handling a crash +* @crash_handler_lock: serializes crash handler queueing and deletion +* @deleting: remoteproc deletion has begun * @crash_cnt: crash counter * @recovery_disabled: flag that state if recovery was disabled * @max_notifyid: largest allocated notify id.
@@ -545,6 +546,8 @@ struct rproc {int index;struct work_struct attach_work;struct work_struct crash_handler; +spinlock_t crash_handler_lock; +bool deleting;unsigned int crash_cnt;bool recovery_disabled;int max_notifyid;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 526/798 staging: rtl8723bs: use kfree_sensitive() for key material
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ivy Lopez <[email protected]>
[ Upstream commit d205dfa8cb825f1954ca1cfa474fc50bf06ee4aa ]
The set_stakey_parm struct contains a 16-byte encryption key. Use kfree_sensitive() instead of kfree() to ensure the key material is zeroed before the memory is freed, preventing potential information leaks.
--- drivers/staging/rtl8723bs/core/rtw_cmd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/staging/rtl8723bs/core/rtw_cmd.c +4 -4
@@ -989,7 +989,7 @@ u8 rtw_setstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 unicast_if (enqueue) { ph2c =rtw_zmalloc (sizeof (struct cmd_obj ));if (!ph2c) { -kfree (psetstakey_para); +kfree_sensitive (psetstakey_para); res = _FAIL; goto exit; }
@@ -997,7 +997,7 @@ u8 rtw_setstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 unicast_ psetstakey_rsp =rtw_zmalloc (sizeof (struct set_stakey_rsp ));if (!psetstakey_rsp) {kfree (ph2c); -kfree (psetstakey_para); +kfree_sensitive (psetstakey_para); res = _FAIL; goto exit; }
@@ -1008,7 +1008,7 @@ u8 rtw_setstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 unicast_ res =rtw_enqueue_cmd (pcmdpriv, ph2c); }else {set_stakey_hdl (padapter, (u8 *)psetstakey_para); -kfree (psetstakey_para); +kfree_sensitive (psetstakey_para); } exit:return res;
@@ -1046,7 +1046,7 @@ u8 rtw_clearstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 enqueu psetstakey_rsp =rtw_zmalloc (sizeof (struct set_stakey_rsp ));if (!psetstakey_rsp) {kfree (ph2c); -kfree (psetstakey_para); +kfree_sensitive (psetstakey_para); res = _FAIL; goto exit; }
Signature · 1 line
2.53.0
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.10.270 release. There are 798 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Mon, 14 Sep 2026 06:54:17 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.270-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.10.y
and the diffstat can be found below.thanks,
greg k-h
Tested on an amd64 laptop (Lenovo ThinkPad T14 Gen 1). Working well, no regressions observed.
Signature · 1 line
-Barry K. Nathan <[email protected]>
Greg Kroah-Hartman
maintainerPATCH 527/798 RDMA/efa: Fix PBL chunk length computation
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yonatan Nachum <[email protected]>
[ Upstream commit 229b42d7450c1cf96f45ec39ebb69211b06bc036 ]
On register MR, when creating the PBL, if it's an indirect PBL we create a chunk list to hold the PBL pages pointers. Each chunk is 4KB in size and can hold 510 addresses (EFA_PTRS_PER_CHUNK) and has a 12-byte control buffer at the end of it holding the next chunk's pointer and its length.
If the PBL number of pages is a multiple of EFA_PTRS_PER_CHUNK, the calculated last chunk length is wrongly computed as 0, even though that chunk is fully populated with 510 real page pointers. This wrong length is used both to DMA map the chunk and is propagated to the device, causing the device to see the chunk as empty and reject the memory registration.
Fix the calculation so it will be performed only if the number of pages isn't a multiple of EFA_PTRS_PER_CHUNK, if it is, its already handled in the above loop correctly.
Also prevent out-of-bounds reach in the chunks array in such scenario.
--- drivers/infiniband/hw/efa/efa_verbs.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/infiniband/hw/efa/efa_verbs.c +9 -4
@@ -1217,9 +1217,11 @@ static int pbl_chunk_list_create(struct efa_dev *dev, struct pbl_context *pbl) chunk_list->chunks[i].length =EFA_CHUNK_USED_SIZE ; } - chunk_list->chunks[chunk_list_size -1 ].length = - ((page_cnt %EFA_PTRS_PER_CHUNK ) *EFA_CHUNK_PAYLOAD_PTR_SIZE ) + -EFA_CHUNK_PTR_SIZE ; + +if (page_cnt %EFA_PTRS_PER_CHUNK !=0 ) + chunk_list->chunks[chunk_list_size -1 ].length = + ((page_cnt %EFA_PTRS_PER_CHUNK ) *EFA_CHUNK_PAYLOAD_PTR_SIZE ) + +EFA_CHUNK_PTR_SIZE ;/* fill the dma addresses of sg list pages to chunks: */ chunk_idx =0 ;
@@ -1231,9 +1233,12 @@ static int pbl_chunk_list_create(struct efa_dev *dev, struct pbl_context *pbl)rdma_block_iter_dma_address (&biter);if (payload_idx ==EFA_PTRS_PER_CHUNK ) { + payload_idx =0 ; chunk_idx++; +if (chunk_idx >= chunk_list_size) +break ; + cur_chunk_buf = chunk_list->chunks[chunk_idx].buf; - payload_idx =0 ; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 528/798 arm64: dts: allwinner: sun50i-a64-pinephone: Fix mpu6050 mount matrix
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ondrej Jirman <[email protected]>
[ Upstream commit dfc735fd93e4814e65894916ec5f807f25a391d1 ]
The current mount matrix for mpu6050 is wrong. The mount matrix is a simple transform from the sensor coordinate space to the device coordinate space described in DT, where, looking at the screen, X points to the right, Y to the top, and Z towards the user.
The mpu6050 is mounted like this (looking at the screen from the front; the sensor is on the near side of the PCB, so its Z axis points towards the user; o marks the pin 1 corner):
+Xs
^
|
+------+
+Ys <--| |
| o |
+------+so this gives:
Xd = -Ys [0, -1, 0] Yd = Xs [1, 0, 0] Zd = Zs [0, 0, 1]
--- arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi +2 -2
@@ -157,8 +157,8 @@ mpu6050@68 { interrupts = <7 5 IRQ_TYPE_EDGE_RISING>; /* PH5 */ vdd-supply = <®_dldo1>; vddio-supply = <®_dldo1>; - mount-matrix = "0", "1", "0", - "-1", "0", "0", + mount-matrix = "0", "-1", "0", + "1", "0", "0", "0", "0", "1"; }; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 529/798 clk: tegra: tegra124-emc: put EMC node on register failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
[ Upstream commit f726279f5eab813f9a8b6f38ddf2a4b062d038ff ]
tegra124_clk_register_emc() stores a device node reference returned by of_parse_phandle() in tegra->emc_node.
If clk_register() fails, the function returns an error before that reference can be consumed and released by the normal runtime path. The tegra_clk_emc object is freed on this failure path, but freeing the object does not drop the OF node reference stored in it.
Drop the EMC node reference before freeing the tegra_clk_emc object. of_node_put() is safe for a NULL node, so this also covers the case where the phandle is absent.
--- drivers/clk/tegra/clk-tegra124-emc.c | 1 + 1 file changed, 1 insertion(+)
drivers/clk/tegra/clk-tegra124-emc.c +1 -0
@@ -530,6 +530,7 @@ struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np, clk =clk_register (NULL , &tegra->hw);if (IS_ERR (clk)) { +of_node_put (tegra->emc_node);kfree (tegra);return clk; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 530/798 clk: palmas: Manage external-control prepare with devm
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Myeonghun Pak <[email protected]>
[ Upstream commit ccda84fcbf3a972973f772384935928f41817b3a ]
palmas_clks_init_configure() prepares the clock when an external control pin is configured. The current driver only drops that prepare reference when external control configuration fails.
If provider registration fails after that point, or if the driver is later removed, the prepare reference remains held.
Register a device-managed action after clk_prepare() succeeds. This balances the prepare reference on subsequent probe failure and driver removal.
--- drivers/clk/clk-palmas.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
drivers/clk/clk-palmas.c +13 -1
@@ -203,6 +203,13 @@ static void palmas_clks_get_clk_data(struct platform_device *pdev, cinfo->ext_control_pin = prop; } +static void palmas_clks_unprepare_ext_control (void *data) +{ +struct palmas_clock_info *cinfo = data; + +clk_unprepare (cinfo->hw.clk); +} +static int palmas_clks_init_configure (struct palmas_clock_info *cinfo) {int ret;
@@ -223,13 +230,18 @@ static int palmas_clks_init_configure(struct palmas_clock_info *cinfo)return ret; } + ret =devm_add_action_or_reset (cinfo->dev, + palmas_clks_unprepare_ext_control, + cinfo); +if (ret) +return ret; + ret =palmas_ext_control_req_config (cinfo->palmas, cinfo->clk_desc->sleep_reqstr_id, cinfo->ext_control_pin, true);if (ret <0 ) {dev_err (cinfo->dev,"Ext config for %s failed, %d\n" , cinfo->clk_desc->clk_name, ret); -clk_unprepare (cinfo->hw.clk);return ret; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 531/798 clk/x86: pmc_atom: add kasprintf return value check
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: longlong yan <[email protected]>
[ Upstream commit 18e9d14cbac33db1c1fb933c26a736eef53dd538 ]
The kasprintf() function returns NULL on memory allocation failure, but the code in plt_clk_register() was not checking this return value. If kasprintf fails, init.name would be NULL and could cause NULL pointer dereference when clkdev_hw_create() uses it.
Add proper error checking for the kasprintf() return value and return ERR_PTR(-ENOMEM) on failure.
--- drivers/clk/x86/clk-pmc-atom.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/clk/x86/clk-pmc-atom.c +3 -0
@@ -171,6 +171,9 @@ static struct clk_plt *plt_clk_register(struct platform_device *pdev, int id,return ERR_PTR (-ENOMEM ); init.name =kasprintf (GFP_KERNEL ,"%s_%d" ,PLT_CLK_NAME_BASE , id); +if (!init.name) +return ERR_PTR (-ENOMEM ); + init.ops = &plt_clk_ops; init.flags =0 ; init.parent_names = parent_names;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 532/798 nilfs2: fix infinite loop in nilfs_clean_segments()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joshua Crofts <[email protected]>
[ Upstream commit ce5a5ad1a8330a2fcfdd9ec2ab341be739e89a18 ]
syzbot reported a hung task in nilfs_transaction_begin(). This occurs because the cleaner ioctl falls into an infinite loop if nilfs_segctor_construct() repeatedly returns -EROFS (e.g. the device is remounted as read-only after an I/O error).
Currently in nilfs_clean_segments(), if err is non-zero, it logs the error and sleeps but doesn't abort when it encounters a terminal error like -EROFS. This causes the thread to loop forever.
Fix this by breaking out of the loop if nilfs_segctor_construct() returns -EROFS. This matches the behaviour in nilfs_segctor_write_out(), which also handles -EROFS.
--- fs/nilfs2/segment.c | 4 ++++ 1 file changed, 4 insertions(+)
fs/nilfs2/segment.c +4 -0
@@ -2554,6 +2554,10 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,break ;nilfs_warn (sb,"error %d cleaning segments" , err); + +if (unlikely (err == -EROFS )) + goto out_unlock; +set_current_state (TASK_INTERRUPTIBLE );schedule_timeout (sci->sc_interval); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 533/798 nilfs2: prevent out-of-bounds read in super root block parsing
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lee <[email protected]>
[ Upstream commit 7cb2f76a6a2ba2130b577cb8ac13e1e46c4fc689 ]
super-root inode metadata size is trusted before nilfs_read_inode_common().
Reject super-root inode sizes whose computed on-disk footprint exceeds the filesystem block size. This prevents malformed filesystem images from making nilfs_read_inode_common() read past the end of the super-root block.
[ryusuke: clarify the commit title]
--- fs/nilfs2/the_nilfs.c | 6 ++++++ 1 file changed, 6 insertions(+)
fs/nilfs2/the_nilfs.c +6 -0
@@ -450,6 +450,12 @@ static int nilfs_store_disk_layout(struct the_nilfs *nilfs, nilfs->ns_inode_size);return -EINVAL ; } +if (NILFS_SR_BYTES (nilfs->ns_inode_size) > nilfs->ns_blocksize) { +nilfs_err (nilfs->ns_sb, +"too large inode size for super root: %d bytes" , + nilfs->ns_inode_size); +return -EINVAL ; + } nilfs->ns_first_ino =le32_to_cpu (sbp->s_first_ino);if (nilfs->ns_first_ino <NILFS_USER_INO ) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 534/798 RDMA/mlx5: Fix stack out-of-bounds read in cc_params debugfs
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit 03826bc1fa6c90405bf05831f2b501a8368dcd27 ]
get_param() reads a congestion parameter as a u32 but formats it with the signed "%d" into an 11-byte stack buffer. A value with bit 31 set, such as 0x80000000, renders as "-2147483648\n" whose full length is 12. snprintf() stores only 11 bytes yet returns 12, so simple_read_from_buffer() treats 12 bytes as valid and reads one byte past lbuf[].
Size the buffer for the widest unsigned decimal, format with "%u" to match the u32, and use scnprintf() so the length passed to simple_read_from_buffer() reflects the bytes actually stored.
--- drivers/infiniband/hw/mlx5/cong.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/infiniband/hw/mlx5/cong.c +2 -4
@@ -377,15 +377,13 @@ static ssize_t get_param(struct file *filp, char __user *buf, size_t count,int offset = param->offset;u32 var =0 ;int ret; -char lbuf[11 ]; +char lbuf[12 ]; ret =mlx5_ib_get_cc_params (param->dev, param->port_num, offset, &var);if (ret)return ret; - ret =snprintf (lbuf,sizeof (lbuf),"%d\n" , var); -if (ret <0 ) -return ret; + ret =scnprintf (lbuf,sizeof (lbuf),"%u\n" , var);return simple_read_from_buffer (buf, count, pos, lbuf, ret); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 535/798 RDMA/mlx5: Send cong param changes to the resolved port mdev
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit 033a79e308e4fe832b0924347eda8c4364055174 ]
mlx5_ib_set_cc_params() resolves the port-specific mlx5_core_dev via mlx5_ib_get_native_port_mdev() but issued MLX5_CMD_OP_MODIFY_CONG_PARAMS through dev->mdev. On an affiliated secondary RoCE port those pointers refer to different devices, so a write to the secondary port's cc_params debugfs file either altered the master port or failed with a master-side command error, while the read path already used the resolved mdev and returned the unchanged secondary value.
Issue the command to the resolved mdev, the same device whose capabilities were checked when its debugfs directory was created. It is already referenced by the get/put pair, so its lifetime is safe.
--- drivers/infiniband/hw/mlx5/cong.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/hw/mlx5/cong.c +1 -1
@@ -339,7 +339,7 @@ static int mlx5_ib_set_cc_params(struct mlx5_ib_dev *dev, u8 port_num,MLX5_SET (field_select_r_roce_rp, field, field_select_r_roce_rp, attr_mask); - err =mlx5_cmd_exec_in (dev->mdev, modify_cong_params, in); + err =mlx5_cmd_exec_in (mdev, modify_cong_params, in);kvfree (in); alloc_err:mlx5_ib_put_native_port_mdev (dev, port_num +1 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 536/798 RDMA/cxgb4: free STAG index when TPT entry write fails
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit fdfb5cea4bf070cdb31d997efd87bb684df041fd ]
write_tpt_entry() allocates a new STAG index with c4iw_get_resource() and bumps stats.stag.cur before programming the entry. When write_adapter_mem() fails, it returns the error without releasing the index or reversing the statistic. No MR is inserted into rhp->mrs, so deregistration never reclaims it, leaking the index until device teardown.
Record whether this call allocated the index and, on a failed write, return it to tpt_table and decrement stats.stag.cur. Key the rollback on both the write error and that flag, not the error alone: a non-reset update carries a caller-owned STAG that this call did not allocate and must not free.
--- drivers/infiniband/hw/cxgb4/mem.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/infiniband/hw/cxgb4/mem.c +3 -1
@@ -277,6 +277,7 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,int err;struct fw_ri_tpte *tpt;u32 stag_idx; +bool stag_idx_allocated = false;static atomic_t key;if (c4iw_fatal_error (rdev))
@@ -299,6 +300,7 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,return -ENOMEM ; }mutex_lock (&rdev->stats.lock); + stag_idx_allocated = true; rdev->stats.stag.cur +=32 ;if (rdev->stats.stag.cur > rdev->stats.stag.max) rdev->stats.stag.max = rdev->stats.stag.cur;
@@ -333,7 +335,7 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry, (rdev->lldi.vr->stag.start >>5 ), sizeof(*tpt), tpt, skb, wr_waitp); -if (reset_tpt_entry) { +if (reset_tpt_entry || (err && stag_idx_allocated)) {c4iw_put_resource (&rdev->resource.tpt_table, stag_idx);mutex_lock (&rdev->stats.lock); rdev->stats.stag.cur -=32 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 537/798 IB/isert: reject PDUs declaring more data than was received
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yehyeong Lee <[email protected]>
[ Upstream commit 957f92ea4022fb6af4618271615a2a21a7b5bef9 ]
isert_recv_done() hands each received PDU to the opcode handlers without ever looking at wc->byte_len, the number of bytes the HCA actually placed in the receive descriptor. The handlers then copy that many bytes - the data-segment length the initiator declared in the BHS (ntoh24(hdr->dlength), via the derived unsol_data_len / imm_data_len) - out of the fixed-size descriptor:
isert_handle_iscsi_dataout():
sg_copy_from_buffer(sg_start, sg_nents, isert_get_data(rx_desc),
unsol_data_len);
isert_handle_scsi_cmd():
sg_copy_from_buffer(cmd->se_cmd.t_data_sg, sg_nents,
isert_get_data(rx_desc), imm_data_len);Because the declared length is never checked against wc->byte_len, an initiator can declare a data segment larger than the bytes it actually sent (and larger than the descriptor) and cause an out-of-bounds read of the receive buffer.
Nothing upstream of isert closes this door:
- __iscsit_check_dataout_hdr() bounds the inbound payload against conn_ops->MaxXmitDataSegmentLength (MXDSL) - a transmit parameter, used here for the inbound check.
- iscsi_set_connection_parameters() sets ops->MaxXmitDataSegmentLength = ops->TargetRecvDataSegmentLength; and TARGETRECVDATASEGMENTLENGTH is absent from the min()-clamp list in iscsi_check_acceptor_state(), so the value the initiator declares is adopted verbatim (type range 512..16777215). The initiator effectively raises its own ceiling.
- isert never clamps the negotiated value to its own fixed receive descriptor (ISER_RX_SIZE, 9216 bytes), so the target core's bound and the descriptor size are unrelated.
The imm_data_len == data_len path is more than an over-read: it aliases the receive descriptor via sg_set_buf() and passes it to the backend as the data source for the SCSI WRITE, so an over-declared length causes heap contents past the descriptor to be written through the backend to the backing store. The backend is the victim of the oversized scatterlist isert hands it, not the cause; no read-back of the written bytes was demonstrated.
Trigger: after login completes (full feature phase), an initiator that has declared a large TargetRecvDataSegmentLength and a FirstBurstLength that permits unsolicited/immediate data sends a PDU whose declared data-segment length exceeds what was received. With KASAN:
BUG: KASAN: slab-out-of-bounds in sg_copy_buffer+0x150/0x1c0 Read of size 4096 at addr ffff888109720800 by task kworker/1:0H/25 Workqueue: ib-comp-wq ib_cq_poll_work Call Trace: sg_copy_buffer+0x150/0x1c0 isert_recv_done+0xba6/0x2390 __ib_process_cq+0xe1/0x390 ib_cq_poll_work+0x46/0x150
isert_recv_done+0xba6 resolves to isert_handle_iscsi_dataout() (ib_isert.c:1160), inlined through isert_rx_opcode().
Validate wc->byte_len against the framing in isert_recv_done() before the PDU reaches any handler, and reinstate the connection if it is short. Because the test compares without subtracting the header length, it also rejects PDUs shorter than the iSER and iSCSI headers, which would otherwise be parsed out of stale descriptor contents. The login handler rejects PDUs shorter than ISER_HEADERS_LEN (commit 29e7b925ae6d ("IB/isert: Reject login PDUs shorter than ISER_HEADERS_LEN")) but does not bound the declared length either; that is fixed in the next patch. The data handlers had no length check at all.
isert reads the data segment from a fixed offset: isert_get_data() returns the iSER header plus ISER_HEADERS_LEN and makes no adjustment for an AHS. The bytes the handlers touch are therefore exactly [ISER_HEADERS_LEN, ISER_HEADERS_LEN + dlength), and comparing that sum against wc->byte_len bounds precisely the region that is read. An AHS term would only make the test stricter without bounding anything further, and cannot cause a false reject: a PDU carrying an AHS is longer, not shorter.
This is a memory-safety fix that verifies the bytes that were actually received; it does not touch RFC 7145 length negotiation and is not the MaxXmitDataSegmentLength negotiation redesign raised in the 2017 "[Query]
iSER-Target: QP errors observed on increasing MaxXmitDataSegmentLength" discussion. That redesign is explicitly out of scope here.
The patched kernel rejects the malformed DataOut PDU and both immediate-data variants with "PDU declares ... bytes were received" and continues to pass normal traffic with no regression.
Reproduced with soft-RoCE (rdma_rxe) and a raw rdma_cm/ibv initiator; no kernel-side test hooks were needed.
--- drivers/infiniband/ulp/isert/ib_isert.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
drivers/infiniband/ulp/isert/ib_isert.c +15 -0
@@ -1338,6 +1338,21 @@ isert_recv_done(struct ib_cq *cq, struct ib_wc *wc)ib_dma_sync_single_for_cpu (ib_dev, rx_desc->dma_addr,ISER_RX_SIZE ,DMA_FROM_DEVICE ); +/* +* The data segment length declared in the BHS is attacker controlled +* and is used further down to read that many bytes out of the fixed +* size receive descriptor, so it has to be checked against the number +* of bytes that were actually received. Comparing without subtracting +* also rejects PDUs shorter than the iSER and iSCSI headers, which +* would otherwise be parsed out of stale descriptor contents. +*/ +if (unlikely (wc->byte_len <ISER_HEADERS_LEN +ntoh24 (hdr->dlength))) { +isert_err ("PDU declares %u data bytes but only %u bytes were received\n" , +ntoh24 (hdr->dlength), wc->byte_len); +iscsit_cause_connection_reinstatement (isert_conn->conn,0 ); +return ; + } +isert_dbg ("DMA: 0x%llx, iSCSI opcode: 0x%02x, ITT: 0x%08x, flags: 0x%02x dlen: %d\n" , rx_desc->dma_addr, hdr->opcode, hdr->itt, hdr->flags, (int )(wc->byte_len -ISER_HEADERS_LEN ));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 538/798 IB/isert: reject login PDUs declaring more data than was received
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yehyeong Lee <[email protected]>
[ Upstream commit 2488b5b4827e5415768afc8daf097e8eb83c98df ]
isert_login_recv_done() records how many bytes the HCA actually placed in the login buffer, but nothing compares that against the length the login PDU's BHS declares. isert_rx_login_req() copies min(login_req_len, MAX_KEY_VALUE_PAIRS) bytes into login->req_buf, and the login code then reads the declared length back out of that buffer - for the first PDU in iscsi_target_locate_portal(),
payload_length = ntoh24(login_req->dlength); tmpbuf = kmemdup_nul(login->req_buf, payload_length, GFP_KERNEL);
and for the ones after it in iscsi_decode_text_input(), reached from iscsi_target_do_login().
login->req_buf is a fixed MAX_KEY_VALUE_PAIRS (8192) byte allocation, so an initiator that declares more than it sends reads off the end of it, before authentication and with the length under its control:
BUG: KASAN: slab-out-of-bounds in kmemdup_nul+0x43/0x80 Read of size 8193 at addr ffff8881056a8000 by task iscsi_np/167 __asan_memcpy+0x23/0x60 kmemdup_nul+0x43/0x80 iscsi_target_locate_portal+0x48d/0x1180 iscsi_target_login_thread+0x19a9/0x3350 Allocated by task 167: __kmalloc_cache_noprof+0x158/0x370 iscsi_target_login_thread+0x971/0x3350 which belongs to the cache kmalloc-8k of size 8192 allocated 8192-byte region
Falsifying the second login PDU instead reaches the other reader, on the same buffer:
BUG: KASAN: slab-out-of-bounds in kmemdup_nul+0x43/0x80 Read of size 8193 at addr ffff888104d10000 by task kworker/1:1/50 Workqueue: isert_login_wq iscsi_target_do_login_rx __asan_memcpy+0x23/0x60 kmemdup_nul+0x43/0x80 iscsi_decode_text_input+0xc6/0x11c0 iscsi_target_do_login+0x261/0x1470 iscsi_target_do_login_rx+0x51d/0x7d0
iscsit over TCP is not exposed: iscsit_get_login_rx() validates the declared length with iscsi_target_check_login_request() and then reads exactly that many bytes off the socket, so the declared length governs how much arrives rather than how much is copied out of an already-filled buffer. isert does not call iscsi_target_check_login_request() at all.
Reject a login PDU whose declared DataSegmentLength exceeds what was received, in both paths that reach isert_rx_login_req():isert_get_login_rx() for the first login PDU and isert_login_recv_done() for the ones after it. dlength <= login_req_len is allowed because the received count can include up to three bytes of iSCSI padding.
Once the check is in place the copy out can no longer exceed the copy in:
the posted login SGE is ISER_RX_PAYLOAD_SIZE, so login_req_len cannot exceed MAX_KEY_VALUE_PAIRS and the min() in isert_rx_login_req() is login_req_len.
Like the existing short-PDU check added by 29e7b925ae6d, the reject in isert_login_recv_done() returns without completing login_req_comp, so a malformed subsequent PDU leaves the login to be torn down by the login timer rather than failing immediately. The first-PDU path returns an error and fails straight away.
Reproduced on 7.2.0-rc4 with soft-RoCE (rdma_rxe) under KASAN, using an initiator that sends the real key=value payload while declaring 8193 in the BHS, on the first login PDU and on the second in separate runs. The reported read size tracks the declared value exactly; 16384 and 61440 behave the same. Unpatched 3 of 3 runs report on each of the two paths, patched 0 of 3 on both, run alternately in a single session, and a normal login still completes on the patched build.
--- drivers/infiniband/ulp/isert/ib_isert.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-)
drivers/infiniband/ulp/isert/ib_isert.c +24 -1
@@ -975,6 +975,21 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login,return 0 ; } +static int +isert_check_login_req (struct isert_conn *isert_conn) +{ +struct iscsi_hdr *hdr =isert_get_iscsi_hdr (isert_conn->login_desc); +u32 dlength =ntoh24 (hdr->dlength); + +if (unlikely (dlength > (u32 )isert_conn->login_req_len)) { +isert_dbg ("login PDU declares %u data bytes but only %d were received\n" , + dlength, isert_conn->login_req_len); +return -EINVAL ; + } + +return 0 ; +} +static void isert_rx_login_req (struct isert_conn *isert_conn) {
@@ -1414,8 +1429,12 @@ isert_login_recv_done(struct ib_cq *cq, struct ib_wc *wc)if (isert_conn->conn) {struct iscsi_login *login = isert_conn->conn->conn_login; -if (login && !login->first_request) +if (login && !login->first_request) { +if (isert_check_login_req (isert_conn)) +return ; +isert_rx_login_req (isert_conn); + } }mutex_lock (&isert_conn->mutex);
@@ -2370,6 +2389,10 @@ isert_get_login_rx(struct iscsi_conn *conn, struct iscsi_login *login)if (!login->first_request)return 0 ; + ret =isert_check_login_req (isert_conn); +if (ret) +return ret; +isert_rx_login_req (isert_conn);isert_info ("before login_comp conn: %p\n" , conn);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 539/798 nvme-fc: unmap cmd_iu DMA on rsp_iu mapping failure in init_request
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guixin Liu <[email protected]>
[ Upstream commit f49d0c3a8d56a7cda1628ae17341a4a42063563c ]
__nvme_fc_init_request() maps cmd_iu and then rsp_iu for DMA. If the rsp_iu mapping fails, the original code only recorded the error and fell
through: it left the already-mapped cmd_iu unmapped and still marked the op as FCPOP_STATE_IDLE before returning. Since blk-mq does not call .exit_request() when .init_request() fails, the cmd_iu mapping is leaked for every op whose rsp_iu mapping fails.
Jump to an error path on rsp_iu mapping failure that unmaps cmd_iu and returns the error without marking the op idle, so it stays in the FCPOP_STATE_UNINIT state set by the initial memset().
--- drivers/nvme/host/fc.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/nvme/host/fc.c +6 -0
@@ -2100,9 +2100,15 @@ __nvme_fc_init_request(struct nvme_fc_ctrl *ctrl,dev_err (ctrl->dev,"FCP Op failed - rspiu dma mapping failed.\n" ); ret = -EFAULT ; + goto out_unmap; }atomic_set (&op->state,FCPOP_STATE_IDLE ); +return 0 ; + +out_unmap: +fc_dma_unmap_single (ctrl->lport->dev, op->fcp_req.cmddma, +sizeof (op->cmd_iu),DMA_TO_DEVICE ); out_on_error:return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 540/798 wifi: rtlwifi: pci: fix error path in rtl_pci_probe()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdun Nihaal <[email protected]>
[ Upstream commit 3c2999d13eeb222ae56631aeb7ca248090f2b210 ]
In the last error path in rtl_pci_probe(), the cleanup functions are skipped due to a wrong goto label. Moreover, the successful call to rtl_init_rfkill(), ieee80211_register_hw(), rtl_debug_add_one() have to be reverted. Fix this issue by updating the labels and adding the relevant cleanup functions to the last error path.
--- drivers/net/wireless/realtek/rtlwifi/pci.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/net/wireless/realtek/rtlwifi/pci.c +5 -1
@@ -2228,13 +2228,17 @@ int rtl_pci_probe(struct pci_dev *pdev,rtl_dbg (rtlpriv,COMP_INIT ,DBG_DMESG ,"%s: failed to register IRQ handler\n" ,wiphy_name (hw->wiphy)); - goto fail3; + goto fail6; } rtlpci->irq_alloc =1 ;set_bit (RTL_STATUS_INTERFACE_START , &rtlpriv->status);return 0 ; +fail6: +rtl_deinit_rfkill (hw); +rtl_debug_remove_one (hw); +ieee80211_unregister_hw (hw); fail5:rtl_pci_deinit (hw); fail4:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 541/798 md/raid5-ppl: fix use-after-free in ppl_do_flush()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sajal Gupta <[email protected]>
[ Upstream commit 371f7a1b392edc8b7cf449cc7713179b588f2d0e ]
The loop in ppl_do_flush() continues iterating after calling ppl_io_unit_finished(), touching io->pending_flushes and leading to a use-after-free.
Add a break statement to stop the loop once io is freed.
--- drivers/md/raid5-ppl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/md/raid5-ppl.c +3 -1
@@ -654,8 +654,10 @@ static void ppl_do_flush(struct ppl_io_unit *io) log->disk_flush_bitmap =0 ;for (i = flushed_disks ; i < raid_disks; i++) { -if (atomic_dec_and_test (&io->pending_flushes)) +if (atomic_dec_and_test (&io->pending_flushes)) {ppl_io_unit_finished (io); +break ; + } } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 542/798 selftests/zram: fix kernel_gte() for POSIX sh
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cheng-Han Wu <[email protected]>
[ Upstream commit 649ba27dfac784427a01f9c95c09ecbcb88900d8 ]
Commit fc4eb486a59d ("selftests/zram: Skip max_comp_streams interface on newer kernel") added kernel_gte() to zram_lib.sh. The function uses the bash-specific [[ ... ]] conditional, but zram selftests source this file while running under /bin/sh.
On systems where /bin/sh is dash, such as Debian, the following test fails:
dash -c '
kernel_major=6; kernel_minor=1; major=6; minor=0
if [ $kernel_major -gt $major ]; then
echo ok
elif [[ $kernel_major -eq $major && $kernel_minor -ge $minor ]]; then
echo ok
fi'with:
dash: 5: [[: not found
Use separate POSIX test expressions joined by && instead.
--- tools/testing/selftests/zram/zram_lib.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/zram/zram_lib.sh +1 -1
@@ -37,7 +37,7 @@ kernel_gte() if [ $kernel_major -gt $major ]; then return 0 - elif [[ $kernel_major -eq $major && $kernel_minor -ge $minor ]]; then + elif [ $kernel_major -eq $major ] && [ $kernel_minor -ge $minor ]; then return 0 fi
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 543/798 power: supply: isp1704_charger: cancel work on remove
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hongyan Xu <[email protected]>
[ Upstream commit 60c5b8a9ef4dbc5d69bbc1a960fe55826cb3b643 ]
The USB notifier and initial VBUS detection can schedule isp->work. The remove path unregisters the notifier and power supply, but does not wait for queued or running work before tearing down the power supply state.
Cancel the work after unregistering the notifier. Do this before unregistering the power supply.
This issue was found by a static analysis tool.
--- drivers/power/supply/isp1704_charger.c | 1 + 1 file changed, 1 insertion(+)
drivers/power/supply/isp1704_charger.c +1 -0
@@ -482,6 +482,7 @@ static int isp1704_charger_remove(struct platform_device *pdev)struct isp1704_charger *isp =platform_get_drvdata (pdev);usb_unregister_notifier (isp->phy, &isp->nb); +cancel_work_sync (&isp->work);power_supply_unregister (isp->psy);isp1704_charger_set_power (isp,0 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 544/798 power: supply: sc2731_charger: Convert to platform remove callback returning void
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uwe Kleine-König <[email protected]>
[ Upstream commit 0569d4cfa800ba303647dbf8170d1e89bdee3ed9 ]
The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove().
Trivially convert this driver from always returning zero in the remove callback to the void returning variant.
Stable-dep-of: dfc859bb8d33 ("power: supply: sc2731_charger: cancel work on remove")
--- drivers/power/supply/sc2731_charger.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/power/supply/sc2731_charger.c +2 -4
@@ -511,13 +511,11 @@ static int sc2731_charger_probe(struct platform_device *pdev)return 0 ; } -static int sc2731_charger_remove (struct platform_device *pdev) +static void sc2731_charger_remove (struct platform_device *pdev) {struct sc2731_charger_info *info =platform_get_drvdata (pdev);usb_unregister_notifier (info->usb_phy, &info->usb_notify); - -return 0 ; }static const struct of_device_id sc2731_charger_of_match[] = {
@@ -532,7 +530,7 @@ static struct platform_driver sc2731_charger_driver = { .of_match_table = sc2731_charger_of_match, }, .probe = sc2731_charger_probe, - .remove = sc2731_charger_remove, + .remove_new = sc2731_charger_remove, };module_platform_driver (sc2731_charger_driver);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 545/798 power: supply: sc2731_charger: cancel work on remove
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hongyan Xu <[email protected]>
[ Upstream commit dfc859bb8d332c525872f1a44028137724fa1998 ]
The USB notifier and initial charger detection can schedule info->work. The remove path unregisters the notifier, but does not cancel queued or running work before the devm-allocated driver data is released.
Set the platform drvdata used by remove, then cancel the work after unregistering the notifier.
This issue was found by a static analysis tool.
--- drivers/power/supply/sc2731_charger.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/power/supply/sc2731_charger.c +2 -0
@@ -466,6 +466,7 @@ static int sc2731_charger_probe(struct platform_device *pdev)mutex_init (&info->lock); info->dev = &pdev->dev;INIT_WORK (&info->work, sc2731_charger_work); +platform_set_drvdata (pdev, info); info->regmap =dev_get_regmap (pdev->dev.parent,NULL );if (!info->regmap) {
@@ -516,6 +517,7 @@ static void sc2731_charger_remove(struct platform_device *pdev)struct sc2731_charger_info *info =platform_get_drvdata (pdev);usb_unregister_notifier (info->usb_phy, &info->usb_notify); +cancel_work_sync (&info->work); }static const struct of_device_id sc2731_charger_of_match[] = {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 546/798 bpf: Fix potential UAF in bpf_netns_link_update_prog
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pu Lehui <[email protected]>
[ Upstream commit 5c5997836381010fc5907b36bc17d3b19407e933 ]
In bpf_netns_link_update_prog, the checks for old_prog and prog type are currently performed locklessly before acquiring netns_bpf_mutex. This creates a race condition that can lead to a UAF issue.
If two threads concurrently execute BPF_LINK_UPDATE on the same netns link, the following execution path can trigger a UAF:
CPU0 CPU1bpf_netns_link_update_prog
if (old_prog && old_prog != link->prog)
return -EPERM;
bpf_netns_link_update_prog
if (old_prog && old_prog != link->prog)
...
old_prog = xchg(&link->prog, new_prog);
bpf_prog_put(old_prog); if (new_prog->type != link->prog->type) <-- trigger UAF
Fix this by moving the old_prog and prog->type checks inside the netns_bpf_mutex critical section. Meanwhile, use guard() to simplify lock management and avoid all the goto jumping.
--- kernel/bpf/net_namespace.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-)
kernel/bpf/net_namespace.c +6 -11
@@ -171,33 +171,28 @@ static int bpf_netns_link_update_prog(struct bpf_link *link,struct net *net;int idx, ret; +guard (mutex)(&netns_bpf_mutex); +if (old_prog && old_prog != link->prog)return -EPERM ;if (new_prog->type != link->prog->type)return -EINVAL ; -mutex_lock (&netns_bpf_mutex); - net = net_link->net; -if (!net || !check_net (net)) { +if (!net || !check_net (net))/* Link auto-detached or netns dying */ - ret = -ENOLINK ; - goto out_unlock; - } +return -ENOLINK ; run_array =rcu_dereference_protected (net->bpf.run_array[type],lockdep_is_held (&netns_bpf_mutex)); idx =link_index (net, type, net_link); ret =bpf_prog_array_update_at (run_array, idx, new_prog);if (ret) - goto out_unlock; +return ret; old_prog =xchg (&link->prog, new_prog);bpf_prog_put (old_prog); - -out_unlock: -mutex_unlock (&netns_bpf_mutex); -return ret; +return 0 ; } static int bpf_netns_link_fill_info(const struct bpf_link *link,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 547/798 lib/test_hmm: fail dmirror_fault() when the mirrored mm is gone
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stanislav Kinsburskii <[email protected]>
[ Upstream commit 6a8024511ddf4877435c34fb3d6028aa8e590649 ]
dmirror_fault() is called from the dmirror_read() and dmirror_write() retry loops after dmirror_do_read() or dmirror_do_write() finds a missing device page table entry.
If the mirrored mm has already exited, mmget_not_zero() fails. The current code returns 0 in that case, which tells the caller that faulting succeeded even though no page was faulted and no device page table entry was installed. The caller then retries the same address, hits -ENOENT again, and can loop forever without making progress.
Return -EFAULT instead, so the ioctl fails when the mirrored mm is no longer faultable.
--- lib/test_hmm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
lib/test_hmm.c +1 -1
@@ -295,7 +295,7 @@ static int dmirror_fault(struct dmirror *dmirror, unsigned long start,/* Since the mm is for the mirrored process, get a reference first. */ if (!mmget_not_zero (mm)) -return 0 ; +return -EFAULT ;for (addr = start; addr < end; addr = range.end) { range.start = addr;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 548/798 clk: qcom: Return expected ENOMEM error on dynamic allocation failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Zapolskiy <[email protected]>
[ Upstream commit 22d9257f08913b6eec3e8ece4d13d9c41f14428b ]
If a dynamic memory allocation fails, the returned error code in clock controller driver probe functions on a few legacy platforms should be set to -ENOMEM instead of -EINVAL.
--- drivers/clk/qcom/common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/clk/qcom/common.c +2 -2
@@ -148,7 +148,7 @@ static int _qcom_cc_register_board_clk(struct device *dev, const char *path,if (!node) { fixed =devm_kzalloc (dev,sizeof (*fixed),GFP_KERNEL );if (!fixed) -return -EINVAL ; +return -ENOMEM ; fixed->fixed_rate = rate; fixed->hw.init = &init_data;
@@ -165,7 +165,7 @@ static int _qcom_cc_register_board_clk(struct device *dev, const char *path,if (add_factor) { factor =devm_kzalloc (dev,sizeof (*factor),GFP_KERNEL );if (!factor) -return -EINVAL ; +return -ENOMEM ; factor->mult = factor->div =1 ; factor->hw.init = &init_data;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 549/798 iommu/dma: Check atomic pool allocation result directly
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aneesh Kumar K.V (Arm) <[email protected]>
[ Upstream commit af95a0ebc0a0db0762be75f51eadf770bad01aaa ]
The non-blocking, non-coherent allocation path uses dma_alloc_from_pool(), which returns the allocated page and fills cpu_addr only on success.
Do not rely on cpu_addr to detect allocation failure in this path. Check the returned page directly before using it for the IOMMU mapping.
--- drivers/iommu/dma-iommu.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/iommu/dma-iommu.c +8 -5
@@ -1038,13 +1038,16 @@ static void *iommu_dma_alloc(struct device *dev, size_t size, }if (IS_ENABLED (CONFIG_DMA_DIRECT_REMAP ) && - !gfpflags_allow_blocking (gfp) && !coherent) + !gfpflags_allow_blocking (gfp) && !coherent) { page =dma_alloc_from_pool (dev,PAGE_ALIGN (size), &cpu_addr, - gfp,NULL ); -else + gfp,NULL ); +if (!page) +return NULL ; + }else { cpu_addr =iommu_dma_alloc_pages (dev, size, &page, gfp, attrs); -if (!cpu_addr) -return NULL ; +if (!cpu_addr) +return NULL ; + } *handle =__iommu_dma_map (dev,page_to_phys (page), size, ioprot, dev->coherent_dma_mask);
Signature · 1 line
2.53.0