* [PATCH 1/3] Input: mms114 - fix multi-touch slot corruption
@ 2026-07-04 6:01 Dmitry Torokhov
2026-07-04 6:01 ` [PATCH 2/3] Input: mms114 - fix endianness portability in I2C packet layout Dmitry Torokhov
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Dmitry Torokhov @ 2026-07-04 6:01 UTC (permalink / raw)
To: linux-input
Cc: Bryam Vargas, Linus Walleij, linux-kernel, stable, sashiko-bot
If the touchscreen controller reports a touch ID of 0, the driver
calculates the slot ID as touch->id - 1, which underflows to UINT_MAX.
This is passed to input_mt_slot() as -1.
Since the input core ignores negative slot values, the active slot remains
unchanged. The driver then reports the touch coordinates for the previously
active slot, corrupting its state.
Fix this by rejecting touch reports with ID 0.
Fixes: 07b8481d4aff ("Input: add MELFAS mms114 touchscreen driver")
Cc: stable@vger.kernel.org
Reported-by: sashiko-bot@kernel.org
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/touchscreen/mms114.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
index 006dded17eb8..23e0283bc6b8 100644
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -248,7 +248,7 @@ static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *tou
unsigned int x;
unsigned int y;
- if (touch->id > MMS114_MAX_TOUCH) {
+ if (touch->id == 0 || touch->id > MMS114_MAX_TOUCH) {
dev_err(&client->dev, "Wrong touch id (%d)\n", touch->id);
return;
}
--
2.55.0.rc0.799.gd6f94ed593-goog
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 2/3] Input: mms114 - fix endianness portability in I2C packet layout 2026-07-04 6:01 [PATCH 1/3] Input: mms114 - fix multi-touch slot corruption Dmitry Torokhov @ 2026-07-04 6:01 ` Dmitry Torokhov 2026-07-04 6:12 ` sashiko-bot 2026-07-04 6:01 ` [PATCH 3/3] Input: mms114 - fix Y-resolution configuration Dmitry Torokhov 2026-07-04 6:11 ` [PATCH 1/3] Input: mms114 - fix multi-touch slot corruption sashiko-bot 2 siblings, 1 reply; 6+ messages in thread From: Dmitry Torokhov @ 2026-07-04 6:01 UTC (permalink / raw) To: linux-input; +Cc: Bryam Vargas, Linus Walleij, linux-kernel, sashiko-bot The driver defines the I2C packet layout using C bitfields in struct mms114_touch. This is not portable as the layout of bitfields within a byte is compiler-dependent and varies with endianness. On Big Endian systems, the fields will be parsed incorrectly. Fix this by redefining struct mms114_touch with plain u8 fields and introducing bitwise macros to extract the values portably. Reported-by: sashiko-bot@kernel.org Assisted-by: Antigravity:gemini-3.5-flash Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> --- drivers/input/touchscreen/mms114.c | 52 +++++++++++++++++++----------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c index 23e0283bc6b8..84afdadb3bcc 100644 --- a/drivers/input/touchscreen/mms114.c +++ b/drivers/input/touchscreen/mms114.c @@ -4,6 +4,8 @@ // Copyright (c) 2012 Samsung Electronics Co., Ltd. // Author: Joonyoung Shim <jy0922.shim@samsung.com> +#include <linux/bitfield.h> +#include <linux/bits.h> #include <linux/module.h> #include <linux/delay.h> #include <linux/of.h> @@ -76,9 +78,16 @@ struct mms_chip { int (*get_version)(struct mms114_data *data); }; +#define MMS114_FLAGS_ID_MASK GENMASK(3, 0) +#define MMS114_FLAGS_TYPE_MASK GENMASK(6, 5) +#define MMS114_FLAGS_PRESSED_MASK BIT(7) + +#define MMS114_XY_HI_X_MASK GENMASK(3, 0) +#define MMS114_XY_HI_Y_MASK GENMASK(7, 4) + struct mms114_touch { - u8 id:4, reserved_bit4:1, type:2, pressed:1; - u8 x_hi:4, y_hi:4; + u8 flags; + u8 xy_hi; u8 x_lo; u8 y_lo; u8 width; @@ -244,28 +253,30 @@ static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *tou { struct i2c_client *client = data->client; struct input_dev *input_dev = data->input_dev; - unsigned int id; + unsigned int id = FIELD_GET(MMS114_FLAGS_ID_MASK, touch->flags); + unsigned int type = FIELD_GET(MMS114_FLAGS_TYPE_MASK, touch->flags); + bool pressed = FIELD_GET(MMS114_FLAGS_PRESSED_MASK, touch->flags); unsigned int x; unsigned int y; - if (touch->id == 0 || touch->id > MMS114_MAX_TOUCH) { - dev_err(&client->dev, "Wrong touch id (%d)\n", touch->id); + if (id == 0 || id > MMS114_MAX_TOUCH) { + dev_err(&client->dev, "Wrong touch id (%d)\n", id); return; } - id = touch->id - 1; - x = touch->x_lo | touch->x_hi << 8; - y = touch->y_lo | touch->y_hi << 8; + id--; + x = touch->x_lo | FIELD_GET(MMS114_XY_HI_X_MASK, touch->xy_hi) << 8; + y = touch->y_lo | FIELD_GET(MMS114_XY_HI_Y_MASK, touch->xy_hi) << 8; dev_dbg(&client->dev, "id: %d, type: %d, pressed: %d, x: %d, y: %d, width: %d, strength: %d\n", - id, touch->type, touch->pressed, + id, type, pressed, x, y, touch->width, touch->strength); input_mt_slot(input_dev, id); - input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, touch->pressed); + input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, pressed); - if (touch->pressed) { + if (pressed) { touchscreen_report_pos(input_dev, &data->props, x, y, true); input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, touch->width); input_report_abs(input_dev, ABS_MT_PRESSURE, touch->strength); @@ -278,21 +289,23 @@ static void mms114_process_touchkey(struct mms114_data *data, struct i2c_client *client = data->client; struct input_dev *input_dev = data->input_dev; unsigned int keycode_id; + unsigned int id = FIELD_GET(MMS114_FLAGS_ID_MASK, touch->flags); + bool pressed = FIELD_GET(MMS114_FLAGS_PRESSED_MASK, touch->flags); - if (touch->id == 0) + if (id == 0) return; - if (touch->id > data->num_keycodes) { + if (id > data->num_keycodes) { dev_err(&client->dev, "Wrong touch id for touchkey (%d)\n", - touch->id); + id); return; } - keycode_id = touch->id - 1; + keycode_id = id - 1; dev_dbg(&client->dev, "keycode id: %d, pressed: %d\n", keycode_id, - touch->pressed); + pressed); - input_report_key(input_dev, data->keycodes[keycode_id], touch->pressed); + input_report_key(input_dev, data->keycodes[keycode_id], pressed); } static irqreturn_t mms114_interrupt(int irq, void *dev_id) @@ -325,8 +338,9 @@ static irqreturn_t mms114_interrupt(int irq, void *dev_id) for (index = 0; index < touch_size; index++) { t = (struct mms114_touch *)((u8 *)touch + index * event_size); + unsigned int type = FIELD_GET(MMS114_FLAGS_TYPE_MASK, t->flags); - switch (t->type) { + switch (type) { case MMS114_TYPE_TOUCHSCREEN: mms114_process_mt(data, t); break; @@ -337,7 +351,7 @@ static irqreturn_t mms114_interrupt(int irq, void *dev_id) default: dev_err(&client->dev, "Wrong touch type (%d)\n", - t->type); + type); break; } } -- 2.55.0.rc0.799.gd6f94ed593-goog ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 2/3] Input: mms114 - fix endianness portability in I2C packet layout 2026-07-04 6:01 ` [PATCH 2/3] Input: mms114 - fix endianness portability in I2C packet layout Dmitry Torokhov @ 2026-07-04 6:12 ` sashiko-bot 0 siblings, 0 replies; 6+ messages in thread From: sashiko-bot @ 2026-07-04 6:12 UTC (permalink / raw) To: Dmitry Torokhov; +Cc: linux-input, dmitry.torokhov Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: Pre-existing issues: - [High] Race condition in suspend causes stuck touches. - [High] Unsafe DMA buffer allocation (stack-allocated memory passed to I2C transfers). -- commit 2e96699ad380d6d47c8e998bc41268e9b77bac90 Author: Dmitry Torokhov <dmitry.torokhov@gmail.com> Input: mms114 - fix endianness portability in I2C packet layout The driver defines the I2C packet layout using C bitfields in struct mms114_touch. This is not portable as the layout of bitfields within a byte is compiler-dependent and varies with endianness. On Big Endian systems, the fields will be parsed incorrectly. > diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c > index 23e0283bc6b8b..84afdadb3bccc 100644 > --- a/drivers/input/touchscreen/mms114.c > +++ b/drivers/input/touchscreen/mms114.c [ ... ] > @@ -325,8 +338,9 @@ static irqreturn_t mms114_interrupt(int irq, void *dev_id) > > for (index = 0; index < touch_size; index++) { > t = (struct mms114_touch *)((u8 *)touch + index * event_size); [Severity: High] This isn't a bug introduced by this patch, but does passing stack-allocated buffers to I2C transfer functions risk memory corruption if the I2C adapter uses DMA? Since kernel stacks are often allocated in vmalloc space (when CONFIG_VMAP_STACK is enabled), they cannot be safely mapped for DMA. In mms114_interrupt(), the touch array is stack-allocated and used as a receive buffer: struct mms114_touch touch[MMS114_MAX_TOUCH]; // ... error = __mms114_read_reg(data, MMS114_INFORMATION, packet_size, touch); Similarly, __mms114_read_reg() and mms114_write_reg() pass local stack variables (u8 buf and u8 buf[2]) to I2C transfers. > + unsigned int type = FIELD_GET(MMS114_FLAGS_TYPE_MASK, t->flags); > > - switch (t->type) { > + switch (type) { > case MMS114_TYPE_TOUCHSCREEN: > mms114_process_mt(data, t); > break; [ ... ] [Severity: High] This is a pre-existing issue, but could the sequence in mms114_suspend() have a race condition that results in stuck touches? In mms114_suspend(), the driver injects artificial release events before disabling the IRQ: /* Release all touch */ for (id = 0; id < MMS114_MAX_TOUCH; id++) { input_mt_slot(input_dev, id); input_mt_report_slot_inactive(input_dev); } // ... input_sync(input_dev); guard(mutex)(&input_dev->mutex); if (input_device_enabled(input_dev)) mms114_stop(data); If a touch interrupt fires and its threaded handler (mms114_interrupt) executes after these release events are injected but before mms114_stop() disables the IRQ, might it report the touch as active again and leave it stuck indefinitely after suspend? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260704060115.353049-1-dmitry.torokhov@gmail.com?part=2 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 3/3] Input: mms114 - fix Y-resolution configuration 2026-07-04 6:01 [PATCH 1/3] Input: mms114 - fix multi-touch slot corruption Dmitry Torokhov 2026-07-04 6:01 ` [PATCH 2/3] Input: mms114 - fix endianness portability in I2C packet layout Dmitry Torokhov @ 2026-07-04 6:01 ` Dmitry Torokhov 2026-07-04 6:08 ` sashiko-bot 2026-07-04 6:11 ` [PATCH 1/3] Input: mms114 - fix multi-touch slot corruption sashiko-bot 2 siblings, 1 reply; 6+ messages in thread From: Dmitry Torokhov @ 2026-07-04 6:01 UTC (permalink / raw) To: linux-input; +Cc: Bryam Vargas, Linus Walleij, linux-kernel In mms114_setup_regs(), the driver mistakenly uses props->max_x instead of props->max_y when configuring the low bits of the Y resolution (MMS114_Y_RESOLUTION). Fix this by using the correct property. Fixes: 07b8481d4aff ("Input: add MELFAS mms114 touchscreen driver") Assisted-by: Antigravity:gemini-3.5-flash Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> --- drivers/input/touchscreen/mms114.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c index 84afdadb3bcc..27911a9f4e9e 100644 --- a/drivers/input/touchscreen/mms114.c +++ b/drivers/input/touchscreen/mms114.c @@ -408,7 +408,7 @@ static int mms114_setup_regs(struct mms114_data *data) if (error < 0) return error; - val = props->max_x & 0xff; + val = props->max_y & 0xff; error = mms114_write_reg(data, MMS114_Y_RESOLUTION, val); if (error < 0) return error; -- 2.55.0.rc0.799.gd6f94ed593-goog ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 3/3] Input: mms114 - fix Y-resolution configuration 2026-07-04 6:01 ` [PATCH 3/3] Input: mms114 - fix Y-resolution configuration Dmitry Torokhov @ 2026-07-04 6:08 ` sashiko-bot 0 siblings, 0 replies; 6+ messages in thread From: sashiko-bot @ 2026-07-04 6:08 UTC (permalink / raw) To: Dmitry Torokhov; +Cc: linux-input, dmitry.torokhov Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: Pre-existing issues: - [High] Unsafe DMA buffer allocation on the stack for I2C transfers. -- commit b2ece0d05aab20ebd4014035e04b87c4d9127c9f Author: Dmitry Torokhov <dmitry.torokhov@gmail.com> Subject: Input: mms114 - fix Y-resolution configuration This commit fixes a copy-paste error in mms114_setup_regs() where props->max_x was being used instead of props->max_y to configure the lower bits of the Y resolution. > diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c > index 84afdadb3bccc..27911a9f4e9eb 100644 > --- a/drivers/input/touchscreen/mms114.c > +++ b/drivers/input/touchscreen/mms114.c > @@ -408,7 +408,7 @@ static int mms114_setup_regs(struct mms114_data *data) > if (error < 0) > return error; > > - val = props->max_x & 0xff; > + val = props->max_y & 0xff; > error = mms114_write_reg(data, MMS114_Y_RESOLUTION, val); [Severity: High] This is a pre-existing issue, but since mms114_write_reg() is called here, is it safe for the driver to use stack-allocated buffers for I2C transfers? Looking at mms114_write_reg(): static int mms114_write_reg(struct mms114_data *data, u8 reg, u8 val) { struct i2c_client *client = data->client; u8 buf[2]; ... buf[0] = reg; buf[1] = val; error = i2c_master_send(client, buf, 2); If the underlying I2C adapter uses DMA for transfers and CONFIG_VMAP_STACK is enabled, passing a stack-allocated buffer to i2c_master_send() can cause memory corruption or kernel panics because stack memory is not DMA-safe. A similar pattern appears in __mms114_read_reg() and mms114_interrupt(): static int __mms114_read_reg(struct mms114_data *data, unsigned int reg, ...) { ... u8 buf = reg; ... xfer[0].buf = &buf; ... error = i2c_transfer(client->adapter, xfer, 2); and in mms114_interrupt(), a large array is allocated on the stack and passed down through __mms114_read_reg(): struct mms114_touch touch[MMS114_MAX_TOUCH]; ... error = __mms114_read_reg(data, MMS114_INFORMATION, MMS114_MAX_TOUCH * sizeof(struct mms114_touch), (u8 *)touch); Could these stack-allocated buffers lead to instability on DMA-capable I2C controllers? Should these buffers be moved to the mms114_data struct so they are dynamically allocated on the heap? > if (error < 0) > return error; -- Sashiko AI review · https://sashiko.dev/#/patchset/20260704060115.353049-1-dmitry.torokhov@gmail.com?part=3 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/3] Input: mms114 - fix multi-touch slot corruption 2026-07-04 6:01 [PATCH 1/3] Input: mms114 - fix multi-touch slot corruption Dmitry Torokhov 2026-07-04 6:01 ` [PATCH 2/3] Input: mms114 - fix endianness portability in I2C packet layout Dmitry Torokhov 2026-07-04 6:01 ` [PATCH 3/3] Input: mms114 - fix Y-resolution configuration Dmitry Torokhov @ 2026-07-04 6:11 ` sashiko-bot 2 siblings, 0 replies; 6+ messages in thread From: sashiko-bot @ 2026-07-04 6:11 UTC (permalink / raw) To: Dmitry Torokhov; +Cc: dmitry.torokhov, linux-input Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider: Pre-existing issues: - [High] If `mms114_start()` fails during system resume, subsequent device close or suspend causes unbalanced `disable_irq()` and `regulator_disable()` calls, leaving the touchscreen permanently broken. - [High] The suspend callback releases all touches before disabling the device interrupt, creating a race window where touches can get permanently stuck. - [High] Stack-allocated buffers are passed directly to I2C transfer functions, which can cause DMA mapping failures or memory corruption. -- commit 6a55987ddd51d1330fd1636cd3e72b4d910ea42b Author: Dmitry Torokhov <dmitry.torokhov@gmail.com> Input: mms114 - fix multi-touch slot corruption This commit fixes a multi-touch slot corruption bug in the mms114 driver. When the touchscreen controller reports a touch ID of 0, the driver calculates the slot ID as touch->id - 1, which underflows to UINT_MAX. The driver fixes this by rejecting touch reports with ID 0. > diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c > index 006dded17eb80..23e0283bc6b8b 100644 > --- a/drivers/input/touchscreen/mms114.c > +++ b/drivers/input/touchscreen/mms114.c > @@ -248,7 +248,7 @@ static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *tou > unsigned int x; > unsigned int y; > > - if (touch->id > MMS114_MAX_TOUCH) { > + if (touch->id == 0 || touch->id > MMS114_MAX_TOUCH) { > dev_err(&client->dev, "Wrong touch id (%d)\n", touch->id); > return; > } [Severity: High] This isn't a bug introduced by this patch, but I have a question about the error handling in mms114_resume(). If mms114_start() fails (e.g. mms114_setup_regs() returns an error) it cleans up the regulators but doesn't call enable_irq(): static int mms114_start(struct mms114_data *data) { ... error = mms114_setup_regs(data); if (error < 0) { regulator_disable(data->io_reg); regulator_disable(data->core_reg); return error; } enable_irq(client->irq); return 0; } In mms114_resume(), the error is passed back up but the input device remains logically open: static int mms114_resume(struct device *dev) { ... if (input_device_enabled(input_dev)) { error = mms114_start(data); if (error) return error; } ... } Because the input device is still logically enabled, won't a subsequent suspend or input_close call mms114_stop(), which unconditionally calls disable_irq() and regulator_disable()? Does this cause an unbalanced IRQ disable depth that permanently masks the interrupt? [Severity: High] This is a pre-existing issue, but I noticed a potential race condition in mms114_suspend(). The suspend callback releases all active touch slots before stopping the device and disabling the interrupt: static int mms114_suspend(struct device *dev) { ... /* Release all touch */ for (id = 0; id < MMS114_MAX_TOUCH; id++) { input_mt_slot(input_dev, id); input_mt_report_slot_inactive(input_dev); } input_mt_report_pointer_emulation(input_dev, true); input_sync(input_dev); guard(mutex)(&input_dev->mutex); if (input_device_enabled(input_dev)) mms114_stop(data); ... } If a touch interrupt fires between the synthetic slot release and the call to mms114_stop() (which disables the IRQ), could the physical touches be reported as active again just as the device is suspended, leaving the touches permanently stuck on resume? [Severity: High] This isn't a bug introduced by this patch, but there seem to be multiple places where stack-allocated buffers are used for I2C transfers. For example, in __mms114_read_reg(), a single byte stack variable is passed: static int __mms114_read_reg(struct mms114_data *data, u8 reg, unsigned int len, void *val) { ... u8 buf = reg; ... xfer[0].buf = &buf; ... error = i2c_transfer(client->adapter, xfer, 2); ... } Similarly in mms114_write_reg(): static int mms114_write_reg(struct mms114_data *data, u8 reg, u8 val) { ... u8 buf[2]; buf[0] = reg; buf[1] = val; error = i2c_master_send(client, buf, 2); ... } And in mms114_interrupt(): struct mms114_touch touch[MMS114_MAX_TOUCH]; ... error = __mms114_read_reg(data, MMS114_INFORMATION, packet_size, touch); ... Since many I2C controllers use DMA, doesn't passing stack memory to i2c_transfer() risk DMA mapping failures or memory corruption when CONFIG_VMAP_STACK is enabled? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260704060115.353049-1-dmitry.torokhov@gmail.com?part=1 ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-07-04 6:12 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-07-04 6:01 [PATCH 1/3] Input: mms114 - fix multi-touch slot corruption Dmitry Torokhov 2026-07-04 6:01 ` [PATCH 2/3] Input: mms114 - fix endianness portability in I2C packet layout Dmitry Torokhov 2026-07-04 6:12 ` sashiko-bot 2026-07-04 6:01 ` [PATCH 3/3] Input: mms114 - fix Y-resolution configuration Dmitry Torokhov 2026-07-04 6:08 ` sashiko-bot 2026-07-04 6:11 ` [PATCH 1/3] Input: mms114 - fix multi-touch slot corruption sashiko-bot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox