input: touchscreen: fts: fix to use touch_id with proper event_id only
authorSeung-Woo Kim <sw0312.kim@samsung.com>
Tue, 31 May 2016 08:29:39 +0000 (17:29 +0900)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Wed, 1 Jun 2016 02:28:00 +0000 (11:28 +0900)
From event handler, touch_id is used as index of array, but in can
be larger than array size, and it causes out of range access for
array. From event data of the fts hw, finger touch_id is only valid
when event_id is enter/leave/motion pointer event. So this patch
fixes to use touch_id as a array index only when the proper event_id
is received.

This issue is found by ubsan checker like following:

   ================================================================================
   UBSAN: Undefined behaviour in drivers/input/touchscreen/fts_ts.c:342:15
   index 13 is out of range for type 'fts_finger [10]'
   CPU: 1 PID: 98 Comm: irq/150-fts_tou Not tainted 4.1.0-01159-gfb62846 #17
   Hardware name: Samsung TM2 board (DT)
   Call trace:
   [<ffffffc00008f440>] dump_backtrace+0x0/0x218
   [<ffffffc00008f668>] show_stack+0x10/0x20
   [<ffffffc00159f378>] dump_stack+0x80/0xfc
   [<ffffffc00159f518>] ubsan_epilogue+0x10/0x6c
   [<ffffffc00159fef4>] __ubsan_handle_out_of_bounds+0xc8/0xf4
   [<ffffffc000ceb980>] fts_interrupt_handler+0x570/0x678
   [<ffffffc000165a98>] irq_thread+0x218/0x378
   [<ffffffc0000ee30c>] kthread+0x194/0x240
   ================================================================================

Change-Id: I3b2195ee0eee39b16cd05552c19c26072706125d
Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
drivers/input/touchscreen/fts_ts.c

index b843a150ae85636f5f2e0de60caa3785753dd91a..6753b8930baf3b538d3a6f93a91d24b939a603b0 100644 (file)
@@ -339,7 +339,10 @@ static unsigned char fts_event_handler_type_b(struct fts_ts_info *info,
                } else if (event_id == EVENTID_MOTION_POINTER)
                        info->finger[touch_id].mcount++;
 
-               info->finger[touch_id].state = event_id;
+               if ((event_id == EVENTID_ENTER_POINTER) ||
+                               (event_id == EVENTID_LEAVE_POINTER) ||
+                               (event_id == EVENTID_MOTION_POINTER))
+                       info->finger[touch_id].state = event_id;
        }
 
        input_sync(info->input_dev);