Re: cdev/devm_* issues (was Re: [TECH TOPIC] Rust for Linux)

Wedson Almeida Filho
2021-07-09T16:54:02Z

On Fri, Jul 09, 2021 at 01:06:22AM +0200, Linus Walleij wrote:
> The crucial part is what happens when a device with GPIOs
> disappears, if e.g. the USB device is unplugged or the driver
> is rmmod:ed by force from the command line. We then unregister
> the struct gpio_chip and drop all devm_* resources taken by the
> driver (referencing the struct dev in the USB device or so) so these
> go away, but the struct gpio_device stays around
> until the last reference from userspace is dropped.
>
> In order to not crash calls from the character device the device is
> "numbed", so any calls will just return "OK" but nothing happens.
> We then hope userspace will be so nice to terminate once it realizes
> that it is no longer needed, closing the chardev and releasing the
> resources held.

In preparation for writing the abstractions to implement a gpio driver in Rust,
I was reading through some of the code you describe above.

Unless I'm missing something (very much possible!), this "numbing" seems to not
be synchronised, that is, there are still race windows when userspace may cause
UAFs in the kernel.

For example, gpiochip_remove sets gdev->chip to NULL; gpio_ioctl returns -ENODEV
if gdev->chip is NULL, which I believe is an instance of what you describe
above. However, what ensures that it remains non-null? I see that in functions
called by gpio_ioctl (e.g., lineinfo_get), gdev->chip is used as if it were
guaranteed to be valid.

Is my reading correct or is there some synchronisation that I'm missing?

Thanks,
-Wedson