diff options
author | Michael Chan <mchan@broadcom.com> | 2014-03-17 23:19:06 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-03-18 16:02:16 -0400 |
commit | f7bd12d09ed6e4093a56dbbfbe8411cc52a738d1 (patch) | |
tree | 9e7e3ee033404737317ef81b50c28391bc15bd6d | |
parent | ff0992e9036e9810e7cd45234fa32ca1e79750e2 (diff) |
cnic: Use proper ulp_ops for per device operations.
For per device operations, cnic needs to dereference the RCU protected
cp->ulp_ops instead of the global cnic_ulp_tbl. In 2 locations,
cnic_send_nlmsg() and cnic_copy_ulp_stats(), it was referencing the
global table. If the device has been unregistered and these functions
are still being called (very unlikely scenarios), it could lead to NULL
pointer dereference.
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/broadcom/cnic.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c index fcf9105a5476..2cb248269c8f 100644 --- a/drivers/net/ethernet/broadcom/cnic.c +++ b/drivers/net/ethernet/broadcom/cnic.c | |||
@@ -342,7 +342,7 @@ static int cnic_send_nlmsg(struct cnic_local *cp, u32 type, | |||
342 | while (retry < 3) { | 342 | while (retry < 3) { |
343 | rc = 0; | 343 | rc = 0; |
344 | rcu_read_lock(); | 344 | rcu_read_lock(); |
345 | ulp_ops = rcu_dereference(cnic_ulp_tbl[CNIC_ULP_ISCSI]); | 345 | ulp_ops = rcu_dereference(cp->ulp_ops[CNIC_ULP_ISCSI]); |
346 | if (ulp_ops) | 346 | if (ulp_ops) |
347 | rc = ulp_ops->iscsi_nl_send_msg( | 347 | rc = ulp_ops->iscsi_nl_send_msg( |
348 | cp->ulp_handle[CNIC_ULP_ISCSI], | 348 | cp->ulp_handle[CNIC_ULP_ISCSI], |
@@ -3244,7 +3244,8 @@ static int cnic_copy_ulp_stats(struct cnic_dev *dev, int ulp_type) | |||
3244 | int rc; | 3244 | int rc; |
3245 | 3245 | ||
3246 | mutex_lock(&cnic_lock); | 3246 | mutex_lock(&cnic_lock); |
3247 | ulp_ops = cnic_ulp_tbl_prot(ulp_type); | 3247 | ulp_ops = rcu_dereference_protected(cp->ulp_ops[ulp_type], |
3248 | lockdep_is_held(&cnic_lock)); | ||
3248 | if (ulp_ops && ulp_ops->cnic_get_stats) | 3249 | if (ulp_ops && ulp_ops->cnic_get_stats) |
3249 | rc = ulp_ops->cnic_get_stats(cp->ulp_handle[ulp_type]); | 3250 | rc = ulp_ops->cnic_get_stats(cp->ulp_handle[ulp_type]); |
3250 | else | 3251 | else |