mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-15 22:31:47 -04:00
HID: core: introduce hid_safe_input_report()
hid_input_report() is used in too many places to have a commit that
doesn't cross subsystem borders. Instead of changing the API, introduce
a new one when things matters in the transport layers:
- usbhid
- i2chid
This effectively revert to the old behavior for those two transport
layers.
Fixes: 0a3fe972a7 ("HID: core: Mitigate potential OOB by removing bogus memset()")
Cc: stable@vger.kernel.org
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
This commit is contained in:
committed by
Jiri Kosina
parent
2c85c61d13
commit
206342541f
@@ -2181,6 +2181,7 @@ static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
|
||||
* @interrupt: distinguish between interrupt and control transfers
|
||||
*
|
||||
* This is data entry for lower layers.
|
||||
* Legacy, please use hid_safe_input_report() instead.
|
||||
*/
|
||||
int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
|
||||
int interrupt)
|
||||
@@ -2191,6 +2192,30 @@ int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hid_input_report);
|
||||
|
||||
/**
|
||||
* hid_safe_input_report - report data from lower layer (usb, bt...)
|
||||
*
|
||||
* @hid: hid device
|
||||
* @type: HID report type (HID_*_REPORT)
|
||||
* @data: report contents
|
||||
* @bufsize: allocated size of the data buffer
|
||||
* @size: useful size of data parameter
|
||||
* @interrupt: distinguish between interrupt and control transfers
|
||||
*
|
||||
* This is data entry for lower layers.
|
||||
* Please use this function instead of the non safe version because we provide
|
||||
* here the size of the buffer, allowing hid-core to make smarter decisions
|
||||
* regarding the incoming buffer.
|
||||
*/
|
||||
int hid_safe_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data,
|
||||
size_t bufsize, u32 size, int interrupt)
|
||||
{
|
||||
return __hid_input_report(hid, type, data, bufsize, size, interrupt, 0,
|
||||
false, /* from_bpf */
|
||||
false /* lock_already_taken */);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hid_safe_input_report);
|
||||
|
||||
bool hid_match_one_id(const struct hid_device *hdev,
|
||||
const struct hid_device_id *id)
|
||||
{
|
||||
|
||||
@@ -574,9 +574,10 @@ static void i2c_hid_get_input(struct i2c_hid *ihid)
|
||||
if (ihid->hid->group != HID_GROUP_RMI)
|
||||
pm_wakeup_event(&ihid->client->dev, 0);
|
||||
|
||||
hid_input_report(ihid->hid, HID_INPUT_REPORT,
|
||||
ihid->inbuf + sizeof(__le16),
|
||||
ret_size - sizeof(__le16), 1);
|
||||
hid_safe_input_report(ihid->hid, HID_INPUT_REPORT,
|
||||
ihid->inbuf + sizeof(__le16),
|
||||
ihid->bufsize - sizeof(__le16),
|
||||
ret_size - sizeof(__le16), 1);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
@@ -283,9 +283,9 @@ static void hid_irq_in(struct urb *urb)
|
||||
break;
|
||||
usbhid_mark_busy(usbhid);
|
||||
if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
|
||||
hid_input_report(urb->context, HID_INPUT_REPORT,
|
||||
urb->transfer_buffer,
|
||||
urb->actual_length, 1);
|
||||
hid_safe_input_report(urb->context, HID_INPUT_REPORT,
|
||||
urb->transfer_buffer, urb->transfer_buffer_length,
|
||||
urb->actual_length, 1);
|
||||
/*
|
||||
* autosuspend refused while keys are pressed
|
||||
* because most keyboards don't wake up when
|
||||
@@ -482,9 +482,10 @@ static void hid_ctrl(struct urb *urb)
|
||||
switch (status) {
|
||||
case 0: /* success */
|
||||
if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN)
|
||||
hid_input_report(urb->context,
|
||||
hid_safe_input_report(urb->context,
|
||||
usbhid->ctrl[usbhid->ctrltail].report->type,
|
||||
urb->transfer_buffer, urb->actual_length, 0);
|
||||
urb->transfer_buffer, urb->transfer_buffer_length,
|
||||
urb->actual_length, 0);
|
||||
break;
|
||||
case -ESHUTDOWN: /* unplug */
|
||||
unplug = 1;
|
||||
|
||||
@@ -1030,6 +1030,8 @@ struct hid_field *hid_find_field(struct hid_device *hdev, unsigned int report_ty
|
||||
int hid_set_field(struct hid_field *, unsigned, __s32);
|
||||
int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
|
||||
int interrupt);
|
||||
int hid_safe_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data,
|
||||
size_t bufsize, u32 size, int interrupt);
|
||||
struct hid_field *hidinput_get_led_field(struct hid_device *hid);
|
||||
unsigned int hidinput_count_leds(struct hid_device *hid);
|
||||
__s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code);
|
||||
|
||||
Reference in New Issue
Block a user