media: streamzap: prevent processing IR data on URB failure

commit 549f6d348167fb2f7800ed7c8d4bce9630c74498 upstream.

If streamzap_callback() receives an urb with any non-critical error
status, i.e. any error code other than -ECONNRESET, -ENOENT or -ESHUTDOWN,
it will try to process IR data, ignoring a possible transfer failure.

Make streamzap_callback() process IR data only when urb->status is 0.
Move processing logic to a separate function to make code cleaner and
more similar to the URB completion handlers in other RC drivers.

Found by Linux Verification Center (linuxtesting.org) with Syzkaller.

Fixes: 19770693c3 ("V4L/DVB: staging/lirc: add lirc_streamzap driver")
Cc: stable@vger.kernel.org
Signed-off-by: Murad Masimov <m.masimov@mt-integration.ru>
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Murad Masimov
2025-01-13 13:51:31 +03:00
committed by Greg Kroah-Hartman
parent 3fcff11317
commit 3eaf580cba

View File

@@ -138,39 +138,10 @@ static void sz_push_half_space(struct streamzap_ir *sz,
sz_push_full_space(sz, value & SZ_SPACE_MASK);
}
/*
* streamzap_callback - usb IRQ handler callback
*
* This procedure is invoked on reception of data from
* the usb remote.
*/
static void streamzap_callback(struct urb *urb)
static void sz_process_ir_data(struct streamzap_ir *sz, int len)
{
struct streamzap_ir *sz;
unsigned int i;
int len;
if (!urb)
return;
sz = urb->context;
len = urb->actual_length;
switch (urb->status) {
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
/*
* this urb is terminated, clean up.
* sz might already be invalid at this point
*/
dev_err(sz->dev, "urb terminated, status: %d\n", urb->status);
return;
default:
break;
}
dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
for (i = 0; i < len; i++) {
dev_dbg(sz->dev, "sz->buf_in[%d]: %x\n",
i, (unsigned char)sz->buf_in[i]);
@@ -219,6 +190,43 @@ static void streamzap_callback(struct urb *urb)
}
ir_raw_event_handle(sz->rdev);
}
/*
* streamzap_callback - usb IRQ handler callback
*
* This procedure is invoked on reception of data from
* the usb remote.
*/
static void streamzap_callback(struct urb *urb)
{
struct streamzap_ir *sz;
int len;
if (!urb)
return;
sz = urb->context;
len = urb->actual_length;
switch (urb->status) {
case 0:
dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
sz_process_ir_data(sz, len);
break;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
/*
* this urb is terminated, clean up.
* sz might already be invalid at this point
*/
dev_err(sz->dev, "urb terminated, status: %d\n", urb->status);
return;
default:
break;
}
usb_submit_urb(urb, GFP_ATOMIC);
}