Skip to content

Commit 0d0777c

Browse files
author
Benjamin Tissoires
committed
HID: core: ensure __hid_request reserves the report ID as the first byte
The low level transport driver expects the first byte to be the report ID, even when the report ID is not use (in which case they just shift the buffer). However, __hid_request() whas not offsetting the buffer it used by one in this case, meaning that the raw_request() callback emitted by the transport driver would be stripped of the first byte. Note: this changes the API for uhid devices when a request is made through hid_hw_request. However, several considerations makes me think this is fine: - every request to a HID device made through hid_hw_request() would see that change, but every request made through hid_hw_raw_request() already has the new behaviour. So that means that the users are already facing situations where they might have or not the first byte being the null report ID when it is 0. We are making things more straightforward in the end. - uhid is mainly used for BLE devices - uhid is also used for testing, but I don't see that change a big issue - for BLE devices, we can check which kernel module is calling hid_hw_request() - and in those modules, we can check which are using a Bluetooth device - and then we can check if the command is used with a report ID or not. - surprise: none of the kernel module are using a report ID 0 - and finally, bluez, in its function set_report()[0], does the same shift if the report ID is 0 and the given buffer has a size > 0. [0] https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/profiles/input/hog-lib.c#n879 Reported-by: Alan Stern <[email protected]> Closes: https://lore.kernel.org/linux-input/[email protected]/ Reported-by: [email protected] Closes: https://syzkaller.appspot.com/bug?extid=8258d5439c49d4c35f43 Tested-by: [email protected] Fixes: 4fa5a7f ("HID: core: implement generic .request()") Cc: [email protected] Link: https://patch.msgid.link/[email protected] Signed-off-by: Benjamin Tissoires <[email protected]>
1 parent 4f15ee9 commit 0d0777c

File tree

1 file changed

+9
-2
lines changed

1 file changed

+9
-2
lines changed

drivers/hid/hid-core.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1976,18 +1976,25 @@ static struct hid_report *hid_get_report(struct hid_report_enum *report_enum,
19761976
int __hid_request(struct hid_device *hid, struct hid_report *report,
19771977
enum hid_class_request reqtype)
19781978
{
1979-
char *buf;
1979+
char *buf, *data_buf;
19801980
int ret;
19811981
u32 len;
19821982

19831983
buf = hid_alloc_report_buf(report, GFP_KERNEL);
19841984
if (!buf)
19851985
return -ENOMEM;
19861986

1987+
data_buf = buf;
19871988
len = hid_report_len(report);
19881989

1990+
if (report->id == 0) {
1991+
/* reserve the first byte for the report ID */
1992+
data_buf++;
1993+
len++;
1994+
}
1995+
19891996
if (reqtype == HID_REQ_SET_REPORT)
1990-
hid_output_report(report, buf);
1997+
hid_output_report(report, data_buf);
19911998

19921999
ret = hid->ll_driver->raw_request(hid, report->id, buf, len,
19932000
report->type, reqtype);

0 commit comments

Comments
 (0)