mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-21 08:19:28 +00:00
HID: hidraw: fix data race on device refcount
The hidraw_open() function increments the hidraw device reference counter. The counter has no dedicated synchronization mechanism, resulting in a potential data race when concurrently opening a device. The race is a regression introduced by commit8590222e4b
("HID: hidraw: Replace hidraw device table mutex with a rwsem"). While minors_rwsem is intended to protect the hidraw_table itself, by instead acquiring the lock for writing, the reference counter is also protected. This is symmetrical to hidraw_release(). Link: https://github.com/systemd/systemd/issues/27947 Fixes:8590222e4b
("HID: hidraw: Replace hidraw device table mutex with a rwsem") Cc: stable@vger.kernel.org Signed-off-by: Ludvig Michaelsson <ludvig.michaelsson@yubico.com> Link: https://lore.kernel.org/r/20230621-hidraw-race-v1-1-a58e6ac69bab@yubico.com Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
This commit is contained in:
parent
4982126e30
commit
944ee77dc6
1 changed files with 7 additions and 2 deletions
|
@ -272,7 +272,12 @@ static int hidraw_open(struct inode *inode, struct file *file)
|
|||
goto out;
|
||||
}
|
||||
|
||||
down_read(&minors_rwsem);
|
||||
/*
|
||||
* Technically not writing to the hidraw_table but a write lock is
|
||||
* required to protect the device refcount. This is symmetrical to
|
||||
* hidraw_release().
|
||||
*/
|
||||
down_write(&minors_rwsem);
|
||||
if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
|
||||
err = -ENODEV;
|
||||
goto out_unlock;
|
||||
|
@ -301,7 +306,7 @@ static int hidraw_open(struct inode *inode, struct file *file)
|
|||
spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags);
|
||||
file->private_data = list;
|
||||
out_unlock:
|
||||
up_read(&minors_rwsem);
|
||||
up_write(&minors_rwsem);
|
||||
out:
|
||||
if (err < 0)
|
||||
kfree(list);
|
||||
|
|
Loading…
Reference in a new issue