[PATCH v2] HID: bpf: Fix signedness bug in hid_bpf_hw_request

Guangshuo Li posted 1 patch 1 week, 5 days ago
drivers/hid/bpf/hid_bpf_dispatch.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
[PATCH v2] HID: bpf: Fix signedness bug in hid_bpf_hw_request
Posted by Guangshuo Li 1 week, 5 days ago
hid_bpf_hw_request() clamps the return value of hid_hw_raw_request() to
the size of the caller-supplied buffer before copying data back to the
BPF buffer.

However, ret is signed while size is unsigned. If hid_hw_raw_request()
returns a negative error code, the comparison promotes ret to size_t.
This makes the negative value look like a very large positive value, so
the error is clamped to size. The following memcpy() then treats the
failed request as a successful transfer and copies stale data back to
the caller.

Handle negative return values before comparing ret with size and jump to
the common cleanup path on error. This preserves negative error codes
while still preventing oversized successful returns from overflowing
the caller-supplied buffer.

Fixes: 2b658c1c442e ("HID: bpf: prevent buffer overflow in hid_hw_request")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
---
v2:
  - Handle negative return values before comparing the return length
    with the unsigned buffer size, as suggested by Emil Tsalapatis.
  - Use the common cleanup path for negative return values.

 drivers/hid/bpf/hid_bpf_dispatch.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c
index d0130658091b..520b8f56a514 100644
--- a/drivers/hid/bpf/hid_bpf_dispatch.c
+++ b/drivers/hid/bpf/hid_bpf_dispatch.c
@@ -445,12 +445,14 @@ hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
 					      reqtype,
 					      (u64)(long)ctx,
 					      true); /* prevent infinite recursions */
-
+	if (ret < 0)
+		goto done;
 	if (ret > size)
 		ret = size;
 	if (ret > 0)
 		memcpy(buf, dma_data, ret);
 
+done:
 	kfree(dma_data);
 	return ret;
 }
-- 
2.43.0
Re: [PATCH v2] HID: bpf: Fix signedness bug in hid_bpf_hw_request
Posted by Emil Tsalapatis 4 days, 20 hours ago
On Mon Jul 13, 2026 at 9:26 AM EDT, Guangshuo Li wrote:
> hid_bpf_hw_request() clamps the return value of hid_hw_raw_request() to
> the size of the caller-supplied buffer before copying data back to the
> BPF buffer.
>
> However, ret is signed while size is unsigned. If hid_hw_raw_request()
> returns a negative error code, the comparison promotes ret to size_t.
> This makes the negative value look like a very large positive value, so
> the error is clamped to size. The following memcpy() then treats the
> failed request as a successful transfer and copies stale data back to
> the caller.
>
> Handle negative return values before comparing ret with size and jump to
> the common cleanup path on error. This preserves negative error codes
> while still preventing oversized successful returns from overflowing
> the caller-supplied buffer.
>
> Fixes: 2b658c1c442e ("HID: bpf: prevent buffer overflow in hid_hw_request")
> Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>

Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>

> ---
> v2:
>   - Handle negative return values before comparing the return length
>     with the unsigned buffer size, as suggested by Emil Tsalapatis.
>   - Use the common cleanup path for negative return values.
>
>  drivers/hid/bpf/hid_bpf_dispatch.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c
> index d0130658091b..520b8f56a514 100644
> --- a/drivers/hid/bpf/hid_bpf_dispatch.c
> +++ b/drivers/hid/bpf/hid_bpf_dispatch.c
> @@ -445,12 +445,14 @@ hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
>  					      reqtype,
>  					      (u64)(long)ctx,
>  					      true); /* prevent infinite recursions */
> -
> +	if (ret < 0)
> +		goto done;
>  	if (ret > size)
>  		ret = size;
>  	if (ret > 0)
>  		memcpy(buf, dma_data, ret);
>  
> +done:
>  	kfree(dma_data);
>  	return ret;
>  }