stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4.9.y 1/2] HID: core: Provide new max_buffer_size attribute to over-ride the default
@ 2023-03-20 13:09 Lee Jones
  2023-03-20 13:09 ` [PATCH v4.9.y 2/2] HID: uhid: Over-ride the default maximum data buffer value with our own Lee Jones
  2023-03-20 14:21 ` [PATCH v4.9.y 1/2] HID: core: Provide new max_buffer_size attribute to over-ride the default Greg Kroah-Hartman
  0 siblings, 2 replies; 3+ messages in thread
From: Lee Jones @ 2023-03-20 13:09 UTC (permalink / raw)
  To: lee; +Cc: stable, Jiri Kosina, Greg Kroah-Hartman

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[Lee: Backported to v4.9.y]
Signed-off-by: Lee Jones <lee@kernel.org>
---
 drivers/hid/hid-core.c | 18 +++++++++++++-----
 include/linux/hid.h    |  3 +++
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index c5207ed5d65b1..b9e6c51173571 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -246,6 +246,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
 	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) {
@@ -269,8 +270,11 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
 	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;
 	}
@@ -1548,6 +1552,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
 	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;
@@ -1564,10 +1569,13 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
 
 	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,
diff --git a/include/linux/hid.h b/include/linux/hid.h
index a07fa623fd0c2..be12e7d14c4a1 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -736,6 +736,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);
@@ -760,6 +761,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;
-- 
2.40.0.rc1.284.g88254d51c5-goog


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH v4.9.y 2/2] HID: uhid: Over-ride the default maximum data buffer value with our own
  2023-03-20 13:09 [PATCH v4.9.y 1/2] HID: core: Provide new max_buffer_size attribute to over-ride the default Lee Jones
@ 2023-03-20 13:09 ` Lee Jones
  2023-03-20 14:21 ` [PATCH v4.9.y 1/2] HID: core: Provide new max_buffer_size attribute to over-ride the default Greg Kroah-Hartman
  1 sibling, 0 replies; 3+ messages in thread
From: Lee Jones @ 2023-03-20 13:09 UTC (permalink / raw)
  To: lee; +Cc: stable, Jiri Kosina, Greg Kroah-Hartman

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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Lee Jones <lee@kernel.org>
---
 drivers/hid/uhid.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c
index f7705a057f0f4..ff13dbbdf675b 100644
--- a/drivers/hid/uhid.c
+++ b/drivers/hid/uhid.c
@@ -400,6 +400,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);
 
-- 
2.40.0.rc1.284.g88254d51c5-goog


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v4.9.y 1/2] HID: core: Provide new max_buffer_size attribute to over-ride the default
  2023-03-20 13:09 [PATCH v4.9.y 1/2] HID: core: Provide new max_buffer_size attribute to over-ride the default Lee Jones
  2023-03-20 13:09 ` [PATCH v4.9.y 2/2] HID: uhid: Over-ride the default maximum data buffer value with our own Lee Jones
@ 2023-03-20 14:21 ` Greg Kroah-Hartman
  1 sibling, 0 replies; 3+ messages in thread
From: Greg Kroah-Hartman @ 2023-03-20 14:21 UTC (permalink / raw)
  To: Lee Jones; +Cc: stable, Jiri Kosina

On Mon, Mar 20, 2023 at 01:09:56PM +0000, Lee Jones wrote:
> commit b1a37ed00d7908a991c1d0f18a8cba3c2aa99bdc upstream.

4.9.y is long end-of-life, sorry.

All other backports are now queued up, thanks.

greg k-h

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-03-20 14:21 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-03-20 13:09 [PATCH v4.9.y 1/2] HID: core: Provide new max_buffer_size attribute to over-ride the default Lee Jones
2023-03-20 13:09 ` [PATCH v4.9.y 2/2] HID: uhid: Over-ride the default maximum data buffer value with our own Lee Jones
2023-03-20 14:21 ` [PATCH v4.9.y 1/2] HID: core: Provide new max_buffer_size attribute to over-ride the default Greg Kroah-Hartman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).