Page MenuHomeFreeBSD

gpioc: fix race in ioctl(GPIOCONFIGEVENTS)
ClosedPublic

Authored by vexeduxr on Mon, Sep 29, 3:47 PM.
Tags
None
Referenced Files
Unknown Object (File)
Tue, Oct 14, 2:57 AM
Unknown Object (File)
Sun, Oct 12, 3:58 PM
Unknown Object (File)
Sat, Oct 11, 4:02 PM
Unknown Object (File)
Fri, Oct 10, 10:07 AM
Unknown Object (File)
Fri, Oct 10, 10:07 AM
Unknown Object (File)
Fri, Oct 10, 10:07 AM
Unknown Object (File)
Fri, Oct 10, 10:07 AM
Unknown Object (File)
Fri, Oct 10, 10:07 AM
Subscribers

Details

Summary

A race can occur in gpioc_ioctl when it is called with GPIOCONFIGEVENTS
closely followed by GPIOSETCONFIG. GPIOSETCONFIG can alter the
priv->pins list, making it no longer empty and opening the door for
access to priv->events while we are reallocating it. Fix this by holding
priv->mtx while handling GPIOCONFIGEVENTS.

Reported by: Qiu-ji Chen
PR: 289120
MFC after: 3 days

Test Plan

This race would be quite hard to hit "naturally", but I managed to hit it with a strategically placed DELAY.
As expected, the race is gone when we hold priv->mtx.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

malloc priv->events with the correct size

sys/dev/gpio/gpioc.c
924

imho, M_NOWAIT is incorrect in this context. M_NOWAIT allocation can fail at any time, and in a non-deterministic manner. Not only when the system runs out of memory, but also when the other side locks one of the allocator's internal structures.

sys/dev/gpio/gpioc.c
924

We can't use M_WAITOK while holding a mutex though. We do the same in gpioc_attach_priv_pin when allocating a new list entry.

sys/dev/gpio/gpioc.c
924

malloc() should not be used with a mutex if the code cannot retry in case of failure; this is bad design practice. In this case, I don't see any disadvantage in using SX lock at first glance if malloc() cannot be moved outside.
However, this raises another question: if the GPIO is located on serial buses (SPI, I2C), its functions may sleep. Is GPIOC aware of this fact?

sys/dev/gpio/gpioc.c
924

Oups, sorry. Mutex is used in interrupt, so SX lock is out of the question.

sys/dev/gpio/gpioc.c
924

The malloc can be moved outside with some rearchitecting. And giving this some more thought, I agree that the call shouldn't fail if the system is under memory strain.

Allocate fifo before locking priv->mtx

This revision is now accepted and ready to land.Tue, Sep 30, 10:13 AM
This revision was automatically updated to reflect the committed changes.
sys/dev/gpio/gpioc.c
924

However, this raises another question: if the GPIO is located on serial buses (SPI, I2C), its functions may sleep. Is GPIOC aware of this fact?

Ah, forgot to reply to this. The code doesn't hold any locks when calling the GPIO functions, and it drops it's locks when setting up the interrupt.