From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: stable@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
patches@lists.linux.dev,
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Subject: [PATCH 7.1 08/21] Input: rmi4 - refactor register descriptor parsing
Date: Thu, 25 Jun 2026 14:04:00 +0100 [thread overview]
Message-ID: <20260625125614.406492194@linuxfoundation.org> (raw)
In-Reply-To: <20260625125613.243729608@linuxfoundation.org>
7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
commit 0adb483fbf2dc43c875cd7550a58b41e92efc52d upstream.
Factor out parsing a register descriptor item from
rmi_read_register_desc() and ensure there are no out-of-bounds accesses.
Use get_unaligned_le16() and get_unaligned_le32() for reading multi-byte
values.
Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Fixes: 2b6a321da9a2 ("Input: synaptics-rmi4 - add support for Synaptics RMI4 devices")
Cc: stable@vger.kernel.org
Assisted-by: Gemini:gemini-3.1-pro
Link: https://patch.msgid.link/20260505045952.1570713-2-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/rmi4/rmi_driver.c | 124 ++++++++++++++++++++++++----------------
1 file changed, 76 insertions(+), 48 deletions(-)
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -22,6 +22,7 @@
#include <uapi/linux/input.h>
#include <linux/rmi.h>
#include <linux/export.h>
+#include <linux/unaligned.h>
#include "rmi_bus.h"
#include "rmi_driver.h"
@@ -558,30 +559,74 @@ int rmi_scan_pdt(struct rmi_device *rmi_
return retval < 0 ? retval : 0;
}
+static int rmi_parse_register_desc_item(struct rmi_register_desc_item *item,
+ const u8 *buf, size_t size)
+{
+ unsigned int offset = 0;
+ unsigned int map_offset = 0;
+ int b;
+
+ if (offset >= size)
+ return -EIO;
+
+ item->reg_size = buf[offset++];
+ if (item->reg_size == 0) {
+ if (size - offset < 2)
+ return -EIO;
+ item->reg_size = get_unaligned_le16(&buf[offset]);
+ offset += 2;
+ }
+
+ if (item->reg_size == 0) {
+ if (size - offset < 4)
+ return -EIO;
+ item->reg_size = get_unaligned_le32(&buf[offset]);
+ offset += 4;
+ }
+
+ do {
+ if (offset >= size)
+ return -EIO;
+
+ for (b = 0; b < 7; b++) {
+ if (buf[offset] & BIT(b)) {
+ if (map_offset >= RMI_REG_DESC_SUBPACKET_BITS)
+ return -EIO;
+ __set_bit(map_offset, item->subpacket_map);
+ }
+ ++map_offset;
+ }
+ } while (buf[offset++] & BIT(7));
+
+ item->num_subpackets = bitmap_weight(item->subpacket_map,
+ RMI_REG_DESC_SUBPACKET_BITS);
+
+ return offset;
+}
+
int rmi_read_register_desc(struct rmi_device *d, u16 addr,
- struct rmi_register_descriptor *rdesc)
+ struct rmi_register_descriptor *rdesc)
{
int ret;
u8 size_presence_reg;
u8 buf[35];
- int presense_offset = 1;
- u8 *struct_buf;
- int reg;
- int offset = 0;
- int map_offset = 0;
+ unsigned int presence_offset;
+ unsigned int map_offset;
+ unsigned int offset;
+ unsigned int reg;
int i;
int b;
/*
* The first register of the register descriptor is the size of
- * the register descriptor's presense register.
+ * the register descriptor's presence register.
*/
ret = rmi_read(d, addr, &size_presence_reg);
if (ret)
return ret;
++addr;
- if (size_presence_reg < 0 || size_presence_reg > 35)
+ if (size_presence_reg < 1 || size_presence_reg > 35)
return -EIO;
memset(buf, 0, sizeof(buf));
@@ -597,16 +642,23 @@ int rmi_read_register_desc(struct rmi_de
addr += size_presence_reg;
if (buf[0] == 0) {
- presense_offset = 3;
- rdesc->struct_size = buf[1] | (buf[2] << 8);
+ if (size_presence_reg < 3)
+ return -EIO;
+ presence_offset = 3;
+ rdesc->struct_size = get_unaligned_le16(&buf[1]);
} else {
+ presence_offset = 1;
rdesc->struct_size = buf[0];
}
- for (i = presense_offset; i < size_presence_reg; i++) {
+ map_offset = 0;
+ for (i = presence_offset; i < size_presence_reg; i++) {
for (b = 0; b < 8; b++) {
- if (buf[i] & (0x1 << b))
+ if (buf[i] & BIT(b)) {
+ if (map_offset >= RMI_REG_DESC_PRESENSE_BITS)
+ return -EIO;
bitmap_set(rdesc->presense_map, map_offset, 1);
+ }
++map_offset;
}
}
@@ -626,7 +678,7 @@ int rmi_read_register_desc(struct rmi_de
* I'm not using devm_kzalloc here since it will not be retained
* after exiting this function
*/
- struct_buf = kzalloc(rdesc->struct_size, GFP_KERNEL);
+ u8 *struct_buf __free(kfree) = kzalloc(rdesc->struct_size, GFP_KERNEL);
if (!struct_buf)
return -ENOMEM;
@@ -638,56 +690,32 @@ int rmi_read_register_desc(struct rmi_de
*/
ret = rmi_read_block(d, addr, struct_buf, rdesc->struct_size);
if (ret)
- goto free_struct_buff;
+ return ret;
reg = find_first_bit(rdesc->presense_map, RMI_REG_DESC_PRESENSE_BITS);
+ offset = 0;
for (i = 0; i < rdesc->num_registers; i++) {
struct rmi_register_desc_item *item = &rdesc->registers[i];
- int reg_size = struct_buf[offset];
+ int item_size;
- ++offset;
- if (reg_size == 0) {
- reg_size = struct_buf[offset] |
- (struct_buf[offset + 1] << 8);
- offset += 2;
- }
-
- if (reg_size == 0) {
- reg_size = struct_buf[offset] |
- (struct_buf[offset + 1] << 8) |
- (struct_buf[offset + 2] << 16) |
- (struct_buf[offset + 3] << 24);
- offset += 4;
- }
+ item_size = rmi_parse_register_desc_item(item,
+ &struct_buf[offset],
+ rdesc->struct_size - offset);
+ if (item_size < 0)
+ return item_size;
item->reg = reg;
- item->reg_size = reg_size;
-
- map_offset = 0;
-
- do {
- for (b = 0; b < 7; b++) {
- if (struct_buf[offset] & (0x1 << b))
- bitmap_set(item->subpacket_map,
- map_offset, 1);
- ++map_offset;
- }
- } while (struct_buf[offset++] & 0x80);
-
- item->num_subpackets = bitmap_weight(item->subpacket_map,
- RMI_REG_DESC_SUBPACKET_BITS);
+ offset += item_size;
rmi_dbg(RMI_DEBUG_CORE, &d->dev,
"%s: reg: %d reg size: %ld subpackets: %d\n", __func__,
item->reg, item->reg_size, item->num_subpackets);
reg = find_next_bit(rdesc->presense_map,
- RMI_REG_DESC_PRESENSE_BITS, reg + 1);
+ RMI_REG_DESC_PRESENSE_BITS, reg + 1);
}
-free_struct_buff:
- kfree(struct_buf);
- return ret;
+ return 0;
}
const struct rmi_register_desc_item *rmi_get_register_desc_item(
next prev parent reply other threads:[~2026-06-25 13:12 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-25 13:03 [PATCH 7.1 00/21] 7.1.2-rc1 review Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.1 01/21] io_uring/net: Avoid msghdr on op_connect/op_bind async data Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.1 02/21] fuse: re-lock request before replacing page cache folio Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.1 03/21] Revert "NFSD: Defer sub-object cleanup in export put callbacks" Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.1 04/21] agp/amd64: Fix broken error propagation in agp_amd64_probe() Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.1 05/21] iio: light: veml6075: add bounds check to veml6075_it_ms index Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.1 06/21] iio: adc: ti-ads1298: add bounds check to pga_settings index Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.1 07/21] Input: rmi4 - fix register descriptor address calculation Greg Kroah-Hartman
2026-06-25 13:04 ` Greg Kroah-Hartman [this message]
2026-06-25 13:04 ` [PATCH 7.1 09/21] Input: rmi4 - fix type overflow in register counts Greg Kroah-Hartman
2026-06-25 13:04 ` [PATCH 7.1 10/21] Input: rmi4 - fix num_subpackets overflow in register descriptor Greg Kroah-Hartman
2026-06-25 13:04 ` [PATCH 7.1 11/21] Input: rmi4 - fix memory leak in rmi_set_attn_data() Greg Kroah-Hartman
2026-06-25 13:04 ` [PATCH 7.1 12/21] Input: rmi4 - iterative IRQ handler Greg Kroah-Hartman
2026-06-25 13:04 ` [PATCH 7.1 13/21] Input: rmi4 - fix bit count in bitmap_copy() Greg Kroah-Hartman
2026-06-25 13:04 ` [PATCH 7.1 14/21] crypto: qat - remove unused character device and IOCTLs Greg Kroah-Hartman
2026-06-25 13:04 ` [PATCH 7.1 15/21] vc_screen: fix null-ptr-deref in vcs_notifier() during concurrent vcs_write Greg Kroah-Hartman
2026-06-25 13:04 ` [PATCH 7.1 16/21] serial: qcom_geni: Fix RX DMA stall when SE_DMA_RX_LEN_IN is zero Greg Kroah-Hartman
2026-06-25 13:04 ` [PATCH 7.1 17/21] serial: 8250_dw: unregister 8250 port if clk_notifier_register() fails Greg Kroah-Hartman
2026-06-25 13:04 ` [PATCH 7.1 18/21] drivers/base/memory: set mem->altmap after successful device registration Greg Kroah-Hartman
2026-06-25 13:04 ` [PATCH 7.1 19/21] ksmbd: reject non-VALID session in compound request branch Greg Kroah-Hartman
2026-06-25 13:04 ` [PATCH 7.1 20/21] media: vidtv: fix NULL pointer dereference in vidtv_mux_push_si Greg Kroah-Hartman
2026-06-25 13:04 ` [PATCH 7.1 21/21] virtiofs: fix UAF on submount umount Greg Kroah-Hartman
2026-06-25 13:54 ` [PATCH 7.1 00/21] 7.1.2-rc1 review Florian Fainelli
2026-06-25 15:27 ` Brett A C Sheffield
2026-06-25 17:30 ` Justin Forbes
2026-06-25 18:19 ` Peter Schneider
2026-06-25 23:55 ` Shuah Khan
2026-06-26 4:59 ` Ron Economos
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260625125614.406492194@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=dmitry.torokhov@gmail.com \
--cc=patches@lists.linux.dev \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.