lkml.org 
[lkml]   [2014]   [Jun]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.2 81/92] can: peak_pci: prevent use after free at netdev removal
    3.2.60-rc1 review patch.  If anyone has any objections, please let me know.

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

    From: Stephane Grosjean <s.grosjean@peak-system.com>

    commit 0b5a958cf4df3a5cd578b861471e62138f55c85e upstream.

    As remarked by Christopher R. Baker in his post at

    http://marc.info/?l=linux-can&m=139707295706465&w=2

    there's a possibility for an use after free condition at device removal.

    This simplified patch introduces an additional variable to prevent the issue.
    Thanks for catching this.

    Reported-by: Christopher R. Baker <cbaker@rec.ri.cmu.edu>
    Signed-off-by: Stephane Grosjean <s.grosjean@peak-system.com>
    Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
    [bwh: Backported to 3.2: adjust context]
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    drivers/net/can/sja1000/peak_pci.c | 14 +++++++++-----
    1 file changed, 9 insertions(+), 5 deletions(-)

    --- a/drivers/net/can/sja1000/peak_pci.c
    +++ b/drivers/net/can/sja1000/peak_pci.c
    @@ -98,7 +98,7 @@ static int __devinit peak_pci_probe(stru
    {
    struct sja1000_priv *priv;
    struct peak_pci_chan *chan;
    - struct net_device *dev;
    + struct net_device *dev, *prev_dev;
    void __iomem *cfg_base, *reg_base;
    u16 sub_sys_id, icr;
    int i, err, channels;
    @@ -213,11 +213,13 @@ failure_remove_channels:
    /* Disable interrupts */
    writew(0x0, cfg_base + PITA_ICR + 2);

    - for (dev = pci_get_drvdata(pdev); dev; dev = chan->prev_dev) {
    - unregister_sja1000dev(dev);
    - free_sja1000dev(dev);
    + for (dev = pci_get_drvdata(pdev); dev; dev = prev_dev) {
    priv = netdev_priv(dev);
    chan = priv->priv;
    + prev_dev = chan->prev_dev;
    +
    + unregister_sja1000dev(dev);
    + free_sja1000dev(dev);
    }

    pci_iounmap(pdev, reg_base);
    @@ -247,10 +249,12 @@ static void __devexit peak_pci_remove(st

    /* Loop over all registered devices */
    while (1) {
    + struct net_device *prev_dev = chan->prev_dev;
    +
    dev_info(&pdev->dev, "removing device %s\n", dev->name);
    unregister_sja1000dev(dev);
    free_sja1000dev(dev);
    - dev = chan->prev_dev;
    + dev = prev_dev;
    if (!dev)
    break;
    priv = netdev_priv(dev);


    \
     
     \ /
      Last update: 2014-06-07 04:41    [W:4.211 / U:0.088 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site