aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAriel Elior <ariele@broadcom.com>2013-08-19 02:12:00 -0400
committerDavid S. Miller <davem@davemloft.net>2013-08-20 03:21:47 -0400
commit5ae30d78042ab7790c40b530153c8fdabe1c0ee1 (patch)
tree17f917d9b23ce1f98fbdf72dd1b32a08b106abe4
parentaeeddb8b9e76d1f250d58b40e8dba8614d61368b (diff)
bnx2x: Protect against VFs' ndos when SR-IOV is disabled
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>
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c49
1 files changed, 31 insertions, 18 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index 44104fb27947..d414b493f80d 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -3084,8 +3084,9 @@ void bnx2x_disable_sriov(struct bnx2x *bp)
3084 pci_disable_sriov(bp->pdev); 3084 pci_disable_sriov(bp->pdev);
3085} 3085}
3086 3086
3087static int bnx2x_vf_ndo_sanity(struct bnx2x *bp, int vfidx, 3087static int bnx2x_vf_ndo_prep(struct bnx2x *bp, int vfidx,
3088 struct bnx2x_virtf *vf) 3088 struct bnx2x_virtf **vf,
3089 struct pf_vf_bulletin_content **bulletin)
3089{ 3090{
3090 if (bp->state != BNX2X_STATE_OPEN) { 3091 if (bp->state != BNX2X_STATE_OPEN) {
3091 BNX2X_ERR("vf ndo called though PF is down\n"); 3092 BNX2X_ERR("vf ndo called though PF is down\n");
@@ -3103,12 +3104,22 @@ static int bnx2x_vf_ndo_sanity(struct bnx2x *bp, int vfidx,
3103 return -EINVAL; 3104 return -EINVAL;
3104 } 3105 }
3105 3106
3106 if (!vf) { 3107 /* init members */
3108 *vf = BP_VF(bp, vfidx);
3109 *bulletin = BP_VF_BULLETIN(bp, vfidx);
3110
3111 if (!*vf) {
3107 BNX2X_ERR("vf ndo called but vf was null. vfidx was %d\n", 3112 BNX2X_ERR("vf ndo called but vf was null. vfidx was %d\n",
3108 vfidx); 3113 vfidx);
3109 return -EINVAL; 3114 return -EINVAL;
3110 } 3115 }
3111 3116
3117 if (!*bulletin) {
3118 BNX2X_ERR("vf ndo called but Bulletin Board struct is null. vfidx was %d\n",
3119 vfidx);
3120 return -EINVAL;
3121 }
3122
3112 return 0; 3123 return 0;
3113} 3124}
3114 3125
@@ -3116,17 +3127,19 @@ int bnx2x_get_vf_config(struct net_device *dev, int vfidx,
3116 struct ifla_vf_info *ivi) 3127 struct ifla_vf_info *ivi)
3117{ 3128{
3118 struct bnx2x *bp = netdev_priv(dev); 3129 struct bnx2x *bp = netdev_priv(dev);
3119 struct bnx2x_virtf *vf = BP_VF(bp, vfidx); 3130 struct bnx2x_virtf *vf = NULL;
3120 struct bnx2x_vlan_mac_obj *mac_obj = &bnx2x_vfq(vf, 0, mac_obj); 3131 struct pf_vf_bulletin_content *bulletin = NULL;
3121 struct bnx2x_vlan_mac_obj *vlan_obj = &bnx2x_vfq(vf, 0, vlan_obj); 3132 struct bnx2x_vlan_mac_obj *mac_obj;
3122 struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx); 3133 struct bnx2x_vlan_mac_obj *vlan_obj;
3123 int rc; 3134 int rc;
3124 3135
3125 /* sanity */ 3136 /* sanity and init */
3126 rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf); 3137 rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
3127 if (rc) 3138 if (rc)
3128 return rc; 3139 return rc;
3129 if (!mac_obj || !vlan_obj || !bulletin) { 3140 mac_obj = &bnx2x_vfq(vf, 0, mac_obj);
3141 vlan_obj = &bnx2x_vfq(vf, 0, vlan_obj);
3142 if (!mac_obj || !vlan_obj) {
3130 BNX2X_ERR("VF partially initialized\n"); 3143 BNX2X_ERR("VF partially initialized\n");
3131 return -EINVAL; 3144 return -EINVAL;
3132 } 3145 }
@@ -3183,11 +3196,11 @@ int bnx2x_set_vf_mac(struct net_device *dev, int vfidx, u8 *mac)
3183{ 3196{
3184 struct bnx2x *bp = netdev_priv(dev); 3197 struct bnx2x *bp = netdev_priv(dev);
3185 int rc, q_logical_state; 3198 int rc, q_logical_state;
3186 struct bnx2x_virtf *vf = BP_VF(bp, vfidx); 3199 struct bnx2x_virtf *vf = NULL;
3187 struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx); 3200 struct pf_vf_bulletin_content *bulletin = NULL;
3188 3201
3189 /* sanity */ 3202 /* sanity and init */
3190 rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf); 3203 rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
3191 if (rc) 3204 if (rc)
3192 return rc; 3205 return rc;
3193 if (!is_valid_ether_addr(mac)) { 3206 if (!is_valid_ether_addr(mac)) {
@@ -3249,11 +3262,11 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
3249{ 3262{
3250 struct bnx2x *bp = netdev_priv(dev); 3263 struct bnx2x *bp = netdev_priv(dev);
3251 int rc, q_logical_state; 3264 int rc, q_logical_state;
3252 struct bnx2x_virtf *vf = BP_VF(bp, vfidx); 3265 struct bnx2x_virtf *vf = NULL;
3253 struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx); 3266 struct pf_vf_bulletin_content *bulletin = NULL;
3254 3267
3255 /* sanity */ 3268 /* sanity and init */
3256 rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf); 3269 rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
3257 if (rc) 3270 if (rc)
3258 return rc; 3271 return rc;
3259 3272