Commit ac075bdd authored by David S. Miller's avatar David S. Miller
Browse files

Merge tag 'mac80211-for-net-2021-04-08.2' of...

Merge tag 'mac80211-for-net-2021-04-08.2' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211



Johannes berg says:

====================
Various small fixes:
 * S1G beacon validation
 * potential leak in nl80211
 * fast-RX confusion with 4-addr mode
 * erroneous WARN_ON that userspace can trigger
 * wrong time units in virt_wifi
 * rfkill userspace API breakage
 * TXQ AC confusing that led to traffic stopped forever
 * connection monitoring time after/before confusion
 * netlink beacon head validation buffer overrun
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3583a4e8 9a6847ba
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include <net/cfg80211.h>
#include <net/rtnetlink.h>
#include <linux/etherdevice.h>
#include <linux/math64.h>
#include <linux/module.h>

static struct wiphy *common_wiphy;
@@ -168,11 +169,11 @@ static void virt_wifi_scan_result(struct work_struct *work)
			     scan_result.work);
	struct wiphy *wiphy = priv_to_wiphy(priv);
	struct cfg80211_scan_info scan_info = { .aborted = false };
	u64 tsf = div_u64(ktime_get_boottime_ns(), 1000);

	informed_bss = cfg80211_inform_bss(wiphy, &channel_5ghz,
					   CFG80211_BSS_FTYPE_PRESP,
					   fake_router_bssid,
					   ktime_get_boottime_ns(),
					   fake_router_bssid, tsf,
					   WLAN_CAPABILITY_ESS, 0,
					   (void *)&ssid, sizeof(ssid),
					   DBM_TO_MBM(-50), GFP_KERNEL);
+68 −12
Original line number Diff line number Diff line
@@ -86,34 +86,90 @@ enum rfkill_hard_block_reasons {
 * @op: operation code
 * @hard: hard state (0/1)
 * @soft: soft state (0/1)
 *
 * Structure used for userspace communication on /dev/rfkill,
 * used for events from the kernel and control to the kernel.
 */
struct rfkill_event {
	__u32 idx;
	__u8  type;
	__u8  op;
	__u8  soft;
	__u8  hard;
} __attribute__((packed));

/**
 * struct rfkill_event_ext - events for userspace on /dev/rfkill
 * @idx: index of dev rfkill
 * @type: type of the rfkill struct
 * @op: operation code
 * @hard: hard state (0/1)
 * @soft: soft state (0/1)
 * @hard_block_reasons: valid if hard is set. One or several reasons from
 *	&enum rfkill_hard_block_reasons.
 *
 * Structure used for userspace communication on /dev/rfkill,
 * used for events from the kernel and control to the kernel.
 *
 * See the extensibility docs below.
 */
struct rfkill_event {
struct rfkill_event_ext {
	__u32 idx;
	__u8  type;
	__u8  op;
	__u8  soft;
	__u8  hard;

	/*
	 * older kernels will accept/send only up to this point,
	 * and if extended further up to any chunk marked below
	 */

	__u8  hard_block_reasons;
} __attribute__((packed));

/*
 * We are planning to be backward and forward compatible with changes
 * to the event struct, by adding new, optional, members at the end.
 * When reading an event (whether the kernel from userspace or vice
 * versa) we need to accept anything that's at least as large as the
 * version 1 event size, but might be able to accept other sizes in
 * the future.
/**
 * DOC: Extensibility
 *
 * Originally, we had planned to allow backward and forward compatible
 * changes by just adding fields at the end of the structure that are
 * then not reported on older kernels on read(), and not written to by
 * older kernels on write(), with the kernel reporting the size it did
 * accept as the result.
 *
 * This would have allowed userspace to detect on read() and write()
 * which kernel structure version it was dealing with, and if was just
 * recompiled it would have gotten the new fields, but obviously not
 * accessed them, but things should've continued to work.
 *
 * Unfortunately, while actually exercising this mechanism to add the
 * hard block reasons field, we found that userspace (notably systemd)
 * did all kinds of fun things not in line with this scheme:
 *
 * 1. treat the (expected) short writes as an error;
 * 2. ask to read sizeof(struct rfkill_event) but then compare the
 *    actual return value to RFKILL_EVENT_SIZE_V1 and treat any
 *    mismatch as an error.
 *
 * As a consequence, just recompiling with a new struct version caused
 * things to no longer work correctly on old and new kernels.
 *
 * Hence, we've rolled back &struct rfkill_event to the original version
 * and added &struct rfkill_event_ext. This effectively reverts to the
 * old behaviour for all userspace, unless it explicitly opts in to the
 * rules outlined here by using the new &struct rfkill_event_ext.
 *
 * Userspace using &struct rfkill_event_ext must adhere to the following
 * rules
 *
 * One exception is the kernel -- we already have two event sizes in
 * that we've made the 'hard' member optional since our only option
 * is to ignore it anyway.
 * 1. accept short writes, optionally using them to detect that it's
 *    running on an older kernel;
 * 2. accept short reads, knowing that this means it's running on an
 *    older kernel;
 * 3. treat reads that are as long as requested as acceptable, not
 *    checking against RFKILL_EVENT_SIZE_V1 or such.
 */
#define RFKILL_EVENT_SIZE_V1	8
#define RFKILL_EVENT_SIZE_V1	sizeof(struct rfkill_event)

/* ioctl for turning off rfkill-input (if present) */
#define RFKILL_IOC_MAGIC	'R'
+3 −1
Original line number Diff line number Diff line
@@ -1788,8 +1788,10 @@ static int ieee80211_change_station(struct wiphy *wiphy,
		}

		if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
		    sta->sdata->u.vlan.sta)
		    sta->sdata->u.vlan.sta) {
			ieee80211_clear_fast_rx(sta);
			RCU_INIT_POINTER(sta->sdata->u.vlan.sta, NULL);
		}

		if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
			ieee80211_vif_dec_num_mcast(sta->sdata);
+4 −1
Original line number Diff line number Diff line
@@ -4707,7 +4707,10 @@ static void ieee80211_sta_conn_mon_timer(struct timer_list *t)
		timeout = sta->rx_stats.last_rx;
	timeout += IEEE80211_CONNECTION_IDLE_TIME;

	if (time_is_before_jiffies(timeout)) {
	/* If timeout is after now, then update timer to fire at
	 * the later date, but do not actually probe at this time.
	 */
	if (time_is_after_jiffies(timeout)) {
		mod_timer(&ifmgd->conn_mon_timer, round_jiffies_up(timeout));
		return;
	}
+1 −1
Original line number Diff line number Diff line
@@ -3573,7 +3573,7 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
	    test_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags))
		goto out;

	if (vif->txqs_stopped[ieee80211_ac_from_tid(txq->tid)]) {
	if (vif->txqs_stopped[txq->ac]) {
		set_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags);
		goto out;
	}
Loading