The asus_report_fixup() function was allocating a new buffer with kmemdup()
when growing the report descriptor but never freeing it. Switch to
devm_kzalloc() to ensure the memory is managed and freed automatically when
the device is removed.
Also fix a harmless out-of-bounds read by copying only the original
descriptor size.
Assisted-by: Gemini-CLI:Google Gemini 3
Signed-off-by: Günther Noack <gnoack@google.com>
---
drivers/hid/hid-asus.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index 8ffcd12038e8..7a08e964b9cc 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -1399,14 +1399,21 @@ static const __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
*/
if (*rsize == rsize_orig &&
rdesc[offs] == 0x09 && rdesc[offs + 1] == 0x76) {
- *rsize = rsize_orig + 1;
- rdesc = kmemdup(rdesc, *rsize, GFP_KERNEL);
- if (!rdesc)
- return NULL;
+ __u8 *new_rdesc;
+
+ new_rdesc = devm_kzalloc(&hdev->dev, rsize_orig + 1,
+ GFP_KERNEL);
+ if (!new_rdesc)
+ return rdesc;
hid_info(hdev, "Fixing up %s keyb report descriptor\n",
drvdata->quirks & QUIRK_T100CHI ?
"T100CHI" : "T90CHI");
+
+ memcpy(new_rdesc, rdesc, rsize_orig);
+ *rsize = rsize_orig + 1;
+ rdesc = new_rdesc;
+
memmove(rdesc + offs + 4, rdesc + offs + 2, 12);
rdesc[offs] = 0x19;
rdesc[offs + 1] = 0x00;
--
2.53.0.335.g19a08e0c02-goog
On Feb 17 2026, Günther Noack wrote:
> The asus_report_fixup() function was allocating a new buffer with kmemdup()
> when growing the report descriptor but never freeing it. Switch to
> devm_kzalloc() to ensure the memory is managed and freed automatically when
> the device is removed.
Actually this one is even worse: you can't use devm_kzalloc because
hid-core.c will later call kfree(dev->rdesc) if dev->rdesc is different
from the one provided by the low level driver. So we are going to have
a double free.
I really wonder if this was ever tested.
Cheers,
Benjamin
>
> Also fix a harmless out-of-bounds read by copying only the original
> descriptor size.
>
> Assisted-by: Gemini-CLI:Google Gemini 3
> Signed-off-by: Günther Noack <gnoack@google.com>
> ---
> drivers/hid/hid-asus.c | 15 +++++++++++----
> 1 file changed, 11 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
> index 8ffcd12038e8..7a08e964b9cc 100644
> --- a/drivers/hid/hid-asus.c
> +++ b/drivers/hid/hid-asus.c
> @@ -1399,14 +1399,21 @@ static const __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
> */
> if (*rsize == rsize_orig &&
> rdesc[offs] == 0x09 && rdesc[offs + 1] == 0x76) {
> - *rsize = rsize_orig + 1;
> - rdesc = kmemdup(rdesc, *rsize, GFP_KERNEL);
> - if (!rdesc)
> - return NULL;
> + __u8 *new_rdesc;
> +
> + new_rdesc = devm_kzalloc(&hdev->dev, rsize_orig + 1,
> + GFP_KERNEL);
> + if (!new_rdesc)
> + return rdesc;
>
> hid_info(hdev, "Fixing up %s keyb report descriptor\n",
> drvdata->quirks & QUIRK_T100CHI ?
> "T100CHI" : "T90CHI");
> +
> + memcpy(new_rdesc, rdesc, rsize_orig);
> + *rsize = rsize_orig + 1;
> + rdesc = new_rdesc;
> +
> memmove(rdesc + offs + 4, rdesc + offs + 2, 12);
> rdesc[offs] = 0x19;
> rdesc[offs + 1] = 0x00;
> --
> 2.53.0.335.g19a08e0c02-goog
>
Hello! On Tue, Feb 17, 2026 at 07:31:23PM +0100, Benjamin Tissoires wrote: > On Feb 17 2026, Günther Noack wrote: > > The asus_report_fixup() function was allocating a new buffer with kmemdup() > > when growing the report descriptor but never freeing it. Switch to > > devm_kzalloc() to ensure the memory is managed and freed automatically when > > the device is removed. > > Actually this one is even worse: you can't use devm_kzalloc because > hid-core.c will later call kfree(dev->rdesc) if dev->rdesc is different > from the one provided by the low level driver. So we are going to have > a double free. The buffer returned by report_fixup() is duplicated first before hid-core stores it in dev->rdesc. The pointer that report_fixup() returns is not managed by the caller. I elaborated in the response to the other patch in [1]. You can see it in the source code in the position marked with (4). [1] https://lore.kernel.org/all/aZTEnPEHcWEkoTJR@google.com/ > I really wonder if this was ever tested. I only convinced myself by staring at the code, because I do not happen to have the matching USB devices here. What it your usual approach to verifying such changes? raw-gadget? —Günther
© 2016 - 2026 Red Hat, Inc.