[Letux-kernel] omap-gpmc gta04 regression 4.7-rc1

Grygorii Strashko grygorii.strashko at ti.com
Tue Jun 7 18:54:18 CEST 2016


On 06/07/2016 07:22 PM, Linus Walleij wrote:
> On Tue, Jun 7, 2016 at 5:29 PM, Grygorii Strashko
> <grygorii.strashko at ti.com> wrote:
>> On 06/07/2016 04:33 PM, Linus Walleij wrote:
>>> On Tue, Jun 7, 2016 at 9:50 AM, Roger Quadros <rogerq at ti.com> wrote:
>>>
>>>> Linus, any idea why of_gpiochip_find_and_xlate() would do a NULL pointer dereference?
>>>
>>> Nope. I see this uses the array fetch function which I did patch around but
>>> "should" not affect this.
>>>
>>>> We have a case here where the GPMC driver registers a gpiochip but after a while
>>>> unregisters it due to some other orthogonal resource not being available.
>>>> Is this registering and unregistering considered acceptable from gpiochip point of view?
>>>
>>> That would be if it doesn't really go away aftert gpiochip_remove() because
>>> some refcount doesn't go zero, so double-check that. It should be fine
>>> anyway though ... just the instance floating around somewhere.
>>>
>>
>> Linus, I've tried to find place in gpiolib.c where gpiochip is removed
>> from gpio_devices list as part of gpiochip_remove(), but I can't. Am I missed smth.?
> 
> It is supposed to happen in  gpiodevice_release() as an effect of the
> references to the kobject in the device going to zero when the last
> put_device() is called in gpiochip_remove().
> 
> Unless there is already some other user that has taken a descriptor,
> such as a kernel driver or userspace.

Ah. Thanks for the info.

> 
>> If that is the case then such kind of crash is possible, because gpiochip_find()
>> uses this list.
> 
> Hm I suspect it could be that the reference count is off, so the device
> isn't removed from the list?
> 
> But we should still numb the device somehow so that the crash doesn't
> happen even if the device is still in the list.

Seems there is a window for the race in
void gpiochip_remove(struct gpio_chip *chip)
{
	struct gpio_device *gdev = chip->gpiodev;
	struct gpio_desc *desc;
	unsigned long	flags;
	unsigned	i;
	bool		requested = false;

	/* FIXME: should the legacy sysfs handling be moved to gpio_device? */
	gpiochip_sysfs_unregister(gdev);
	/* Numb the device, cancelling all outstanding operations */
	gdev->chip = NULL;
^^^^^ Once we've reached this point the gpiochip_find() will start crashing :(

	struct gpio_chip *gpiochip_find(void *data,
	{
		[...]
		spin_lock_irqsave(&gpio_lock, flags);
		list_for_each_entry(gdev, &gpio_devices, list)
			if (match(gdev->chip, data))
					^^^^ chip is null, match = of_gpiochip_find_and_xlate()
				break;



	gpiochip_irqchip_remove(chip);
	acpi_gpiochip_remove(chip);
	gpiochip_remove_pin_ranges(chip);
	gpiochip_free_hogs(chip);
	[...]

	/*
	 * The gpiochip side puts its use of the device to rest here:
	 * if there are no userspace clients, the chardev and device will
	 * be removed, else it will be dangling until the last user is
	 * gone.
	 */
	put_device(&gdev->dev);
^^^ if i understand right gpiodev/chip will be in gpio_devices list till this point
    [if not used]




-- 
regards,
-grygorii


More information about the Letux-kernel mailing list