lkml.org 
[lkml]   [2023]   [May]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 4.14 11/20] media: dvb-core: Fix kernel WARNING for blocking operation in wait_event*()
    Date
    From: Takashi Iwai <tiwai@suse.de>

    [ Upstream commit b8c75e4a1b325ea0a9433fa8834be97b5836b946 ]

    Using a semaphore in the wait_event*() condition is no good idea.
    It hits a kernel WARN_ON() at prepare_to_wait_event() like:
    do not call blocking ops when !TASK_RUNNING; state=1 set at
    prepare_to_wait_event+0x6d/0x690

    For avoiding the potential deadlock, rewrite to an open-coded loop
    instead. Unlike the loop in wait_event*(), this uses wait_woken()
    after the condition check, hence the task state stays consistent.

    CVE-2023-31084 was assigned to this bug.

    Link: https://lore.kernel.org/r/CA+UBctCu7fXn4q41O_3=id1+OdyQ85tZY1x+TkT-6OVBL6KAUw@mail.gmail.com/

    Link: https://lore.kernel.org/linux-media/20230512151800.1874-1-tiwai@suse.de
    Reported-by: Yu Hao <yhao016@ucr.edu>
    Closes: https://nvd.nist.gov/vuln/detail/CVE-2023-31084
    Signed-off-by: Takashi Iwai <tiwai@suse.de>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/media/dvb-core/dvb_frontend.c | 16 ++++++++++++----
    1 file changed, 12 insertions(+), 4 deletions(-)

    diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
    index e3a4a4688c2ec..651234584eb2c 100644
    --- a/drivers/media/dvb-core/dvb_frontend.c
    +++ b/drivers/media/dvb-core/dvb_frontend.c
    @@ -301,14 +301,22 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
    }

    if (events->eventw == events->eventr) {
    - int ret;
    + struct wait_queue_entry wait;
    + int ret = 0;

    if (flags & O_NONBLOCK)
    return -EWOULDBLOCK;

    - ret = wait_event_interruptible(events->wait_queue,
    - dvb_frontend_test_event(fepriv, events));
    -
    + init_waitqueue_entry(&wait, current);
    + add_wait_queue(&events->wait_queue, &wait);
    + while (!dvb_frontend_test_event(fepriv, events)) {
    + wait_woken(&wait, TASK_INTERRUPTIBLE, 0);
    + if (signal_pending(current)) {
    + ret = -ERESTARTSYS;
    + break;
    + }
    + }
    + remove_wait_queue(&events->wait_queue, &wait);
    if (ret < 0)
    return ret;
    }
    --
    2.39.2
    \
     
     \ /
      Last update: 2023-05-25 22:39    [W:4.656 / U:0.096 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site