lkml.org 
[lkml]   [2020]   [Jun]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 55/78] net: alx: fix race condition in alx_remove
    Date
    From: Zekun Shen <bruceshenzk@gmail.com>

    [ Upstream commit e89df5c4322c1bf495f62d74745895b5fd2a4393 ]

    There is a race condition exist during termination. The path is
    alx_stop and then alx_remove. An alx_schedule_link_check could be called
    before alx_stop by interrupt handler and invoke alx_link_check later.
    Alx_stop frees the napis, and alx_remove cancels any pending works.
    If any of the work is scheduled before termination and invoked before
    alx_remove, a null-ptr-deref occurs because both expect alx->napis[i].

    This patch fix the race condition by moving cancel_work_sync functions
    before alx_free_napis inside alx_stop. Because interrupt handler can call
    alx_schedule_link_check again, alx_free_irq is moved before
    cancel_work_sync calls too.

    Signed-off-by: Zekun Shen <bruceshenzk@gmail.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/net/ethernet/atheros/alx/main.c | 9 +++++----
    1 file changed, 5 insertions(+), 4 deletions(-)

    diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
    index 5e5022fa1d047..85029d43da758 100644
    --- a/drivers/net/ethernet/atheros/alx/main.c
    +++ b/drivers/net/ethernet/atheros/alx/main.c
    @@ -1250,8 +1250,12 @@ static int __alx_open(struct alx_priv *alx, bool resume)

    static void __alx_stop(struct alx_priv *alx)
    {
    - alx_halt(alx);
    alx_free_irq(alx);
    +
    + cancel_work_sync(&alx->link_check_wk);
    + cancel_work_sync(&alx->reset_wk);
    +
    + alx_halt(alx);
    alx_free_rings(alx);
    alx_free_napis(alx);
    }
    @@ -1863,9 +1867,6 @@ static void alx_remove(struct pci_dev *pdev)
    struct alx_priv *alx = pci_get_drvdata(pdev);
    struct alx_hw *hw = &alx->hw;

    - cancel_work_sync(&alx->link_check_wk);
    - cancel_work_sync(&alx->reset_wk);
    -
    /* restore permanent mac address */
    alx_set_macaddr(hw, hw->perm_addr);

    --
    2.25.1
    \
     
     \ /
      Last update: 2020-06-29 22:39    [W:4.066 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site