cw1200: Fix concurrency use-after-free bugs in cw1200_hw_scan()
The function cw1200_bss_info_changed() and cw1200_hw_scan() can be concurrently executed. The two functions both access a possible shared variable "frame.skb". This shared variable is freed by dev_kfree_skb() in cw1200_upload_beacon(), which is called by cw1200_bss_info_changed(). The free operation is protected by a mutex lock "priv->conf_mutex" in cw1200_bss_info_changed(). In cw1200_hw_scan(), this shared variable is accessed without the protection of the mutex lock "priv->conf_mutex". Thus, concurrency use-after-free bugs may occur. To fix these bugs, the original calls to mutex_lock(&priv->conf_mutex) and mutex_unlock(&priv->conf_mutex) are moved to the places, which can protect the accesses to the shared variable. Signed-off-by: Jia-Ju Bai <baijiaju1990@gmail.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
		
							parent
							
								
									861cb5eb46
								
							
						
					
					
						commit
						4f68ef64cd
					
				| @ -78,6 +78,10 @@ int cw1200_hw_scan(struct ieee80211_hw *hw, | ||||
| 	if (req->n_ssids > WSM_SCAN_MAX_NUM_OF_SSIDS) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	/* will be unlocked in cw1200_scan_work() */ | ||||
| 	down(&priv->scan.lock); | ||||
| 	mutex_lock(&priv->conf_mutex); | ||||
| 
 | ||||
| 	frame.skb = ieee80211_probereq_get(hw, priv->vif->addr, NULL, 0, | ||||
| 		req->ie_len); | ||||
| 	if (!frame.skb) | ||||
| @ -86,19 +90,15 @@ int cw1200_hw_scan(struct ieee80211_hw *hw, | ||||
| 	if (req->ie_len) | ||||
| 		skb_put_data(frame.skb, req->ie, req->ie_len); | ||||
| 
 | ||||
| 	/* will be unlocked in cw1200_scan_work() */ | ||||
| 	down(&priv->scan.lock); | ||||
| 	mutex_lock(&priv->conf_mutex); | ||||
| 
 | ||||
| 	ret = wsm_set_template_frame(priv, &frame); | ||||
| 	if (!ret) { | ||||
| 		/* Host want to be the probe responder. */ | ||||
| 		ret = wsm_set_probe_responder(priv, true); | ||||
| 	} | ||||
| 	if (ret) { | ||||
| 		dev_kfree_skb(frame.skb); | ||||
| 		mutex_unlock(&priv->conf_mutex); | ||||
| 		up(&priv->scan.lock); | ||||
| 		dev_kfree_skb(frame.skb); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| @ -120,10 +120,9 @@ int cw1200_hw_scan(struct ieee80211_hw *hw, | ||||
| 		++priv->scan.n_ssids; | ||||
| 	} | ||||
| 
 | ||||
| 	mutex_unlock(&priv->conf_mutex); | ||||
| 
 | ||||
| 	if (frame.skb) | ||||
| 		dev_kfree_skb(frame.skb); | ||||
| 	mutex_unlock(&priv->conf_mutex); | ||||
| 	queue_work(priv->workqueue, &priv->scan.work); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user