aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2015-10-15 07:05:55 -0400
committerJohannes Berg <johannes.berg@intel.com>2015-10-16 03:15:44 -0400
commitd34265a3eebe994b3b9a0e4cabbc2dbb8436388b (patch)
treec185e722bdda0c7ea9abfdaecb7c1d1e42ab6e2c /net/wireless
parent480908a7ec5f2d37d5610b7d9bc48a38f2093876 (diff)
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>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/reg.c64
1 files changed, 35 insertions, 29 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index a95fc3abb8e1..5775f2fda31f 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -273,6 +273,9 @@ MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
273 273
274static void reg_free_request(struct regulatory_request *request) 274static void reg_free_request(struct regulatory_request *request)
275{ 275{
276 if (request == &core_request_world)
277 return;
278
276 if (request != get_last_request()) 279 if (request != get_last_request())
277 kfree(request); 280 kfree(request);
278} 281}
@@ -1905,13 +1908,17 @@ static void reg_set_request_processed(void)
1905 * The wireless subsystem can use this function to process 1908 * The wireless subsystem can use this function to process
1906 * a regulatory request issued by the regulatory core. 1909 * a regulatory request issued by the regulatory core.
1907 */ 1910 */
1908static void reg_process_hint_core(struct regulatory_request *core_request) 1911static enum reg_request_treatment
1912reg_process_hint_core(struct regulatory_request *core_request)
1909{ 1913{
1910 if (reg_query_database(core_request)) { 1914 if (reg_query_database(core_request)) {
1911 core_request->intersect = false; 1915 core_request->intersect = false;
1912 core_request->processed = false; 1916 core_request->processed = false;
1913 reg_update_last_request(core_request); 1917 reg_update_last_request(core_request);
1918 return REG_REQ_OK;
1914 } 1919 }
1920
1921 return REG_REQ_IGNORE;
1915} 1922}
1916 1923
1917static enum reg_request_treatment 1924static enum reg_request_treatment
@@ -1957,16 +1964,15 @@ __reg_process_hint_user(struct regulatory_request *user_request)
1957 * The wireless subsystem can use this function to process 1964 * The wireless subsystem can use this function to process
1958 * a regulatory request initiated by userspace. 1965 * a regulatory request initiated by userspace.
1959 */ 1966 */
1960static void reg_process_hint_user(struct regulatory_request *user_request) 1967static enum reg_request_treatment
1968reg_process_hint_user(struct regulatory_request *user_request)
1961{ 1969{
1962 enum reg_request_treatment treatment; 1970 enum reg_request_treatment treatment;
1963 1971
1964 treatment = __reg_process_hint_user(user_request); 1972 treatment = __reg_process_hint_user(user_request);
1965 if (treatment == REG_REQ_IGNORE || 1973 if (treatment == REG_REQ_IGNORE ||
1966 treatment == REG_REQ_ALREADY_SET) { 1974 treatment == REG_REQ_ALREADY_SET)
1967 reg_free_request(user_request); 1975 return REG_REQ_IGNORE;
1968 return;
1969 }
1970 1976
1971 user_request->intersect = treatment == REG_REQ_INTERSECT; 1977 user_request->intersect = treatment == REG_REQ_INTERSECT;
1972 user_request->processed = false; 1978 user_request->processed = false;
@@ -1975,9 +1981,10 @@ static void reg_process_hint_user(struct regulatory_request *user_request)
1975 reg_update_last_request(user_request); 1981 reg_update_last_request(user_request);
1976 user_alpha2[0] = user_request->alpha2[0]; 1982 user_alpha2[0] = user_request->alpha2[0];
1977 user_alpha2[1] = user_request->alpha2[1]; 1983 user_alpha2[1] = user_request->alpha2[1];
1978 } else { 1984 return REG_REQ_OK;
1979 reg_free_request(user_request);
1980 } 1985 }
1986
1987 return REG_REQ_IGNORE;
1981} 1988}
1982 1989
1983static enum reg_request_treatment 1990static enum reg_request_treatment
@@ -2025,15 +2032,12 @@ reg_process_hint_driver(struct wiphy *wiphy,
2025 case REG_REQ_OK: 2032 case REG_REQ_OK:
2026 break; 2033 break;
2027 case REG_REQ_IGNORE: 2034 case REG_REQ_IGNORE:
2028 reg_free_request(driver_request); 2035 return REG_REQ_IGNORE;
2029 return REG_REQ_OK;
2030 case REG_REQ_INTERSECT: 2036 case REG_REQ_INTERSECT:
2031 case REG_REQ_ALREADY_SET: 2037 case REG_REQ_ALREADY_SET:
2032 regd = reg_copy_regd(get_cfg80211_regdom()); 2038 regd = reg_copy_regd(get_cfg80211_regdom());
2033 if (IS_ERR(regd)) { 2039 if (IS_ERR(regd))
2034 reg_free_request(driver_request); 2040 return REG_REQ_IGNORE;
2035 return REG_REQ_OK;
2036 }
2037 2041
2038 tmp = get_wiphy_regdom(wiphy); 2042 tmp = get_wiphy_regdom(wiphy);
2039 rcu_assign_pointer(wiphy->regd, regd); 2043 rcu_assign_pointer(wiphy->regd, regd);
@@ -2056,12 +2060,12 @@ reg_process_hint_driver(struct wiphy *wiphy,
2056 return REG_REQ_ALREADY_SET; 2060 return REG_REQ_ALREADY_SET;
2057 } 2061 }
2058 2062
2059 if (reg_query_database(driver_request)) 2063 if (reg_query_database(driver_request)) {
2060 reg_update_last_request(driver_request); 2064 reg_update_last_request(driver_request);
2061 else 2065 return REG_REQ_OK;
2062 reg_free_request(driver_request); 2066 }
2063 2067
2064 return REG_REQ_OK; 2068 return REG_REQ_IGNORE;
2065} 2069}
2066 2070
2067static enum reg_request_treatment 2071static enum reg_request_treatment
@@ -2127,29 +2131,28 @@ reg_process_hint_country_ie(struct wiphy *wiphy,
2127 case REG_REQ_OK: 2131 case REG_REQ_OK:
2128 break; 2132 break;
2129 case REG_REQ_IGNORE: 2133 case REG_REQ_IGNORE:
2130 return REG_REQ_OK; 2134 return REG_REQ_IGNORE;
2131 case REG_REQ_ALREADY_SET: 2135 case REG_REQ_ALREADY_SET:
2132 reg_free_request(country_ie_request); 2136 reg_free_request(country_ie_request);
2133 return REG_REQ_ALREADY_SET; 2137 return REG_REQ_ALREADY_SET;
2134 case REG_REQ_INTERSECT: 2138 case REG_REQ_INTERSECT:
2135 reg_free_request(country_ie_request);
2136 /* 2139 /*
2137 * This doesn't happen yet, not sure we 2140 * This doesn't happen yet, not sure we
2138 * ever want to support it for this case. 2141 * ever want to support it for this case.
2139 */ 2142 */
2140 WARN_ONCE(1, "Unexpected intersection for country IEs"); 2143 WARN_ONCE(1, "Unexpected intersection for country IEs");
2141 return REG_REQ_OK; 2144 return REG_REQ_IGNORE;
2142 } 2145 }
2143 2146
2144 country_ie_request->intersect = false; 2147 country_ie_request->intersect = false;
2145 country_ie_request->processed = false; 2148 country_ie_request->processed = false;
2146 2149
2147 if (reg_query_database(country_ie_request)) 2150 if (reg_query_database(country_ie_request)) {
2148 reg_update_last_request(country_ie_request); 2151 reg_update_last_request(country_ie_request);
2149 else 2152 return REG_REQ_OK;
2150 reg_free_request(country_ie_request); 2153 }
2151 2154
2152 return REG_REQ_OK; 2155 return REG_REQ_IGNORE;
2153} 2156}
2154 2157
2155/* This processes *all* regulatory hints */ 2158/* This processes *all* regulatory hints */
@@ -2163,11 +2166,11 @@ static void reg_process_hint(struct regulatory_request *reg_request)
2163 2166
2164 switch (reg_request->initiator) { 2167 switch (reg_request->initiator) {
2165 case NL80211_REGDOM_SET_BY_CORE: 2168 case NL80211_REGDOM_SET_BY_CORE:
2166 reg_process_hint_core(reg_request); 2169 treatment = reg_process_hint_core(reg_request);
2167 return; 2170 break;
2168 case NL80211_REGDOM_SET_BY_USER: 2171 case NL80211_REGDOM_SET_BY_USER:
2169 reg_process_hint_user(reg_request); 2172 treatment = reg_process_hint_user(reg_request);
2170 return; 2173 break;
2171 case NL80211_REGDOM_SET_BY_DRIVER: 2174 case NL80211_REGDOM_SET_BY_DRIVER:
2172 if (!wiphy) 2175 if (!wiphy)
2173 goto out_free; 2176 goto out_free;
@@ -2183,6 +2186,9 @@ static void reg_process_hint(struct regulatory_request *reg_request)
2183 goto out_free; 2186 goto out_free;
2184 } 2187 }
2185 2188
2189 if (treatment == REG_REQ_IGNORE)
2190 goto out_free;
2191
2186 WARN(treatment != REG_REQ_OK && treatment != REG_REQ_ALREADY_SET, 2192 WARN(treatment != REG_REQ_OK && treatment != REG_REQ_ALREADY_SET,
2187 "unexpected treatment value %d\n", treatment); 2193 "unexpected treatment value %d\n", treatment);
2188 2194