FAILED: patch "[PATCH] Input: rmi4 - refactor register descriptor parsing" failed to apply to 6.1-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x 0adb483fbf2dc43c875cd7550a58b41e92efc52d
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026062529-remote-recovery-e8fe@gregkh' --subject-prefix 'PATCH 6.1.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 0adb483fbf2dc43c875cd7550a58b41e92efc52d Mon Sep 17 00:00:00 2001
From: Dmitry Torokhov <[email protected]>
Date: Mon, 4 May 2026 21:59:32 -0700
Subject: [PATCH] Input: rmi4 - refactor register descriptor parsing
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.
drivers/input/rmi4/rmi_driver.c +76 -48
@@ -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_dev, void *ctx,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_device *d, u16 addr, 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_device *d, u16 addr,* 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_device *d, u16 addr,*/ 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(
Sasha Levin
maintainerPATCH 1/1 Input: rmi4 - refactor register descriptor parsing
From: Dmitry Torokhov <[email protected]>
[ Upstream commit 0adb483fbf2dc43c875cd7550a58b41e92efc52d ]
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.
--- drivers/input/rmi4/rmi_driver.c | 124 +++++++++++++++++++------------- 1 file changed, 76 insertions(+), 48 deletions(-)
drivers/input/rmi4/rmi_driver.c +76 -48
@@ -21,6 +21,7 @@#include <linux/irqdomain.h> #include <uapi/linux/input.h> #include <linux/rmi.h> +#include <asm/unaligned.h> #include "rmi_bus.h" #include "rmi_driver.h"
@@ -557,30 +558,74 @@ int rmi_scan_pdt(struct rmi_device *rmi_dev, void *ctx,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));
@@ -596,16 +641,23 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr, ++addr;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; } }
@@ -625,7 +677,7 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr,* 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 ;
@@ -637,56 +689,32 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr,*/ 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]; - - ++offset; -if (reg_size ==0 ) { - reg_size = struct_buf[offset] | - (struct_buf[offset +1 ] <<8 ); - offset +=2 ; - } +int item_size; -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(
Signature · 1 line
2.53.0