wacom_penpartner_irq(), wacom_pl_irq(), wacom_ptu_irq(), wacom_dtu_irq(), wacom_dtus_irq() and wacom_graphire_irq() dereference pen_input and, for the latter two, pad_input without checking them. As described in "HID: wacom: check the input device in the shared report helpers", a partial interface leaves one or two of the three input devices NULL on a fully successful probe, and wacom_wac_irq() still dispatches to these handlers. Seven locations fault, each reproduced on linux-next 20260925 (x86_64, KASAN) from one /dev/uhid device plus a single UHID_INPUT2 write. For wacom_dtus_irq() and wacom_graphire_irq(), all hardware served by these handlers is expected to have both pen and pad on a single interface (the one exception is GRAPHIRE, which is pen-only). Rather than scattering checks per branch, validate the expected input devices at function entry and bail out early if any are missing. wacom_dtu_irq() gets a check too. Its only dereference is in a dev_dbg(), so it does not fault with CONFIG_DYNAMIC_DEBUG=n, but it is unconditional in the source. Fixes: 2a6cdbdd4cc0 ("HID: wacom: Introduce new 'touch_input' device") Fixes: 862cf5535c0c ("HID: wacom: Introduce a new WACOM_DEVICETYPE_PAD device_type") Cc: stable@vger.kernel.org Signed-off-by: Jinmo Yang --- drivers/hid/wacom_wac.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 567b01882eb1..aa08afb3c5ef 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -128,6 +128,12 @@ static int wacom_penpartner_irq(struct wacom_wac *wacom) unsigned char *data = wacom->data; struct input_dev *input = wacom->pen_input; + if (!input) { + dev_warn_once(&container_of(wacom, struct wacom, wacom_wac)->hdev->dev, + "%s: pen_input is NULL\n", __func__); + return 0; + } + switch (data[0]) { case 1: if (data[5] & 0x80) { @@ -174,6 +180,12 @@ static int wacom_pl_irq(struct wacom_wac *wacom) struct input_dev *input = wacom->pen_input; int prox, pressure; + if (!input) { + dev_warn_once(&container_of(wacom, struct wacom, wacom_wac)->hdev->dev, + "%s: pen_input is NULL\n", __func__); + return 0; + } + if (data[0] != WACOM_REPORT_PENABLED) { dev_dbg(input->dev.parent, "%s: received unknown report #%d\n", __func__, data[0]); @@ -233,6 +245,12 @@ static int wacom_ptu_irq(struct wacom_wac *wacom) unsigned char *data = wacom->data; struct input_dev *input = wacom->pen_input; + if (!input) { + dev_warn_once(&container_of(wacom, struct wacom, wacom_wac)->hdev->dev, + "%s: pen_input is NULL\n", __func__); + return 0; + } + if (data[0] != WACOM_REPORT_PENABLED) { dev_dbg(input->dev.parent, "%s: received unknown report #%d\n", __func__, data[0]); @@ -263,6 +281,12 @@ static int wacom_dtu_irq(struct wacom_wac *wacom) struct input_dev *input = wacom->pen_input; int prox = data[1] & 0x20; + if (!input) { + dev_warn_once(&container_of(wacom, struct wacom, wacom_wac)->hdev->dev, + "%s: pen_input is NULL\n", __func__); + return 0; + } + dev_dbg(input->dev.parent, "%s: received report #%d", __func__, data[0]); @@ -293,6 +317,13 @@ static int wacom_dtus_irq(struct wacom_wac *wacom) struct input_dev *input = wacom->pen_input; unsigned short prox, pressure = 0; + if (!input || !wacom->pad_input) { + dev_warn_once(&container_of(wacom, struct wacom, wacom_wac)->hdev->dev, + "%s: expected pen and pad input devices\n", + __func__); + return 0; + } + if (data[0] != WACOM_REPORT_DTUS && data[0] != WACOM_REPORT_DTUSPAD) { dev_dbg(input->dev.parent, "%s: received unknown report #%d", __func__, data[0]); @@ -349,6 +380,12 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) int rw = 0; int retval = 0; + if (!input || (!pad_input && features->type != GRAPHIRE)) { + dev_warn_once(&container_of(wacom, struct wacom, wacom_wac)->hdev->dev, + "%s: missing input device(s)\n", __func__); + return 0; + } + if (features->type == GRAPHIRE_BT) { if (data[0] != WACOM_REPORT_PENABLED_BT) { dev_dbg(input->dev.parent, -- 2.53.0