Commit c888393b authored by Arik Nemtsov's avatar Arik Nemtsov Committed by Johannes Berg

cfg80211: avoid freeing last_request while in flight

Avoid freeing the last request while it is being processed. This can
happen in some cases if reg_work is kicked for some reason while the
currently pending request is in flight.

Cc: Sander Eikelenboom <linux@eikelenboom.it>
Tested-by: default avatarEliad Peller <eliad@wizery.com>
Tested-by: default avatarColleen Twitty <colleen@cozybit.com>
Signed-off-by: default avatarArik Nemtsov <arik@wizery.com>
Signed-off-by: default avatarLuis R. Rodriguez <mcgrof@suse.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 4f267c11
...@@ -263,8 +263,16 @@ static char user_alpha2[2]; ...@@ -263,8 +263,16 @@ static char user_alpha2[2];
module_param(ieee80211_regdom, charp, 0444); module_param(ieee80211_regdom, charp, 0444);
MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
static void reg_free_request(struct regulatory_request *lr) static void reg_free_request(struct regulatory_request *request)
{ {
if (request != get_last_request())
kfree(request);
}
static void reg_free_last_request(void)
{
struct regulatory_request *lr = get_last_request();
if (lr != &core_request_world && lr) if (lr != &core_request_world && lr)
kfree_rcu(lr, rcu_head); kfree_rcu(lr, rcu_head);
} }
...@@ -277,7 +285,7 @@ static void reg_update_last_request(struct regulatory_request *request) ...@@ -277,7 +285,7 @@ static void reg_update_last_request(struct regulatory_request *request)
if (lr == request) if (lr == request)
return; return;
reg_free_request(lr); reg_free_last_request();
rcu_assign_pointer(last_request, request); rcu_assign_pointer(last_request, request);
} }
...@@ -1661,7 +1669,7 @@ reg_process_hint_user(struct regulatory_request *user_request) ...@@ -1661,7 +1669,7 @@ reg_process_hint_user(struct regulatory_request *user_request)
if (treatment == REG_REQ_IGNORE || if (treatment == REG_REQ_IGNORE ||
treatment == REG_REQ_ALREADY_SET || treatment == REG_REQ_ALREADY_SET ||
treatment == REG_REQ_USER_HINT_HANDLED) { treatment == REG_REQ_USER_HINT_HANDLED) {
kfree(user_request); reg_free_request(user_request);
return treatment; return treatment;
} }
...@@ -1722,14 +1730,14 @@ reg_process_hint_driver(struct wiphy *wiphy, ...@@ -1722,14 +1730,14 @@ reg_process_hint_driver(struct wiphy *wiphy,
break; break;
case REG_REQ_IGNORE: case REG_REQ_IGNORE:
case REG_REQ_USER_HINT_HANDLED: case REG_REQ_USER_HINT_HANDLED:
kfree(driver_request); reg_free_request(driver_request);
return treatment; return treatment;
case REG_REQ_INTERSECT: case REG_REQ_INTERSECT:
/* fall through */ /* fall through */
case REG_REQ_ALREADY_SET: case REG_REQ_ALREADY_SET:
regd = reg_copy_regd(get_cfg80211_regdom()); regd = reg_copy_regd(get_cfg80211_regdom());
if (IS_ERR(regd)) { if (IS_ERR(regd)) {
kfree(driver_request); reg_free_request(driver_request);
return REG_REQ_IGNORE; return REG_REQ_IGNORE;
} }
rcu_assign_pointer(wiphy->regd, regd); rcu_assign_pointer(wiphy->regd, regd);
...@@ -1824,10 +1832,10 @@ reg_process_hint_country_ie(struct wiphy *wiphy, ...@@ -1824,10 +1832,10 @@ reg_process_hint_country_ie(struct wiphy *wiphy,
case REG_REQ_USER_HINT_HANDLED: case REG_REQ_USER_HINT_HANDLED:
/* fall through */ /* fall through */
case REG_REQ_ALREADY_SET: case REG_REQ_ALREADY_SET:
kfree(country_ie_request); reg_free_request(country_ie_request);
return treatment; return treatment;
case REG_REQ_INTERSECT: case REG_REQ_INTERSECT:
kfree(country_ie_request); reg_free_request(country_ie_request);
/* /*
* This doesn't happen yet, not sure we * This doesn't happen yet, not sure we
* ever want to support it for this case. * ever want to support it for this case.
...@@ -1888,7 +1896,7 @@ static void reg_process_hint(struct regulatory_request *reg_request) ...@@ -1888,7 +1896,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
return; return;
out_free: out_free:
kfree(reg_request); reg_free_request(reg_request);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment