Commit eb507906 authored by David S. Miller's avatar David S. Miller

Merge tag 'mac80211-for-net-2020-01-15' of...

Merge tag 'mac80211-for-net-2020-01-15' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211

Johannes Berg says:

====================
A few fixes:
 * -O3 enablement fallout, thanks to Arnd who ran this
 * fixes for a few leaks, thanks to Felix
 * channel 12 regulatory fix for custom regdomains
 * check for a crash reported by syzbot
   (NULL function is called on drivers that don't have it)
 * fix TKIP replay protection after setup with some APs
   (from Jouni)
 * restrict obtaining some mesh data to avoid WARN_ONs
 * fix deadlocks with auto-disconnect (socket owner)
 * fix radar detection events with multiple devices
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8c4df83f 81c044fc
...@@ -3548,6 +3548,9 @@ struct cfg80211_update_owe_info { ...@@ -3548,6 +3548,9 @@ struct cfg80211_update_owe_info {
* *
* @start_radar_detection: Start radar detection in the driver. * @start_radar_detection: Start radar detection in the driver.
* *
* @end_cac: End running CAC, probably because a related CAC
* was finished on another phy.
*
* @update_ft_ies: Provide updated Fast BSS Transition information to the * @update_ft_ies: Provide updated Fast BSS Transition information to the
* driver. If the SME is in the driver/firmware, this information can be * driver. If the SME is in the driver/firmware, this information can be
* used in building Authentication and Reassociation Request frames. * used in building Authentication and Reassociation Request frames.
...@@ -3874,6 +3877,8 @@ struct cfg80211_ops { ...@@ -3874,6 +3877,8 @@ struct cfg80211_ops {
struct net_device *dev, struct net_device *dev,
struct cfg80211_chan_def *chandef, struct cfg80211_chan_def *chandef,
u32 cac_time_ms); u32 cac_time_ms);
void (*end_cac)(struct wiphy *wiphy,
struct net_device *dev);
int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev, int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_update_ft_ies_params *ftie); struct cfg80211_update_ft_ies_params *ftie);
int (*crit_proto_start)(struct wiphy *wiphy, int (*crit_proto_start)(struct wiphy *wiphy,
......
...@@ -2954,6 +2954,28 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy, ...@@ -2954,6 +2954,28 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
return err; return err;
} }
static void ieee80211_end_cac(struct wiphy *wiphy,
struct net_device *dev)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
mutex_lock(&local->mtx);
list_for_each_entry(sdata, &local->interfaces, list) {
/* it might be waiting for the local->mtx, but then
* by the time it gets it, sdata->wdev.cac_started
* will no longer be true
*/
cancel_delayed_work(&sdata->dfs_cac_timer_work);
if (sdata->wdev.cac_started) {
ieee80211_vif_release_channel(sdata);
sdata->wdev.cac_started = false;
}
}
mutex_unlock(&local->mtx);
}
static struct cfg80211_beacon_data * static struct cfg80211_beacon_data *
cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon) cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon)
{ {
...@@ -4023,6 +4045,7 @@ const struct cfg80211_ops mac80211_config_ops = { ...@@ -4023,6 +4045,7 @@ const struct cfg80211_ops mac80211_config_ops = {
#endif #endif
.get_channel = ieee80211_cfg_get_channel, .get_channel = ieee80211_cfg_get_channel,
.start_radar_detection = ieee80211_start_radar_detection, .start_radar_detection = ieee80211_start_radar_detection,
.end_cac = ieee80211_end_cac,
.channel_switch = ieee80211_channel_switch, .channel_switch = ieee80211_channel_switch,
.set_qos_map = ieee80211_set_qos_map, .set_qos_map = ieee80211_set_qos_map,
.set_ap_chanwidth = ieee80211_set_ap_chanwidth, .set_ap_chanwidth = ieee80211_set_ap_chanwidth,
......
...@@ -328,6 +328,9 @@ u32 airtime_link_metric_get(struct ieee80211_local *local, ...@@ -328,6 +328,9 @@ u32 airtime_link_metric_get(struct ieee80211_local *local,
unsigned long fail_avg = unsigned long fail_avg =
ewma_mesh_fail_avg_read(&sta->mesh->fail_avg); ewma_mesh_fail_avg_read(&sta->mesh->fail_avg);
if (sta->mesh->plink_state != NL80211_PLINK_ESTAB)
return MAX_METRIC;
/* Try to get rate based on HW/SW RC algorithm. /* Try to get rate based on HW/SW RC algorithm.
* Rate is returned in units of Kbps, correct this * Rate is returned in units of Kbps, correct this
* to comply with airtime calculation units * to comply with airtime calculation units
......
...@@ -263,9 +263,21 @@ int ieee80211_tkip_decrypt_data(struct arc4_ctx *ctx, ...@@ -263,9 +263,21 @@ int ieee80211_tkip_decrypt_data(struct arc4_ctx *ctx,
if ((keyid >> 6) != key->conf.keyidx) if ((keyid >> 6) != key->conf.keyidx)
return TKIP_DECRYPT_INVALID_KEYIDX; return TKIP_DECRYPT_INVALID_KEYIDX;
if (rx_ctx->ctx.state != TKIP_STATE_NOT_INIT && /* Reject replays if the received TSC is smaller than or equal to the
(iv32 < rx_ctx->iv32 || * last received value in a valid message, but with an exception for
(iv32 == rx_ctx->iv32 && iv16 <= rx_ctx->iv16))) * the case where a new key has been set and no valid frame using that
* key has yet received and the local RSC was initialized to 0. This
* exception allows the very first frame sent by the transmitter to be
* accepted even if that transmitter were to use TSC 0 (IEEE 802.11
* described TSC to be initialized to 1 whenever a new key is taken into
* use).
*/
if (iv32 < rx_ctx->iv32 ||
(iv32 == rx_ctx->iv32 &&
(iv16 < rx_ctx->iv16 ||
(iv16 == rx_ctx->iv16 &&
(rx_ctx->iv32 || rx_ctx->iv16 ||
rx_ctx->ctx.state != TKIP_STATE_NOT_INIT)))))
return TKIP_DECRYPT_REPLAY; return TKIP_DECRYPT_REPLAY;
if (only_iv) { if (only_iv) {
......
...@@ -10843,6 +10843,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, ...@@ -10843,6 +10843,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
if (err) if (err)
return err; return err;
cfg80211_sinfo_release_content(&sinfo);
if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG)) if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG))
wdev->cqm_config->last_rssi_event_value = wdev->cqm_config->last_rssi_event_value =
(s8) sinfo.rx_beacon_signal_avg; (s8) sinfo.rx_beacon_signal_avg;
...@@ -13796,6 +13797,8 @@ static int nl80211_probe_mesh_link(struct sk_buff *skb, struct genl_info *info) ...@@ -13796,6 +13797,8 @@ static int nl80211_probe_mesh_link(struct sk_buff *skb, struct genl_info *info)
if (err) if (err)
return err; return err;
cfg80211_sinfo_release_content(&sinfo);
return rdev_probe_mesh_link(rdev, dev, dest, buf, len); return rdev_probe_mesh_link(rdev, dev, dest, buf, len);
} }
......
...@@ -538,6 +538,10 @@ static inline int ...@@ -538,6 +538,10 @@ static inline int
rdev_set_wiphy_params(struct cfg80211_registered_device *rdev, u32 changed) rdev_set_wiphy_params(struct cfg80211_registered_device *rdev, u32 changed)
{ {
int ret; int ret;
if (!rdev->ops->set_wiphy_params)
return -EOPNOTSUPP;
trace_rdev_set_wiphy_params(&rdev->wiphy, changed); trace_rdev_set_wiphy_params(&rdev->wiphy, changed);
ret = rdev->ops->set_wiphy_params(&rdev->wiphy, changed); ret = rdev->ops->set_wiphy_params(&rdev->wiphy, changed);
trace_rdev_return_int(&rdev->wiphy, ret); trace_rdev_return_int(&rdev->wiphy, ret);
...@@ -1167,6 +1171,16 @@ rdev_start_radar_detection(struct cfg80211_registered_device *rdev, ...@@ -1167,6 +1171,16 @@ rdev_start_radar_detection(struct cfg80211_registered_device *rdev,
return ret; return ret;
} }
static inline void
rdev_end_cac(struct cfg80211_registered_device *rdev,
struct net_device *dev)
{
trace_rdev_end_cac(&rdev->wiphy, dev);
if (rdev->ops->end_cac)
rdev->ops->end_cac(&rdev->wiphy, dev);
trace_rdev_return_void(&rdev->wiphy);
}
static inline int static inline int
rdev_set_mcast_rate(struct cfg80211_registered_device *rdev, rdev_set_mcast_rate(struct cfg80211_registered_device *rdev,
struct net_device *dev, struct net_device *dev,
......
...@@ -2261,14 +2261,15 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) ...@@ -2261,14 +2261,15 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
static void handle_channel_custom(struct wiphy *wiphy, static void handle_channel_custom(struct wiphy *wiphy,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
const struct ieee80211_regdomain *regd) const struct ieee80211_regdomain *regd,
u32 min_bw)
{ {
u32 bw_flags = 0; u32 bw_flags = 0;
const struct ieee80211_reg_rule *reg_rule = NULL; const struct ieee80211_reg_rule *reg_rule = NULL;
const struct ieee80211_power_rule *power_rule = NULL; const struct ieee80211_power_rule *power_rule = NULL;
u32 bw; u32 bw;
for (bw = MHZ_TO_KHZ(20); bw >= MHZ_TO_KHZ(5); bw = bw / 2) { for (bw = MHZ_TO_KHZ(20); bw >= min_bw; bw = bw / 2) {
reg_rule = freq_reg_info_regd(MHZ_TO_KHZ(chan->center_freq), reg_rule = freq_reg_info_regd(MHZ_TO_KHZ(chan->center_freq),
regd, bw); regd, bw);
if (!IS_ERR(reg_rule)) if (!IS_ERR(reg_rule))
...@@ -2324,8 +2325,14 @@ static void handle_band_custom(struct wiphy *wiphy, ...@@ -2324,8 +2325,14 @@ static void handle_band_custom(struct wiphy *wiphy,
if (!sband) if (!sband)
return; return;
/*
* We currently assume that you always want at least 20 MHz,
* otherwise channel 12 might get enabled if this rule is
* compatible to US, which permits 2402 - 2472 MHz.
*/
for (i = 0; i < sband->n_channels; i++) for (i = 0; i < sband->n_channels; i++)
handle_channel_custom(wiphy, &sband->channels[i], regd); handle_channel_custom(wiphy, &sband->channels[i], regd,
MHZ_TO_KHZ(20));
} }
/* Used by drivers prior to wiphy registration */ /* Used by drivers prior to wiphy registration */
...@@ -3885,6 +3892,25 @@ bool regulatory_pre_cac_allowed(struct wiphy *wiphy) ...@@ -3885,6 +3892,25 @@ bool regulatory_pre_cac_allowed(struct wiphy *wiphy)
} }
EXPORT_SYMBOL(regulatory_pre_cac_allowed); EXPORT_SYMBOL(regulatory_pre_cac_allowed);
static void cfg80211_check_and_end_cac(struct cfg80211_registered_device *rdev)
{
struct wireless_dev *wdev;
/* If we finished CAC or received radar, we should end any
* CAC running on the same channels.
* the check !cfg80211_chandef_dfs_usable contain 2 options:
* either all channels are available - those the CAC_FINISHED
* event has effected another wdev state, or there is a channel
* in unavailable state in wdev chandef - those the RADAR_DETECTED
* event has effected another wdev state.
* In both cases we should end the CAC on the wdev.
*/
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
if (wdev->cac_started &&
!cfg80211_chandef_dfs_usable(&rdev->wiphy, &wdev->chandef))
rdev_end_cac(rdev, wdev->netdev);
}
}
void regulatory_propagate_dfs_state(struct wiphy *wiphy, void regulatory_propagate_dfs_state(struct wiphy *wiphy,
struct cfg80211_chan_def *chandef, struct cfg80211_chan_def *chandef,
enum nl80211_dfs_state dfs_state, enum nl80211_dfs_state dfs_state,
...@@ -3911,8 +3937,10 @@ void regulatory_propagate_dfs_state(struct wiphy *wiphy, ...@@ -3911,8 +3937,10 @@ void regulatory_propagate_dfs_state(struct wiphy *wiphy,
cfg80211_set_dfs_state(&rdev->wiphy, chandef, dfs_state); cfg80211_set_dfs_state(&rdev->wiphy, chandef, dfs_state);
if (event == NL80211_RADAR_DETECTED || if (event == NL80211_RADAR_DETECTED ||
event == NL80211_RADAR_CAC_FINISHED) event == NL80211_RADAR_CAC_FINISHED) {
cfg80211_sched_dfs_chan_update(rdev); cfg80211_sched_dfs_chan_update(rdev);
cfg80211_check_and_end_cac(rdev);
}
nl80211_radar_notify(rdev, chandef, event, NULL, GFP_KERNEL); nl80211_radar_notify(rdev, chandef, event, NULL, GFP_KERNEL);
} }
......
...@@ -1307,14 +1307,14 @@ void cfg80211_autodisconnect_wk(struct work_struct *work) ...@@ -1307,14 +1307,14 @@ void cfg80211_autodisconnect_wk(struct work_struct *work)
if (wdev->conn_owner_nlportid) { if (wdev->conn_owner_nlportid) {
switch (wdev->iftype) { switch (wdev->iftype) {
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
cfg80211_leave_ibss(rdev, wdev->netdev, false); __cfg80211_leave_ibss(rdev, wdev->netdev, false);
break; break;
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO: case NL80211_IFTYPE_P2P_GO:
cfg80211_stop_ap(rdev, wdev->netdev, false); __cfg80211_stop_ap(rdev, wdev->netdev, false);
break; break;
case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_MESH_POINT:
cfg80211_leave_mesh(rdev, wdev->netdev); __cfg80211_leave_mesh(rdev, wdev->netdev);
break; break;
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_P2P_CLIENT:
......
...@@ -646,6 +646,11 @@ DEFINE_EVENT(wiphy_netdev_evt, rdev_flush_pmksa, ...@@ -646,6 +646,11 @@ DEFINE_EVENT(wiphy_netdev_evt, rdev_flush_pmksa,
TP_ARGS(wiphy, netdev) TP_ARGS(wiphy, netdev)
); );
DEFINE_EVENT(wiphy_netdev_evt, rdev_end_cac,
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
TP_ARGS(wiphy, netdev)
);
DECLARE_EVENT_CLASS(station_add_change, DECLARE_EVENT_CLASS(station_add_change,
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 *mac, TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 *mac,
struct station_parameters *params), struct station_parameters *params),
......
...@@ -564,7 +564,7 @@ __frame_add_frag(struct sk_buff *skb, struct page *page, ...@@ -564,7 +564,7 @@ __frame_add_frag(struct sk_buff *skb, struct page *page,
struct skb_shared_info *sh = skb_shinfo(skb); struct skb_shared_info *sh = skb_shinfo(skb);
int page_offset; int page_offset;
page_ref_inc(page); get_page(page);
page_offset = ptr - page_address(page); page_offset = ptr - page_address(page);
skb_add_rx_frag(skb, sh->nr_frags, page, page_offset, len, size); skb_add_rx_frag(skb, sh->nr_frags, page, page_offset, len, size);
} }
......
...@@ -657,7 +657,8 @@ struct iw_statistics *get_wireless_stats(struct net_device *dev) ...@@ -657,7 +657,8 @@ struct iw_statistics *get_wireless_stats(struct net_device *dev)
return NULL; return NULL;
} }
static int iw_handler_get_iwstats(struct net_device * dev, /* noinline to avoid a bogus warning with -O3 */
static noinline int iw_handler_get_iwstats(struct net_device * dev,
struct iw_request_info * info, struct iw_request_info * info,
union iwreq_data * wrqu, union iwreq_data * wrqu,
char * extra) char * extra)
......
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