]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for all trees
authorSasha Levin <sashal@kernel.org>
Tue, 19 May 2026 13:33:43 +0000 (09:33 -0400)
committerSasha Levin <sashal@kernel.org>
Tue, 19 May 2026 13:33:43 +0000 (09:33 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-6.18/hid-core-introduce-hid_safe_input_report.patch [new file with mode: 0644]
queue-6.18/hid-pass-the-buffer-size-to-hid_report_raw_event.patch [new file with mode: 0644]
queue-6.18/series
queue-7.0/hid-core-introduce-hid_safe_input_report.patch [new file with mode: 0644]
queue-7.0/hid-pass-the-buffer-size-to-hid_report_raw_event.patch [new file with mode: 0644]
queue-7.0/series

diff --git a/queue-6.18/hid-core-introduce-hid_safe_input_report.patch b/queue-6.18/hid-core-introduce-hid_safe_input_report.patch
new file mode 100644 (file)
index 0000000..7c58fec
--- /dev/null
@@ -0,0 +1,137 @@
+From 44249ea21a917b6b743516b02cd2609386b34a2a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 May 2026 10:47:23 +0200
+Subject: HID: core: introduce hid_safe_input_report()
+
+From: Benjamin Tissoires <bentiss@kernel.org>
+
+[ Upstream commit 206342541fc887ae919774a43942dc883161fece ]
+
+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: 0a3fe972a7cb ("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>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-core.c             | 25 +++++++++++++++++++++++++
+ drivers/hid/i2c-hid/i2c-hid-core.c |  7 ++++---
+ drivers/hid/usbhid/hid-core.c      | 11 ++++++-----
+ include/linux/hid.h                |  2 ++
+ 4 files changed, 37 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index 9e8eb727c6c98..e67ea3a7d1395 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -2177,6 +2177,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)
+@@ -2187,6 +2188,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)
+ {
+diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
+index 5a183af3d5c6a..e0a302544cef4 100644
+--- a/drivers/hid/i2c-hid/i2c-hid-core.c
++++ b/drivers/hid/i2c-hid/i2c-hid-core.c
+@@ -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;
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index df3cc89dfb37f..4a493b46d9ee7 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -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;
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index d29efcf2e0789..204ada8d12e5c 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -990,6 +990,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);
+-- 
+2.53.0
+
diff --git a/queue-6.18/hid-pass-the-buffer-size-to-hid_report_raw_event.patch b/queue-6.18/hid-pass-the-buffer-size-to-hid_report_raw_event.patch
new file mode 100644 (file)
index 0000000..5673a79
--- /dev/null
@@ -0,0 +1,363 @@
+From 4da6998a6cf9176b21b4546759cdb3a6c3456e83 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 May 2026 10:47:22 +0200
+Subject: HID: pass the buffer size to hid_report_raw_event
+
+From: Benjamin Tissoires <bentiss@kernel.org>
+
+[ Upstream commit 2c85c61d1332e1e16f020d76951baf167dcb6f7a ]
+
+commit 0a3fe972a7cb ("HID: core: Mitigate potential OOB by removing
+bogus memset()") enforced the provided data to be at least the size of
+the declared buffer in the report descriptor to prevent a buffer
+overflow. However, we can try to be smarter by providing both the buffer
+size and the data size, meaning that hid_report_raw_event() can make
+better decision whether we should plaining reject the buffer (buffer
+overflow attempt) or if we can safely memset it to 0 and pass it to the
+rest of the stack.
+
+Fixes: 0a3fe972a7cb ("HID: core: Mitigate potential OOB by removing bogus memset()")
+Cc: stable@vger.kernel.org
+Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
+Acked-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Stable-dep-of: 206342541fc8 ("HID: core: introduce hid_safe_input_report()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/bpf/hid_bpf_dispatch.c |  6 +++--
+ drivers/hid/hid-core.c             | 42 ++++++++++++++++++++----------
+ drivers/hid/hid-gfrm.c             |  4 +--
+ drivers/hid/hid-logitech-hidpp.c   |  2 +-
+ drivers/hid/hid-multitouch.c       |  2 +-
+ drivers/hid/hid-primax.c           |  2 +-
+ drivers/hid/hid-vivaldi-common.c   |  2 +-
+ drivers/hid/wacom_sys.c            |  6 ++---
+ drivers/staging/greybus/hid.c      |  2 +-
+ include/linux/hid.h                |  4 +--
+ include/linux/hid_bpf.h            | 14 ++++++----
+ 11 files changed, 53 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c
+index cf465a5fe43af..eb9f40c988d02 100644
+--- a/drivers/hid/bpf/hid_bpf_dispatch.c
++++ b/drivers/hid/bpf/hid_bpf_dispatch.c
+@@ -24,7 +24,8 @@ EXPORT_SYMBOL(hid_ops);
+ u8 *
+ dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type, u8 *data,
+-                            u32 *size, int interrupt, u64 source, bool from_bpf)
++                            size_t *buf_size, u32 *size, int interrupt, u64 source,
++                            bool from_bpf)
+ {
+       struct hid_bpf_ctx_kern ctx_kern = {
+               .ctx = {
+@@ -74,6 +75,7 @@ dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type
+               *size = ret;
+       }
++      *buf_size = ctx_kern.ctx.allocated_size;
+       return ctx_kern.data;
+ }
+ EXPORT_SYMBOL_GPL(dispatch_hid_bpf_device_event);
+@@ -508,7 +510,7 @@ __hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *b
+       if (ret)
+               return ret;
+-      return hid_ops->hid_input_report(ctx->hid, type, buf, size, 0, (u64)(long)ctx, true,
++      return hid_ops->hid_input_report(ctx->hid, type, buf, size, size, 0, (u64)(long)ctx, true,
+                                        lock_already_taken);
+ }
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index 8be4e06af4636..9e8eb727c6c98 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -2029,24 +2029,32 @@ int __hid_request(struct hid_device *hid, struct hid_report *report,
+ }
+ EXPORT_SYMBOL_GPL(__hid_request);
+-int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
+-                       int interrupt)
++int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data,
++                       size_t bufsize, u32 size, int interrupt)
+ {
+       struct hid_report_enum *report_enum = hid->report_enum + type;
+       struct hid_report *report;
+       struct hid_driver *hdrv;
+       int max_buffer_size = HID_MAX_BUFFER_SIZE;
+       u32 rsize, csize = size;
++      size_t bsize = bufsize;
+       u8 *cdata = data;
+       int ret = 0;
+       report = hid_get_report(report_enum, data);
+       if (!report)
+-              goto out;
++              return 0;
++
++      if (unlikely(bsize < csize)) {
++              hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n",
++                                   report->id, csize, bsize);
++              return -EINVAL;
++      }
+       if (report_enum->numbered) {
+               cdata++;
+               csize--;
++              bsize--;
+       }
+       rsize = hid_compute_report_size(report);
+@@ -2059,11 +2067,16 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
+       else if (rsize > max_buffer_size)
+               rsize = max_buffer_size;
++      if (bsize < rsize) {
++              hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n",
++                                   report->id, rsize, bsize);
++              return -EINVAL;
++      }
++
+       if (csize < rsize) {
+-              hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %d)\n",
+-                                   report->id, rsize, csize);
+-              ret = -EINVAL;
+-              goto out;
++              dbg_hid("report %d is too short, (%d < %d)\n", report->id,
++                      csize, rsize);
++              memset(cdata + csize, 0, rsize - csize);
+       }
+       if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
+@@ -2071,7 +2084,7 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
+       if (hid->claimed & HID_CLAIMED_HIDRAW) {
+               ret = hidraw_report_event(hid, data, size);
+               if (ret)
+-                      goto out;
++                      return ret;
+       }
+       if (hid->claimed != HID_CLAIMED_HIDRAW && report->maxfield) {
+@@ -2083,15 +2096,15 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
+       if (hid->claimed & HID_CLAIMED_INPUT)
+               hidinput_report_event(hid, report);
+-out:
++
+       return ret;
+ }
+ EXPORT_SYMBOL_GPL(hid_report_raw_event);
+ static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
+-                            u8 *data, u32 size, int interrupt, u64 source, bool from_bpf,
+-                            bool lock_already_taken)
++                            u8 *data, size_t bufsize, u32 size, int interrupt, u64 source,
++                            bool from_bpf, bool lock_already_taken)
+ {
+       struct hid_report_enum *report_enum;
+       struct hid_driver *hdrv;
+@@ -2116,7 +2129,8 @@ static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
+       report_enum = hid->report_enum + type;
+       hdrv = hid->driver;
+-      data = dispatch_hid_bpf_device_event(hid, type, data, &size, interrupt, source, from_bpf);
++      data = dispatch_hid_bpf_device_event(hid, type, data, &bufsize, &size, interrupt,
++                                           source, from_bpf);
+       if (IS_ERR(data)) {
+               ret = PTR_ERR(data);
+               goto unlock;
+@@ -2145,7 +2159,7 @@ static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
+                       goto unlock;
+       }
+-      ret = hid_report_raw_event(hid, type, data, size, interrupt);
++      ret = hid_report_raw_event(hid, type, data, bufsize, size, interrupt);
+ unlock:
+       if (!lock_already_taken)
+@@ -2167,7 +2181,7 @@ static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
+ int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
+                    int interrupt)
+ {
+-      return __hid_input_report(hid, type, data, size, interrupt, 0,
++      return __hid_input_report(hid, type, data, size, size, interrupt, 0,
+                                 false, /* from_bpf */
+                                 false /* lock_already_taken */);
+ }
+diff --git a/drivers/hid/hid-gfrm.c b/drivers/hid/hid-gfrm.c
+index 699186ff2349e..d2a56bf92b416 100644
+--- a/drivers/hid/hid-gfrm.c
++++ b/drivers/hid/hid-gfrm.c
+@@ -66,7 +66,7 @@ static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report,
+       switch (data[1]) {
+       case GFRM100_SEARCH_KEY_DOWN:
+               ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_dn,
+-                                         sizeof(search_key_dn), 1);
++                                         sizeof(search_key_dn), sizeof(search_key_dn), 1);
+               break;
+       case GFRM100_SEARCH_KEY_AUDIO_DATA:
+@@ -74,7 +74,7 @@ static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report,
+       case GFRM100_SEARCH_KEY_UP:
+               ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_up,
+-                                         sizeof(search_key_up), 1);
++                                         sizeof(search_key_up), sizeof(search_key_up), 1);
+               break;
+       default:
+diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
+index faef80cb2adbd..2eb67d0caebb2 100644
+--- a/drivers/hid/hid-logitech-hidpp.c
++++ b/drivers/hid/hid-logitech-hidpp.c
+@@ -3664,7 +3664,7 @@ static int hidpp10_consumer_keys_raw_event(struct hidpp_device *hidpp,
+       memcpy(&consumer_report[1], &data[3], 4);
+       /* We are called from atomic context */
+       hid_report_raw_event(hidpp->hid_dev, HID_INPUT_REPORT,
+-                           consumer_report, 5, 1);
++                           consumer_report, sizeof(consumer_report), 5, 1);
+       return 1;
+ }
+diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
+index 21bfaf9bbd733..a543d48221070 100644
+--- a/drivers/hid/hid-multitouch.c
++++ b/drivers/hid/hid-multitouch.c
+@@ -531,7 +531,7 @@ static void mt_get_feature(struct hid_device *hdev, struct hid_report *report)
+               }
+               ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf,
+-                                         size, 0);
++                                         size, size, 0);
+               if (ret)
+                       dev_warn(&hdev->dev, "failed to report feature\n");
+       }
+diff --git a/drivers/hid/hid-primax.c b/drivers/hid/hid-primax.c
+index e44d79dff8de6..8db054280afbc 100644
+--- a/drivers/hid/hid-primax.c
++++ b/drivers/hid/hid-primax.c
+@@ -44,7 +44,7 @@ static int px_raw_event(struct hid_device *hid, struct hid_report *report,
+                       data[0] |= (1 << (data[idx] - 0xE0));
+                       data[idx] = 0;
+               }
+-              hid_report_raw_event(hid, HID_INPUT_REPORT, data, size, 0);
++              hid_report_raw_event(hid, HID_INPUT_REPORT, data, size, size, 0);
+               return 1;
+       default:        /* unknown report */
+diff --git a/drivers/hid/hid-vivaldi-common.c b/drivers/hid/hid-vivaldi-common.c
+index bf734055d4b69..b12bb5cc091aa 100644
+--- a/drivers/hid/hid-vivaldi-common.c
++++ b/drivers/hid/hid-vivaldi-common.c
+@@ -85,7 +85,7 @@ void vivaldi_feature_mapping(struct hid_device *hdev,
+       }
+       ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, report_data,
+-                                 report_len, 0);
++                                 report_len, report_len, 0);
+       if (ret) {
+               dev_warn(&hdev->dev, "failed to report feature %d\n",
+                        field->report->id);
+diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
+index 9a57504e51a19..a448cfcca4c47 100644
+--- a/drivers/hid/wacom_sys.c
++++ b/drivers/hid/wacom_sys.c
+@@ -90,7 +90,7 @@ static void wacom_wac_queue_flush(struct hid_device *hdev,
+                       kfree(buf);
+                       continue;
+               }
+-              err = hid_report_raw_event(hdev, HID_INPUT_REPORT, buf, size, false);
++              err = hid_report_raw_event(hdev, HID_INPUT_REPORT, buf, size, size, false);
+               if (err) {
+                       hid_warn(hdev, "%s: unable to flush event due to error %d\n",
+                                __func__, err);
+@@ -334,7 +334,7 @@ static void wacom_feature_mapping(struct hid_device *hdev,
+                                              data, n, WAC_CMD_RETRIES);
+                       if (ret == n && features->type == HID_GENERIC) {
+                               ret = hid_report_raw_event(hdev,
+-                                      HID_FEATURE_REPORT, data, n, 0);
++                                      HID_FEATURE_REPORT, data, n, n, 0);
+                       } else if (ret == 2 && features->type != HID_GENERIC) {
+                               features->touch_max = data[1];
+                       } else {
+@@ -395,7 +395,7 @@ static void wacom_feature_mapping(struct hid_device *hdev,
+                                       data, n, WAC_CMD_RETRIES);
+               if (ret == n) {
+                       ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT,
+-                                                 data, n, 0);
++                                                 data, n, n, 0);
+               } else {
+                       hid_warn(hdev, "%s: could not retrieve sensor offsets\n",
+                                __func__);
+diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c
+index 63c77a3df5911..afa78c96ede89 100644
+--- a/drivers/staging/greybus/hid.c
++++ b/drivers/staging/greybus/hid.c
+@@ -201,7 +201,7 @@ static void gb_hid_init_report(struct gb_hid *ghid, struct hid_report *report)
+        * we just need to setup the input fields, so using
+        * hid_report_raw_event is safe.
+        */
+-      hid_report_raw_event(ghid->hid, report->type, ghid->inbuf, size, 1);
++      hid_report_raw_event(ghid->hid, report->type, ghid->inbuf, ghid->bufsize, size, 1);
+ }
+ static void gb_hid_init_reports(struct gb_hid *ghid)
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index a4ddb94e3ee56..d29efcf2e0789 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -1258,8 +1258,8 @@ static inline u32 hid_report_len(struct hid_report *report)
+       return DIV_ROUND_UP(report->size, 8) + (report->id > 0);
+ }
+-int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
+-                       int interrupt);
++int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data,
++                       size_t bufsize, u32 size, int interrupt);
+ /* HID quirks API */
+ unsigned long hid_lookup_quirk(const struct hid_device *hdev);
+diff --git a/include/linux/hid_bpf.h b/include/linux/hid_bpf.h
+index a2e47dbcf82c8..19fffa4574a47 100644
+--- a/include/linux/hid_bpf.h
++++ b/include/linux/hid_bpf.h
+@@ -72,8 +72,8 @@ struct hid_ops {
+       int (*hid_hw_output_report)(struct hid_device *hdev, __u8 *buf, size_t len,
+                                   u64 source, bool from_bpf);
+       int (*hid_input_report)(struct hid_device *hid, enum hid_report_type type,
+-                              u8 *data, u32 size, int interrupt, u64 source, bool from_bpf,
+-                              bool lock_already_taken);
++                              u8 *data, size_t bufsize, u32 size, int interrupt, u64 source,
++                              bool from_bpf, bool lock_already_taken);
+       struct module *owner;
+       const struct bus_type *bus_type;
+ };
+@@ -200,7 +200,8 @@ struct hid_bpf {
+ #ifdef CONFIG_HID_BPF
+ u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, u8 *data,
+-                                u32 *size, int interrupt, u64 source, bool from_bpf);
++                                size_t *buf_size, u32 *size, int interrupt, u64 source,
++                                bool from_bpf);
+ int dispatch_hid_bpf_raw_requests(struct hid_device *hdev,
+                                 unsigned char reportnum, __u8 *buf,
+                                 u32 size, enum hid_report_type rtype,
+@@ -215,8 +216,11 @@ int hid_bpf_device_init(struct hid_device *hid);
+ const u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, const u8 *rdesc, unsigned int *size);
+ #else /* CONFIG_HID_BPF */
+ static inline u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type,
+-                                              u8 *data, u32 *size, int interrupt,
+-                                              u64 source, bool from_bpf) { return data; }
++                                              u8 *data, size_t *buf_size, u32 *size,
++                                              int interrupt, u64 source, bool from_bpf)
++{
++      return data;
++}
+ static inline int dispatch_hid_bpf_raw_requests(struct hid_device *hdev,
+                                               unsigned char reportnum, u8 *buf,
+                                               u32 size, enum hid_report_type rtype,
+-- 
+2.53.0
+
index 85b156e0f0f7ce94ce32889f4612760509d672eb..c71be7aa3e5eeb88de0c0c1ac20d6e9536604273 100644 (file)
@@ -893,3 +893,5 @@ kvm-reject-wrapped-offset-in-kvm_reset_dirty_gfn.patch
 kvm-s390-pci-fix-gait-table-indexing-due-to-double-scaling-pointer-arithmetic.patch
 kvm-x86-fix-xen-hypercall-tracepoint-argument-assignment.patch
 bluetooth-btmtk-accept-too-short-wmt-func_ctrl-events.patch
+hid-pass-the-buffer-size-to-hid_report_raw_event.patch
+hid-core-introduce-hid_safe_input_report.patch
diff --git a/queue-7.0/hid-core-introduce-hid_safe_input_report.patch b/queue-7.0/hid-core-introduce-hid_safe_input_report.patch
new file mode 100644 (file)
index 0000000..6ec6608
--- /dev/null
@@ -0,0 +1,137 @@
+From a50c6d2fff76eee79b207502cbfec44ed539f7e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 May 2026 10:47:23 +0200
+Subject: HID: core: introduce hid_safe_input_report()
+
+From: Benjamin Tissoires <bentiss@kernel.org>
+
+[ Upstream commit 206342541fc887ae919774a43942dc883161fece ]
+
+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: 0a3fe972a7cb ("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>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-core.c             | 25 +++++++++++++++++++++++++
+ drivers/hid/i2c-hid/i2c-hid-core.c |  7 ++++---
+ drivers/hid/usbhid/hid-core.c      | 11 ++++++-----
+ include/linux/hid.h                |  2 ++
+ 4 files changed, 37 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index 93a3393cf1476..eaac6c84377e3 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -2177,6 +2177,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)
+@@ -2187,6 +2188,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)
+ {
+diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
+index 5a183af3d5c6a..e0a302544cef4 100644
+--- a/drivers/hid/i2c-hid/i2c-hid-core.c
++++ b/drivers/hid/i2c-hid/i2c-hid-core.c
+@@ -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;
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index fd3e1aedc5cbc..047d390d5aae1 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -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;
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index ddf9291d945c1..101e05acf931a 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -998,6 +998,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);
+-- 
+2.53.0
+
diff --git a/queue-7.0/hid-pass-the-buffer-size-to-hid_report_raw_event.patch b/queue-7.0/hid-pass-the-buffer-size-to-hid_report_raw_event.patch
new file mode 100644 (file)
index 0000000..98c4f96
--- /dev/null
@@ -0,0 +1,363 @@
+From e0d6236a1f09c8cb285fa03956b21298cd672ebc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 May 2026 10:47:22 +0200
+Subject: HID: pass the buffer size to hid_report_raw_event
+
+From: Benjamin Tissoires <bentiss@kernel.org>
+
+[ Upstream commit 2c85c61d1332e1e16f020d76951baf167dcb6f7a ]
+
+commit 0a3fe972a7cb ("HID: core: Mitigate potential OOB by removing
+bogus memset()") enforced the provided data to be at least the size of
+the declared buffer in the report descriptor to prevent a buffer
+overflow. However, we can try to be smarter by providing both the buffer
+size and the data size, meaning that hid_report_raw_event() can make
+better decision whether we should plaining reject the buffer (buffer
+overflow attempt) or if we can safely memset it to 0 and pass it to the
+rest of the stack.
+
+Fixes: 0a3fe972a7cb ("HID: core: Mitigate potential OOB by removing bogus memset()")
+Cc: stable@vger.kernel.org
+Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
+Acked-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Stable-dep-of: 206342541fc8 ("HID: core: introduce hid_safe_input_report()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/bpf/hid_bpf_dispatch.c |  6 +++--
+ drivers/hid/hid-core.c             | 42 ++++++++++++++++++++----------
+ drivers/hid/hid-gfrm.c             |  4 +--
+ drivers/hid/hid-logitech-hidpp.c   |  2 +-
+ drivers/hid/hid-multitouch.c       |  2 +-
+ drivers/hid/hid-primax.c           |  2 +-
+ drivers/hid/hid-vivaldi-common.c   |  2 +-
+ drivers/hid/wacom_sys.c            |  6 ++---
+ drivers/staging/greybus/hid.c      |  2 +-
+ include/linux/hid.h                |  4 +--
+ include/linux/hid_bpf.h            | 14 ++++++----
+ 11 files changed, 53 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c
+index 50c7b45c59e3f..d0130658091b0 100644
+--- a/drivers/hid/bpf/hid_bpf_dispatch.c
++++ b/drivers/hid/bpf/hid_bpf_dispatch.c
+@@ -24,7 +24,8 @@ EXPORT_SYMBOL(hid_ops);
+ u8 *
+ dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type, u8 *data,
+-                            u32 *size, int interrupt, u64 source, bool from_bpf)
++                            size_t *buf_size, u32 *size, int interrupt, u64 source,
++                            bool from_bpf)
+ {
+       struct hid_bpf_ctx_kern ctx_kern = {
+               .ctx = {
+@@ -74,6 +75,7 @@ dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type
+               *size = ret;
+       }
++      *buf_size = ctx_kern.ctx.allocated_size;
+       return ctx_kern.data;
+ }
+ EXPORT_SYMBOL_GPL(dispatch_hid_bpf_device_event);
+@@ -505,7 +507,7 @@ __hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *b
+       if (ret)
+               return ret;
+-      return hid_ops->hid_input_report(ctx->hid, type, buf, size, 0, (u64)(long)ctx, true,
++      return hid_ops->hid_input_report(ctx->hid, type, buf, size, size, 0, (u64)(long)ctx, true,
+                                        lock_already_taken);
+ }
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index 868c65684aa82..93a3393cf1476 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -2029,24 +2029,32 @@ int __hid_request(struct hid_device *hid, struct hid_report *report,
+ }
+ EXPORT_SYMBOL_GPL(__hid_request);
+-int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
+-                       int interrupt)
++int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data,
++                       size_t bufsize, u32 size, int interrupt)
+ {
+       struct hid_report_enum *report_enum = hid->report_enum + type;
+       struct hid_report *report;
+       struct hid_driver *hdrv;
+       int max_buffer_size = HID_MAX_BUFFER_SIZE;
+       u32 rsize, csize = size;
++      size_t bsize = bufsize;
+       u8 *cdata = data;
+       int ret = 0;
+       report = hid_get_report(report_enum, data);
+       if (!report)
+-              goto out;
++              return 0;
++
++      if (unlikely(bsize < csize)) {
++              hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n",
++                                   report->id, csize, bsize);
++              return -EINVAL;
++      }
+       if (report_enum->numbered) {
+               cdata++;
+               csize--;
++              bsize--;
+       }
+       rsize = hid_compute_report_size(report);
+@@ -2059,11 +2067,16 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
+       else if (rsize > max_buffer_size)
+               rsize = max_buffer_size;
++      if (bsize < rsize) {
++              hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n",
++                                   report->id, rsize, bsize);
++              return -EINVAL;
++      }
++
+       if (csize < rsize) {
+-              hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %d)\n",
+-                                   report->id, rsize, csize);
+-              ret = -EINVAL;
+-              goto out;
++              dbg_hid("report %d is too short, (%d < %d)\n", report->id,
++                      csize, rsize);
++              memset(cdata + csize, 0, rsize - csize);
+       }
+       if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
+@@ -2071,7 +2084,7 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
+       if (hid->claimed & HID_CLAIMED_HIDRAW) {
+               ret = hidraw_report_event(hid, data, size);
+               if (ret)
+-                      goto out;
++                      return ret;
+       }
+       if (hid->claimed != HID_CLAIMED_HIDRAW && report->maxfield) {
+@@ -2083,15 +2096,15 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
+       if (hid->claimed & HID_CLAIMED_INPUT)
+               hidinput_report_event(hid, report);
+-out:
++
+       return ret;
+ }
+ EXPORT_SYMBOL_GPL(hid_report_raw_event);
+ static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
+-                            u8 *data, u32 size, int interrupt, u64 source, bool from_bpf,
+-                            bool lock_already_taken)
++                            u8 *data, size_t bufsize, u32 size, int interrupt, u64 source,
++                            bool from_bpf, bool lock_already_taken)
+ {
+       struct hid_report_enum *report_enum;
+       struct hid_driver *hdrv;
+@@ -2116,7 +2129,8 @@ static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
+       report_enum = hid->report_enum + type;
+       hdrv = hid->driver;
+-      data = dispatch_hid_bpf_device_event(hid, type, data, &size, interrupt, source, from_bpf);
++      data = dispatch_hid_bpf_device_event(hid, type, data, &bufsize, &size, interrupt,
++                                           source, from_bpf);
+       if (IS_ERR(data)) {
+               ret = PTR_ERR(data);
+               goto unlock;
+@@ -2145,7 +2159,7 @@ static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
+                       goto unlock;
+       }
+-      ret = hid_report_raw_event(hid, type, data, size, interrupt);
++      ret = hid_report_raw_event(hid, type, data, bufsize, size, interrupt);
+ unlock:
+       if (!lock_already_taken)
+@@ -2167,7 +2181,7 @@ static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
+ int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
+                    int interrupt)
+ {
+-      return __hid_input_report(hid, type, data, size, interrupt, 0,
++      return __hid_input_report(hid, type, data, size, size, interrupt, 0,
+                                 false, /* from_bpf */
+                                 false /* lock_already_taken */);
+ }
+diff --git a/drivers/hid/hid-gfrm.c b/drivers/hid/hid-gfrm.c
+index 699186ff2349e..d2a56bf92b416 100644
+--- a/drivers/hid/hid-gfrm.c
++++ b/drivers/hid/hid-gfrm.c
+@@ -66,7 +66,7 @@ static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report,
+       switch (data[1]) {
+       case GFRM100_SEARCH_KEY_DOWN:
+               ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_dn,
+-                                         sizeof(search_key_dn), 1);
++                                         sizeof(search_key_dn), sizeof(search_key_dn), 1);
+               break;
+       case GFRM100_SEARCH_KEY_AUDIO_DATA:
+@@ -74,7 +74,7 @@ static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report,
+       case GFRM100_SEARCH_KEY_UP:
+               ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_up,
+-                                         sizeof(search_key_up), 1);
++                                         sizeof(search_key_up), sizeof(search_key_up), 1);
+               break;
+       default:
+diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
+index d1dea7297712d..e9aa99ade5aac 100644
+--- a/drivers/hid/hid-logitech-hidpp.c
++++ b/drivers/hid/hid-logitech-hidpp.c
+@@ -3665,7 +3665,7 @@ static int hidpp10_consumer_keys_raw_event(struct hidpp_device *hidpp,
+       memcpy(&consumer_report[1], &data[3], 4);
+       /* We are called from atomic context */
+       hid_report_raw_event(hidpp->hid_dev, HID_INPUT_REPORT,
+-                           consumer_report, 5, 1);
++                           consumer_report, sizeof(consumer_report), 5, 1);
+       return 1;
+ }
+diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
+index e82a3c4e5b44e..eeab0b6e32ccc 100644
+--- a/drivers/hid/hid-multitouch.c
++++ b/drivers/hid/hid-multitouch.c
+@@ -533,7 +533,7 @@ static void mt_get_feature(struct hid_device *hdev, struct hid_report *report)
+               }
+               ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf,
+-                                         size, 0);
++                                         size, size, 0);
+               if (ret)
+                       dev_warn(&hdev->dev, "failed to report feature\n");
+       }
+diff --git a/drivers/hid/hid-primax.c b/drivers/hid/hid-primax.c
+index e44d79dff8de6..8db054280afbc 100644
+--- a/drivers/hid/hid-primax.c
++++ b/drivers/hid/hid-primax.c
+@@ -44,7 +44,7 @@ static int px_raw_event(struct hid_device *hid, struct hid_report *report,
+                       data[0] |= (1 << (data[idx] - 0xE0));
+                       data[idx] = 0;
+               }
+-              hid_report_raw_event(hid, HID_INPUT_REPORT, data, size, 0);
++              hid_report_raw_event(hid, HID_INPUT_REPORT, data, size, size, 0);
+               return 1;
+       default:        /* unknown report */
+diff --git a/drivers/hid/hid-vivaldi-common.c b/drivers/hid/hid-vivaldi-common.c
+index bf734055d4b69..b12bb5cc091aa 100644
+--- a/drivers/hid/hid-vivaldi-common.c
++++ b/drivers/hid/hid-vivaldi-common.c
+@@ -85,7 +85,7 @@ void vivaldi_feature_mapping(struct hid_device *hdev,
+       }
+       ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, report_data,
+-                                 report_len, 0);
++                                 report_len, report_len, 0);
+       if (ret) {
+               dev_warn(&hdev->dev, "failed to report feature %d\n",
+                        field->report->id);
+diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
+index 0d1c6d90fe21c..a32320b351e3e 100644
+--- a/drivers/hid/wacom_sys.c
++++ b/drivers/hid/wacom_sys.c
+@@ -90,7 +90,7 @@ static void wacom_wac_queue_flush(struct hid_device *hdev,
+                       kfree(buf);
+                       continue;
+               }
+-              err = hid_report_raw_event(hdev, HID_INPUT_REPORT, buf, size, false);
++              err = hid_report_raw_event(hdev, HID_INPUT_REPORT, buf, size, size, false);
+               if (err) {
+                       hid_warn(hdev, "%s: unable to flush event due to error %d\n",
+                                __func__, err);
+@@ -334,7 +334,7 @@ static void wacom_feature_mapping(struct hid_device *hdev,
+                                              data, n, WAC_CMD_RETRIES);
+                       if (ret == n && features->type == HID_GENERIC) {
+                               ret = hid_report_raw_event(hdev,
+-                                      HID_FEATURE_REPORT, data, n, 0);
++                                      HID_FEATURE_REPORT, data, n, n, 0);
+                       } else if (ret == 2 && features->type != HID_GENERIC) {
+                               features->touch_max = data[1];
+                       } else {
+@@ -395,7 +395,7 @@ static void wacom_feature_mapping(struct hid_device *hdev,
+                                       data, n, WAC_CMD_RETRIES);
+               if (ret == n) {
+                       ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT,
+-                                                 data, n, 0);
++                                                 data, n, n, 0);
+               } else {
+                       hid_warn(hdev, "%s: could not retrieve sensor offsets\n",
+                                __func__);
+diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c
+index 1f58c907c0368..f1f9f6fbc00e5 100644
+--- a/drivers/staging/greybus/hid.c
++++ b/drivers/staging/greybus/hid.c
+@@ -201,7 +201,7 @@ static void gb_hid_init_report(struct gb_hid *ghid, struct hid_report *report)
+        * we just need to setup the input fields, so using
+        * hid_report_raw_event is safe.
+        */
+-      hid_report_raw_event(ghid->hid, report->type, ghid->inbuf, size, 1);
++      hid_report_raw_event(ghid->hid, report->type, ghid->inbuf, ghid->bufsize, size, 1);
+ }
+ static void gb_hid_init_reports(struct gb_hid *ghid)
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index 31324609af4df..ddf9291d945c1 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -1266,8 +1266,8 @@ static inline u32 hid_report_len(struct hid_report *report)
+       return DIV_ROUND_UP(report->size, 8) + (report->id > 0);
+ }
+-int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
+-                       int interrupt);
++int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data,
++                       size_t bufsize, u32 size, int interrupt);
+ /* HID quirks API */
+ unsigned long hid_lookup_quirk(const struct hid_device *hdev);
+diff --git a/include/linux/hid_bpf.h b/include/linux/hid_bpf.h
+index a2e47dbcf82c8..19fffa4574a47 100644
+--- a/include/linux/hid_bpf.h
++++ b/include/linux/hid_bpf.h
+@@ -72,8 +72,8 @@ struct hid_ops {
+       int (*hid_hw_output_report)(struct hid_device *hdev, __u8 *buf, size_t len,
+                                   u64 source, bool from_bpf);
+       int (*hid_input_report)(struct hid_device *hid, enum hid_report_type type,
+-                              u8 *data, u32 size, int interrupt, u64 source, bool from_bpf,
+-                              bool lock_already_taken);
++                              u8 *data, size_t bufsize, u32 size, int interrupt, u64 source,
++                              bool from_bpf, bool lock_already_taken);
+       struct module *owner;
+       const struct bus_type *bus_type;
+ };
+@@ -200,7 +200,8 @@ struct hid_bpf {
+ #ifdef CONFIG_HID_BPF
+ u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, u8 *data,
+-                                u32 *size, int interrupt, u64 source, bool from_bpf);
++                                size_t *buf_size, u32 *size, int interrupt, u64 source,
++                                bool from_bpf);
+ int dispatch_hid_bpf_raw_requests(struct hid_device *hdev,
+                                 unsigned char reportnum, __u8 *buf,
+                                 u32 size, enum hid_report_type rtype,
+@@ -215,8 +216,11 @@ int hid_bpf_device_init(struct hid_device *hid);
+ const u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, const u8 *rdesc, unsigned int *size);
+ #else /* CONFIG_HID_BPF */
+ static inline u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type,
+-                                              u8 *data, u32 *size, int interrupt,
+-                                              u64 source, bool from_bpf) { return data; }
++                                              u8 *data, size_t *buf_size, u32 *size,
++                                              int interrupt, u64 source, bool from_bpf)
++{
++      return data;
++}
+ static inline int dispatch_hid_bpf_raw_requests(struct hid_device *hdev,
+                                               unsigned char reportnum, u8 *buf,
+                                               u32 size, enum hid_report_type rtype,
+-- 
+2.53.0
+
index 77ad490b88ca8d096a5f1782b2ae2daf154f1b30..cac06c2fed73874c7d037f3487a05fe570875147 100644 (file)
@@ -1059,3 +1059,5 @@ kvm-reject-wrapped-offset-in-kvm_reset_dirty_gfn.patch
 kvm-s390-pci-fix-gait-table-indexing-due-to-double-scaling-pointer-arithmetic.patch
 kvm-x86-fix-xen-hypercall-tracepoint-argument-assignment.patch
 bluetooth-btmtk-accept-too-short-wmt-func_ctrl-events.patch
+hid-pass-the-buffer-size-to-hid_report_raw_event.patch
+hid-core-introduce-hid_safe_input_report.patch