[PATCH 3/3] HID: asus: avoid memory leak in asus_report_fixup()

Günther Noack posted 3 patches 1 month, 2 weeks ago
There is a newer version of this series
[PATCH 3/3] HID: asus: avoid memory leak in asus_report_fixup()
Posted by Günther Noack 1 month, 2 weeks ago
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
Re: [PATCH 3/3] HID: asus: avoid memory leak in asus_report_fixup()
Posted by Benjamin Tissoires 1 month, 2 weeks ago
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
> 
Re: [PATCH 3/3] HID: asus: avoid memory leak in asus_report_fixup()
Posted by Günther Noack 1 month, 2 weeks ago
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