mirror of https://gitee.com/openkylin/linux.git
cfg80211: reg: centralize freeing ignored requests
Instead of having a lot of places that free ignored requests and then return REG_REQ_OK, make reg_process_hint() process REG_REQ_IGNORE by freeing the request, and let functions it calls return that instead of freeing. This also fixes a leak when a second (different) country IE hint was ignored. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
480908a7ec
commit
d34265a3ee
|
@ -273,6 +273,9 @@ MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
|
||||||
|
|
||||||
static void reg_free_request(struct regulatory_request *request)
|
static void reg_free_request(struct regulatory_request *request)
|
||||||
{
|
{
|
||||||
|
if (request == &core_request_world)
|
||||||
|
return;
|
||||||
|
|
||||||
if (request != get_last_request())
|
if (request != get_last_request())
|
||||||
kfree(request);
|
kfree(request);
|
||||||
}
|
}
|
||||||
|
@ -1905,13 +1908,17 @@ static void reg_set_request_processed(void)
|
||||||
* The wireless subsystem can use this function to process
|
* The wireless subsystem can use this function to process
|
||||||
* a regulatory request issued by the regulatory core.
|
* a regulatory request issued by the regulatory core.
|
||||||
*/
|
*/
|
||||||
static void reg_process_hint_core(struct regulatory_request *core_request)
|
static enum reg_request_treatment
|
||||||
|
reg_process_hint_core(struct regulatory_request *core_request)
|
||||||
{
|
{
|
||||||
if (reg_query_database(core_request)) {
|
if (reg_query_database(core_request)) {
|
||||||
core_request->intersect = false;
|
core_request->intersect = false;
|
||||||
core_request->processed = false;
|
core_request->processed = false;
|
||||||
reg_update_last_request(core_request);
|
reg_update_last_request(core_request);
|
||||||
|
return REG_REQ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return REG_REQ_IGNORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum reg_request_treatment
|
static enum reg_request_treatment
|
||||||
|
@ -1957,16 +1964,15 @@ __reg_process_hint_user(struct regulatory_request *user_request)
|
||||||
* The wireless subsystem can use this function to process
|
* The wireless subsystem can use this function to process
|
||||||
* a regulatory request initiated by userspace.
|
* a regulatory request initiated by userspace.
|
||||||
*/
|
*/
|
||||||
static void reg_process_hint_user(struct regulatory_request *user_request)
|
static enum reg_request_treatment
|
||||||
|
reg_process_hint_user(struct regulatory_request *user_request)
|
||||||
{
|
{
|
||||||
enum reg_request_treatment treatment;
|
enum reg_request_treatment treatment;
|
||||||
|
|
||||||
treatment = __reg_process_hint_user(user_request);
|
treatment = __reg_process_hint_user(user_request);
|
||||||
if (treatment == REG_REQ_IGNORE ||
|
if (treatment == REG_REQ_IGNORE ||
|
||||||
treatment == REG_REQ_ALREADY_SET) {
|
treatment == REG_REQ_ALREADY_SET)
|
||||||
reg_free_request(user_request);
|
return REG_REQ_IGNORE;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
user_request->intersect = treatment == REG_REQ_INTERSECT;
|
user_request->intersect = treatment == REG_REQ_INTERSECT;
|
||||||
user_request->processed = false;
|
user_request->processed = false;
|
||||||
|
@ -1975,9 +1981,10 @@ static void reg_process_hint_user(struct regulatory_request *user_request)
|
||||||
reg_update_last_request(user_request);
|
reg_update_last_request(user_request);
|
||||||
user_alpha2[0] = user_request->alpha2[0];
|
user_alpha2[0] = user_request->alpha2[0];
|
||||||
user_alpha2[1] = user_request->alpha2[1];
|
user_alpha2[1] = user_request->alpha2[1];
|
||||||
} else {
|
return REG_REQ_OK;
|
||||||
reg_free_request(user_request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return REG_REQ_IGNORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum reg_request_treatment
|
static enum reg_request_treatment
|
||||||
|
@ -2025,15 +2032,12 @@ reg_process_hint_driver(struct wiphy *wiphy,
|
||||||
case REG_REQ_OK:
|
case REG_REQ_OK:
|
||||||
break;
|
break;
|
||||||
case REG_REQ_IGNORE:
|
case REG_REQ_IGNORE:
|
||||||
reg_free_request(driver_request);
|
return REG_REQ_IGNORE;
|
||||||
return REG_REQ_OK;
|
|
||||||
case REG_REQ_INTERSECT:
|
case REG_REQ_INTERSECT:
|
||||||
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))
|
||||||
reg_free_request(driver_request);
|
return REG_REQ_IGNORE;
|
||||||
return REG_REQ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp = get_wiphy_regdom(wiphy);
|
tmp = get_wiphy_regdom(wiphy);
|
||||||
rcu_assign_pointer(wiphy->regd, regd);
|
rcu_assign_pointer(wiphy->regd, regd);
|
||||||
|
@ -2056,14 +2060,14 @@ reg_process_hint_driver(struct wiphy *wiphy,
|
||||||
return REG_REQ_ALREADY_SET;
|
return REG_REQ_ALREADY_SET;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg_query_database(driver_request))
|
if (reg_query_database(driver_request)) {
|
||||||
reg_update_last_request(driver_request);
|
reg_update_last_request(driver_request);
|
||||||
else
|
|
||||||
reg_free_request(driver_request);
|
|
||||||
|
|
||||||
return REG_REQ_OK;
|
return REG_REQ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return REG_REQ_IGNORE;
|
||||||
|
}
|
||||||
|
|
||||||
static enum reg_request_treatment
|
static enum reg_request_treatment
|
||||||
__reg_process_hint_country_ie(struct wiphy *wiphy,
|
__reg_process_hint_country_ie(struct wiphy *wiphy,
|
||||||
struct regulatory_request *country_ie_request)
|
struct regulatory_request *country_ie_request)
|
||||||
|
@ -2127,31 +2131,30 @@ reg_process_hint_country_ie(struct wiphy *wiphy,
|
||||||
case REG_REQ_OK:
|
case REG_REQ_OK:
|
||||||
break;
|
break;
|
||||||
case REG_REQ_IGNORE:
|
case REG_REQ_IGNORE:
|
||||||
return REG_REQ_OK;
|
return REG_REQ_IGNORE;
|
||||||
case REG_REQ_ALREADY_SET:
|
case REG_REQ_ALREADY_SET:
|
||||||
reg_free_request(country_ie_request);
|
reg_free_request(country_ie_request);
|
||||||
return REG_REQ_ALREADY_SET;
|
return REG_REQ_ALREADY_SET;
|
||||||
case REG_REQ_INTERSECT:
|
case REG_REQ_INTERSECT:
|
||||||
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.
|
||||||
*/
|
*/
|
||||||
WARN_ONCE(1, "Unexpected intersection for country IEs");
|
WARN_ONCE(1, "Unexpected intersection for country IEs");
|
||||||
return REG_REQ_OK;
|
return REG_REQ_IGNORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
country_ie_request->intersect = false;
|
country_ie_request->intersect = false;
|
||||||
country_ie_request->processed = false;
|
country_ie_request->processed = false;
|
||||||
|
|
||||||
if (reg_query_database(country_ie_request))
|
if (reg_query_database(country_ie_request)) {
|
||||||
reg_update_last_request(country_ie_request);
|
reg_update_last_request(country_ie_request);
|
||||||
else
|
|
||||||
reg_free_request(country_ie_request);
|
|
||||||
|
|
||||||
return REG_REQ_OK;
|
return REG_REQ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return REG_REQ_IGNORE;
|
||||||
|
}
|
||||||
|
|
||||||
/* This processes *all* regulatory hints */
|
/* This processes *all* regulatory hints */
|
||||||
static void reg_process_hint(struct regulatory_request *reg_request)
|
static void reg_process_hint(struct regulatory_request *reg_request)
|
||||||
{
|
{
|
||||||
|
@ -2163,11 +2166,11 @@ static void reg_process_hint(struct regulatory_request *reg_request)
|
||||||
|
|
||||||
switch (reg_request->initiator) {
|
switch (reg_request->initiator) {
|
||||||
case NL80211_REGDOM_SET_BY_CORE:
|
case NL80211_REGDOM_SET_BY_CORE:
|
||||||
reg_process_hint_core(reg_request);
|
treatment = reg_process_hint_core(reg_request);
|
||||||
return;
|
break;
|
||||||
case NL80211_REGDOM_SET_BY_USER:
|
case NL80211_REGDOM_SET_BY_USER:
|
||||||
reg_process_hint_user(reg_request);
|
treatment = reg_process_hint_user(reg_request);
|
||||||
return;
|
break;
|
||||||
case NL80211_REGDOM_SET_BY_DRIVER:
|
case NL80211_REGDOM_SET_BY_DRIVER:
|
||||||
if (!wiphy)
|
if (!wiphy)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
@ -2183,6 +2186,9 @@ static void reg_process_hint(struct regulatory_request *reg_request)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (treatment == REG_REQ_IGNORE)
|
||||||
|
goto out_free;
|
||||||
|
|
||||||
WARN(treatment != REG_REQ_OK && treatment != REG_REQ_ALREADY_SET,
|
WARN(treatment != REG_REQ_OK && treatment != REG_REQ_ALREADY_SET,
|
||||||
"unexpected treatment value %d\n", treatment);
|
"unexpected treatment value %d\n", treatment);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue