lkml.org 
[lkml]   [2018]   [Jul]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 129/157] media: dvb_frontend: fix locking issues at dvb_frontend_get_event()
    Date
    4.14-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Mauro Carvalho Chehab <mchehab@s-opensource.com>

    commit 76d81243a487c09619822ef8e7201a756e58a87d upstream.

    As warned by smatch:
    drivers/media/dvb-core/dvb_frontend.c:314 dvb_frontend_get_event() warn: inconsistent returns 'sem:&fepriv->sem'.
    Locked on: line 288
    line 295
    line 306
    line 314
    Unlocked on: line 303

    The lock implementation for get event is wrong, as, if an
    interrupt occurs, down_interruptible() will fail, and the
    routine will call up() twice when userspace calls the ioctl
    again.

    The bad code is there since when Linux migrated to git, in
    2005.

    Cc: stable@vger.kernel.org
    Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/media/dvb-core/dvb_frontend.c | 23 +++++++++++++++--------
    1 file changed, 15 insertions(+), 8 deletions(-)

    --- a/drivers/media/dvb-core/dvb_frontend.c
    +++ b/drivers/media/dvb-core/dvb_frontend.c
    @@ -275,8 +275,20 @@ static void dvb_frontend_add_event(struc
    wake_up_interruptible (&events->wait_queue);
    }

    +static int dvb_frontend_test_event(struct dvb_frontend_private *fepriv,
    + struct dvb_fe_events *events)
    +{
    + int ret;
    +
    + up(&fepriv->sem);
    + ret = events->eventw != events->eventr;
    + down(&fepriv->sem);
    +
    + return ret;
    +}
    +
    static int dvb_frontend_get_event(struct dvb_frontend *fe,
    - struct dvb_frontend_event *event, int flags)
    + struct dvb_frontend_event *event, int flags)
    {
    struct dvb_frontend_private *fepriv = fe->frontend_priv;
    struct dvb_fe_events *events = &fepriv->events;
    @@ -294,13 +306,8 @@ static int dvb_frontend_get_event(struct
    if (flags & O_NONBLOCK)
    return -EWOULDBLOCK;

    - up(&fepriv->sem);
    -
    - ret = wait_event_interruptible (events->wait_queue,
    - events->eventw != events->eventr);
    -
    - if (down_interruptible (&fepriv->sem))
    - return -ERESTARTSYS;
    + ret = wait_event_interruptible(events->wait_queue,
    + dvb_frontend_test_event(fepriv, events));

    if (ret < 0)
    return ret;

    \
     
     \ /
      Last update: 2018-07-01 19:42    [W:4.203 / U:0.236 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site