From: Dmitry Antipov <dmantipov@yandex.ru>
To: Jiri Kosina <jikos@kernel.org>, Benjamin Tissoires <bentiss@kernel.org>
Cc: linux-input@vger.kernel.org, lvc-project@linuxtesting.org,
Dmitry Antipov <dmantipov@yandex.ru>,
syzbot+d632e93ffcd1452bc61e@syzkaller.appspotmail.com,
syzbot+c492a9e154f81127551f@syzkaller.appspotmail.com
Subject: [PATCH v5 3/3] HID: roccat: use kref to manage device instances
Date: Tue, 29 Sep 2026 09:57:43 +0300 [thread overview]
Message-ID: <20260929065743.134635-4-dmantipov@yandex.ru> (raw)
In-Reply-To: <20260929065743.134635-1-dmantipov@yandex.ru>
Use kref to manage 'struct roccat_device' instances and fix both memory
leaks and UaF-triggering races between roccat_open()/roccat_release()
and roccat_connect()/roccat_disconnect() pairs. To avoid the scenario
when opened device is disconnected and its slot indexed by minor number
is reused by another device, release the slot in roccat_free_device()
rather than in roccat_disconnect(). This way, there is a time frame when
disconnected device may still occupy the slot; to reject such a device,
add extra roccat_device_available() checks to roccat_open() and
roccat_ioctl(). Add extra WARN_ON() device check to roccat_disconnect()
and a few debugging quirks to roccat_free_device() as well.
Reported-by: syzbot+d632e93ffcd1452bc61e@syzkaller.appspotmail.com
Reported-by: syzbot+c492a9e154f81127551f@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=d632e93ffcd1452bc61e
Closes: https://syzkaller.appspot.com/bug?extid=c492a9e154f81127551f
Link: https://sashiko.dev/#/patchset/20260902094551.200587-1-dmantipov@yandex.ru?part=2
Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
---
v5: adjusted to match 7.3-rc5
v4: unchanged
v3: release device slot in roccat_free_device(), add required checks
to roccat_open() and roccat_ioctl(), few more debugging quirks
v2: unconditionally get/put device reference during
first open and last close, respectively (Sashiko)
---
drivers/hid/hid-roccat.c | 33 +++++++++++++++++++++++----------
1 file changed, 23 insertions(+), 10 deletions(-)
diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c
index f50ae6b34e95..d8dfc7f22026 100644
--- a/drivers/hid/hid-roccat.c
+++ b/drivers/hid/hid-roccat.c
@@ -40,6 +40,7 @@ struct roccat_device {
unsigned int minor;
int report_size;
int open;
+ struct kref ref;
wait_queue_head_t wait;
struct device *dev;
struct hid_device *hid;
@@ -76,12 +77,20 @@ static bool roccat_device_available(struct roccat_device *device)
return dev ? device_is_registered(dev) : false;
}
-static void roccat_free_device(struct roccat_device *device)
+static void roccat_free_device(struct kref *ref)
{
+ struct roccat_device *device;
int i;
+ WARN_ON(!mutex_is_locked(&devices_lock));
+
+ device = container_of(ref, struct roccat_device, ref);
for (i = 0; i < ROCCAT_CBUF_SIZE; i++)
kfree(device->cbuf[i].value);
+
+ devices[device->minor] = NULL;
+ mutex_destroy(&device->readers_lock);
+ mutex_destroy(&device->cbuf_lock);
kfree(device);
}
@@ -175,7 +184,7 @@ static int roccat_open(struct inode *inode, struct file *file)
device = devices[minor];
- if (!device) {
+ if (!device || !roccat_device_available(device)) {
pr_emerg("roccat device with minor %d doesn't exist\n", minor);
error = -ENODEV;
goto exit_err_devices;
@@ -197,6 +206,7 @@ static int roccat_open(struct inode *inode, struct file *file)
--device->open;
goto exit_err_readers;
}
+ kref_get(&device->ref);
}
reader->device = device;
@@ -235,9 +245,8 @@ static int roccat_release(struct inode *inode, struct file *file)
if (roccat_device_available(device)) {
hid_hw_power(device->hid, PM_HINT_NORMAL);
hid_hw_close(device->hid);
- } else {
- roccat_free_device(device);
}
+ kref_put(&device->ref, roccat_free_device);
}
mutex_unlock(&devices_lock);
@@ -349,6 +358,7 @@ int roccat_connect(const struct class *klass, struct hid_device *hid, int report
INIT_LIST_HEAD(&device->readers);
mutex_init(&device->readers_lock);
mutex_init(&device->cbuf_lock);
+ kref_init(&device->ref);
device->minor = minor;
device->hid = hid;
device->cbuf_end = 0;
@@ -368,18 +378,21 @@ void roccat_disconnect(int minor)
mutex_lock(&devices_lock);
device = devices[minor];
+ if (WARN_ON(!device))
+ goto out;
- device_destroy(device->dev->class, MKDEV(roccat_major, minor));
- WRITE_ONCE(device->dev, NULL);
- devices[minor] = NULL;
+ if (!WARN_ON(!roccat_device_available(device))) {
+ device_destroy(device->dev->class, MKDEV(roccat_major, minor));
+ WRITE_ONCE(device->dev, NULL);
+ }
if (device->open) {
hid_hw_close(device->hid);
wake_up_interruptible(&device->wait);
- } else {
- roccat_free_device(device);
}
+ kref_put(&device->ref, roccat_free_device);
+out:
mutex_unlock(&devices_lock);
}
EXPORT_SYMBOL_GPL(roccat_disconnect);
@@ -394,7 +407,7 @@ static long roccat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
mutex_lock(&devices_lock);
device = devices[minor];
- if (!device) {
+ if (!device || !roccat_device_available(device)) {
retval = -ENODEV;
goto out;
}
--
2.55.0
prev parent reply other threads:[~2026-09-29 6:58 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-29 6:57 [PATCH v5 0/3] Latest Roccat HID fixes Dmitry Antipov
2026-09-29 6:57 ` [PATCH v5 1/3] HID: roccat: use device_is_registered() to check whether device is available Dmitry Antipov
2026-09-29 7:14 ` sashiko-bot
2026-09-29 6:57 ` [PATCH v5 2/3] HID: roccat: fix device access in roccat_release() Dmitry Antipov
2026-09-29 6:57 ` Dmitry Antipov [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260929065743.134635-4-dmantipov@yandex.ru \
--to=dmantipov@yandex.ru \
--cc=bentiss@kernel.org \
--cc=jikos@kernel.org \
--cc=linux-input@vger.kernel.org \
--cc=lvc-project@linuxtesting.org \
--cc=syzbot+c492a9e154f81127551f@syzkaller.appspotmail.com \
--cc=syzbot+d632e93ffcd1452bc61e@syzkaller.appspotmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox