gpio fixes for v7.1-rc5

- propagate the error code from regulator_enable() in resume path in
   gpio-pca953x
 - take the device lock when calling device_is_bound() in virtual GPIO
   drivers
 - fix software node leak in remove path in gpio-aggregator
 - fix a potential use-after-free in gpio-aggregator
 - harden the GPIO character device uAPI: check that line config
   attributes are correctly zeroed
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEkeUTLeW1Rh17omX8BZ0uy/82hMMFAmoQIysACgkQBZ0uy/82
 hMO9PRAAkaQ58li/hZYklF0O9jDsnhmK/XdPbCQvGnfRyW+838+iIyreP7NrfCN1
 XmicF7Tvt5Spq0qadSvfddMzlWcR7W15XKKVs4QgulPTZubyIyTty5SjNZZcRBxc
 pqq5Png7agZ0b7L3rFqp2sEU3044oI9+2nkWHhmxRVgoXKQVdD0AqddAJ/xiZg/b
 K1M4mjo4k12nUwo9acPMmAvOftwCiGX56p9qdXl4iobBo9Cn8qfnZgC4Oq8uOHPP
 jeEqINv6aXzw3YZOA+XFeNfqbUwyUSWp0e4KzONgrupFZxV7aqFBIlDYPFnsBMku
 yh0jYQwJZmStIzMoLfElPyudtNNZlssj9egby3b5J4n5npDg2ZZGjfbBmmhFXY4I
 madjzj22EJ/6RyVuieskKG+1P8cUlRJcvHNGAgNmhwKZxz19J5jPceQe0mit1Ofq
 lxAkbsT6XsHoqpcwmYCnsNlO9g3yiUTDjk769wK0mLe28I95Qz/t8KMVQK+PO+ij
 gCWgu/PvsnodIMBJTpiNAJNRHc3YKpevqdTdFY9o2VyZJV+mkdQVjRlYSWxtm4s0
 Liz0f5vP3SVavwqAh9iSs8SUgUSrH5hvLltyj7LBaOF/eGaVqGL8nVj0oWloL1WX
 F7sjO1HSYSWRlJRQoi0/NBE8163JfLpHJih3gZfkRKv1+vqcdvw=
 =4Qne
 -----END PGP SIGNATURE-----

Merge tag 'gpio-fixes-for-v7.1-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux

Pull gpio fixes from Bartosz Golaszewski:

 - propagate the error code from regulator_enable() in resume path in
   gpio-pca953x

 - take the device lock when calling device_is_bound() in virtual GPIO
   drivers

 - fix software node leak in remove path in gpio-aggregator

 - fix a potential use-after-free in gpio-aggregator

 - harden the GPIO character device uAPI: check that line config
   attributes are correctly zeroed

* tag 'gpio-fixes-for-v7.1-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux:
  gpio: virtuser: lock device when calling device_is_bound()
  gpio: aggregator: lock device when calling device_is_bound()
  gpio: sim: lock device when calling device_is_bound()
  gpio: aggregator: remove the software node when deactivating the aggregator
  gpio: aggregator: fix a potential use-after-free
  gpio: cdev: check if uAPI v2 config attributes are correctly zeroed
  gpio: pca953x: propagate regulator_enable() error from resume
master
Linus Torvalds 2026-05-22 12:28:47 -07:00
commit 99e08debac
5 changed files with 38 additions and 12 deletions

View File

@ -968,9 +968,12 @@ static int gpio_aggregator_activate(struct gpio_aggregator *aggr)
}
wait_for_device_probe();
if (!device_is_bound(&pdev->dev)) {
ret = -ENXIO;
goto err_unregister_pdev;
scoped_guard(device, &pdev->dev) {
if (!device_is_bound(&pdev->dev)) {
ret = -ENXIO;
goto err_unregister_pdev;
}
}
aggr->pdev = pdev;
@ -979,8 +982,8 @@ static int gpio_aggregator_activate(struct gpio_aggregator *aggr)
err_unregister_pdev:
platform_device_unregister(pdev);
err_remove_lookup_table:
kfree(aggr->lookups->dev_id);
gpiod_remove_lookup_table(aggr->lookups);
kfree(aggr->lookups->dev_id);
err_remove_swnode:
fwnode_remove_software_node(swnode);
err_remove_lookups:
@ -991,11 +994,15 @@ err_remove_lookups:
static void gpio_aggregator_deactivate(struct gpio_aggregator *aggr)
{
struct fwnode_handle *swnode;
swnode = dev_fwnode(&aggr->pdev->dev);
platform_device_unregister(aggr->pdev);
aggr->pdev = NULL;
gpiod_remove_lookup_table(aggr->lookups);
kfree(aggr->lookups->dev_id);
kfree(aggr->lookups);
fwnode_remove_software_node(swnode);
}
static void gpio_aggregator_lockup_configfs(struct gpio_aggregator *aggr,

View File

@ -1411,7 +1411,7 @@ static int pca953x_resume(struct device *dev)
ret = regulator_enable(chip->regulator);
if (ret) {
dev_err(dev, "Failed to enable regulator: %d\n", ret);
return 0;
return ret;
}
}

View File

@ -901,7 +901,7 @@ static int gpio_sim_device_activate(struct gpio_sim_device *dev)
struct platform_device *pdev;
struct fwnode_handle *swnode;
struct gpio_sim_bank *bank;
int ret;
int ret = 0;
lockdep_assert_held(&dev->lock);
@ -945,9 +945,12 @@ static int gpio_sim_device_activate(struct gpio_sim_device *dev)
}
wait_for_device_probe();
if (!device_is_bound(&pdev->dev)) {
ret = -ENXIO;
goto err_unregister_pdev;
scoped_guard(device, &pdev->dev) {
if (!device_is_bound(&pdev->dev)) {
ret = -ENXIO;
goto err_unregister_pdev;
}
}
dev->pdev = pdev;

View File

@ -1477,9 +1477,12 @@ gpio_virtuser_device_activate(struct gpio_virtuser_device *dev)
}
wait_for_device_probe();
if (!device_is_bound(&pdev->dev)) {
ret = -ENXIO;
goto err_unregister_pdev;
scoped_guard(device, &pdev->dev) {
if (!device_is_bound(&pdev->dev)) {
ret = -ENXIO;
goto err_unregister_pdev;
}
}
dev->pdev = pdev;

View File

@ -1184,6 +1184,7 @@ static int gpio_v2_line_flags_validate(u64 flags)
static int gpio_v2_line_config_validate(struct gpio_v2_line_config *lc,
unsigned int num_lines)
{
size_t unused_attrs;
unsigned int i;
u64 flags;
int ret;
@ -1191,9 +1192,21 @@ static int gpio_v2_line_config_validate(struct gpio_v2_line_config *lc,
if (lc->num_attrs > GPIO_V2_LINE_NUM_ATTRS_MAX)
return -EINVAL;
unused_attrs = GPIO_V2_LINE_NUM_ATTRS_MAX - lc->num_attrs;
if (!mem_is_zero(lc->padding, sizeof(lc->padding)))
return -EINVAL;
for (i = 0; i < lc->num_attrs; i++) {
if (lc->attrs[i].attr.padding != 0)
return -EINVAL;
}
if (unused_attrs) {
if (!mem_is_zero(&lc->attrs[lc->num_attrs], unused_attrs * sizeof(*lc->attrs)))
return -EINVAL;
}
for (i = 0; i < num_lines; i++) {
flags = gpio_v2_line_config_flags(lc, i);
ret = gpio_v2_line_flags_validate(flags);