Commit 99e08deb authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents c2240725 a4fa45c1
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -968,10 +968,13 @@ static int gpio_aggregator_activate(struct gpio_aggregator *aggr)
	}

	wait_for_device_probe();

	scoped_guard(device, &pdev->dev) {
		if (!device_is_bound(&pdev->dev)) {
			ret = -ENXIO;
			goto err_unregister_pdev;
		}
	}

	aggr->pdev = pdev;
	return 0;
@@ -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 @@ static int gpio_aggregator_activate(struct gpio_aggregator *aggr)

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,
+1 −1
Original line number Diff line number Diff line
@@ -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;
		}
	}

+7 −4
Original line number Diff line number Diff line
@@ -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,10 +945,13 @@ static int gpio_sim_device_activate(struct gpio_sim_device *dev)
	}

	wait_for_device_probe();

	scoped_guard(device, &pdev->dev) {
		if (!device_is_bound(&pdev->dev)) {
			ret = -ENXIO;
			goto err_unregister_pdev;
		}
	}

	dev->pdev = pdev;
	return 0;
+6 −3
Original line number Diff line number Diff line
@@ -1477,10 +1477,13 @@ gpio_virtuser_device_activate(struct gpio_virtuser_device *dev)
	}

	wait_for_device_probe();

	scoped_guard(device, &pdev->dev) {
		if (!device_is_bound(&pdev->dev)) {
			ret = -ENXIO;
			goto err_unregister_pdev;
		}
	}

	dev->pdev = pdev;
	return 0;
+13 −0
Original line number Diff line number Diff line
@@ -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);