From: Joe Jin Date: Mon, 27 Aug 2012 11:06:14 +0000 (+0800) Subject: cnic: Fix occasional NULL pointer dereference during reboot. X-Git-Tag: v2.6.39-400.9.0~338^2~124 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=652470062df94a5d6222f5ff00497b9b52716e27;p=users%2Fjedix%2Flinux-maple.git cnic: Fix occasional NULL pointer dereference during reboot. We register with bnx2x before we allocate ctx_tbl structure, so it is possible for bnx2x to call cnic_ctl before the structure is allocated. This can sometimes cause NULL pointer dereference of cp->ctx_tbl. We fix this by adding simple checking for valid state before proceeding. The cnic_ctl call is RCU protected so we don't have to deal with race conditions. Because of the additional checking, we need to finish the shutdown before clearing the CNIC_UP flag. (backported from upstream commit a2028b2376a858cb68a7fcc129f6508f59b45381) Signed-off-by: Michael Chan Signed-off-by: David S. Miller Signed-off-by: Joe Jin --- diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 2d7660d8396b..5d7129d049bd 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -286,6 +286,9 @@ static int cnic_get_l5_cid(struct cnic_local *cp, u32 cid, u32 *l5_cid) { u32 i; + if (!cp->ctx_tbl) + return -EINVAL; + for (i = 0; i < cp->max_cid_space; i++) { if (cp->ctx_tbl[i].cid == cid) { *l5_cid = i; @@ -3213,6 +3216,9 @@ static int cnic_ctl(void *data, struct cnic_ctl_info *info) u32 l5_cid; struct cnic_local *cp = dev->cnic_priv; + if (!test_bit(CNIC_F_CNIC_UP, &dev->flags)) + break; + if (cnic_get_l5_cid(cp, cid, &l5_cid) == 0) { struct cnic_context *ctx = &cp->ctx_tbl[l5_cid]; @@ -4246,8 +4252,6 @@ static int cnic_cm_shutdown(struct cnic_dev *dev) struct cnic_local *cp = dev->cnic_priv; int i; - cp->stop_cm(dev); - if (!cp->csk_tbl) return 0; @@ -5283,6 +5287,7 @@ static void cnic_stop_hw(struct cnic_dev *dev) i++; } cnic_shutdown_rings(dev); + cp->stop_cm(dev); clear_bit(CNIC_F_CNIC_UP, &dev->flags); rcu_assign_pointer(cp->ulp_ops[CNIC_ULP_L4], NULL); synchronize_rcu();