lkml.org 
[lkml]   [2021]   [Sep]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 095/175] media: uvc: dont do DMA on stack
    Date
    From: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

    commit 1a10d7fdb6d0e235e9d230916244cc2769d3f170 upstream.

    As warned by smatch:
    drivers/media/usb/uvc/uvc_v4l2.c:911 uvc_ioctl_g_input() error: doing dma on the stack (&i)
    drivers/media/usb/uvc/uvc_v4l2.c:943 uvc_ioctl_s_input() error: doing dma on the stack (&i)

    those two functions call uvc_query_ctrl passing a pointer to
    a data at the DMA stack. those are used to send URBs via
    usb_control_msg(). Using DMA stack is not supported and should
    not work anymore on modern Linux versions.

    So, use a kmalloc'ed buffer.

    Cc: stable@vger.kernel.org # Kernel 4.9 and upper
    Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/media/usb/uvc/uvc_v4l2.c | 34 +++++++++++++++++++++++-----------
    1 file changed, 23 insertions(+), 11 deletions(-)

    --- a/drivers/media/usb/uvc/uvc_v4l2.c
    +++ b/drivers/media/usb/uvc/uvc_v4l2.c
    @@ -881,8 +881,8 @@ static int uvc_ioctl_g_input(struct file
    {
    struct uvc_fh *handle = fh;
    struct uvc_video_chain *chain = handle->chain;
    + u8 *buf;
    int ret;
    - u8 i;

    if (chain->selector == NULL ||
    (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
    @@ -890,22 +890,27 @@ static int uvc_ioctl_g_input(struct file
    return 0;
    }

    + buf = kmalloc(1, GFP_KERNEL);
    + if (!buf)
    + return -ENOMEM;
    +
    ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, chain->selector->id,
    chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
    - &i, 1);
    - if (ret < 0)
    - return ret;
    + buf, 1);
    + if (!ret)
    + *input = *buf - 1;

    - *input = i - 1;
    - return 0;
    + kfree(buf);
    +
    + return ret;
    }

    static int uvc_ioctl_s_input(struct file *file, void *fh, unsigned int input)
    {
    struct uvc_fh *handle = fh;
    struct uvc_video_chain *chain = handle->chain;
    + u8 *buf;
    int ret;
    - u32 i;

    ret = uvc_acquire_privileges(handle);
    if (ret < 0)
    @@ -921,10 +926,17 @@ static int uvc_ioctl_s_input(struct file
    if (input >= chain->selector->bNrInPins)
    return -EINVAL;

    - i = input + 1;
    - return uvc_query_ctrl(chain->dev, UVC_SET_CUR, chain->selector->id,
    - chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
    - &i, 1);
    + buf = kmalloc(1, GFP_KERNEL);
    + if (!buf)
    + return -ENOMEM;
    +
    + *buf = input + 1;
    + ret = uvc_query_ctrl(chain->dev, UVC_SET_CUR, chain->selector->id,
    + chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
    + buf, 1);
    + kfree(buf);
    +
    + return ret;
    }

    static int uvc_ioctl_queryctrl(struct file *file, void *fh,

    \
     
     \ /
      Last update: 2021-09-20 19:04    [W:2.987 / U:0.700 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site