From patchwork Wed Jun 12 12:28:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 13694893 X-Patchwork-Delegate: johannes@sipsolutions.net Received: from sipsolutions.net (s3.sipsolutions.net [168.119.38.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EA0DC14E2ED for ; Wed, 12 Jun 2024 12:30:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=168.119.38.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718195449; cv=none; b=Lc2XAiQRKomsBbSMEFhAQA2yiUtAWmvI5TCH3YvWkggNT9kx2yUIziA7rTBDOVC4uyK0Nrmlarbc1OvbaO47hNfd0lGTxbkgpAjbIBQfjCTYFYHFgdE9epKFLtzxXkUdITUmtdK/vHsGtsrnijgwraMRNAZIgfJ/61TXXYzGyxI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718195449; c=relaxed/simple; bh=WCogMhUgOX1OREF4rhsOes1Vkd+EtoLDjwiOmGHncwQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XwgHZd7rtM5J1sfZkUivX/QmmxQKcHNVPWWH9HLs/9IlItBNixmQ+UG4NSPS17wDCfZ9+z9ULGL4KXnFG3RjdzVDbwB7blDAtGSyUsbUe0UAgJAYma3/ULA85LZrWeFwDVM4R145u1tDn/oI4YIDifTPqTTbpND/kE6BjV7H5i8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sipsolutions.net; spf=pass smtp.mailfrom=sipsolutions.net; dkim=pass (2048-bit key) header.d=sipsolutions.net header.i=@sipsolutions.net header.b=bd55W97S; arc=none smtp.client-ip=168.119.38.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sipsolutions.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=sipsolutions.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=sipsolutions.net header.i=@sipsolutions.net header.b="bd55W97S" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=QKXjViKQthO3mP8DrmMgh5GD1NR0gqfmc1M9peKCgr8=; t=1718195448; x=1719405048; b=bd55W97SLeHVtp39dOy0dN6fKiTmMTesJizuzs/X9mWYeal lSWrsXEyWq6AeF4I0ojYIfEZ3qZwhuAbqDNdycyOfe8W+7Y68ItlRfb9ontEDiZZ0o+44lDU2KJVk Z/wvtVjnwDFWRIJILPWv33092pY+v6g50GTn7hg23Ppn7bB3MYKzZtTyZ0jVnKuQ1uQ03nsccMlQu tw/ukijeLWl4UokUjFRMvjGjB+hMElYLPmZhelE8VLf5a1g/aKGQgY35Ijso1b0i32hWbVFcADmB3 kx1UXq150dPV7UwjyYiSliMOS4YaU3CoDIMl7hiAgStvZhMeaAOQIYbbveLViv9g==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.97) (envelope-from ) id 1sHN7l-0000000AGRh-11mF; Wed, 12 Jun 2024 14:30:45 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg , Miriam Rachel Korenblit Subject: [PATCH 1/3] wifi: mac80211: refactor CSA queue block/unblock Date: Wed, 12 Jun 2024 14:28:35 +0200 Message-ID: <20240612143037.1ad22f10392d.If21490c2c67aae28f3c54038363181ee920ce3d1@changeid> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240612123037.36687-5-johannes@sipsolutions.net> References: <20240612123037.36687-5-johannes@sipsolutions.net> Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Johannes Berg This code is duplicated many times, refactor it into new separate functions. Reviewed-by: Miriam Rachel Korenblit Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 20 ++++---------------- net/mac80211/ieee80211_i.h | 3 +++ net/mac80211/iface.c | 29 ++++++++++++++++++++++++----- net/mac80211/mlme.c | 33 ++++++--------------------------- 4 files changed, 37 insertions(+), 48 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 3236477424b8..7eb2e5bedb6f 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1615,11 +1615,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev, /* abort any running channel switch or color change */ link_conf->csa_active = false; link_conf->color_change_active = false; - if (sdata->csa_blocked_queues) { - ieee80211_wake_vif_queues(local, sdata, - IEEE80211_QUEUE_STOP_REASON_CSA); - sdata->csa_blocked_queues = false; - } + ieee80211_vif_unblock_queues_csa(sdata); ieee80211_free_next_beacon(link); @@ -3757,11 +3753,7 @@ static int __ieee80211_csa_finalize(struct ieee80211_link_data *link_data) ieee80211_link_info_change_notify(sdata, link_data, changed); - if (sdata->csa_blocked_queues) { - ieee80211_wake_vif_queues(local, sdata, - IEEE80211_QUEUE_STOP_REASON_CSA); - sdata->csa_blocked_queues = false; - } + ieee80211_vif_unblock_queues_csa(sdata); err = drv_post_channel_switch(link_data); if (err) @@ -4038,12 +4030,8 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, link_data->csa.chanreq = chanreq; link_conf->csa_active = true; - if (params->block_tx && - !ieee80211_hw_check(&local->hw, HANDLES_QUIET_CSA)) { - ieee80211_stop_vif_queues(local, sdata, - IEEE80211_QUEUE_STOP_REASON_CSA); - sdata->csa_blocked_queues = true; - } + if (params->block_tx) + ieee80211_vif_block_queues_csa(sdata); cfg80211_ch_switch_started_notify(sdata->dev, &link_data->csa.chanreq.oper, link_id, diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3e735c9436d3..b482763e9f99 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1823,6 +1823,9 @@ ieee80211_have_rx_timestamp(struct ieee80211_rx_status *status) void ieee80211_vif_inc_num_mcast(struct ieee80211_sub_if_data *sdata); void ieee80211_vif_dec_num_mcast(struct ieee80211_sub_if_data *sdata); +void ieee80211_vif_block_queues_csa(struct ieee80211_sub_if_data *sdata); +void ieee80211_vif_unblock_queues_csa(struct ieee80211_sub_if_data *sdata); + /* This function returns the number of multicast stations connected to this * interface. It returns -1 if that number is not tracked, that is for netdevs * not in AP or AP_VLAN mode or when using 4addr. diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 6b7580c61e0c..f06e165d6c7a 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -544,11 +544,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do sdata->vif.bss_conf.csa_active = false; if (sdata->vif.type == NL80211_IFTYPE_STATION) sdata->deflink.u.mgd.csa.waiting_bcn = false; - if (sdata->csa_blocked_queues) { - ieee80211_wake_vif_queues(local, sdata, - IEEE80211_QUEUE_STOP_REASON_CSA); - sdata->csa_blocked_queues = false; - } + ieee80211_vif_unblock_queues_csa(sdata); wiphy_work_cancel(local->hw.wiphy, &sdata->deflink.csa.finalize_work); wiphy_work_cancel(local->hw.wiphy, @@ -2345,3 +2341,26 @@ void ieee80211_vif_dec_num_mcast(struct ieee80211_sub_if_data *sdata) else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) atomic_dec(&sdata->u.vlan.num_mcast_sta); } + +void ieee80211_vif_block_queues_csa(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + + if (ieee80211_hw_check(&local->hw, HANDLES_QUIET_CSA)) + return; + + ieee80211_stop_vif_queues(local, sdata, + IEEE80211_QUEUE_STOP_REASON_CSA); + sdata->csa_blocked_queues = true; +} + +void ieee80211_vif_unblock_queues_csa(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + + if (sdata->csa_blocked_queues) { + ieee80211_wake_vif_queues(local, sdata, + IEEE80211_QUEUE_STOP_REASON_CSA); + sdata->csa_blocked_queues = false; + } +} diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ef3280fafbe9..ac376ec47a59 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2166,7 +2166,6 @@ static void ieee80211_csa_switch_work(struct wiphy *wiphy, static void ieee80211_chswitch_post_beacon(struct ieee80211_link_data *link) { struct ieee80211_sub_if_data *sdata = link->sdata; - struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; int ret; @@ -2174,11 +2173,7 @@ static void ieee80211_chswitch_post_beacon(struct ieee80211_link_data *link) WARN_ON(!link->conf->csa_active); - if (sdata->csa_blocked_queues) { - ieee80211_wake_vif_queues(local, sdata, - IEEE80211_QUEUE_STOP_REASON_CSA); - sdata->csa_blocked_queues = false; - } + ieee80211_vif_unblock_queues_csa(sdata); link->conf->csa_active = false; link->u.mgd.csa.blocked_tx = false; @@ -2242,11 +2237,7 @@ ieee80211_sta_abort_chanswitch(struct ieee80211_link_data *link) ieee80211_link_unreserve_chanctx(link); - if (sdata->csa_blocked_queues) { - ieee80211_wake_vif_queues(local, sdata, - IEEE80211_QUEUE_STOP_REASON_CSA); - sdata->csa_blocked_queues = false; - } + ieee80211_vif_unblock_queues_csa(sdata); link->conf->csa_active = false; link->u.mgd.csa.blocked_tx = false; @@ -2571,12 +2562,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link, link->u.mgd.beacon_crc_valid = false; link->u.mgd.csa.blocked_tx = csa_ie.mode; - if (csa_ie.mode && - !ieee80211_hw_check(&local->hw, HANDLES_QUIET_CSA)) { - ieee80211_stop_vif_queues(local, sdata, - IEEE80211_QUEUE_STOP_REASON_CSA); - sdata->csa_blocked_queues = true; - } + if (csa_ie.mode) + ieee80211_vif_block_queues_csa(sdata); cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chanreq.oper, link->link_id, csa_ie.count, @@ -3670,11 +3657,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, sdata->deflink.u.mgd.csa.blocked_tx = false; sdata->deflink.u.mgd.csa.waiting_bcn = false; sdata->deflink.u.mgd.csa.ignored_same_chan = false; - if (sdata->csa_blocked_queues) { - ieee80211_wake_vif_queues(local, sdata, - IEEE80211_QUEUE_STOP_REASON_CSA); - sdata->csa_blocked_queues = false; - } + ieee80211_vif_unblock_queues_csa(sdata); /* existing TX TSPEC sessions no longer exist */ memset(ifmgd->tx_tspec, 0, sizeof(ifmgd->tx_tspec)); @@ -4045,11 +4028,7 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) sdata->vif.bss_conf.csa_active = false; sdata->deflink.u.mgd.csa.waiting_bcn = false; sdata->deflink.u.mgd.csa.blocked_tx = false; - if (sdata->csa_blocked_queues) { - ieee80211_wake_vif_queues(local, sdata, - IEEE80211_QUEUE_STOP_REASON_CSA); - sdata->csa_blocked_queues = false; - } + ieee80211_vif_unblock_queues_csa(sdata); ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), tx, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, From patchwork Wed Jun 12 12:28:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 13694895 X-Patchwork-Delegate: johannes@sipsolutions.net Received: from sipsolutions.net (s3.sipsolutions.net [168.119.38.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 90BE0172BB4 for ; Wed, 12 Jun 2024 12:30:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=168.119.38.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718195452; cv=none; b=kzax9fsaoymxfCIEtcjUnf+4ValC3eTeDjZs5b/HD8Q3hPRaNBVZj9MVdyituVpProuKL3LTHuZm0PAnUkasgJqALGFdAoouhopmek0WQlN9g2gRrcjbyQOJ9k4UFwnOibXKxNZDNl53beNnfO560o6aoXDE2V1Z1bgqZBpxrY8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718195452; c=relaxed/simple; bh=rXWVpPJSmrZeIMwIYPumKfK4GVLNb4W1vc4dJkf2o4A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=B6E/XRVh3PzIC8bfNfvMDKp5VaZivulqNf3AyJHW9P+HS/8MUPd9nwTtjp9Zb3UpuWe4JFnhtSGoMVyFrY23tMy0jP56qXakXaFtjU62zovEyXZAKIJqtGUgxvj4+PA4bJe95jMP6rbbERVHczqaPc0Yzw8sHuXIAghiIhgot44= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sipsolutions.net; spf=pass smtp.mailfrom=sipsolutions.net; dkim=pass (2048-bit key) header.d=sipsolutions.net header.i=@sipsolutions.net header.b=hXT7fCCj; arc=none smtp.client-ip=168.119.38.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sipsolutions.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=sipsolutions.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=sipsolutions.net header.i=@sipsolutions.net header.b="hXT7fCCj" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=f+tBL6jsuxg4/cteUR+Zg4T0+hK93MbFfuCAnwuxS4Q=; t=1718195450; x=1719405050; b=hXT7fCCjOIGXwFWbtinKEi9/jLM9pd0QXaVcD38g7ONDxQt AxDdBf9CZnEgZ5C36Ygzkykj0+EFu4Fxe80p/rprTVixmbO+KLlKbCiJtldX3hhy6oCrHEV4+ZbtF RXSkVf56f5G8Ld5AfRbLV77cztGDbNj/MsuWF0NQEFZ50w1Gryl6w7Gk5bbP4rFtyrGKhTkT8zHpK yVOAP1dJwjTm4ThTBmqjut5PSBOqHoZAAMy3OIArAASPEKhFJflZPGbdAo39jJci765L/dr8sTq9m vyTdLeXexUsltJtBc2Mhp2QBKxFRC68HdlXFMZIS6JNBaFZkTAEjgFjlhLXXwEsg==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.97) (envelope-from ) id 1sHN7m-0000000AGRh-07bo; Wed, 12 Jun 2024 14:30:46 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg , Miriam Rachel Korenblit Subject: [PATCH 2/3] wifi: mac80211: restrict public action ECSA frame handling Date: Wed, 12 Jun 2024 14:28:36 +0200 Message-ID: <20240612143037.ec7ccc45903e.Ife17d55c7ecbf98060f9c52889f3c8ba48798970@changeid> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240612123037.36687-5-johannes@sipsolutions.net> References: <20240612123037.36687-5-johannes@sipsolutions.net> Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Johannes Berg Public action extended channel switch announcement (ECSA) frames cannot be protected well, the spec is unclear about what should happen in the presence of stations that can receive protected dual and stations that cannot. Mitigate these issues by not treating public action frames as the absolute truth, only treat them as a hint to stop transmitting (quiet mode), and do the remainder of the CSA handling only when receiving the next beacon (or protected action frame) that contains the CSA; or, if it doesn't, simply stop being quiet and continue operating normally. This limits the exposure to malicious ECSA public action frames, since they cannot cause a disconnect now, only a short interruption in traffic. Reviewed-by: Miriam Rachel Korenblit Signed-off-by: Johannes Berg --- net/mac80211/ibss.c | 3 +- net/mac80211/ieee80211_i.h | 4 ++- net/mac80211/mesh.c | 2 +- net/mac80211/mlme.c | 59 ++++++++++++++++++++++++++++++++------ net/mac80211/spectmgmt.c | 15 ++++++---- 5 files changed, 65 insertions(+), 18 deletions(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index bf338f3d4dd3..7db4c3ee7e6d 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -785,7 +785,8 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, err = ieee80211_parse_ch_switch_ie(sdata, elems, ifibss->chandef.chan->band, vht_cap_info, &conn, - ifibss->bssid, &csa_ie); + ifibss->bssid, false, + &csa_ie); /* can't switch to destination channel, fail */ if (err < 0) goto disconnect; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index b482763e9f99..cb3e28f88089 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -2218,6 +2218,8 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, * @conn: contains information about own capabilities and restrictions * to decide which channel switch announcements can be accepted * @bssid: the currently connected bssid (for reporting) + * @unprot_action: whether the frame was an unprotected frame or not, + * used for reporting * @csa_ie: parsed 802.11 csa elements on count, mode, chandef and mesh ttl. * All of them will be filled with if success only. * Return: 0 on success, <0 on error and >0 if there is nothing to parse. @@ -2227,7 +2229,7 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, enum nl80211_band current_band, u32 vht_cap_info, struct ieee80211_conn_settings *conn, - u8 *bssid, + u8 *bssid, bool unprot_action, struct ieee80211_csa_ie *csa_ie); /* Suspend/resume and hw reconfiguration */ diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 6d4510221c98..f94e4be0be12 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -1312,7 +1312,7 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, memset(¶ms, 0, sizeof(params)); err = ieee80211_parse_ch_switch_ie(sdata, elems, sband->band, vht_cap_info, &conn, - sdata->vif.addr, + sdata->vif.addr, false, &csa_ie); if (err < 0) return false; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ac376ec47a59..fff158b1615f 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2352,7 +2352,8 @@ ieee80211_sta_other_link_csa_disappeared(struct ieee80211_link_data *link, enum ieee80211_csa_source { IEEE80211_CSA_SOURCE_BEACON, IEEE80211_CSA_SOURCE_OTHER_LINK, - IEEE80211_CSA_SOURCE_ACTION, + IEEE80211_CSA_SOURCE_PROT_ACTION, + IEEE80211_CSA_SOURCE_UNPROT_ACTION, }; static void @@ -2393,7 +2394,9 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link, current_band, bss->vht_cap_info, &link->u.mgd.conn, - link->u.mgd.bssid, &csa_ie); + link->u.mgd.bssid, + source == IEEE80211_CSA_SOURCE_UNPROT_ACTION, + &csa_ie); if (res == 0) { ch_switch.block_tx = csa_ie.mode; ch_switch.chandef = csa_ie.chanreq.oper; @@ -2412,12 +2415,17 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link, res = 1; } - if (res < 0) + if (res < 0) { + /* ignore this case, not a protected frame */ + if (source == IEEE80211_CSA_SOURCE_UNPROT_ACTION) + return; goto drop_connection; + } if (link->conf->csa_active) { switch (source) { - case IEEE80211_CSA_SOURCE_ACTION: + case IEEE80211_CSA_SOURCE_PROT_ACTION: + case IEEE80211_CSA_SOURCE_UNPROT_ACTION: /* already processing - disregard action frames */ return; case IEEE80211_CSA_SOURCE_BEACON: @@ -2466,9 +2474,35 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link, } } - /* nothing to do at all - no active CSA nor a new one */ - if (res) + /* no active CSA nor a new one */ + if (res) { + /* + * However, we may have stopped queues when receiving a public + * action frame that couldn't be protected, if it had the quiet + * bit set. This is a trade-off, we want to be quiet as soon as + * possible, but also don't trust the public action frame much, + * as it can't be protected. + */ + if (unlikely(link->u.mgd.csa.blocked_tx)) { + link->u.mgd.csa.blocked_tx = false; + ieee80211_vif_unblock_queues_csa(sdata); + } return; + } + + /* + * We don't really trust public action frames, but block queues (go to + * quiet mode) for them anyway, we should get a beacon soon to either + * know what the CSA really is, or figure out the public action frame + * was actually an attack. + */ + if (source == IEEE80211_CSA_SOURCE_UNPROT_ACTION) { + if (csa_ie.mode) { + link->u.mgd.csa.blocked_tx = true; + ieee80211_vif_block_queues_csa(sdata); + } + return; + } if (link->conf->chanreq.oper.chan->band != csa_ie.chanreq.oper.chan->band) { @@ -7453,12 +7487,16 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, mgmt->u.action.u.chan_switch.variable, ies_len, true, NULL); - if (elems && !elems->parse_error) + if (elems && !elems->parse_error) { + enum ieee80211_csa_source src = + IEEE80211_CSA_SOURCE_PROT_ACTION; + ieee80211_sta_process_chanswitch(link, rx_status->mactime, rx_status->device_timestamp, elems, elems, - IEEE80211_CSA_SOURCE_ACTION); + src); + } kfree(elems); } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) { struct ieee802_11_elems *elems; @@ -7479,6 +7517,9 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, ies_len, true, NULL); if (elems && !elems->parse_error) { + enum ieee80211_csa_source src = + IEEE80211_CSA_SOURCE_UNPROT_ACTION; + /* for the handling code pretend it was an IE */ elems->ext_chansw_ie = &mgmt->u.action.u.ext_chan_switch.data; @@ -7487,7 +7528,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, rx_status->mactime, rx_status->device_timestamp, elems, elems, - IEEE80211_CSA_SOURCE_ACTION); + src); } kfree(elems); diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index df96d3db1c0e..e91ca4ccdd37 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c @@ -223,7 +223,7 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, enum nl80211_band current_band, u32 vht_cap_info, struct ieee80211_conn_settings *conn, - u8 *bssid, + u8 *bssid, bool unprot_action, struct ieee80211_csa_ie *csa_ie) { enum nl80211_band new_band = current_band; @@ -258,8 +258,10 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, if (!ieee80211_operating_class_to_band(new_op_class, &new_band)) { new_op_class = 0; - sdata_info(sdata, "cannot understand ECSA IE operating class, %d, ignoring\n", - ext_chansw_elem->new_operating_class); + if (!unprot_action) + sdata_info(sdata, + "cannot understand ECSA IE operating class, %d, ignoring\n", + ext_chansw_elem->new_operating_class); } else { new_chan_no = ext_chansw_elem->new_ch_num; csa_ie->count = ext_chansw_elem->count; @@ -293,9 +295,10 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band); new_chan = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); if (!new_chan || new_chan->flags & IEEE80211_CHAN_DISABLED) { - sdata_info(sdata, - "BSS %pM switches to unsupported channel (%d MHz), disconnecting\n", - bssid, new_freq); + if (!unprot_action) + sdata_info(sdata, + "BSS %pM switches to unsupported channel (%d MHz), disconnecting\n", + bssid, new_freq); return -EINVAL; } From patchwork Wed Jun 12 12:28:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 13694894 X-Patchwork-Delegate: johannes@sipsolutions.net Received: from sipsolutions.net (s3.sipsolutions.net [168.119.38.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 90B8D172799 for ; Wed, 12 Jun 2024 12:30:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=168.119.38.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718195452; cv=none; b=b7PyaotYdiPG41xSTeHy5dQLnHHk6HUVboKuwIzGJux5SKgX7VMMYubB2ITIcL61uFewe1IywgriKvdkMX0rvOBq+eyRMak8llLpaTmMPaV/5dWpDfMs/8zQAwscDNQl6uRCck/6KXoUbSADOIEheVKLc07yFYXBe2NFbTlRVX4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718195452; c=relaxed/simple; bh=RywbknV8SP0fOLGcJYxg4qNIa4JkeIxwQQlegGFPnAg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Nj4YGOmS0+FrVbyObKQd8r70IfEW6f/GlaXSPQ1DrIZ9D4Swy7Vx6O4wZuWUMliXW6cHcdQU9SzZekPN9oFvovCoU8wLEgTauJIe281NL6E92lf9Tf4HBortqaAIMsuGAIXqUFoC8fGd6VoadDpgLjijgxbYZFBIUmRoYA0Tloc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sipsolutions.net; spf=pass smtp.mailfrom=sipsolutions.net; dkim=pass (2048-bit key) header.d=sipsolutions.net header.i=@sipsolutions.net header.b=Kp2pCGcJ; arc=none smtp.client-ip=168.119.38.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sipsolutions.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=sipsolutions.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=sipsolutions.net header.i=@sipsolutions.net header.b="Kp2pCGcJ" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sipsolutions.net; s=mail; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Content-Type:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-To: Resent-Cc:Resent-Message-ID; bh=LFVrlfKjtdFmRd6RQ+XaAHOlKyCDa66dUA8J2QyEWdQ=; t=1718195450; x=1719405050; b=Kp2pCGcJQanwpMesrAR7YdM0B8+YEuCSNbSstm62NyDxCI/ BbBTUYMDxugX6ga9nU9x9yxvinOdAyFoyizZiP3ufH5WPw59FbdIz9ZSnQB72g4ryqJK+6rA1nKUR eEGKfrGJKqwtSrFPFhzrWYwCQdyYc1jfCnJUpa3EABo/gPl4UiRnXGP6wb9RQQi/kaicZCKOoaVIU hlr6r3ojyna/XaZWg3lA35hy3vS3LdRN7mdsJhR+0hrc9pJ5MCt0nRLIe0AMjGqXX+4XsGH2yacuP HrUjoH/xDYBxjEiZR0oNUDFgsdIM7XhyrUMNdOgbY1JY1oCBGQTbXvg92YrMgsdg==; Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.97) (envelope-from ) id 1sHN7o-0000000AGRh-0dfg; Wed, 12 Jun 2024 14:30:48 +0200 From: Johannes Berg To: linux-wireless@vger.kernel.org Cc: Johannes Berg , Miriam Rachel Korenblit Subject: [PATCH 3/3] wifi: mac80211: handle protected dual of public action Date: Wed, 12 Jun 2024 14:28:37 +0200 Message-ID: <20240612143037.db642feb8b2e.I184fa5c9bffb68099171701e403c2aa733f60fde@changeid> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240612123037.36687-5-johannes@sipsolutions.net> References: <20240612123037.36687-5-johannes@sipsolutions.net> Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Johannes Berg The code currently handles ECSA (extended channel switch announcement) public action frames. Handle also their protected dual, which actually is protected. Reviewed-by: Miriam Rachel Korenblit Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 22 ++++++++++++++-------- net/mac80211/rx.c | 1 + 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index fff158b1615f..e76b887a46eb 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -7429,6 +7429,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, { struct ieee80211_link_data *link = &sdata->deflink; struct ieee80211_rx_status *rx_status; + struct ieee802_11_elems *elems; struct ieee80211_mgmt *mgmt; u16 fc; int ies_len; @@ -7472,9 +7473,8 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, !ether_addr_equal(mgmt->bssid, sdata->vif.cfg.ap_addr)) break; - if (mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) { - struct ieee802_11_elems *elems; - + switch (mgmt->u.action.category) { + case WLAN_CATEGORY_SPECTRUM_MGMT: ies_len = skb->len - offsetof(struct ieee80211_mgmt, u.action.u.chan_switch.variable); @@ -7498,9 +7498,9 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, src); } kfree(elems); - } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) { - struct ieee802_11_elems *elems; - + break; + case WLAN_CATEGORY_PUBLIC: + case WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION: ies_len = skb->len - offsetof(struct ieee80211_mgmt, u.action.u.ext_chan_switch.variable); @@ -7517,8 +7517,13 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, ies_len, true, NULL); if (elems && !elems->parse_error) { - enum ieee80211_csa_source src = - IEEE80211_CSA_SOURCE_UNPROT_ACTION; + enum ieee80211_csa_source src; + + if (mgmt->u.action.category == + WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION) + src = IEEE80211_CSA_SOURCE_PROT_ACTION; + else + src = IEEE80211_CSA_SOURCE_UNPROT_ACTION; /* for the handling code pretend it was an IE */ elems->ext_chansw_ie = @@ -7532,6 +7537,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, } kfree(elems); + break; } break; } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 4914692750e5..0ff9062a130c 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -3617,6 +3617,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) break; case WLAN_CATEGORY_PUBLIC: + case WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION: if (len < IEEE80211_MIN_ACTION_SIZE + 1) goto invalid; if (sdata->vif.type != NL80211_IFTYPE_STATION)