nslots is derived from the ABS_MT_SLOT maximum reported by the virtio device. A device could report a bogus maximum (e.g. -1) making nslots <= 0, and input_mt_init_slots() can independently fail too (e.g. it rejects slot counts over 1024). Neither case was handled here, and input_mt_init_slots() failing took down the whole probe, losing the rest of the input device over a problem isolated to multitouch.
Instead of failing the probe, warn and disable the ABS_MT_SLOT capability in either case, and let the rest of the device register normally. This recovery assumes input_mt_init_slots() is called with flags == 0: with nonzero flags it can fail after already mutating the input_dev (e.g. via input_set_abs_params()), which this recovery does not account for. Signed-off-by: Hari Mishal <[email protected]> --- v2: per review, disable multitouch instead of failing the whole probe when the reported slot count is invalid or input_mt_init_slots() otherwise fails. drivers/virtio/virtio_input.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/virtio/virtio_input.c b/drivers/virtio/virtio_input.c index deec24e8e682..786f5150724f 100644 --- a/drivers/virtio/virtio_input.c +++ b/drivers/virtio/virtio_input.c @@ -312,9 +312,25 @@ static int virtinput_probe(struct virtio_device *vdev) if (test_bit(ABS_MT_SLOT, vi->idev->absbit)) { nslots = input_abs_get_max(vi->idev, ABS_MT_SLOT) + 1; - err = input_mt_init_slots(vi->idev, nslots, 0); - if (err) - goto err_mt_init_slots; + if (nslots <= 0) { + dev_warn(&vdev->dev, + "invalid multitouch slot count %d, disabling multitouch\n", + nslots); + __clear_bit(ABS_MT_SLOT, vi->idev->absbit); + } else { + /* + * flags is 0: input_mt_init_slots() can only fail + * before touching *idev, so the recovery below is + * a full rollback. + */ + err = input_mt_init_slots(vi->idev, nslots, 0); + if (err) { + dev_warn(&vdev->dev, + "failed to init %d multitouch slots (%d), disabling multitouch\n", + nslots, err); + __clear_bit(ABS_MT_SLOT, vi->idev->absbit); + } + } } } @@ -331,7 +347,6 @@ static int virtinput_probe(struct virtio_device *vdev) spin_lock_irqsave(&vi->lock, flags); vi->ready = false; spin_unlock_irqrestore(&vi->lock, flags); -err_mt_init_slots: input_free_device(vi->idev); err_input_alloc: vdev->config->del_vqs(vdev); -- 2.43.0

