From patchwork Fri Dec 5 17:52:53 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Kirsher, Jeffrey T" X-Patchwork-Id: 418246 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 01CCF1400F1 for ; Sat, 6 Dec 2014 04:54:19 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751940AbaLERyJ (ORCPT ); Fri, 5 Dec 2014 12:54:09 -0500 Received: from mga03.intel.com ([134.134.136.65]:7187 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751913AbaLERyB (ORCPT ); Fri, 5 Dec 2014 12:54:01 -0500 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP; 05 Dec 2014 09:51:49 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.07,523,1413270000"; d="scan'208";a="619336972" Received: from avabhyan-mobl.amr.corp.intel.com (HELO jtkirshe-mobl.amr.corp.intel.com) ([10.252.142.89]) by orsmga001.jf.intel.com with ESMTP; 05 Dec 2014 09:53:30 -0800 From: Jeff Kirsher To: davem@davemloft.net Cc: Emil Tantilov , netdev@vger.kernel.org, nhorman@redhat.com, sassmann@redhat.com, jogreene@redhat.com, Daniel Borkmann , Jeff Kirsher Subject: [net-next 14/14] ixgbevf: fix possible crashes in probe and remove Date: Fri, 5 Dec 2014 09:52:53 -0800 Message-Id: <1417801973-28793-15-git-send-email-jeffrey.t.kirsher@intel.com> X-Mailer: git-send-email 1.9.3 In-Reply-To: <1417801973-28793-1-git-send-email-jeffrey.t.kirsher@intel.com> References: <1417801973-28793-1-git-send-email-jeffrey.t.kirsher@intel.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Emil Tantilov This patch resolves couple of issues in ixgbevf_probe/remove(): 1. Fix a case where adapter->state is tested after free_netdev() this is same as the patch for ixgbe from Daniel Borkmann : commit b5b2ffc0574e1f27 ("ixgbe: fix use after free adapter->state test in ixgbe_remove/ixgbe_probe") 2. Move pci_set_drvdata() after all the error checks in ixgbevf_probe() and then add a check in ixgbevf_probe() to avoid running the cleanup functions twice in cases where probe failed. CC: Daniel Borkmann Signed-off-by: Emil Tantilov Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 54f7f9cd..3b0ddf7 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -3737,6 +3737,7 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct ixgbe_hw *hw = NULL; const struct ixgbevf_info *ii = ixgbevf_info_tbl[ent->driver_data]; int err, pci_using_dac; + bool disable_dev = false; err = pci_enable_device(pdev); if (err) @@ -3771,7 +3772,6 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) SET_NETDEV_DEV(netdev, &pdev->dev); - pci_set_drvdata(pdev, netdev); adapter = netdev_priv(netdev); adapter->netdev = netdev; @@ -3860,6 +3860,7 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) goto err_register; + pci_set_drvdata(pdev, netdev); netif_carrier_off(netdev); ixgbevf_init_last_counter_stats(adapter); @@ -3889,12 +3890,13 @@ err_sw_init: ixgbevf_reset_interrupt_capability(adapter); iounmap(adapter->io_addr); err_ioremap: + disable_dev = !test_and_set_bit(__IXGBEVF_DISABLED, &adapter->state); free_netdev(netdev); err_alloc_etherdev: pci_release_regions(pdev); err_pci_reg: err_dma: - if (!test_and_set_bit(__IXGBEVF_DISABLED, &adapter->state)) + if (!adapter || disable_dev) pci_disable_device(pdev); return err; } @@ -3911,7 +3913,13 @@ err_dma: static void ixgbevf_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); - struct ixgbevf_adapter *adapter = netdev_priv(netdev); + struct ixgbevf_adapter *adapter; + bool disable_dev; + + if (!netdev) + return; + + adapter = netdev_priv(netdev); set_bit(__IXGBEVF_REMOVING, &adapter->state); @@ -3931,9 +3939,10 @@ static void ixgbevf_remove(struct pci_dev *pdev) hw_dbg(&adapter->hw, "Remove complete\n"); + disable_dev = !test_and_set_bit(__IXGBEVF_DISABLED, &adapter->state); free_netdev(netdev); - if (!test_and_set_bit(__IXGBEVF_DISABLED, &adapter->state)) + if (disable_dev) pci_disable_device(pdev); }