Skip to content

Commit

Permalink
bnx2x: Protect against VFs' ndos when SR-IOV is disabled
Browse files Browse the repository at this point in the history
Since SR-IOV can be activated dynamically and iproute2 can be called
asynchronously, the various callbacks need a robust sanity check before
attempting to access the SR-IOV database and members since there are numerous
states in which it can find the driver (e.g., PF is down, sriov was not enabled
yet, VF is down, etc.).

In many of the states the callback result will be null pointer dereference.

Signed-off-by: Ariel Elior <ariele@broadcom.com>
Signed-off-by: Yuval Mintz <yuvalmin@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Ariel Elior authored and David S. Miller committed Aug 20, 2013
1 parent aeeddb8 commit 5ae30d7
Showing 1 changed file with 31 additions and 18 deletions.
49 changes: 31 additions & 18 deletions drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
Original file line number Diff line number Diff line change
Expand Up @@ -3084,8 +3084,9 @@ void bnx2x_disable_sriov(struct bnx2x *bp)
pci_disable_sriov(bp->pdev);
}

static int bnx2x_vf_ndo_sanity(struct bnx2x *bp, int vfidx,
struct bnx2x_virtf *vf)
static int bnx2x_vf_ndo_prep(struct bnx2x *bp, int vfidx,
struct bnx2x_virtf **vf,
struct pf_vf_bulletin_content **bulletin)
{
if (bp->state != BNX2X_STATE_OPEN) {
BNX2X_ERR("vf ndo called though PF is down\n");
Expand All @@ -3103,30 +3104,42 @@ static int bnx2x_vf_ndo_sanity(struct bnx2x *bp, int vfidx,
return -EINVAL;
}

if (!vf) {
/* init members */
*vf = BP_VF(bp, vfidx);
*bulletin = BP_VF_BULLETIN(bp, vfidx);

if (!*vf) {
BNX2X_ERR("vf ndo called but vf was null. vfidx was %d\n",
vfidx);
return -EINVAL;
}

if (!*bulletin) {
BNX2X_ERR("vf ndo called but Bulletin Board struct is null. vfidx was %d\n",
vfidx);
return -EINVAL;
}

return 0;
}

int bnx2x_get_vf_config(struct net_device *dev, int vfidx,
struct ifla_vf_info *ivi)
{
struct bnx2x *bp = netdev_priv(dev);
struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
struct bnx2x_vlan_mac_obj *mac_obj = &bnx2x_vfq(vf, 0, mac_obj);
struct bnx2x_vlan_mac_obj *vlan_obj = &bnx2x_vfq(vf, 0, vlan_obj);
struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
struct bnx2x_virtf *vf = NULL;
struct pf_vf_bulletin_content *bulletin = NULL;
struct bnx2x_vlan_mac_obj *mac_obj;
struct bnx2x_vlan_mac_obj *vlan_obj;
int rc;

/* sanity */
rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
/* sanity and init */
rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
if (rc)
return rc;
if (!mac_obj || !vlan_obj || !bulletin) {
mac_obj = &bnx2x_vfq(vf, 0, mac_obj);
vlan_obj = &bnx2x_vfq(vf, 0, vlan_obj);
if (!mac_obj || !vlan_obj) {
BNX2X_ERR("VF partially initialized\n");
return -EINVAL;
}
Expand Down Expand Up @@ -3183,11 +3196,11 @@ int bnx2x_set_vf_mac(struct net_device *dev, int vfidx, u8 *mac)
{
struct bnx2x *bp = netdev_priv(dev);
int rc, q_logical_state;
struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
struct bnx2x_virtf *vf = NULL;
struct pf_vf_bulletin_content *bulletin = NULL;

/* sanity */
rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
/* sanity and init */
rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
if (rc)
return rc;
if (!is_valid_ether_addr(mac)) {
Expand Down Expand Up @@ -3249,11 +3262,11 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
{
struct bnx2x *bp = netdev_priv(dev);
int rc, q_logical_state;
struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
struct bnx2x_virtf *vf = NULL;
struct pf_vf_bulletin_content *bulletin = NULL;

/* sanity */
rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
/* sanity and init */
rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
if (rc)
return rc;

Expand Down

0 comments on commit 5ae30d7

Please sign in to comment.