--- /dev/null
+From stable-owner@vger.kernel.org Mon Mar 20 14:09:39 2023
+From: Lee Jones <lee@kernel.org>
+Date: Mon, 20 Mar 2023 13:09:22 +0000
+Subject: HID: core: Provide new max_buffer_size attribute to over-ride the default
+To: lee@kernel.org
+Cc: stable@vger.kernel.org, Jiri Kosina <jkosina@suse.cz>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Message-ID: <20230320130923.2771901-1-lee@kernel.org>
+
+From: Lee Jones <lee@kernel.org>
+
+commit b1a37ed00d7908a991c1d0f18a8cba3c2aa99bdc upstream.
+
+Presently, when a report is processed, its proposed size, provided by
+the user of the API (as Report Size * Report Count) is compared against
+the subsystem default HID_MAX_BUFFER_SIZE (16k). However, some
+low-level HID drivers allocate a reduced amount of memory to their
+buffers (e.g. UHID only allocates UHID_DATA_MAX (4k) buffers), rending
+this check inadequate in some cases.
+
+In these circumstances, if the received report ends up being smaller
+than the proposed report size, the remainder of the buffer is zeroed.
+That is, the space between sizeof(csize) (size of the current report)
+and the rsize (size proposed i.e. Report Size * Report Count), which can
+be handled up to HID_MAX_BUFFER_SIZE (16k). Meaning that memset()
+shoots straight past the end of the buffer boundary and starts zeroing
+out in-use values, often resulting in calamity.
+
+This patch introduces a new variable into 'struct hid_ll_driver' where
+individual low-level drivers can over-ride the default maximum value of
+HID_MAX_BUFFER_SIZE (16k) with something more sympathetic to the
+interface.
+
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+[Lee: Backported to v4.14.y]
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-core.c | 18 +++++++++++++-----
+ include/linux/hid.h | 3 +++
+ 2 files changed, 16 insertions(+), 5 deletions(-)
+
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -245,6 +245,7 @@ static int hid_add_field(struct hid_pars
+ unsigned usages;
+ unsigned offset;
+ unsigned i;
++ unsigned int max_buffer_size = HID_MAX_BUFFER_SIZE;
+
+ report = hid_register_report(parser->device, report_type, parser->global.report_id);
+ if (!report) {
+@@ -268,8 +269,11 @@ static int hid_add_field(struct hid_pars
+ offset = report->size;
+ report->size += parser->global.report_size * parser->global.report_count;
+
++ if (parser->device->ll_driver->max_buffer_size)
++ max_buffer_size = parser->device->ll_driver->max_buffer_size;
++
+ /* Total size check: Allow for possible report index byte */
+- if (report->size > (HID_MAX_BUFFER_SIZE - 1) << 3) {
++ if (report->size > (max_buffer_size - 1) << 3) {
+ hid_err(parser->device, "report is too long\n");
+ return -1;
+ }
+@@ -1568,6 +1572,7 @@ int hid_report_raw_event(struct hid_devi
+ 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;
+ unsigned int a;
+ u32 rsize, csize = size;
+ u8 *cdata = data;
+@@ -1584,10 +1589,13 @@ int hid_report_raw_event(struct hid_devi
+
+ rsize = hid_compute_report_size(report);
+
+- if (report_enum->numbered && rsize >= HID_MAX_BUFFER_SIZE)
+- rsize = HID_MAX_BUFFER_SIZE - 1;
+- else if (rsize > HID_MAX_BUFFER_SIZE)
+- rsize = HID_MAX_BUFFER_SIZE;
++ if (hid->ll_driver->max_buffer_size)
++ max_buffer_size = hid->ll_driver->max_buffer_size;
++
++ if (report_enum->numbered && rsize >= max_buffer_size)
++ rsize = max_buffer_size - 1;
++ else if (rsize > max_buffer_size)
++ rsize = max_buffer_size;
+
+ if (csize < rsize) {
+ dbg_hid("report %d is too short, (%d < %d)\n", report->id,
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -770,6 +770,7 @@ struct hid_driver {
+ * @raw_request: send raw report request to device (e.g. feature report)
+ * @output_report: send output report to device
+ * @idle: send idle request to device
++ * @max_buffer_size: over-ride maximum data buffer size (default: HID_MAX_BUFFER_SIZE)
+ */
+ struct hid_ll_driver {
+ int (*start)(struct hid_device *hdev);
+@@ -794,6 +795,8 @@ struct hid_ll_driver {
+ int (*output_report) (struct hid_device *hdev, __u8 *buf, size_t len);
+
+ int (*idle)(struct hid_device *hdev, int report, int idle, int reqtype);
++
++ unsigned int max_buffer_size;
+ };
+
+ extern struct hid_ll_driver i2c_hid_ll_driver;
--- /dev/null
+From stable-owner@vger.kernel.org Mon Mar 20 14:09:38 2023
+From: Lee Jones <lee@kernel.org>
+Date: Mon, 20 Mar 2023 13:09:23 +0000
+Subject: HID: uhid: Over-ride the default maximum data buffer value with our own
+To: lee@kernel.org
+Cc: stable@vger.kernel.org, Jiri Kosina <jkosina@suse.cz>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Message-ID: <20230320130923.2771901-2-lee@kernel.org>
+
+From: Lee Jones <lee@kernel.org>
+
+commit 1c5d4221240a233df2440fe75c881465cdf8da07 upstream.
+
+The default maximum data buffer size for this interface is UHID_DATA_MAX
+(4k). When data buffers are being processed, ensure this value is used
+when ensuring the sanity, rather than a value between the user provided
+value and HID_MAX_BUFFER_SIZE (16k).
+
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/uhid.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/hid/uhid.c
++++ b/drivers/hid/uhid.c
+@@ -399,6 +399,7 @@ struct hid_ll_driver uhid_hid_driver = {
+ .parse = uhid_hid_parse,
+ .raw_request = uhid_hid_raw_request,
+ .output_report = uhid_hid_output_report,
++ .max_buffer_size = UHID_DATA_MAX,
+ };
+ EXPORT_SYMBOL_GPL(uhid_hid_driver);
+