lkml.org 
[lkml]   [2020]   [Jan]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH] rapidio/mport_cdev: Fix race in mport_cdev_release()
    Date
    From: Alexander Sverdlin <alexander.sverdlin@nokia.com>

    While get_dma_channel() is protected against concurrent calls, there is a
    race against kref_put() in mport_cdev_release():

    CPU0 CPU1

    get_dma_channel()
    kref_init(&priv->md->dma_ref);
    ...
    mport_cdev_release_dma()
    kref_put(&md->dma_ref,
    mport_release_def_dma);
    get_dma_channel()
    if (priv->md->dma_chan) {
    ...
    kref_get(&priv->md->dma_ref);
    mport_release_def_dma()
    md->dma_chan = NULL;

    which may appear like this:

    ------------[ cut here ]------------
    WARNING: CPU: 1 PID: 12057 at .../linux/include/linux/kref.h:46 rio_dma_transfer.isra.12+0x8e0/0xbe8 [rio_mport_cdev]
    ...
    CPU: 1 PID: 12057 Comm: ... Tainted: G O 4.9.109-... #1
    Stack : ...

    Call Trace:
    [<ffffffff80140040>] show_stack+0x90/0xb0
    [<ffffffff803eeeb8>] dump_stack+0x88/0xc0
    [<ffffffff80159670>] __warn+0x108/0x120
    [<ffffffffc0541df0>] rio_dma_transfer.isra.12+0x8e0/0xbe8 [rio_mport_cdev]
    [<ffffffffc05426fc>] mport_cdev_ioctl+0x604/0x2988 [rio_mport_cdev]
    [<ffffffff802881e8>] do_vfs_ioctl+0xb8/0x780
    [<ffffffff80288938>] SyS_ioctl+0x88/0xc0
    [<ffffffff80146ae8>] syscall_common+0x34/0x58
    ---[ end trace 78842d4915cfc502 ]---

    Fixes: e8de370188d0 ("rapidio: add mport char device driver")
    Cc: stable@vger.kernel.org
    Signed-off-by: Alexander Sverdlin <alexander.sverdlin@nokia.com>
    ---
    drivers/rapidio/devices/rio_mport_cdev.c | 2 ++
    1 file changed, 2 insertions(+)

    diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c
    index 8155f59..a6276dc 100644
    --- a/drivers/rapidio/devices/rio_mport_cdev.c
    +++ b/drivers/rapidio/devices/rio_mport_cdev.c
    @@ -1980,6 +1980,7 @@ static void mport_cdev_release_dma(struct file *filp)
    current->comm, task_pid_nr(current), wret);
    }

    + mutex_lock(&priv->dma_lock);
    if (priv->dmach != priv->md->dma_chan) {
    rmcd_debug(EXIT, "Release DMA channel for filp=%p %s(%d)",
    filp, current->comm, task_pid_nr(current));
    @@ -1990,6 +1991,7 @@ static void mport_cdev_release_dma(struct file *filp)
    }

    priv->dmach = NULL;
    + mutex_unlock(&priv->dma_lock);
    }
    #else
    #define mport_cdev_release_dma(priv) do {} while (0)
    --
    2.4.6
    \
     
     \ /
      Last update: 2020-01-14 15:00    [W:4.236 / U:0.664 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site