| From 2ac97f0f6654da14312d125005c77a6010e0ea38 Mon Sep 17 00:00:00 2001 |
| From: Jason Gerecke <killertofu@gmail.com> |
| Date: Tue, 25 Apr 2017 11:29:56 -0700 |
| Subject: HID: wacom: Have wacom_tpc_irq guard against possible NULL dereference |
| |
| From: Jason Gerecke <killertofu@gmail.com> |
| |
| commit 2ac97f0f6654da14312d125005c77a6010e0ea38 upstream. |
| |
| The following Smatch complaint was generated in response to commit |
| 2a6cdbd ("HID: wacom: Introduce new 'touch_input' device"): |
| |
| drivers/hid/wacom_wac.c:1586 wacom_tpc_irq() |
| error: we previously assumed 'wacom->touch_input' could be null (see line 1577) |
| |
| The 'touch_input' and 'pen_input' variables point to the 'struct input_dev' |
| used for relaying touch and pen events to userspace, respectively. If a |
| device does not have a touch interface or pen interface, the associated |
| input variable is NULL. The 'wacom_tpc_irq()' function is responsible for |
| forwarding input reports to a more-specific IRQ handler function. An |
| unknown report could theoretically be mistaken as e.g. a touch report |
| on a device which does not have a touch interface. This can be prevented |
| by only calling the pen/touch functions are called when the pen/touch |
| pointers are valid. |
| |
| Fixes: 2a6cdbd ("HID: wacom: Introduce new 'touch_input' device") |
| Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com> |
| Reviewed-by: Ping Cheng <ping.cheng@wacom.com> |
| Signed-off-by: Jiri Kosina <jkosina@suse.cz> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/hid/wacom_wac.c | 47 ++++++++++++++++++++++++----------------------- |
| 1 file changed, 24 insertions(+), 23 deletions(-) |
| |
| --- a/drivers/hid/wacom_wac.c |
| +++ b/drivers/hid/wacom_wac.c |
| @@ -1400,37 +1400,38 @@ static int wacom_tpc_irq(struct wacom_wa |
| { |
| unsigned char *data = wacom->data; |
| |
| - if (wacom->pen_input) |
| + if (wacom->pen_input) { |
| dev_dbg(wacom->pen_input->dev.parent, |
| "%s: received report #%d\n", __func__, data[0]); |
| - else if (wacom->touch_input) |
| + |
| + if (len == WACOM_PKGLEN_PENABLED || |
| + data[0] == WACOM_REPORT_PENABLED) |
| + return wacom_tpc_pen(wacom); |
| + } |
| + else if (wacom->touch_input) { |
| dev_dbg(wacom->touch_input->dev.parent, |
| "%s: received report #%d\n", __func__, data[0]); |
| |
| - switch (len) { |
| - case WACOM_PKGLEN_TPC1FG: |
| - return wacom_tpc_single_touch(wacom, len); |
| - |
| - case WACOM_PKGLEN_TPC2FG: |
| - return wacom_tpc_mt_touch(wacom); |
| - |
| - case WACOM_PKGLEN_PENABLED: |
| - return wacom_tpc_pen(wacom); |
| - |
| - default: |
| - switch (data[0]) { |
| - case WACOM_REPORT_TPC1FG: |
| - case WACOM_REPORT_TPCHID: |
| - case WACOM_REPORT_TPCST: |
| - case WACOM_REPORT_TPC1FGE: |
| + switch (len) { |
| + case WACOM_PKGLEN_TPC1FG: |
| return wacom_tpc_single_touch(wacom, len); |
| |
| - case WACOM_REPORT_TPCMT: |
| - case WACOM_REPORT_TPCMT2: |
| - return wacom_mt_touch(wacom); |
| + case WACOM_PKGLEN_TPC2FG: |
| + return wacom_tpc_mt_touch(wacom); |
| |
| - case WACOM_REPORT_PENABLED: |
| - return wacom_tpc_pen(wacom); |
| + default: |
| + switch (data[0]) { |
| + case WACOM_REPORT_TPC1FG: |
| + case WACOM_REPORT_TPCHID: |
| + case WACOM_REPORT_TPCST: |
| + case WACOM_REPORT_TPC1FGE: |
| + return wacom_tpc_single_touch(wacom, len); |
| + |
| + case WACOM_REPORT_TPCMT: |
| + case WACOM_REPORT_TPCMT2: |
| + return wacom_mt_touch(wacom); |
| + |
| + } |
| } |
| } |
| |