Archive-only list for patches
 help / color / mirror / Atom feed
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 6.18 47/60] Input: rmi4 - refactor register descriptor parsing
Date: Thu, 25 Jun 2026 14:03:32 +0100	[thread overview]
Message-ID: <20260625125652.585033247@linuxfoundation.org> (raw)
In-Reply-To: <20260625125645.554579168@linuxfoundation.org>

6.18-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(



  parent reply	other threads:[~2026-06-25 13:07 UTC|newest]

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-25 13:02 [PATCH 6.18 00/60] 6.18.37-rc1 review Greg Kroah-Hartman
2026-06-25 13:02 ` [PATCH 6.18 01/60] io_uring/net: Avoid msghdr on op_connect/op_bind async data Greg Kroah-Hartman
2026-06-25 13:02 ` [PATCH 6.18 02/60] net: stmmac: fix stm32 (and potentially others) resume regression Greg Kroah-Hartman
2026-06-25 13:02 ` [PATCH 6.18 03/60] fuse: re-lock request before replacing page cache folio Greg Kroah-Hartman
2026-06-25 13:02 ` [PATCH 6.18 04/60] Revert "NFSD: Defer sub-object cleanup in export put callbacks" Greg Kroah-Hartman
2026-06-25 13:02 ` [PATCH 6.18 05/60] debugobjects: Allow to refill the pool before SYSTEM_SCHEDULING Greg Kroah-Hartman
2026-06-25 13:02 ` [PATCH 6.18 06/60] debugobjects: Use LD_WAIT_CONFIG instead of LD_WAIT_SLEEP Greg Kroah-Hartman
2026-06-25 13:02 ` [PATCH 6.18 07/60] debugobjects: Do not fill_pool() if pi_blocked_on Greg Kroah-Hartman
2026-06-25 13:02 ` [PATCH 6.18 08/60] debugobjects: Dont call fill_pool() in early boot hardirq context Greg Kroah-Hartman
2026-06-25 13:02 ` [PATCH 6.18 09/60] RDMA/bnxt_re: zero shared page before exposing to userspace Greg Kroah-Hartman
2026-06-25 13:02 ` [PATCH 6.18 10/60] i2c: stub: Reject I2C block transfers with invalid length Greg Kroah-Hartman
2026-06-25 13:02 ` [PATCH 6.18 11/60] net: qualcomm: rmnet: fix endpoint use-after-free in rmnet_dellink() Greg Kroah-Hartman
2026-06-25 13:02 ` [PATCH 6.18 12/60] agp/amd64: Fix broken error propagation in agp_amd64_probe() Greg Kroah-Hartman
2026-06-25 13:02 ` [PATCH 6.18 13/60] ACPI: scan: Use async schedule function in acpi_scan_clear_dep_fn() Greg Kroah-Hartman
2026-06-25 13:02 ` [PATCH 6.18 14/60] rose: fix dev_put() leak in rose_loopback_timer() Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 15/60] rose: hold loopback neighbour reference across timer callback Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 16/60] rose: fix race between loopback timer and module removal Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 17/60] rose: clear neighbour pointer after rose_neigh_put() in state machines Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 18/60] rose: guard rose_neigh_put() against NULL in timer expiry Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 19/60] rose: fix netdev double-hold in rose_rx_call_request() Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 20/60] rose: fix notifier unregistered too early in rose_exit() Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 21/60] rose: set SOCK_DESTROY in rose_kill_by_device() for prompt cleanup Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 22/60] rose: disconnect orphaned STATE_2 sockets when device is gone Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 23/60] rose: fix netdev double-hold in rose_make_new() Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 24/60] rose: release netdev ref and destroy orphaned incoming sockets Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 25/60] rose: drop CALL_REQUEST in loopback timer when device is not running Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 26/60] rose: cancel neighbour timers in rose_neigh_put() before freeing Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 27/60] rose: clear neighbour pointer in rose_kill_by_device() Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 28/60] rose: dont free fd-owned sockets when reaping in the heartbeat Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 29/60] regulator: core: fix locking in regulator_resolve_supply() error path Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 30/60] hv: utils: handle and propagate errors in kvp_register Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 31/60] Drivers: hv: vmbus: Improve the logic of reserving fb_mmio on Gen2 VMs Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 32/60] firmware: samsung: acpm: Fix cross-thread RX length corruption Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 33/60] sctp: disable BH before calling udp_tunnel_xmit_skb() Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 34/60] mm: introduce VM_MAYBE_GUARD and make visible in /proc/$pid/smaps Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 35/60] mm: add atomic VMA flags and set VM_MAYBE_GUARD as such Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 36/60] mm: update vma_modify_flags() to handle residual flags, document Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 37/60] mm: implement sticky VMA flags Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 38/60] mm: introduce copy-on-fork VMAs and make VM_MAYBE_GUARD one Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 39/60] mm: set the VM_MAYBE_GUARD flag on guard region install Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 40/60] mm: propagate VM_SOFTDIRTY on merge Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 41/60] testing/selftests/mm: add soft-dirty merge self-test Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 42/60] net: export netif_open for self_test usage Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 43/60] net: net_failover: Fix the deadlock in slave register Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 44/60] iio: light: veml6075: add bounds check to veml6075_it_ms index Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 45/60] iio: adc: ti-ads1298: add bounds check to pga_settings index Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 46/60] Input: rmi4 - fix register descriptor address calculation Greg Kroah-Hartman
2026-06-25 13:03 ` Greg Kroah-Hartman [this message]
2026-06-25 13:03 ` [PATCH 6.18 48/60] Input: rmi4 - fix type overflow in register counts Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 49/60] Input: rmi4 - fix num_subpackets overflow in register descriptor Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 50/60] Input: rmi4 - fix memory leak in rmi_set_attn_data() Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 51/60] Input: rmi4 - iterative IRQ handler Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 52/60] Input: rmi4 - fix bit count in bitmap_copy() Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 53/60] crypto: qat - remove unused character device and IOCTLs Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 54/60] vc_screen: fix null-ptr-deref in vcs_notifier() during concurrent vcs_write Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 55/60] serial: qcom_geni: Fix RX DMA stall when SE_DMA_RX_LEN_IN is zero Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 56/60] drivers/base/memory: set mem->altmap after successful device registration Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 57/60] ksmbd: reject non-VALID session in compound request branch Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 58/60] media: vidtv: fix NULL pointer dereference in vidtv_mux_push_si Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 59/60] virtiofs: fix UAF on submount umount Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 6.18 60/60] mm: do not copy page tables unnecessarily for VM_UFFD_WP Greg Kroah-Hartman
2026-06-25 13:33 ` [PATCH 6.18 00/60] 6.18.37-rc1 review Florian Fainelli
2026-06-25 15:27 ` Brett A C Sheffield
2026-06-25 17:11 ` Peter Schneider
2026-06-26  0:04 ` Shuah Khan
2026-06-26  5:11 ` 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=20260625125652.585033247@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox