Skip to content

Commit 431ad23

Browse files
bryamzxzgregkh
authored andcommitted
Input: touchwin - reset the packet index on every complete packet
commit 478cdd7 upstream. tw_interrupt() accumulates each non-zero serial byte into a fixed three-byte buffer with a running index that is only reset once a full packet has been received *and* the device's two Y bytes agree: tw->data[tw->idx++] = data; if (tw->idx == TW_LENGTH && tw->data[1] == tw->data[2]) { ... tw->idx = 0; } The reset is gated on tw->data[1] == tw->data[2], a value the device controls. A malicious, malfunctioning or counterfeit Touchwindow peripheral can stream non-zero bytes whose 2nd and 3rd bytes differ: the index reaches TW_LENGTH without the equality holding, is never reset, and keeps growing, so tw->data[tw->idx++] walks off the end of the three-byte array and the rest of the heap-allocated struct tw, one attacker-chosen byte at a time -- an unbounded, device-driven heap out-of-bounds write. Reset the index on every completed packet and report an event only when the two Y bytes match, like the other serio touchscreen drivers do. Fixes: 11ea317 ("Input: add driver for Touchwin serial touchscreens") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Link: https://patch.msgid.link/20260613-b4-disp-69921bfd-v1-1-82c036899959@proton.me Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 1126668 commit 431ad23

1 file changed

Lines changed: 9 additions & 6 deletions

File tree

drivers/input/touchscreen/touchwin.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,15 @@ static irqreturn_t tw_interrupt(struct serio *serio,
6363
if (data) { /* touch */
6464
tw->touched = 1;
6565
tw->data[tw->idx++] = data;
66-
/* verify length and that the two Y's are the same */
67-
if (tw->idx == TW_LENGTH && tw->data[1] == tw->data[2]) {
68-
input_report_abs(dev, ABS_X, tw->data[0]);
69-
input_report_abs(dev, ABS_Y, tw->data[1]);
70-
input_report_key(dev, BTN_TOUCH, 1);
71-
input_sync(dev);
66+
/* a full packet ends the accumulation, valid or not */
67+
if (tw->idx == TW_LENGTH) {
68+
/* report only if the two Y's are the same */
69+
if (tw->data[1] == tw->data[2]) {
70+
input_report_abs(dev, ABS_X, tw->data[0]);
71+
input_report_abs(dev, ABS_Y, tw->data[1]);
72+
input_report_key(dev, BTN_TOUCH, 1);
73+
input_sync(dev);
74+
}
7275
tw->idx = 0;
7376
}
7477
} else if (tw->touched) { /* untouch */

0 commit comments

Comments
 (0)