[PATCH v3 1/2] Input: synaptics-rmi4 - fix irq[] overrun with 7 interrupt sources
Wei Jie LAW <[email protected]>
| Newsgroups | org.kernel.vger.stable,org.kernel.vger.linux-input,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
From: Wei Jie Law <[email protected]> rmi_read_pdt_entry() takes the interrupt source count straight out of the Page Description Table entry the device supplies: entry->interrupt_source_count = buf[4] & RMI_PDT_INT_SOURCE_COUNT_MASK; RMI_PDT_INT_SOURCE_COUNT_MASK is 0x07, so the value can be 7, and rmi_create_function() copies it verbatim into fn->num_of_irqs. But struct rmi_function declares int irq[RMI_FN_MAX_IRQS]; with RMI_FN_MAX_IRQS == 6, and both rmi_create_function_irq() and rmi_unregister_function() index that array up to fn->num_of_irqs. A device declaring 7 interrupt sources for a function that has a handler -- F01 always does -- makes the driver write irq[6], which is the storage of the following member, unsigned int irq_pos. The function's position in the interrupt bitmap then holds a Linux virq number, and that value feeds set_bit(fn->irq_pos, ...) in rmi_f11_probe()/rmi_f12_probe() and the irq_dispose_mapping() loop on teardown. UBSAN reports every store in the loop body and the read on the unregister path: UBSAN: array-index-out-of-bounds in drivers/input/rmi4/rmi_bus.c:183:10 index 6 is out of range for type 'int [6]' Workqueue: events uhid_device_add_worker dump_stack_lvl+0x64/0x80 __ubsan_handle_out_of_bounds+0xc8/0x100 rmi_function_probe+0x1c1/0x210 [rmi_core] UBSAN: array-index-out-of-bounds in drivers/input/rmi4/rmi_bus.c:186:28 UBSAN: array-index-out-of-bounds in drivers/input/rmi4/rmi_bus.c:187:35 UBSAN: array-index-out-of-bounds in drivers/input/rmi4/rmi_bus.c:189:32 UBSAN: array-index-out-of-bounds in drivers/input/rmi4/rmi_bus.c:191:54 UBSAN: array-index-out-of-bounds in drivers/input/rmi4/rmi_bus.c:282:30 Size the array to match the three bit field that feeds it. Clamping num_of_irqs instead would silently drop an interrupt source a device is allowed to declare, and would desynchronise irq_pos for every function created after it. Reproduced with an emulated RMI4 device that publishes a single F01 PDT entry with interrupt_source_count = 7, driven over /dev/uhid and again over dummy_hcd plus raw-gadget, on v6.12.69 and v6.12.105 with CONFIG_UBSAN_BOUNDS=y. No reports after this change, and the same device now probes normally. Fixes: 24d28e4f1271 ("Input: synaptics-rmi4 - convert irq distribution to irq_domain") Cc: [email protected] Signed-off-by: Wei Jie Law <[email protected]> --- drivers/input/rmi4/rmi_bus.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/input/rmi4/rmi_bus.h b/drivers/input/rmi4/rmi_bus.h index 90122df21f74..faf2ebb00d52 100644 --- a/drivers/input/rmi4/rmi_bus.h +++ b/drivers/input/rmi4/rmi_bus.h @@ -12,10 +12,13 @@ struct rmi_device; /* - * The interrupt source count in the function descriptor can represent up to - * 6 interrupt sources in the normal manner. + * The interrupt source count in the function descriptor is a three bit field + * (RMI_PDT_INT_SOURCE_COUNT_MASK), so a device can legitimately declare up to + * 7 interrupt sources for a single function. irq[] must be able to hold all + * of them: rmi_create_function_irq() and rmi_unregister_function() both walk + * it up to fn->num_of_irqs. */ -#define RMI_FN_MAX_IRQS 6 +#define RMI_FN_MAX_IRQS 7 /** * struct rmi_function - represents the implementation of an RMI4 -- 2.43.0