FAILED: patch "[PATCH] Input: rmi4 - refactor register descriptor parsing" failed to apply to 6.12-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.12-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.12.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 '2026062528-cyclist-operable-1e2f@gregkh' --subject-prefix 'PATCH 6.12.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/2 Input: include export.h in modules using EXPORT_SYMBOL*()
From: Dmitry Torokhov <[email protected]>
[ Upstream commit df595059d54383c42607b59f1f9ea74dade280fe ]
A number of modules in the input subsystem use EXPORT_SYMBOL() and friends without explicitly including the corresponding header <linux/export.h>. While the build currently succeeds due to this header being pulled in transitively, this is not guaranteed to be the case in the future.
Let's add the explicit include to make the dependencies clear and prevent future build breakage.
Stable-dep-of: 0adb483fbf2d ("Input: rmi4 - refactor register descriptor parsing")
--- drivers/input/ff-core.c | 2 +- drivers/input/ff-memless.c | 1 + drivers/input/gameport/gameport.c | 1 + drivers/input/input-poller.c | 1 + drivers/input/input.c | 1 + drivers/input/joystick/iforce/iforce-main.c | 1 + drivers/input/joystick/iforce/iforce-packets.c | 1 + drivers/input/misc/ad714x.c | 1 + drivers/input/misc/adxl34x.c | 1 + drivers/input/misc/cma3000_d0x.c | 1 + drivers/input/rmi4/rmi_2d_sensor.c | 1 + drivers/input/rmi4/rmi_bus.c | 1 + drivers/input/rmi4/rmi_driver.c | 1 + drivers/input/serio/hil_mlc.c | 1 + drivers/input/serio/hp_sdc.c | 1 + drivers/input/serio/i8042.c | 1 + drivers/input/serio/libps2.c | 1 + drivers/input/serio/serio.c | 1 + drivers/input/sparse-keymap.c | 1 + drivers/input/touchscreen.c | 1 + drivers/input/touchscreen/ad7879.c | 1 + drivers/input/touchscreen/cyttsp_core.c | 1 + drivers/input/touchscreen/goodix_berlin_core.c | 1 + drivers/input/touchscreen/tsc200x-core.c | 1 + drivers/input/touchscreen/wm9705.c | 1 + drivers/input/touchscreen/wm9712.c | 1 + drivers/input/touchscreen/wm9713.c | 1 + drivers/input/touchscreen/wm97xx-core.c | 1 + 28 files changed, 28 insertions(+), 1 deletion(-)
drivers/input/ff-core.c +1 -1
@@ -8,9 +8,9 @@/* #define DEBUG */ +#include <linux/export.h> #include <linux/input.h> #include <linux/limits.h> -#include <linux/module.h> #include <linux/mutex.h> #include <linux/overflow.h> #include <linux/sched.h>
drivers/input/ff-memless.c +1 -0
@@ -10,6 +10,7 @@#define pr_fmt (fmt) KBUILD_MODNAME ": " fmt +#include <linux/export.h> #include <linux/slab.h> #include <linux/input.h> #include <linux/module.h>
drivers/input/gameport/gameport.c +1 -0
@@ -9,6 +9,7 @@#define pr_fmt (fmt) KBUILD_MODNAME ": " fmt +#include <linux/export.h> #include <linux/stddef.h> #include <linux/module.h> #include <linux/io.h>
drivers/input/input-poller.c +1 -0
@@ -4,6 +4,7 @@*/ #include <linux/device.h> +#include <linux/export.h> #include <linux/input.h> #include <linux/jiffies.h> #include <linux/mutex.h>
drivers/input/input.c +1 -0
@@ -8,6 +8,7 @@#define pr_fmt (fmt) KBUILD_BASENAME ": " fmt +#include <linux/export.h> #include <linux/init.h> #include <linux/types.h> #include <linux/idr.h>
drivers/input/joystick/iforce/iforce-main.c +1 -0
@@ -6,6 +6,7 @@* USB/RS232 I-Force joysticks and wheels. */ +#include <linux/export.h> #include <linux/unaligned.h> #include "iforce.h"
drivers/input/joystick/iforce/iforce-packets.c +1 -0
@@ -6,6 +6,7 @@* USB/RS232 I-Force joysticks and wheels. */ +#include <linux/export.h> #include <linux/unaligned.h> #include "iforce.h"
drivers/input/misc/ad714x.c +1 -0
@@ -6,6 +6,7 @@*/ #include <linux/device.h> +#include <linux/export.h> #include <linux/input.h> #include <linux/interrupt.h> #include <linux/slab.h>
drivers/input/misc/adxl34x.c +1 -0
@@ -9,6 +9,7 @@#include <linux/device.h> #include <linux/delay.h> +#include <linux/export.h> #include <linux/input.h> #include <linux/interrupt.h> #include <linux/irq.h>
drivers/input/misc/cma3000_d0x.c +1 -0
@@ -6,6 +6,7 @@* Author: Hemanth V <[email protected]> */ +#include <linux/export.h> #include <linux/types.h> #include <linux/interrupt.h> #include <linux/delay.h>
drivers/input/rmi4/rmi_2d_sensor.c +1 -0
@@ -4,6 +4,7 @@* Copyright (c) 2011 Unixphere */ +#include <linux/export.h> #include <linux/kernel.h> #include <linux/device.h> #include <linux/of.h>
drivers/input/rmi4/rmi_bus.c +1 -0
@@ -4,6 +4,7 @@* Copyright (c) 2011 Unixphere */ +#include <linux/export.h> #include <linux/kernel.h> #include <linux/device.h> #include <linux/irq.h>
drivers/input/rmi4/rmi_driver.c +1 -0
@@ -21,6 +21,7 @@#include <linux/irqdomain.h> #include <uapi/linux/input.h> #include <linux/rmi.h> +#include <linux/export.h> #include "rmi_bus.h" #include "rmi_driver.h"
drivers/input/serio/hil_mlc.c +1 -0
@@ -54,6 +54,7 @@#include <linux/hil_mlc.h> #include <linux/errno.h> +#include <linux/export.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h>
drivers/input/serio/hp_sdc.c +1 -0
@@ -63,6 +63,7 @@#include <linux/hp_sdc.h> #include <linux/errno.h> +#include <linux/export.h> #include <linux/init.h> #include <linux/module.h> #include <linux/ioport.h>
drivers/input/serio/i8042.c +1 -0
@@ -10,6 +10,7 @@#include <linux/types.h> #include <linux/delay.h> +#include <linux/export.h> #include <linux/module.h> #include <linux/interrupt.h> #include <linux/ioport.h>
drivers/input/serio/libps2.c +1 -0
@@ -8,6 +8,7 @@#include <linux/delay.h> +#include <linux/export.h> #include <linux/module.h> #include <linux/sched.h> #include <linux/interrupt.h>
drivers/input/serio/serio.c +1 -0
@@ -9,6 +9,7 @@#define pr_fmt (fmt) KBUILD_MODNAME ": " fmt +#include <linux/export.h> #include <linux/stddef.h> #include <linux/module.h> #include <linux/serio.h>
drivers/input/sparse-keymap.c +1 -0
@@ -10,6 +10,7 @@* Copyright (C) 2005 Dmitry Torokhov <[email protected]> */ +#include <linux/export.h> #include <linux/input.h> #include <linux/input/sparse-keymap.h> #include <linux/module.h>
drivers/input/touchscreen.c +1 -0
@@ -6,6 +6,7 @@* Copyright (c) 2014 Sebastian Reichel <[email protected]> */ +#include <linux/export.h> #include <linux/property.h> #include <linux/input.h> #include <linux/input/mt.h>
drivers/input/touchscreen/ad7879.c +1 -0
@@ -22,6 +22,7 @@#include <linux/device.h> #include <linux/delay.h> +#include <linux/export.h> #include <linux/input.h> #include <linux/interrupt.h> #include <linux/irq.h>
drivers/input/touchscreen/cyttsp_core.c +1 -0
@@ -14,6 +14,7 @@*/ #include <linux/delay.h> +#include <linux/export.h> #include <linux/input.h> #include <linux/input/mt.h> #include <linux/input/touchscreen.h>
drivers/input/touchscreen/goodix_berlin_core.c +1 -0
@@ -24,6 +24,7 @@*/ #include <linux/bitfield.h> +#include <linux/export.h> #include <linux/gpio/consumer.h> #include <linux/input.h> #include <linux/input/mt.h>
drivers/input/touchscreen/tsc200x-core.c +1 -0
@@ -10,6 +10,7 @@* based on TSC2301 driver by Klaus K. Pedersen <[email protected]> */ +#include <linux/export.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/input.h>
drivers/input/touchscreen/wm9705.c +1 -0
@@ -9,6 +9,7 @@* Russell King <[email protected]> */ +#include <linux/export.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h>
drivers/input/touchscreen/wm9712.c +1 -0
@@ -9,6 +9,7 @@* Russell King <[email protected]> */ +#include <linux/export.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h>
drivers/input/touchscreen/wm9713.c +1 -0
@@ -9,6 +9,7 @@* Russell King <[email protected]> */ +#include <linux/export.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h>
drivers/input/touchscreen/wm97xx-core.c +1 -0
@@ -29,6 +29,7 @@* - Support for async sampling control for noisy LCDs. */ +#include <linux/export.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h>
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 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
@@ -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;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]; - - ++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