diff options
author | Ariel Elior <ariele@broadcom.com> | 2013-08-19 02:12:00 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-08-20 03:21:47 -0400 |
commit | 5ae30d78042ab7790c40b530153c8fdabe1c0ee1 (patch) | |
tree | 17f917d9b23ce1f98fbdf72dd1b32a08b106abe4 | |
parent | aeeddb8b9e76d1f250d58b40e8dba8614d61368b (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.c | 49 |
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 | ||
3087 | static int bnx2x_vf_ndo_sanity(struct bnx2x *bp, int vfidx, | 3087 | static 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 | ||