Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH 2/2] ath10k: handle tdls peer events
From: mpubbise @ 2017-10-10  6:50 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Manikanta Pubbisetty
In-Reply-To: <1507618202-25473-1-git-send-email-mpubbise@qti.qualcomm.com>

From: Manikanta Pubbisetty <mpubbise@qti.qualcomm.com>

Handle tdls peer events from the target. TDLS events for the peer
could be discover, teardown, etc. As of now, adding the logic to
handle tdls teardown events alone.

Teardown due to peer traffic indication(PTR) timeout is one such
teardown event from the target.

Tested this change on QCA9888 with 10.4-3.5.1-00018 fw version.

Signed-off-by: Manikanta Pubbisetty <mpubbise@qti.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/wmi.c |   59 +++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 38a9708..344f19c 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -29,6 +29,7 @@
 #include "p2p.h"
 #include "hw.h"
 #include "hif.h"
+#include "txrx.h"
 
 #define ATH10K_WMI_BARRIER_ECHO_ID 0xBA991E9
 #define ATH10K_WMI_BARRIER_TIMEOUT_HZ (3 * HZ)
@@ -4456,6 +4457,61 @@ void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb)
 		   __le32_to_cpu(ev->rate_max));
 }
 
+void ath10k_wmi_handle_tdls_peer_event(struct ath10k *ar, struct sk_buff *skb)
+{
+	struct wmi_tdls_peer_event *ev;
+	struct ath10k_peer *peer;
+	struct ath10k_vif *arvif;
+	u8 reason;
+
+	ev = (struct wmi_tdls_peer_event *)skb->data;
+
+	spin_lock_bh(&ar->data_lock);
+	peer = ath10k_peer_find(ar, ev->vdev_id, ev->peer_macaddr.addr);
+	spin_unlock_bh(&ar->data_lock);
+
+	if (!peer) {
+		ath10k_warn(ar, "failed to find peer entry for %pM\n",
+			    ev->peer_macaddr.addr);
+		return;
+	}
+
+	switch (ev->peer_status) {
+	case WMI_TDLS_SHOULD_TEARDOWN:
+		switch (ev->peer_reason) {
+		case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
+		case WMI_TDLS_TEARDOWN_REASON_NO_RESPONSE:
+		case WMI_TDLS_TEARDOWN_REASON_RSSI:
+			reason = WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE;
+			break;
+		default:
+			reason = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
+			break;
+		}
+
+		arvif = ath10k_get_arvif(ar, ev->vdev_id);
+		if (!arvif) {
+			ath10k_warn(ar, "received tdls peer event for invalid vdev id %u\n",
+				    ev->vdev_id);
+			return;
+		}
+
+		ieee80211_tdls_oper_request(arvif->vif, ev->peer_macaddr.addr,
+					    NL80211_TDLS_TEARDOWN, reason,
+					    GFP_ATOMIC);
+
+		ath10k_dbg(ar, ATH10K_DBG_WMI,
+			   "received tdls teardown event for peer %pM reason %u\n",
+			   ev->peer_macaddr.addr, ev->peer_reason);
+		break;
+	default:
+		ath10k_dbg(ar, ATH10K_DBG_WMI,
+			   "received unknown tdls peer event %u\n",
+			   ev->peer_status);
+		break;
+	}
+}
+
 void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar, struct sk_buff *skb)
 {
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PDEV_FTM_INTG_EVENTID\n");
@@ -5477,6 +5533,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
 	case WMI_10_4_PDEV_TPC_CONFIG_EVENTID:
 		ath10k_wmi_event_pdev_tpc_config(ar, skb);
 		break;
+	case WMI_10_4_TDLS_PEER_EVENTID:
+		ath10k_wmi_handle_tdls_peer_event(ar, skb);
+		break;
 	default:
 		ath10k_warn(ar, "Unknown eventid: %d\n", id);
 		break;
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 1/2] ath10k: update tdls teardown state to target
From: mpubbise @ 2017-10-10  6:50 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Manikanta Pubbisetty
In-Reply-To: <1507618202-25473-1-git-send-email-mpubbise@qti.qualcomm.com>

From: Manikanta Pubbisetty <mpubbise@qti.qualcomm.com>

It is required to update the teardown state of the peer when
a tdls link with that peer is terminated. This information is
useful for the target to perform some cleanups wrt the tdls peer.

Without proper cleanup, target assumes that the peer is connected and
blocks future connection requests, updating the teardown state of the
peer addresses the problem.

Tested this change on QCA9888 with 10.4-3.5.1-00018 fw version.

Signed-off-by: Manikanta Pubbisetty <mpubbise@qti.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/mac.c |   10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 5683f1a..35b7523 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -6183,6 +6183,16 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
 			   "mac vdev %d peer delete %pM sta %pK (sta gone)\n",
 			   arvif->vdev_id, sta->addr, sta);
 
+		if (sta->tdls) {
+			ret = ath10k_mac_tdls_peer_update(ar, arvif->vdev_id,
+							  sta,
+							  WMI_TDLS_PEER_STATE_TEARDOWN);
+			if (ret)
+				ath10k_warn(ar, "failed to update tdls peer state for %pM state %d: %i\n",
+					    sta->addr,
+					    WMI_TDLS_PEER_STATE_TEARDOWN, ret);
+		}
+
 		ret = ath10k_peer_delete(ar, arvif->vdev_id, sta->addr);
 		if (ret)
 			ath10k_warn(ar, "failed to delete peer %pM for vdev %d: %i\n",
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 0/2] ath10k: more on tdls support for 10.4 firmwares
From: mpubbise @ 2017-10-10  6:50 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Manikanta Pubbisetty

From: Manikanta Pubbisetty <mpubbise@qti.qualcomm.com>

This patchset includes a bug fix and an enhancement of tdls functionality
for 10.4 firmwares.

First patch in this series is a bug fix, second one is an enhancement.

Manikanta Pubbisetty (2):
  ath10k: update tdls teardown state to target
  ath10k: handle tdls peer events

 drivers/net/wireless/ath/ath10k/mac.c |   10 ++++++
 drivers/net/wireless/ath/ath10k/wmi.c |   59 +++++++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+)

-- 
1.7.9.5

^ permalink raw reply

* Contributing to Linux-wireless drivers.
From: Himanshu Jha @ 2017-10-10  6:05 UTC (permalink / raw)
  To: linux-wireless

----- Forwarded message from Himanshu Jha <himanshujha199640@gmail.com> -----

Date: Fri, 6 Oct 2017 02:05:39 +0530
From: Himanshu Jha <himanshujha199640@gmail.com>
To: kvalo@codeaurora.org
Subject: Contributing to Linux-wireless drivers.
User-Agent: Mutt/1.5.24 (2015-08-30)

Hi Kalle,


I am an undergraduate student in ECE(3rd year) and wish to contribute to linux-wireless
drivers. I am familiar with the kernel development process and have many
patches accepted in the past 2 months with variety of tools used such as
coccinelle,Kasan,smatch,sparse and checkpatch.

I have basic knowledge of Linux kernel internals and competent C skills,
also planning to learn Device Drivers in future. 

The wiki page https://wireless.wiki.kernel.org/ is not working
correctly, for every page it shows 

"This topic does not exist yet
You've followed a link to a topic that doesn't exist yet. If permissions
allow, you may create it by clicking on “Create this page”.
Earlier I used to visit this without any issues, don't know what is the
problem now ?

Also, since I am beginner is there any small project that I could work on
to enhance my knowledge. Please provide me any links to
Documentation/tutorials which I can follow and help the community.
Lastly, I will next year surely apply for GSoC under Linux-wireless and
I don't seem to find any participation since 2012. Also, if there is
any project that someone didn't try and is open then please let me know!

I am really sorry for this direct email to you but nobody helped me on
IRC channel.

Thanks
Himanshu Jha

----- End forwarded message -----

^ permalink raw reply

* Re: pull-request: iwlwifi 2017-10-06
From: Kalle Valo @ 2017-10-10  5:56 UTC (permalink / raw)
  To: Luca Coelho; +Cc: linux-wireless, linuxwifi
In-Reply-To: <1507288582.908.127.camel@coelho.fi>

Luca Coelho <luca@coelho.fi> writes:

> Here is the second set of fixes for 4.14.  More details in the tag
> description.
>
> I have sent this out before and kbuildbot didn't find any issues. 
> Please let me know if there are any issues.
>
> Cheers,
> Luca.
>
>
> The following changes since commit c503dd38f850be28867ef7a42d9abe5ade81a9bd:
>
>   brcmsmac: make some local variables 'static const' to reduce stack size (2017-10-02 16:52:55 +0300)
>
> are available in the git repository at:
>
>   git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-fixes.git tags/iwlwifi-for-kalle-2017-10-06
>
> for you to fetch changes up to 44fd09dad5d2b78efbabbbbf623774e561e36cca:
>
>   iwlwifi: nvm: set the correct offsets to 3168 series (2017-10-06 13:59:44 +0300)
>
> ----------------------------------------------------------------
> Second set of iwlwifi fixes for 4.14
>
> * Fix support for 3168 device series;
> * Fix a potential crash when using FW debugging recording;
> * Improve channel flags parsing to avoid warnings on too long traces;
> * Return -ENODATA when the temperature is not available, since the
>   -EIO we were returning was causing fatal errors in userspace;
> * Avoid printing too many messages in dmesg when using monitor mode,
>   since this can become very noisy and completely flood the logs;
>
> ----------------------------------------------------------------

Pulled, thanks.

Actually I pulled this already yesterday but forgot to reply.

-- 
Kalle Valo

^ permalink raw reply

* Re: [PATCH] timer: Remove meaningless .data/.function assignments
From: David Miller @ 2017-10-10  1:05 UTC (permalink / raw)
  To: keescook
  Cc: tglx, khc, aditya.shankar, ganesh.krishna, gregkh, axboe, netdev,
	linux-wireless, devel, linux-kernel
In-Reply-To: <20171010001032.GA119829@beast>

From: Kees Cook <keescook@chromium.org>
Date: Mon, 9 Oct 2017 17:10:32 -0700

> Several timer users needlessly reset their .function/.data fields during
> their timer callback, but nothing else changes them. Some users do not
> use their .data field at all. Each instance is removed here.
> 
> Cc: Krzysztof Halasa <khc@pm.waw.pl>
> Cc: Aditya Shankar <aditya.shankar@microchip.com>
> Cc: Ganesh Krishna <ganesh.krishna@microchip.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Jens Axboe <axboe@fb.com>
> Cc: netdev@vger.kernel.org
> Cc: linux-wireless@vger.kernel.org
> Cc: devel@driverdev.osuosl.org
> Signed-off-by: Kees Cook <keescook@chromium.org>
> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> # for staging
> Acked-by: Krzysztof Halasa <khc@pm.waw.pl> # for wan/hdlc*
> Acked-by: Jens Axboe <axboe@kernel.dk> # for amiflop
> ---
> This should go via the timer/core tree, please. It's been acked by each
> of the maintainers. Thanks!

For networking bits:

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply

* [PATCH] timer: Remove meaningless .data/.function assignments
From: Kees Cook @ 2017-10-10  0:10 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Krzysztof Halasa, Aditya Shankar, Ganesh Krishna,
	Greg Kroah-Hartman, Jens Axboe, netdev, linux-wireless, devel,
	linux-kernel

Several timer users needlessly reset their .function/.data fields during
their timer callback, but nothing else changes them. Some users do not
use their .data field at all. Each instance is removed here.

Cc: Krzysztof Halasa <khc@pm.waw.pl>
Cc: Aditya Shankar <aditya.shankar@microchip.com>
Cc: Ganesh Krishna <ganesh.krishna@microchip.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jens Axboe <axboe@fb.com>
Cc: netdev@vger.kernel.org
Cc: linux-wireless@vger.kernel.org
Cc: devel@driverdev.osuosl.org
Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> # for staging
Acked-by: Krzysztof Halasa <khc@pm.waw.pl> # for wan/hdlc*
Acked-by: Jens Axboe <axboe@kernel.dk> # for amiflop
---
This should go via the timer/core tree, please. It's been acked by each
of the maintainers. Thanks!
---
 drivers/block/amiflop.c                           | 3 +--
 drivers/net/wan/hdlc_cisco.c                      | 2 --
 drivers/net/wan/hdlc_fr.c                         | 2 --
 drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 4 +---
 4 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 49908c74bfcb..4e3fb9f104af 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -323,7 +323,7 @@ static void fd_deselect (int drive)
 
 }
 
-static void motor_on_callback(unsigned long nr)
+static void motor_on_callback(unsigned long ignored)
 {
 	if (!(ciaa.pra & DSKRDY) || --on_attempts == 0) {
 		complete_all(&motor_on_completion);
@@ -344,7 +344,6 @@ static int fd_motor_on(int nr)
 		fd_select(nr);
 
 		reinit_completion(&motor_on_completion);
-		motor_on_timer.data = nr;
 		mod_timer(&motor_on_timer, jiffies + HZ/2);
 
 		on_attempts = 10;
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index a408abc25512..f4b0ab34f048 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c
@@ -276,8 +276,6 @@ static void cisco_timer(unsigned long arg)
 	spin_unlock(&st->lock);
 
 	st->timer.expires = jiffies + st->settings.interval * HZ;
-	st->timer.function = cisco_timer;
-	st->timer.data = arg;
 	add_timer(&st->timer);
 }
 
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index 78596e42a3f3..07f265fa2826 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -644,8 +644,6 @@ static void fr_timer(unsigned long arg)
 			state(hdlc)->settings.t391 * HZ;
 	}
 
-	state(hdlc)->timer.function = fr_timer;
-	state(hdlc)->timer.data = arg;
 	add_timer(&state(hdlc)->timer);
 }
 
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
index ac5aaafa461c..60f088babf27 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
@@ -266,7 +266,7 @@ static void update_scan_time(void)
 		last_scanned_shadow[i].time_scan = jiffies;
 }
 
-static void remove_network_from_shadow(unsigned long arg)
+static void remove_network_from_shadow(unsigned long unused)
 {
 	unsigned long now = jiffies;
 	int i, j;
@@ -287,7 +287,6 @@ static void remove_network_from_shadow(unsigned long arg)
 	}
 
 	if (last_scanned_cnt != 0) {
-		hAgingTimer.data = arg;
 		mod_timer(&hAgingTimer, jiffies + msecs_to_jiffies(AGING_TIME));
 	}
 }
@@ -304,7 +303,6 @@ static int is_network_in_shadow(struct network_info *pstrNetworkInfo,
 	int i;
 
 	if (last_scanned_cnt == 0) {
-		hAgingTimer.data = (unsigned long)user_void;
 		mod_timer(&hAgingTimer, jiffies + msecs_to_jiffies(AGING_TIME));
 		state = -1;
 	} else {
-- 
2.7.4


-- 
Kees Cook
Pixel Security

^ permalink raw reply related

* Re: [RFC] mac80211: Add airtime fairness accounting
From: Toke Høiland-Jørgensen @ 2017-10-09 20:25 UTC (permalink / raw)
  To: Johannes Berg, make-wifi-fast, linux-wireless
In-Reply-To: <1507575007.26041.59.camel@sipsolutions.net>

Johannes Berg <johannes@sipsolutions.net> writes:

> Hi,
>
>> Right, but most of these are constant values that are straight
>> forward to add as long as you know how the frame was received, no?
>> Maybe not as a general function in mac80211, but the driver should be
>> able to perform a reasonable computation in the absence of
>> information from the hardware.
>
> Yes, I think so.

Cool. I'll go with that, then.

>> What does iwl put into the status.tx_time field of ieee80211_tx_info,
>> BTW? That was the only driver I could find that used the field, and
>> it looks like it just writes something it gets from the hardware into
>> it.
>> So does that value include overhead? And what about retransmissions?
>
> It comes from the firmware - as far as I can tell, yes, it'll include
> retransmissions and the whole frame exchange sequence
> (RTS-CTS-data-ack or RTS-CTS-ampdu-blockack).

Excellent! Just what we need :)

>> > I don't know if there's an easy answer. Perhaps not accounting for
>> > the
>> > overhead but assuming that clients won't be stupid and will
>> > actually
>> > do aggregation when they ramp up their rates is reasonable in most
>> > scenarios, but I'm afraid that we'll find interop issues - we found
>> > for example that if you enable U-APSD lots of devices won't do
>> > aggregation any more ...
>> 
>> What do you mean by "interop" here, exactly? Just that stations doing
>> weird things will see reduced performance?
>
> Well, the case that we did find is that sometimes U-APSD kills
> aggregation, so then you'd have a lot of single frames and
> significantly under-estimate air-time usage in this case. Thus, this
> station would get far more than its fair share of air time, because of
> a bug that makes it not use aggregation... That doesn't sound very
> good to me.
>
> Perhaps at least taking aggregation into account would be doable - we
> _should_ know this, at least partially.

Yeah, ath9k certainly gets that as part of the RX information from the
chip.

>> One of the things I would also like to try, is to sometimes promote
>> or demote packets between AC levels. E.g., if a station has one VO
>> packet and a bunch of BE packets queued, it may sometimes be more
>> efficient to just put the VO packet at the beginning of a BE
>> aggregate. I still need to figure out for which values of 'sometimes'
>> this is a good idea, but I'd like to at least be able to support this
>> sort of shenanigans, which I believe what I proposed above will.
>
> I don't think that's a good idea. It's possible (and this can be done
> at least in synthetic scenarios) that VO traffic _completely_ drowns
> out all lower-priority traffic, so demoting frames that way would get
> them the wrong EDCA parameters.
>
> Yes, it might be better for throughput, but it would almost certainly
> be worse for latency for those frames, which is kinda the whole point
> of the ACs.

Well, some of the tests I did while porting ath9k to the iTXQs indicated
that for voice-like traffic we can get very close to the same actual
end-to-end latency for BE-marked traffic that we do with VO-marked
traffic. This is in part because the FQ sparse flow prioritisation makes
sure that such flows get queueing priority.

Now obviously, there are going to be tradeoffs, and scenarios where
latency will suffer. But I would at least like to be able to explore
this, and I think with the API we are currently discussing that will be
possible. Another thing I want to explore is doing soft admission
control; i.e., if someone sends bulk traffic marked as VO, it will be
automatically demoted to BE traffic rather than locking everyone else
out. We've tested that with some success in the Cake scheduler, and it
may be applicable to WiFi as well.

>> > Also, in iwlwifi we actually have a HW queue per TID to facilitate
>> > aggregation, though we could just let mac80211 pick the next TXQ to
>> > serve and skip in the unlikely case that the HW queue for that is
>> > already full (which really shouldn't happen).
>> 
>> Yeah, there may be a need for the driver to be able to express some
>> constraints on the queues it can accept currently; may a bitmap of
>> eligible TID numbers, or just a way of saying "can't use this TXQ,
>> please give me another". But it may also be that it's enough for the
>> driver to just give up and try again later if it can't use the TXQ it
>> is assigned...
>
> I guess it could just move on to the next TID. There doesn't seem to
> be much point in saying "I can't service this high-priority TID, give
> me something lower priority instead" because it really should be
> servicing the higher priority first anyway, so just skipping if it
> can't be serviced seems fine.

Suppose so. I'll try it out :)

-Toke

^ permalink raw reply

* Re: [RFC] mac80211: Add airtime fairness accounting
From: Johannes Berg @ 2017-10-09 18:50 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen, make-wifi-fast, linux-wireless
In-Reply-To: <87zi90binm.fsf@toke.dk>

Hi,

> Right, but most of these are constant values that are straight
> forward to add as long as you know how the frame was received, no?
> Maybe not as a general function in mac80211, but the driver should be
> able to perform a reasonable computation in the absence of
> information from the hardware.

Yes, I think so.

> What does iwl put into the status.tx_time field of ieee80211_tx_info,
> BTW? That was the only driver I could find that used the field, and
> it looks like it just writes something it gets from the hardware into
> it.
> So does that value include overhead? And what about retransmissions?

It comes from the firmware - as far as I can tell, yes, it'll include
retransmissions and the whole frame exchange sequence (RTS-CTS-data-ack 
or RTS-CTS-ampdu-blockack).

> > I don't know if there's an easy answer. Perhaps not accounting for
> > the
> > overhead but assuming that clients won't be stupid and will
> > actually
> > do aggregation when they ramp up their rates is reasonable in most
> > scenarios, but I'm afraid that we'll find interop issues - we found
> > for example that if you enable U-APSD lots of devices won't do
> > aggregation any more ...
> 
> What do you mean by "interop" here, exactly? Just that stations doing
> weird things will see reduced performance?

Well, the case that we did find is that sometimes U-APSD kills
aggregation, so then you'd have a lot of single frames and
significantly under-estimate air-time usage in this case. Thus, this
station would get far more than its fair share of air time, because of
a bug that makes it not use aggregation... That doesn't sound very good
to me.

Perhaps at least taking aggregation into account would be doable - we
_should_ know this, at least partially.

> I'm pretty sure it will work for ath9k. That just picks a TXQ and
> keeps pulling packets until it has filled an aggregate. 

OK

> That would still be possible if mac80211 picks the TXQ instead of the
> driver itself. 

Right.

> So I was asking more generally, but if you don't see anything obvious
> that would prevent me from doing this, I guess I'll go and try it out
> :)

:-)

> > It might also be hard to combine that - if you have space on your
> > VI
> > queue, how do you then pick the queue? We can't really go *all* the
> > way and do scheduling *entirely* in software, getting rid of per-AC
> > queues, since the per-AC queues also work to assign the EDCA
> > parameters etc.
> 
> We'll need to keep putting packets into different hardware queues,
> sure.

> But deciding which one can be done at the last instant (i.e., for
> ath9k,
> ask mac80211 for a TXQ, look at which AC that TXQ belongs to, and
> start
> putting packets into that hardware queue).

Right.

> One of the things I would also like to try, is to sometimes promote
> or demote packets between AC levels. E.g., if a station has one VO
> packet and a bunch of BE packets queued, it may sometimes be more
> efficient to just put the VO packet at the beginning of a BE
> aggregate. I still need to figure out for which values of 'sometimes'
> this is a good idea, but I'd like to at least be able to support this
> sort of shenanigans, which I believe what I proposed above will.

I don't think that's a good idea. It's possible (and this can be done
at least in synthetic scenarios) that VO traffic _completely_ drowns
out all lower-priority traffic, so demoting frames that way would get
them the wrong EDCA parameters.

Yes, it might be better for throughput, but it would almost certainly
be worse for latency for those frames, which is kinda the whole point
of the ACs.

> > Also, in iwlwifi we actually have a HW queue per TID to facilitate
> > aggregation, though we could just let mac80211 pick the next TXQ to
> > serve and skip in the unlikely case that the HW queue for that is
> > already full (which really shouldn't happen).
> 
> Yeah, there may be a need for the driver to be able to express some
> constraints on the queues it can accept currently; may a bitmap of
> eligible TID numbers, or just a way of saying "can't use this TXQ,
> please give me another". But it may also be that it's enough for the
> driver to just give up and try again later if it can't use the TXQ it
> is assigned...

I guess it could just move on to the next TID. There doesn't seem to be
much point in saying "I can't service this high-priority TID, give me
something lower priority instead" because it really should be servicing
the higher priority first anyway, so just skipping if it can't be
serviced seems fine.

johannes

^ permalink raw reply

* usb/net/rt2x00: warning in rt2800_eeprom_word_index
From: Andrey Konovalov @ 2017-10-09 17:50 UTC (permalink / raw)
  To: Stanislaw Gruszka, Helmut Schaa, Kalle Valo, linux-wireless,
	netdev, LKML
  Cc: Dmitry Vyukov, Kostya Serebryany, syzkaller

Hi!

I've got the following report while fuzzing the kernel with syzkaller.

On commit 8a5776a5f49812d29fe4b2d0a2d71675c3facf3f (4.14-rc4).

I'm not sure whether this is a bug in the driver, or just a way to
report misbehaving device. In the latter case this shouldn't be a
WARN() call, since WARN() means bug in the kernel.

phy2: invalid access of EEPROM word 39
------------[ cut here ]------------
WARNING: CPU: 1 PID: 5591 at
drivers/net/wireless/ralink/rt2x00/rt2800lib.c:399
rt2800_eeprom_word_index.isra.15+0x149/0x1c0
Modules linked in:
CPU: 1 PID: 5591 Comm: syz-executor Not tainted
4.14.0-rc4-43423-g7263a3720c3f #392
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
task: ffff880069933180 task.stack: ffff88005aee8000
RIP: 0010:rt2800_eeprom_word_index.isra.15+0x149/0x1c0
drivers/net/wireless/ralink/rt2x00/rt2800lib.c:397
RSP: 0018:ffff88005aeed960 EFLAGS: 00010282
RAX: 0000000000000026 RBX: ffff88005af0c5c0 RCX: 0000000000000000
RDX: 0000000000000026 RSI: ffffffff813292c9 RDI: ffffed000b5ddb1e
RBP: ffff88005aeed978 R08: ffff88005aeecd90 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000027
R13: ffff880068631018 R14: 0000000000000052 R15: 0000000000000000
FS:  0000000001c60940(0000) GS:ffff88006c700000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000001967000 CR3: 0000000068089000 CR4: 00000000000006e0
Call Trace:
 rt2800_eeprom_addr drivers/net/wireless/ralink/rt2x00/rt2800lib.c:409
 rt2800_probe_hw_mode drivers/net/wireless/ralink/rt2x00/rt2800lib.c:9321
 rt2800_probe_hw+0x19ef/0x27b0
drivers/net/wireless/ralink/rt2x00/rt2800lib.c:9456
 rt2800usb_probe_hw+0x6e/0x200
drivers/net/wireless/ralink/rt2x00/rt2800usb.c:768
 rt2x00lib_probe_dev+0x9e5/0x2800
drivers/net/wireless/ralink/rt2x00/rt2x00dev.c:1427
 rt2x00usb_probe+0x67b/0x990 drivers/net/wireless/ralink/rt2x00/rt2x00usb.c:837
 rt2800usb_probe+0x21/0x30 drivers/net/wireless/ralink/rt2x00/rt2800usb.c:1410
 usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
 really_probe drivers/base/dd.c:413
 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653
 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710
 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
 device_add+0xd0b/0x1660 drivers/base/core.c:1835
 usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932
 generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174
 usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266
 really_probe drivers/base/dd.c:413
 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653
 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710
 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
 device_add+0xd0b/0x1660 drivers/base/core.c:1835
 usb_new_device+0x7b8/0x1020 drivers/usb/core/hub.c:2538
 hub_port_connect drivers/usb/core/hub.c:4984
 hub_port_connect_change drivers/usb/core/hub.c:5090
 port_event drivers/usb/core/hub.c:5196
 hub_event_impl+0x1971/0x3760 drivers/usb/core/hub.c:5310
 gfs_hub_events_handle+0x881/0xae0 drivers/usb/core/hub.c:1853
 hub_ioctl+0x53d/0x680 drivers/usb/core/hub.c:1903
 proc_ioctl+0x435/0x680 drivers/usb/core/devio.c:2175
 proc_ioctl_default drivers/usb/core/devio.c:2198
 usbdev_do_ioctl+0xee9/0x3790 drivers/usb/core/devio.c:2512
 usbdev_ioctl+0x2a/0x40 drivers/usb/core/devio.c:2556
 vfs_ioctl fs/ioctl.c:45
 do_vfs_ioctl+0x1c4/0x15c0 fs/ioctl.c:685
 SYSC_ioctl fs/ioctl.c:700
 SyS_ioctl+0x94/0xc0 fs/ioctl.c:691
 entry_SYSCALL_64_fastpath+0x23/0xc2 arch/x86/entry/entry_64.S:202
RIP: 0033:0x447707
RSP: 002b:00007ffd565109b8 EFLAGS: 00000206 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00000000ffffffff RCX: 0000000000447707
RDX: 00007ffd565109d0 RSI: 00000000c0105512 RDI: 0000000000000015
RBP: 0000000000000005 R08: 0000000001c60940 R09: 0000000001c60940
R10: 00000000004a8e59 R11: 0000000000000206 R12: 0000000000000015
R13: 0000000000000000 R14: 00007ffd56510888 R15: 00007ffd565108f8
Code: ea 03 80 3c 02 00 75 72 4c 8b ab 70 01 00 00 4d 85 ed 74 3a e8
29 c5 9b fd 44 89 e2 4c 89 ee 48 c7 c7 e0 4d d5 86 e8 f1 6d 84 fd <0f>
ff 31 db e9 4c ff ff ff 48 89 df e8 36 f2 cd fd e9 34 ff ff
---[ end trace a71f41162bce05c3 ]---

^ permalink raw reply

* usb/net/rtlwifi: trying to register non-static key in rtl_c2hcmd_launcher
From: Andrey Konovalov @ 2017-10-09 17:50 UTC (permalink / raw)
  To: Larry Finger, Chaoming Li, Kalle Valo, linux-wireless, netdev,
	LKML
  Cc: Dmitry Vyukov, Kostya Serebryany, syzkaller

Hi!

I've got the following report while fuzzing the kernel with syzkaller.

On commit 8a5776a5f49812d29fe4b2d0a2d71675c3facf3f (4.14-rc4).

INFO: trying to register non-static key.
the code is fine but needs lockdep annotation.
turning off the locking correctness validator.
CPU: 0 PID: 24 Comm: kworker/0:1 Not tainted
4.14.0-rc4-43418-g43a3f84d2109-dirty #391
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Workqueue: usb_hub_wq hub_event
Call Trace:
 __dump_stack lib/dump_stack.c:16
 dump_stack+0x292/0x395 lib/dump_stack.c:52
 register_lock_class+0x6c4/0x1a00 kernel/locking/lockdep.c:769
 __lock_acquire+0x27e/0x4550 kernel/locking/lockdep.c:3385
 lock_acquire+0x259/0x620 kernel/locking/lockdep.c:4002
 __raw_spin_lock_irqsave ./include/linux/spinlock_api_smp.h:110
 _raw_spin_lock_irqsave+0xcc/0x110 kernel/locking/spinlock.c:159
 rtl_c2hcmd_launcher+0x3ca/0x5d0
drivers/net/wireless/realtek/rtlwifi/base.c:2052
 rtl_deinit_core+0x79/0x350 drivers/net/wireless/realtek/rtlwifi/base.c:590
 rtl_usb_probe+0x1ca3/0x2470 drivers/net/wireless/realtek/rtlwifi/usb.c:1128
 rtl8192cu_probe+0x29/0x30
drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c:398
 usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
 really_probe drivers/base/dd.c:413
 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653
 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710
 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
 device_add+0xd0b/0x1660 drivers/base/core.c:1835
 usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932
 generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174
 usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266
 really_probe drivers/base/dd.c:413
 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653
 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710
 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
 device_add+0xd0b/0x1660 drivers/base/core.c:1835
 usb_new_device+0x7b8/0x1020 drivers/usb/core/hub.c:2457
 hub_port_connect drivers/usb/core/hub.c:4903
 hub_port_connect_change drivers/usb/core/hub.c:5009
 port_event drivers/usb/core/hub.c:5115
 hub_event+0x194d/0x3740 drivers/usb/core/hub.c:5195
 process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119
 worker_thread+0x221/0x1850 kernel/workqueue.c:2253
 kthread+0x3a1/0x470 kernel/kthread.c:231
 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431

^ permalink raw reply

* usb/nfs/pn533: use-after-free in pn533_send_complete
From: Andrey Konovalov @ 2017-10-09 17:50 UTC (permalink / raw)
  To: Samuel Ortiz, Stephen Hemminger, Johannes Berg,
	Michał Mirosław, Andrey Rusalin, linux-wireless, LKML
  Cc: Dmitry Vyukov, Kostya Serebryany, syzkaller

Hi!

I've got the following report while fuzzing the kernel with syzkaller.

On commit 8a5776a5f49812d29fe4b2d0a2d71675c3facf3f (4.14-rc4).

usb 1-1: NFC: Can't submit reader poweron cmd response -90
pn533_usb 1-1:6.1: NFC: Couldn't poweron the reader (error -90)
pn533_usb: probe of 1-1:6.1 failed with error -90
==================================================================
BUG: KASAN: use-after-free in pn533_send_complete+0xc4/0xd0
Read of size 8 at addr ffff880069a51e28 by task swapper/1/0

CPU: 1 PID: 0 Comm: swapper/1 Not tainted
4.14.0-rc4-43418-g43a3f84d2109-dirty #391
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Call Trace:
 <IRQ>
 __dump_stack lib/dump_stack.c:16
 dump_stack+0x292/0x395 lib/dump_stack.c:52
 print_address_description+0x78/0x280 mm/kasan/report.c:252
 kasan_report_error mm/kasan/report.c:351
 kasan_report+0x23d/0x350 mm/kasan/report.c:409
 __asan_report_load8_noabort+0x19/0x20 mm/kasan/report.c:430
 pn533_send_complete+0xc4/0xd0 drivers/nfc/pn533/usb.c:431
 __usb_hcd_giveback_urb+0x2e0/0x650 drivers/usb/core/hcd.c:1779
 usb_hcd_giveback_urb+0x337/0x420 drivers/usb/core/hcd.c:1845
 dummy_timer+0xba9/0x39f0 drivers/usb/gadget/udc/dummy_hcd.c:1965
 call_timer_fn+0x2a2/0x940 kernel/time/timer.c:1281
 expire_timers kernel/time/timer.c:1320
 __run_timers+0x87f/0xd40 kernel/time/timer.c:1620
 run_timer_softirq+0x83/0x140 kernel/time/timer.c:1646
 __do_softirq+0x2ee/0xc0f kernel/softirq.c:284
 invoke_softirq kernel/softirq.c:364
 irq_exit+0x171/0x1a0 kernel/softirq.c:405
 exiting_irq ./arch/x86/include/asm/apic.h:638
 smp_apic_timer_interrupt+0x2b9/0x8d0 arch/x86/kernel/apic/apic.c:1048
 apic_timer_interrupt+0x9d/0xb0
 </IRQ>
RIP: 0010:native_safe_halt+0x6/0x10 ./arch/x86/include/asm/irqflags.h:53
RSP: 0018:ffff88006bac7b90 EFLAGS: 00000282 ORIG_RAX: ffffffffffffff10
RAX: dffffc0000000020 RBX: 1ffff1000d758f76 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffff88006baa3a64
RBP: ffff88006bac7b90 R08: ffff88006bac6c01 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000000 R12: 1ffff1000d758f82
R13: ffff88006bac7cd0 R14: ffffffff8881ecc8 R15: 0000000000000000
 arch_safe_halt ./arch/x86/include/asm/paravirt.h:93
 default_idle+0x127/0x690 arch/x86/kernel/process.c:341
 arch_cpu_idle+0xf/0x20 arch/x86/kernel/process.c:332
 default_idle_call+0x3b/0x60 kernel/sched/idle.c:98
 cpuidle_idle_call kernel/sched/idle.c:156
 do_idle+0x33a/0x410 kernel/sched/idle.c:246
 cpu_startup_entry+0x1d/0x20 kernel/sched/idle.c:351
 start_secondary+0x3de/0x500 arch/x86/kernel/smpboot.c:278
 secondary_startup_64+0xa5/0xa5 arch/x86/kernel/head_64.S:235

Allocated by task 41:
 save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59
 save_stack+0x43/0xd0 mm/kasan/kasan.c:447
 set_track mm/kasan/kasan.c:459
 kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:551
 kasan_slab_alloc+0x12/0x20 mm/kasan/kasan.c:489
 slab_post_alloc_hook mm/slab.h:444
 slab_alloc_node mm/slub.c:2745
 __kmalloc_node_track_caller+0x14b/0x380 mm/slub.c:4340
 alloc_dr drivers/base/devres.c:91
 devm_kmalloc+0xb4/0x200 drivers/base/devres.c:781
 devm_kzalloc ./include/linux/device.h:662
 pn533_usb_probe+0x43/0xb40 drivers/nfc/pn533/usb.c:462
 usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
 really_probe drivers/base/dd.c:413
 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653
 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710
 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
 device_add+0xd0b/0x1660 drivers/base/core.c:1835
 usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932
 generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174
 usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266
 really_probe drivers/base/dd.c:413
 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653
 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710
 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
 device_add+0xd0b/0x1660 drivers/base/core.c:1835
 usb_new_device+0x7b8/0x1020 drivers/usb/core/hub.c:2457
 hub_port_connect drivers/usb/core/hub.c:4903
 hub_port_connect_change drivers/usb/core/hub.c:5009
 port_event drivers/usb/core/hub.c:5115
 hub_event+0x194d/0x3740 drivers/usb/core/hub.c:5195
 process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119
 worker_thread+0x221/0x1850 kernel/workqueue.c:2253
 kthread+0x3a1/0x470 kernel/kthread.c:231
 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431

Freed by task 41:
 save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59
 save_stack+0x43/0xd0 mm/kasan/kasan.c:447
 set_track mm/kasan/kasan.c:459
 kasan_slab_free+0x72/0xc0 mm/kasan/kasan.c:524
 slab_free_hook mm/slub.c:1390
 slab_free_freelist_hook mm/slub.c:1412
 slab_free mm/slub.c:2988
 kfree+0xf6/0x2f0 mm/slub.c:3919
 release_nodes+0x5a5/0xd60 drivers/base/devres.c:496
 devres_release_all+0x101/0x190 drivers/base/devres.c:517
 really_probe drivers/base/dd.c:460
 driver_probe_device+0x2d8/0xa00 drivers/base/dd.c:557
 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653
 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710
 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
 device_add+0xd0b/0x1660 drivers/base/core.c:1835
 usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932
 generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174
 usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266
 really_probe drivers/base/dd.c:413
 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653
 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710
 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
 device_add+0xd0b/0x1660 drivers/base/core.c:1835
 usb_new_device+0x7b8/0x1020 drivers/usb/core/hub.c:2457
 hub_port_connect drivers/usb/core/hub.c:4903
 hub_port_connect_change drivers/usb/core/hub.c:5009
 port_event drivers/usb/core/hub.c:5115
 hub_event+0x194d/0x3740 drivers/usb/core/hub.c:5195
 process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119
 worker_thread+0x221/0x1850 kernel/workqueue.c:2253
 kthread+0x3a1/0x470 kernel/kthread.c:231
 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431

The buggy address belongs to the object at ffff880069a51e00
 which belongs to the cache kmalloc-96 of size 96
The buggy address is located 40 bytes inside of
 96-byte region [ffff880069a51e00, ffff880069a51e60)
The buggy address belongs to the page:
page:ffffea0001a69440 count:1 mapcount:0 mapping:          (null) index:0x0
flags: 0x100000000000100(slab)
raw: 0100000000000100 0000000000000000 0000000000000000 0000000180200020
raw: ffffea0001a46ec0 0000000e00000002 ffff88006c003680 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff880069a51d00: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
 ffff880069a51d80: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
>ffff880069a51e00: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
                                  ^
 ffff880069a51e80: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
 ffff880069a51f00: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
==================================================================

^ permalink raw reply

* usb/net/ath6kl: GPF in ath6kl_usb_alloc_urb_from_pipe
From: Andrey Konovalov @ 2017-10-09 17:50 UTC (permalink / raw)
  To: Kalle Valo, linux-wireless, netdev, LKML
  Cc: Dmitry Vyukov, Kostya Serebryany, syzkaller

Hi!

I've got the following report while fuzzing the kernel with syzkaller.

On commit 8a5776a5f49812d29fe4b2d0a2d71675c3facf3f (4.14-rc4).

usb 1-1: New USB device found, idVendor=0cf3, idProduct=9375
usb 1-1: New USB device strings: Mfr=2, Product=255, SerialNumber=8
usb 1-1: Product: a
usb 1-1: Manufacturer: a
usb 1-1: SerialNumber: a
gadgetfs: configuration #9
kasan: CONFIG_KASAN_INLINE enabled
kasan: GPF could be caused by NULL-ptr deref or user memory access
general protection fault: 0000 [#1] PREEMPT SMP KASAN
Modules linked in:
CPU: 1 PID: 1494 Comm: kworker/1:1 Not tainted
4.14.0-rc4-43418-g43a3f84d2109 #379
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Workqueue: usb_hub_wq hub_event
task: ffff880068e9ca40 task.stack: ffff880068948000
RIP: 0010:__lock_acquire+0xe18/0x4550 kernel/locking/lockdep.c:3376
RSP: 0018:ffff88006894d788 EFLAGS: 00010006
RAX: dffffc0000000000 RBX: dffffc0000000000 RCX: 0000000000000000
RDX: 0000000000000003 RSI: 0000000000000000 RDI: 1ffff1000d129b3c
RBP: ffff88006894dd08 R08: 0000000000000001 R09: 0000000000000001
R10: 0000000000000000 R11: ffffffff89789760 R12: ffff880068e9ca40
R13: dffffc0000000000 R14: 0000000000000001 R15: 0000000000000018
FS:  0000000000000000(0000) GS:ffff88006c500000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f9558dca000 CR3: 0000000066dc4000 CR4: 00000000000006e0
Call Trace:
 lock_acquire+0x259/0x620 kernel/locking/lockdep.c:4002
 __raw_spin_lock_irqsave ./include/linux/spinlock_api_smp.h:110
 _raw_spin_lock_irqsave+0xcc/0x110 kernel/locking/spinlock.c:159
 ath6kl_usb_alloc_urb_from_pipe+0x103/0x4c0
drivers/net/wireless/ath/ath6kl/usb.c:135
 ath6kl_usb_post_recv_transfers.constprop.10+0x228/0x420
drivers/net/wireless/ath/ath6kl/usb.c:410
 ath6kl_usb_start_recv_pipes drivers/net/wireless/ath/ath6kl/usb.c:484
 hif_start drivers/net/wireless/ath/ath6kl/usb.c:682
 ath6kl_usb_power_on+0x8a/0x120 drivers/net/wireless/ath/ath6kl/usb.c:1041
 ath6kl_hif_power_on drivers/net/wireless/ath/ath6kl/hif-ops.h:136
 ath6kl_core_init+0x180/0x1190 drivers/net/wireless/ath/ath6kl/core.c:97
 ath6kl_usb_probe+0xdf4/0x1420 drivers/net/wireless/ath/ath6kl/usb.c:1147
 usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
 really_probe drivers/base/dd.c:413
 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653
 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710
 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
 device_add+0xd0b/0x1660 drivers/base/core.c:1835
 usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932
 generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174
 usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266
 really_probe drivers/base/dd.c:413
 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653
 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710
 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
 device_add+0xd0b/0x1660 drivers/base/core.c:1835
 usb_new_device+0x7b8/0x1020 drivers/usb/core/hub.c:2457
 hub_port_connect drivers/usb/core/hub.c:4903
 hub_port_connect_change drivers/usb/core/hub.c:5009
 port_event drivers/usb/core/hub.c:5115
 hub_event+0x194d/0x3740 drivers/usb/core/hub.c:5195
 process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119
 worker_thread+0x221/0x1850 kernel/workqueue.c:2253
 kthread+0x3a1/0x470 kernel/kthread.c:231
 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431
Code: 89 f0 c7 07 00 00 00 00 48 81 c4 58 05 00 00 5b 41 5c 41 5d 41
5e 41 5f 5d c3 48 b8 00 00 00 00 00 fc ff df 4c 89 fa 48 c1 ea 03 <80>
3c 02 00 0f 85 b2 36 00 00 49 81 3f 00 52 bb 88 41 be 00 00
RIP: __lock_acquire+0xe18/0x4550 RSP: ffff88006894d788
---[ end trace 56dead20dbd7b387 ]---

^ permalink raw reply

* usb/net/ar5523: warning in ar5523_submit_rx_cmd/usb_submit_urb
From: Andrey Konovalov @ 2017-10-09 17:49 UTC (permalink / raw)
  To: Pontus Fuchs, Kalle Valo, linux-wireless, netdev, LKML
  Cc: Dmitry Vyukov, Kostya Serebryany, syzkaller

Hi!

I've got the following report while fuzzing the kernel with syzkaller.

On commit 8a5776a5f49812d29fe4b2d0a2d71675c3facf3f (4.14-rc4).

It seems that the driver doesn't check the endpoint type provided in
the USB descriptor.

usb 1-1: BOGUS urb xfer, pipe 3 != type 1
------------[ cut here ]------------
WARNING: CPU: 1 PID: 2265 at drivers/usb/core/urb.c:449
usb_submit_urb+0xf8a/0x11d0
Modules linked in:
CPU: 1 PID: 2265 Comm: kworker/1:2 Not tainted
4.14.0-rc4-43418-g43a3f84d2109 #379
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Workqueue: usb_hub_wq hub_event
task: ffff88006abc8000 task.stack: ffff880063e08000
RIP: 0010:usb_submit_urb+0xf8a/0x11d0 drivers/usb/core/urb.c:448
RSP: 0000:ffff880063e0ded0 EFLAGS: 00010286
RAX: 0000000000000029 RBX: ffff8800694cbf00 RCX: 0000000000000000
RDX: 0000000000000029 RSI: ffffffff86a76d40 RDI: ffffed000c7c1bcc
RBP: ffff880063e0dfd0 R08: 1ffff1000c7c1a72 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000000 R12: 1ffff1000c7c1be1
R13: 0000000000000001 R14: 0000000000000003 R15: ffff88006bb47e10
FS:  0000000000000000(0000) GS:ffff88006c500000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f43b3d37000 CR3: 00000000695d4000 CR4: 00000000000006e0
Call Trace:
 ar5523_submit_rx_cmd+0x20a/0x320 drivers/net/wireless/ath/ar5523/ar5523.c:208
 ar5523_probe+0x1683/0x3af0 drivers/net/wireless/ath/ar5523/ar5523.c:1643
 usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
 really_probe drivers/base/dd.c:413
 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653
 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710
 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
 device_add+0xd0b/0x1660 drivers/base/core.c:1835
 usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932
 generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174
 usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266
 really_probe drivers/base/dd.c:413
 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653
 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
 __device_attach+0x26e/0x3d0 drivers/base/dd.c:710
 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
 device_add+0xd0b/0x1660 drivers/base/core.c:1835
 usb_new_device+0x7b8/0x1020 drivers/usb/core/hub.c:2457
 hub_port_connect drivers/usb/core/hub.c:4903
 hub_port_connect_change drivers/usb/core/hub.c:5009
 port_event drivers/usb/core/hub.c:5115
 hub_event+0x194d/0x3740 drivers/usb/core/hub.c:5195
 process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119
 worker_thread+0x221/0x1850 kernel/workqueue.c:2253
 kthread+0x3a1/0x470 kernel/kthread.c:231
 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431
Code: 48 8b 85 30 ff ff ff 48 8d b8 98 00 00 00 e8 6e df c7 fe 45 89
e8 44 89 f1 4c 89 fa 48 89 c6 48 c7 c7 c0 ce 04 87 e8 50 6d 16 fd <0f>
ff e9 9b f7 ff ff e8 9a f1 5f fd e9 80 f7 ff ff e8 60 c4 2d
---[ end trace 4ec8ea7915652acc ]---

^ permalink raw reply

* Re: pull-request: mac80211 2017-10-09
From: David Miller @ 2017-10-09 16:53 UTC (permalink / raw)
  To: johannes; +Cc: netdev, linux-wireless
In-Reply-To: <20171009074013.1979-1-johannes@sipsolutions.net>

From: Johannes Berg <johannes@sipsolutions.net>
Date: Mon,  9 Oct 2017 09:40:12 +0200

> The QCA folks found another netlink problem - we were missing validation
> of some attributes. It's not super problematic since one can only read a
> few bytes beyond the message (and that memory must exist), but here's the
> fix for it.
> 
> I thought perhaps we can make nla_parse_nested() require a policy, but
> given the two-stage validation/parsing in regular netlink that won't work.
> 
> Please pull and let me know if there's any problem.

Yeah, nested parsing is messy validation-wise.

Pulled, thanks Johannes.

^ permalink raw reply

* Re: [PATCH 0/3] linux-firmware: ath10k update 20170918
From: Ben Hutchings @ 2017-10-09 16:46 UTC (permalink / raw)
  To: Kalle Valo, linux-firmware; +Cc: linux-wireless, ath10k
In-Reply-To: <1505746857-31938-1-git-send-email-kvalo@qca.qualcomm.com>

[-- Attachment #1: Type: text/plain, Size: 1003 bytes --]

On Mon, 2017-09-18 at 18:00 +0300, Kalle Valo wrote:
> Few firmware fixes to user reported issues for ath10k, but the other "fix"
> being a revert back to older firmware. Also a small board-2.bin update.

I've applied this series, thanks.

Ben.

> Kalle Valo (3):
>   ath10k: QCA6174 hw3.0: update firmware-6.bin to
>     WLAN.RM.4.4.1-00051-QCARMSWP-1
>   ath10k: QCA6174 hw3.0: update board-2.bin
>   Revert "ath10k: QCA988X hw2.0: update firmware to 10.2.4.70.63-2"
> 
>  WHENCE                                            |   4 +-
>  ath10k/QCA6174/hw3.0/board-2.bin                  | Bin 477060 -> 501748 bytes
>  ath10k/QCA6174/hw3.0/firmware-6.bin               | Bin 711408 -> 727776 bytes
>  ath10k/QCA6174/hw3.0/notice_ath10k_firmware-6.txt |  97 +++++-----------------
>  ath10k/QCA988X/hw2.0/firmware-5.bin               | Bin 249384 -> 248188 bytes
>  5 files changed, 25 insertions(+), 76 deletions(-)
> 
-- 
Ben Hutchings
Humour is the best antidote to reality.


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH V2 0/8] qtnfmac: get rid of redundant state caching in driver
From: Sergey Matyukevich @ 2017-10-09 16:00 UTC (permalink / raw)
  To: igor.mitsyanko.os; +Cc: linux-wireless, avinashp, johannes
In-Reply-To: <20171005013813.13332-1-igor.mitsyanko.os@quantenna.com>

> In many cases qtnfmac driver stores state info (like current channel,
> interface state) in driver's internal state that is either unused or
> duplicates information that is available elsewhere. Cleanup driver
> to get rid of not needed cached data.
> 
> It was part of bigger changeset when it was V1.
> 
> Changelist V1->V2:
> PATCH 3:
>   - add missing cpu_to_le16() to CMD len field initialization.
> 
> Igor Mitsyanko (8):
>   qtnfmac: do not cache AP settings in driver structures
>   qtnfmac: pass all AP settings to wireless card for processing
>   qtnfmac: pass channel definition to WiFi card on START_AP command
>   qtnfmac: get rid of QTNF_STATE_AP_CONFIG
>   qtnfmac: get rid of QTNF_STATE_AP_START flag
>   qtnfmac: do not cache BSS state in per-VIF structure
>   qtnfmac: make encryption info a part of CONNECT command.
>   qtnfmac: do not cache current channel info in driver's state
> 
>  drivers/net/wireless/quantenna/qtnfmac/cfg80211.c  | 110 ++------------
>  drivers/net/wireless/quantenna/qtnfmac/commands.c  | 163 +++++++++++----------
>  drivers/net/wireless/quantenna/qtnfmac/commands.h  |   3 +-
>  drivers/net/wireless/quantenna/qtnfmac/core.h      |  24 +--
>  drivers/net/wireless/quantenna/qtnfmac/event.c     |  14 --
>  drivers/net/wireless/quantenna/qtnfmac/qlink.h     |  92 +++++++++---
>  .../net/wireless/quantenna/qtnfmac/qlink_util.c    |  45 ++++++
>  .../net/wireless/quantenna/qtnfmac/qlink_util.h    |   3 +
>  8 files changed, 224 insertions(+), 230 deletions(-)

For the whole patchset:
Reviewed-by: Sergey Matyukevich <sergey.matyukevich.os@quantenna.com>

^ permalink raw reply

* Re: [PATCH 10/13] timer: Remove expires and data arguments from DEFINE_TIMER
From: Ralf Baechle @ 2017-10-09 13:27 UTC (permalink / raw)
  To: Kees Cook
  Cc: Thomas Gleixner, Andrew Morton, Arnd Bergmann,
	Benjamin Herrenschmidt, Chris Metcalf, Geert Uytterhoeven,
	Greg Kroah-Hartman, Guenter Roeck, Harish Patil, Heiko Carstens,
	James E.J. Bottomley, John Stultz, Julian Wiedmann, Kalle Valo,
	Lai Jiangshan, Len Brown, Manish Chopra, Mark Gross,
	Martin K. Petersen, Martin Schwidefsky, Michael Ellerman,
	Michael Reed, netdev, Oleg Nesterov, Paul Mackerras, Pavel Machek,
	Petr Mladek, Rafael J. Wysocki, Sebastian Reichel, Stefan Richter,
	Stephen Boyd, Sudip Mukherjee, Tejun Heo, Ursula Braun,
	Viresh Kumar, Wim Van Sebroeck, linux1394-devel, linux-mips,
	linux-pm, linuxppc-dev, linux-s390, linux-scsi, linux-watchdog,
	linux-wireless, linux-kernel
In-Reply-To: <1507159627-127660-11-git-send-email-keescook@chromium.org>

On Wed, Oct 04, 2017 at 04:27:04PM -0700, Kees Cook wrote:

> Subject: [PATCH 10/13] timer: Remove expires and data arguments from
>  DEFINE_TIMER
> 
> Drop the arguments from the macro and adjust all callers with the
> following script:
> 
>   perl -pi -e 's/DEFINE_TIMER\((.*), 0, 0\);/DEFINE_TIMER($1);/g;' \
>     $(git grep DEFINE_TIMER | cut -d: -f1 | sort -u | grep -v timer.h)
> 
> Signed-off-by: Kees Cook <keescook@chromium.org>
> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> # for m68k parts
> ---
>  arch/arm/mach-ixp4xx/dsmg600-setup.c      | 2 +-
>  arch/arm/mach-ixp4xx/nas100d-setup.c      | 2 +-
>  arch/m68k/amiga/amisound.c                | 2 +-
>  arch/m68k/mac/macboing.c                  | 2 +-
>  arch/mips/mti-malta/malta-display.c       | 2 +-
>  arch/parisc/kernel/pdc_cons.c             | 2 +-
>  arch/s390/mm/cmm.c                        | 2 +-
>  drivers/atm/idt77105.c                    | 4 ++--
>  drivers/atm/iphase.c                      | 2 +-
>  drivers/block/ataflop.c                   | 8 ++++----
>  drivers/char/dtlk.c                       | 2 +-
>  drivers/char/hangcheck-timer.c            | 2 +-
>  drivers/char/nwbutton.c                   | 2 +-
>  drivers/char/rtc.c                        | 2 +-
>  drivers/input/touchscreen/s3c2410_ts.c    | 2 +-
>  drivers/net/cris/eth_v10.c                | 6 +++---
>  drivers/net/hamradio/yam.c                | 2 +-
>  drivers/net/wireless/atmel/at76c50x-usb.c | 2 +-
>  drivers/staging/speakup/main.c            | 2 +-
>  drivers/staging/speakup/synth.c           | 2 +-
>  drivers/tty/cyclades.c                    | 2 +-
>  drivers/tty/isicom.c                      | 2 +-
>  drivers/tty/moxa.c                        | 2 +-
>  drivers/tty/rocket.c                      | 2 +-
>  drivers/tty/vt/keyboard.c                 | 2 +-
>  drivers/tty/vt/vt.c                       | 2 +-
>  drivers/watchdog/alim7101_wdt.c           | 2 +-
>  drivers/watchdog/machzwd.c                | 2 +-
>  drivers/watchdog/mixcomwd.c               | 2 +-
>  drivers/watchdog/sbc60xxwdt.c             | 2 +-
>  drivers/watchdog/sc520_wdt.c              | 2 +-
>  drivers/watchdog/via_wdt.c                | 2 +-
>  drivers/watchdog/w83877f_wdt.c            | 2 +-
>  drivers/xen/grant-table.c                 | 2 +-
>  fs/pstore/platform.c                      | 2 +-
>  include/linux/timer.h                     | 4 ++--
>  kernel/irq/spurious.c                     | 2 +-
>  lib/random32.c                            | 2 +-
>  net/atm/mpc.c                             | 2 +-
>  net/decnet/dn_route.c                     | 2 +-
>  net/ipv6/ip6_flowlabel.c                  | 2 +-
>  net/netrom/nr_loopback.c                  | 2 +-
>  security/keys/gc.c                        | 2 +-
>  sound/oss/midibuf.c                       | 2 +-
>  sound/oss/soundcard.c                     | 2 +-
>  sound/oss/sys_timer.c                     | 2 +-
>  sound/oss/uart6850.c                      | 2 +-
>  47 files changed, 54 insertions(+), 54 deletions(-)

Acked-by: Ralf Baechle <ralf@linux-mips.org>

Thanks,

  Ralf

^ permalink raw reply

* Re: [PATCH 09/13] timer: Remove users of expire and data arguments to DEFINE_TIMER
From: Ralf Baechle @ 2017-10-09 13:23 UTC (permalink / raw)
  To: Kees Cook
  Cc: Thomas Gleixner, Wim Van Sebroeck, Guenter Roeck,
	Geert Uytterhoeven, linux-mips, linux-watchdog, Andrew Morton,
	Arnd Bergmann, Benjamin Herrenschmidt, Chris Metcalf,
	Greg Kroah-Hartman, Harish Patil, Heiko Carstens,
	James E.J. Bottomley, John Stultz, Julian Wiedmann, Kalle Valo,
	Lai Jiangshan, Len Brown, Manish Chopra, Mark Gross,
	Martin K. Petersen, Martin Schwidefsky, Michael Ellerman,
	Michael Reed, netdev, Oleg Nesterov, Paul Mackerras, Pavel Machek,
	Petr Mladek, Rafael J. Wysocki, Sebastian Reichel, Stefan Richter,
	Stephen Boyd, Sudip Mukherjee, Tejun Heo, Ursula Braun,
	Viresh Kumar, linux1394-devel, linux-pm, linuxppc-dev, linux-s390,
	linux-scsi, linux-wireless, linux-kernel
In-Reply-To: <1507159627-127660-10-git-send-email-keescook@chromium.org>

On Wed, Oct 04, 2017 at 04:27:03PM -0700, Kees Cook wrote:

> Subject: [PATCH 09/13] timer: Remove users of expire and data arguments to
>  DEFINE_TIMER
> 
> The expire and data arguments of DEFINE_TIMER are only used in two places
> and are ignored by the code (malta-display.c only uses mod_timer(),
> never add_timer(), so the preset expires value is ignored). Set both
> sets of arguments to zero.
> 
> Cc: Ralf Baechle <ralf@linux-mips.org>
> Cc: Wim Van Sebroeck <wim@iguana.be>
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: Geert Uytterhoeven <geert@linux-m68k.org>
> Cc: linux-mips@linux-mips.org
> Cc: linux-watchdog@vger.kernel.org
> Signed-off-by: Kees Cook <keescook@chromium.org>
> ---
>  arch/mips/mti-malta/malta-display.c | 6 +++---
>  drivers/watchdog/alim7101_wdt.c     | 4 ++--
>  2 files changed, 5 insertions(+), 5 deletions(-)

For malta-display:

Acked-by: Ralf Baechle <ralf@linux-mips.org>

  Ralf

^ permalink raw reply

* Re: [RFC] mac80211: Add airtime fairness accounting
From: Toke Høiland-Jørgensen @ 2017-10-09 12:38 UTC (permalink / raw)
  To: Johannes Berg, make-wifi-fast, linux-wireless
In-Reply-To: <1507549222.26041.38.camel@sipsolutions.net>

Johannes Berg <johannes@sipsolutions.net> writes:

> On Mon, 2017-10-09 at 11:42 +0200, Toke H=C3=B8iland-J=C3=B8rgensen wrote:
>
>> Well, the padding and spacing between frames is at most 11 bytes (4-
>> byte delimiter, 4-byte FCS and 3-byte padding), which is ~0.7% of a
>> full-sized frame. I'm not too worried about errors on that scale,
>> TBH.
>
> I'm not sure - this really should take the whole frame exchange
> sequence into consideration, since the "dead" IFS time and the ACK etc.
> is also airtime consumed for that station, even if there's no actual
> transmission going on.
>
> If you factor that in, the overhead reduction with aggregation is
> considerable! With an 80 MHz 2x2 MCS 9 (866Mbps PHY rate) A-MPDU
> containing 64 packets, you can reach >650Mbps (with protection),
> without A-MPDU you can reach only about 45Mbps I think.
>
> You'd think that a 1500 byte frame takes 1.5ms for the 1Mbps client,
> and ~14=C2=B5s for the above mentioned VHT rate.
>
> In reality, however, the overhead for both is comparable in absolute
> numbers, it's >200=C2=B5s.
>
> If you don't take any of this overhead into account at all, then you'll
> vastly over-allocate time for clients sending small (non-aggregated)
> frames, because for those - even with slow rates - the overhead will
> dominate.

Right, but most of these are constant values that are straight forward
to add as long as you know how the frame was received, no? Maybe not as
a general function in mac80211, but the driver should be able to
perform a reasonable computation in the absence of information from the
hardware.

What does iwl put into the status.tx_time field of ieee80211_tx_info,
BTW? That was the only driver I could find that used the field, and it
looks like it just writes something it gets from the hardware into it.
So does that value include overhead? And what about retransmissions?

> I don't know if there's an easy answer. Perhaps not accounting for the
> overhead but assuming that clients won't be stupid and will actually
> do aggregation when they ramp up their rates is reasonable in most
> scenarios, but I'm afraid that we'll find interop issues - we found
> for example that if you enable U-APSD lots of devices won't do
> aggregation any more ...

What do you mean by "interop" here, exactly? Just that stations doing
weird things will see reduced performance?

>> > > Ideally, I would prefer the scheduling to be "two-pass": First,
>> > > decide which physical station to send to, then decide which TID
>> > > on that station to service.=20
>> >=20
>> > Yeah, that would make more sense.
>> >=20
>> > > But because everything is done at the TID/TXQ level, that is not
>> > > quite trivial to achieve I think...
>> >=20
>> > Well you can group the TXQs, I guess. They all have a STA pointer,
>> > so
>> > you could put a one- or two-bit "schedule color" field into each
>> > station and if you find a TXQ with the same station color you just
>> > skip it or something like that?
>>=20
>> Couldn't we add something like a get_next_txq(phy) function to
>> mac80211 that the drivers can call to get the queue to pull packets
>> from? That way, responsibility for scheduling both stations and QoS
>> levels falls to mac80211, which makes it possible to do clever
>> scheduling stuff without having to re-implement it in every driver.
>> Also, this function could handle all the special TXQs for PS and non-
>> data frames that you were talking about in your other email?
>>=20
>> Unless there's some reason I'm missing that the driver really needs
>> to schedule the TXQs, I think this would make a lot of sense?
>
> I have no idea, that's something you'll have to ask Felix I guess. I'd
> think it should work, but the scheduling might have other constraints
> like wanting to fill certain A-MPDU buffers, or getting a specific
> channel (though that's already decided once you pick the station).

I'm pretty sure it will work for ath9k. That just picks a TXQ and keeps
pulling packets until it has filled an aggregate. That would still be
possible if mac80211 picks the TXQ instead of the driver itself. So I
was asking more generally, but if you don't see anything obvious that
would prevent me from doing this, I guess I'll go and try it out :)

> It might also be hard to combine that - if you have space on your VI
> queue, how do you then pick the queue? We can't really go *all* the
> way and do scheduling *entirely* in software, getting rid of per-AC
> queues, since the per-AC queues also work to assign the EDCA
> parameters etc.

We'll need to keep putting packets into different hardware queues, sure.
But deciding which one can be done at the last instant (i.e., for ath9k,
ask mac80211 for a TXQ, look at which AC that TXQ belongs to, and start
putting packets into that hardware queue).

One of the things I would also like to try, is to sometimes promote or
demote packets between AC levels. E.g., if a station has one VO packet
and a bunch of BE packets queued, it may sometimes be more efficient to
just put the VO packet at the beginning of a BE aggregate. I still need
to figure out for which values of 'sometimes' this is a good idea, but
I'd like to at least be able to support this sort of shenanigans, which
I believe what I proposed above will.

> Also, in iwlwifi we actually have a HW queue per TID to facilitate
> aggregation, though we could just let mac80211 pick the next TXQ to
> serve and skip in the unlikely case that the HW queue for that is
> already full (which really shouldn't happen).

Yeah, there may be a need for the driver to be able to express some
constraints on the queues it can accept currently; may a bitmap of
eligible TID numbers, or just a way of saying "can't use this TXQ,
please give me another". But it may also be that it's enough for the
driver to just give up and try again later if it can't use the TXQ it is
assigned...

-Toke

^ permalink raw reply

* Re: [RFC] mac80211: Add airtime fairness accounting
From: Johannes Berg @ 2017-10-09 11:40 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen, make-wifi-fast, linux-wireless
In-Reply-To: <878tgkd5d1.fsf@toke.dk>

On Mon, 2017-10-09 at 11:42 +0200, Toke Høiland-Jørgensen wrote:

> Well, the padding and spacing between frames is at most 11 bytes (4-
> byte delimiter, 4-byte FCS and 3-byte padding), which is ~0.7% of a
> full-sized frame. I'm not too worried about errors on that scale,
> TBH.

I'm not sure - this really should take the whole frame exchange
sequence into consideration, since the "dead" IFS time and the ACK etc.
is also airtime consumed for that station, even if there's no actual
transmission going on.

If you factor that in, the overhead reduction with aggregation is
considerable! With an 80 MHz 2x2 MCS 9 (866Mbps PHY rate) A-MPDU
containing 64 packets, you can reach >650Mbps (with protection),
without A-MPDU you can reach only about 45Mbps I think.

You'd think that a 1500 byte frame takes 1.5ms for the 1Mbps client,
and ~14µs for the above mentioned VHT rate.

In reality, however, the overhead for both is comparable in absolute
numbers, it's >200µs.

If you don't take any of this overhead into account at all, then you'll
vastly over-allocate time for clients sending small (non-aggregated)
frames, because for those - even with slow rates - the overhead will
dominate.

If you do take this overhead into account but don't account for
aggregation, you'll vastly under-allocate time for HT/VHT clients that
use aggregation.

I don't know if there's an easy answer. Perhaps not accounting for the
overhead but assuming that clients won't be stupid and will actually do
aggregation when they ramp up their rates is reasonable in most
scenarios, but I'm afraid that we'll find interop issues - we found for
example that if you enable U-APSD lots of devices won't do aggregation
any more ...

> Sure, it would be better to have it be accurate, but there are other
> imperfections, especially on the RX side (we can't count
> retransmissions, for instance, since the receiver obviously doesn't
> see those).

Sure.

> There's a separate scheduling loop for each hardware queue (one per
> AC), which only schedules all TXQs with that AC. The hardware will
> prioritise higher ACs by dequeueing from the high-priority hardware
> queue first.

Ok, I guess that addresses that issue.

> Yeah, that's what we have currently in ath9k. However, it's rare in
> practice that a station transmits the same amount of data on all ACs
> (for one, since the max aggregation size is smaller at the higher ACs
> that becomes difficult). But you are quite right that this is
> something that should be fixed :)

Not sure the amount of data matters that much, but ok.

> > > Ideally, I would prefer the scheduling to be "two-pass": First,
> > > decide which physical station to send to, then decide which TID
> > > on that station to service. 
> > 
> > Yeah, that would make more sense.
> > 
> > > But because everything is done at the TID/TXQ level, that is not
> > > quite trivial to achieve I think...
> > 
> > Well you can group the TXQs, I guess. They all have a STA pointer,
> > so
> > you could put a one- or two-bit "schedule color" field into each
> > station and if you find a TXQ with the same station color you just
> > skip it or something like that?
> 
> Couldn't we add something like a get_next_txq(phy) function to
> mac80211 that the drivers can call to get the queue to pull packets
> from? That way, responsibility for scheduling both stations and QoS
> levels falls to mac80211, which makes it possible to do clever
> scheduling stuff without having to re-implement it in every driver.
> Also, this function could handle all the special TXQs for PS and non-
> data frames that you were talking about in your other email?
> 
> Unless there's some reason I'm missing that the driver really needs
> to schedule the TXQs, I think this would make a lot of sense?

I have no idea, that's something you'll have to ask Felix I guess. I'd
think it should work, but the scheduling might have other constraints
like wanting to fill certain A-MPDU buffers, or getting a specific
channel (though that's already decided once you pick the station).

It might also be hard to combine that - if you have space on your VI
queue, how do you then pick the queue? We can't really go *all* the way
and do scheduling *entirely* in software, getting rid of per-AC queues,
since the per-AC queues also work to assign the EDCA parameters etc.

Also, in iwlwifi we actually have a HW queue per TID to facilitate
aggregation, though we could just let mac80211 pick the next TXQ to
serve and skip in the unlikely case that the HW queue for that is
already full (which really shouldn't happen).

johannes

^ permalink raw reply

* [PATCH] regdb: write firmware file format (version code 20)
From: Johannes Berg @ 2017-10-09  9:50 UTC (permalink / raw)
  To: linux-wireless; +Cc: Seth Forshee, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

TODO: clean up the Makefile stuff ...

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 Makefile |  53 ++++++++++++-------------
 README   |   4 +-
 db2fw.py | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 160 insertions(+), 30 deletions(-)
 create mode 100755 db2fw.py

diff --git a/Makefile b/Makefile
index 907ff282fc92..e708982a453d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,5 @@
 # Install prefix
 PREFIX ?= /usr
-CRDA_PATH ?= $(PREFIX)/lib/crda
-CRDA_KEY_PATH ?= $(CRDA_PATH)/pubkeys
 
 MANDIR ?= $(PREFIX)/share/man/
 
@@ -30,39 +28,47 @@ REGDB_AUTHOR ?= $(shell if [ -f $(DISTRO_PRIVKEY) ]; then \
 		fi)
 
 REGDB_PRIVKEY ?= ~/.wireless-regdb-$(REGDB_AUTHOR).key.priv.pem
-REGDB_PUBKEY ?= $(REGDB_AUTHOR).key.pub.pem
-
-REGDB_UPSTREAM_PUBKEY ?= sforshee.key.pub.pem
+REGDB_PUBCERT ?= $(REGDB_AUTHOR).x509.pem
 
 REGDB_CHANGED = $(shell $(SHA1SUM) -c --status sha1sum.txt >/dev/null 2>&1; \
         if [ $$? -ne 0 ]; then \
-                echo maintainer-clean $(REGDB_PUBKEY); \
+                echo maintainer-clean $(REGDB_PUBCERT); \
         fi)
 
 .PHONY: all clean mrproper install maintainer-clean install-distro-key
 
-all: $(REGDB_CHANGED) regulatory.bin sha1sum.txt
+all: $(REGDB_CHANGED) regulatory.db.p7s sha1sum.txt
 
 clean:
 	@rm -f *.pyc *.gz
 
 maintainer-clean: clean
-	@rm -f regulatory.bin
+	@rm -f regulatory.db regulatory.db.p7s
 
 mrproper: clean maintainer-clean
-	@echo Removed public key, regulatory.bin and compresed man pages
-	@rm -f $(REGDB_PUBKEY) .custom
+	@echo Removed public key, regulatory.db* and compressed man pages
+	@rm -f $(REGDB_PUBCERT) .custom
+
+regulatory.db: db.txt db2fw.py
+	@echo "Generating $@"
+	./db2fw.py regulatory.db db.txt
 
-regulatory.bin: db.txt $(REGDB_PRIVKEY) $(REGDB_PUBKEY)
-	@echo Generating $@ digitally signed by $(REGDB_AUTHOR)...
-	./db2bin.py regulatory.bin db.txt $(REGDB_PRIVKEY)
+regulatory.db.p7s: regulatory.db $(REGDB_PRIVKEY) $(REGDB_PUBCERT)
+	@echo "Signing regulatory.db (by $(REGDB_AUTHOR))..."
+	@openssl smime -sign \
+		-signer $(REGDB_PUBCERT) \
+		-inkey $(REGDB_PRIVKEY) \
+		-in $< -nosmimecap -binary \
+		-outform DER -out $@
 
 sha1sum.txt: db.txt
 	sha1sum $< > $@
 
-$(REGDB_PUBKEY): $(REGDB_PRIVKEY)
-	@echo "Generating public key for $(REGDB_AUTHOR)..."
-	openssl rsa -in $(REGDB_PRIVKEY) -out $(REGDB_PUBKEY) -pubout -outform PEM
+$(REGDB_PUBCERT): $(REGDB_PRIVKEY)
+	@echo "Generating certificate for $(REGDB_AUTHOR)..."
+	@openssl req -config regulatory.openssl.conf \
+		-key $(REGDB_PRIVKEY) -days 36500 -utf8 -nodes -batch \
+		-x509 -outform PEM -out $(REGDB_PUBCERT)
 	@echo $(REGDB_PUBKEY) > .custom
 
 
@@ -97,16 +103,7 @@ install-distro-key: maintainer-clean $(DISTRO_PRIVKEY)
 #	make maintainer-clean
 #	make
 #	sudo make install
-install: regulatory.bin.5.gz
-	install -m 755 -d $(DESTDIR)/$(CRDA_PATH)
-	install -m 755 -d $(DESTDIR)/$(CRDA_KEY_PATH)
-	if [ -f .custom ]; then \
-		install -m 644 -t $(DESTDIR)/$(CRDA_KEY_PATH)/ $(shell cat .custom); \
-	fi
-	install -m 644 -t $(DESTDIR)/$(CRDA_KEY_PATH)/ $(REGDB_UPSTREAM_PUBKEY)
-	install -m 644 -t $(DESTDIR)/$(CRDA_PATH)/ regulatory.bin
+install: regulatory.db.5.gz
+	install -m 644 -t $(DESTDIR)/$(CRDA_PATH)/ regulatory.db
 	install -m 755 -d $(DESTDIR)/$(MANDIR)/man5/
-	install -m 644 -t $(DESTDIR)/$(MANDIR)/man5/ regulatory.bin.5.gz
-
-uninstall:
-	rm -rf $(DESTDIR)/$(CRDA_PATH)/
+	install -m 644 -t $(DESTDIR)/$(MANDIR)/man5/ regulatory.db.5.gz
diff --git a/README b/README
index 065b67241c41..4028223725da 100644
--- a/README
+++ b/README
@@ -18,8 +18,8 @@ python module is used by the web viewer (Regulatory.py) which is
 implemented as a MoinMoin macro (and used on http://wireless.kernel.org)
 to allow viewing the database for verification.
 
-The dbparse module is also used by db2bin.py, the `compiler', which
-compiles and signs the binary database.
+The dbparse module is also used by db2bin.py and db2fw.py, the `compilers'
+that compile the database to its binary formats.
 
 For more information, please see the CRDA git repository:
 
diff --git a/db2fw.py b/db2fw.py
new file mode 100755
index 000000000000..7b2b14151e69
--- /dev/null
+++ b/db2fw.py
@@ -0,0 +1,133 @@
+#!/usr/bin/env python
+
+from cStringIO import StringIO
+import struct
+import hashlib
+from dbparse import DBParser
+import sys
+
+MAGIC = 0x52474442
+VERSION = 20
+
+if len(sys.argv) < 3:
+    print 'Usage: %s output-file input-file' % sys.argv[0]
+    sys.exit(2)
+
+def create_rules(countries):
+    result = {}
+    for c in countries.itervalues():
+        for rule in c.permissions:
+            result[rule] = 1
+    return result.keys()
+
+def create_collections(countries):
+    result = {}
+    for c in countries.itervalues():
+        result[(c.permissions, c.dfs_region)] = 1
+    return result.keys()
+
+
+def be32(output, val):
+    output.write(struct.pack('>I', val))
+def be16(output, val):
+    output.write(struct.pack('>H', val))
+
+class PTR(object):
+    def __init__(self, output):
+        self._output = output
+        self._pos = output.tell()
+        be16(output, 0)
+        self._written = False
+
+    def set(self, val=None):
+        if val is None:
+            val = self._output.tell()
+        assert val & 3 == 0
+        self._offset = val
+        pos = self._output.tell()
+        self._output.seek(self._pos)
+        be16(self._output, val >> 2)
+        self._output.seek(pos)
+        self._written = True
+
+    def get(self):
+        return self._offset
+
+    @property
+    def written(self):
+        return self._written
+
+p = DBParser()
+countries = p.parse(file(sys.argv[2]))
+rules = create_rules(countries)
+rules.sort(cmp=lambda x, y: cmp(x.freqband, y.freqband))
+collections = create_collections(countries)
+collections.sort(cmp=lambda x, y: cmp(x[0][0].freqband, y[0][0].freqband))
+
+output = StringIO()
+
+# struct regdb_file_header
+be32(output, MAGIC)
+be32(output, VERSION)
+
+country_ptrs = {}
+countrynames = countries.keys()
+countrynames.sort()
+for alpha2 in countrynames:
+    coll = countries[alpha2]
+    output.write(struct.pack('>cc', str(alpha2[0]), str(alpha2[1])))
+    country_ptrs[alpha2] = PTR(output)
+output.write('\x00' * 4)
+
+reg_rules = {}
+flags = 0
+for reg_rule in rules:
+    freq_range, power_rule = reg_rule.freqband, reg_rule.power
+    reg_rules[reg_rule] = output.tell()
+    assert power_rule.max_ant_gain == 0
+    flags = 0
+    # convert to new rule flags
+    assert reg_rule.flags & ~0x899 == 0
+    if reg_rule.flags & 1<<0:
+        flags |= 1<<0
+    if reg_rule.flags & 1<<3:
+        flags |= 1<<1
+    if reg_rule.flags & 1<<4:
+        flags |= 1<<2
+    if reg_rule.flags & 1<<7:
+        flags |= 1<<3
+    if reg_rule.flags & 1<<11:
+        flags |= 1<<4
+    rule_len = 16
+    cac_timeout = 0 # TODO
+    if not (flags & 1<<2):
+        cac_timeout = 0
+    if cac_timeout:
+        rule_len += 2
+    output.write(struct.pack('>BBHIII', rule_len, flags, power_rule.max_eirp * 100,
+                             freq_range.start * 1000, freq_range.end * 1000, freq_range.maxbw * 1000,
+                             ))
+    if cac_timeout:
+        output.write(struct.pack('>H', cac_timeout))
+    while rule_len % 4:
+        output.write('\0')
+        rule_len += 1
+
+for coll in collections:
+    for alpha2 in countrynames:
+        if (countries[alpha2].permissions, countries[alpha2].dfs_region) == coll:
+            assert not country_ptrs[alpha2].written
+            country_ptrs[alpha2].set()
+    slen = 3
+    output.write(struct.pack('>BBBx', slen, len(list(coll[0])), coll[1]))
+    coll = list(coll[0])
+    for regrule in coll:
+        be16(output, reg_rules[regrule] >> 2)
+    if len(coll) % 2:
+        be16(output, 0)
+
+for alpha2 in countrynames:
+    assert country_ptrs[alpha2].written
+
+outfile = open(sys.argv[1], 'w')
+outfile.write(output.getvalue())
-- 
2.14.2

^ permalink raw reply related

* [PATCH v2 1/4] cfg80211: support loading regulatory database as firmware file
From: Johannes Berg @ 2017-10-09  9:50 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20171009095018.5289-1-johannes@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

As the current regulatory database is only about 4k big, and already
difficult to extend, we decided that overall it would be better to
get rid of the complications with CRDA and load the database into the
kernel directly, but in a new format that is extensible.

The new file format can be extended since it carries a length field
on all the structs that need to be extensible.

In order to be able to request firmware when the module initializes,
move cfg80211 from subsys_initcall() to the later fs_initcall(); the
firmware loader is at the same level but linked earlier, so it can
be called from there. Otherwise, when both the firmware loader and
cfg80211 are built-in, the request will crash the kernel. We also
need to be before device_initcall() so that cfg80211 is available
for devices when they initialize.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 Documentation/networking/regulatory.txt |   8 +
 net/wireless/Kconfig                    |   4 +-
 net/wireless/core.c                     |   2 +-
 net/wireless/reg.c                      | 296 +++++++++++++++++++++++++++++---
 4 files changed, 286 insertions(+), 24 deletions(-)

diff --git a/Documentation/networking/regulatory.txt b/Documentation/networking/regulatory.txt
index 7818b5fe448b..46c8d8b1cc66 100644
--- a/Documentation/networking/regulatory.txt
+++ b/Documentation/networking/regulatory.txt
@@ -19,6 +19,14 @@ core regulatory domain all wireless devices should adhere to.
 How to get regulatory domains to the kernel
 -------------------------------------------
 
+When the regulatory domain is first set up, the kernel will request a
+database file (regulatory.db) containing all the regulatory rules. It
+will then use that database when it needs to look up the rules for a
+given country.
+
+How to get regulatory domains to the kernel (old CRDA solution)
+---------------------------------------------------------------
+
 Userspace gets a regulatory domain in the kernel by having
 a userspace agent build it and send it via nl80211. Only
 expected regulatory domains will be respected by the kernel.
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index 6c606120abfe..24eec5516649 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -19,6 +19,7 @@ config WEXT_PRIV
 config CFG80211
 	tristate "cfg80211 - wireless configuration API"
 	depends on RFKILL || !RFKILL
+	select FW_LOADER
 	---help---
 	  cfg80211 is the Linux wireless LAN (802.11) configuration API.
 	  Enable this if you have a wireless device.
@@ -167,7 +168,8 @@ config CFG80211_CRDA_SUPPORT
 	depends on CFG80211
 	help
 	  You should enable this option unless you know for sure you have no
-	  need for it, for example when using internal regdb (above.)
+	  need for it, for example when using internal regdb (above) or the
+	  database loaded as a firmware file.
 
 	  If unsure, say Y.
 
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 7b33e8c366bc..fdde0d98fde1 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1384,7 +1384,7 @@ static int __init cfg80211_init(void)
 out_fail_pernet:
 	return err;
 }
-subsys_initcall(cfg80211_init);
+fs_initcall(cfg80211_init);
 
 static void __exit cfg80211_exit(void)
 {
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 6e94f6934a0e..3187a941b7bf 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -54,6 +54,7 @@
 #include <linux/nl80211.h>
 #include <linux/platform_device.h>
 #include <linux/moduleparam.h>
+#include <linux/firmware.h>
 #include <net/cfg80211.h>
 #include "core.h"
 #include "reg.h"
@@ -100,7 +101,7 @@ static struct regulatory_request core_request_world = {
 static struct regulatory_request __rcu *last_request =
 	(void __force __rcu *)&core_request_world;
 
-/* To trigger userspace events */
+/* To trigger userspace events and load firmware */
 static struct platform_device *reg_pdev;
 
 /*
@@ -443,7 +444,6 @@ reg_copy_regd(const struct ieee80211_regdomain *src_regd)
 	return regd;
 }
 
-#ifdef CONFIG_CFG80211_INTERNAL_REGDB
 struct reg_regdb_apply_request {
 	struct list_head list;
 	const struct ieee80211_regdomain *regdom;
@@ -475,41 +475,44 @@ static void reg_regdb_apply(struct work_struct *work)
 
 static DECLARE_WORK(reg_regdb_work, reg_regdb_apply);
 
-static int reg_query_builtin(const char *alpha2)
+static int reg_schedule_apply(const struct ieee80211_regdomain *regdom)
 {
-	const struct ieee80211_regdomain *regdom = NULL;
 	struct reg_regdb_apply_request *request;
-	unsigned int i;
-
-	for (i = 0; i < reg_regdb_size; i++) {
-		if (alpha2_equal(alpha2, reg_regdb[i]->alpha2)) {
-			regdom = reg_regdb[i];
-			break;
-		}
-	}
-
-	if (!regdom)
-		return -ENODATA;
 
 	request = kzalloc(sizeof(struct reg_regdb_apply_request), GFP_KERNEL);
-	if (!request)
-		return -ENOMEM;
-
-	request->regdom = reg_copy_regd(regdom);
-	if (IS_ERR_OR_NULL(request->regdom)) {
-		kfree(request);
+	if (!request) {
+		kfree(regdom);
 		return -ENOMEM;
 	}
 
+	request->regdom = regdom;
+
 	mutex_lock(&reg_regdb_apply_mutex);
 	list_add_tail(&request->list, &reg_regdb_apply_list);
 	mutex_unlock(&reg_regdb_apply_mutex);
 
 	schedule_work(&reg_regdb_work);
-
 	return 0;
 }
 
+#ifdef CONFIG_CFG80211_INTERNAL_REGDB
+static int reg_query_builtin(const char *alpha2)
+{
+	const struct ieee80211_regdomain *regdom = NULL;
+	unsigned int i;
+
+	for (i = 0; i < reg_regdb_size; i++) {
+		if (alpha2_equal(alpha2, reg_regdb[i]->alpha2)) {
+			regdom = reg_copy_regd(reg_regdb[i]);
+			break;
+		}
+	}
+	if (!regdom)
+		return -ENODATA;
+
+	return reg_schedule_apply(regdom);
+}
+
 /* Feel free to add any other sanity checks here */
 static void reg_regdb_size_check(void)
 {
@@ -599,12 +602,258 @@ static inline int call_crda(const char *alpha2)
 }
 #endif /* CONFIG_CFG80211_CRDA_SUPPORT */
 
+/* code to directly load a firmware database through request_firmware */
+static const struct fwdb_header *regdb;
+static unsigned int fwregdb_attempts = 10;
+
+struct fwdb_country {
+	u8 alpha2[2];
+	__be16 coll_ptr;
+	/* this struct cannot be extended */
+} __packed __aligned(4);
+
+struct fwdb_collection {
+	u8 len;
+	u8 n_rules;
+	u8 dfs_region;
+	/* no optional data yet */
+	/* aligned to 2, then followed by __be16 array of rule pointers */
+} __packed __aligned(4);
+
+enum fwdb_flags {
+	FWDB_FLAG_NO_OFDM	= BIT(0),
+	FWDB_FLAG_NO_OUTDOOR	= BIT(1),
+	FWDB_FLAG_DFS		= BIT(2),
+	FWDB_FLAG_NO_IR		= BIT(3),
+	FWDB_FLAG_AUTO_BW	= BIT(4),
+};
+
+struct fwdb_rule {
+	u8 len;
+	u8 flags;
+	__be16 max_eirp;
+	__be32 start, end, max_bw;
+	/* start of optional data */
+	__be16 cac_timeout;
+} __packed __aligned(4);
+
+#define FWDB_MAGIC 0x52474442
+#define FWDB_VERSION 20
+
+struct fwdb_header {
+	__be32 magic;
+	__be32 version;
+	struct fwdb_country country[];
+} __packed __aligned(4);
+
+static bool valid_rule(const u8 *data, unsigned int size, u16 rule_ptr)
+{
+	struct fwdb_rule *rule = (void *)(data + (rule_ptr << 2));
+
+	if ((u8 *)rule + sizeof(rule->len) > data + size)
+		return false;
+
+	/* mandatory fields */
+	if (rule->len < offsetofend(struct fwdb_rule, max_bw))
+		return false;
+
+	return true;
+}
+
+static bool valid_country(const u8 *data, unsigned int size,
+			  const struct fwdb_country *country)
+{
+	unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2;
+	struct fwdb_collection *coll = (void *)(data + ptr);
+	__be16 *rules_ptr;
+	unsigned int i;
+
+	/* make sure we can read len/n_rules */
+	if ((u8 *)coll + offsetofend(typeof(*coll), n_rules) > data + size)
+		return false;
+
+	/* make sure base struct and all rules fit */
+	if ((u8 *)coll + ALIGN(coll->len, 2) +
+	    (coll->n_rules * 2) > data + size)
+		return false;
+
+	/* mandatory fields must exist */
+	if (coll->len < offsetofend(struct fwdb_collection, dfs_region))
+		return false;
+
+	rules_ptr = (void *)((u8 *)coll + ALIGN(coll->len, 2));
+
+	for (i = 0; i < coll->n_rules; i++) {
+		u16 rule_ptr = be16_to_cpu(rules_ptr[i]);
+
+		if (!valid_rule(data, size, rule_ptr))
+			return false;
+	}
+
+	return true;
+}
+
+static bool valid_regdb(const u8 *data, unsigned int size)
+{
+	const struct fwdb_header *hdr = (void *)data;
+	const struct fwdb_country *country;
+
+	if (size < sizeof(*hdr))
+		return false;
+
+	if (hdr->magic != cpu_to_be32(FWDB_MAGIC))
+		return false;
+
+	if (hdr->version != cpu_to_be32(FWDB_VERSION))
+		return false;
+
+	country = &hdr->country[0];
+	while ((u8 *)(country + 1) <= data + size) {
+		if (!country->coll_ptr)
+			break;
+		if (!valid_country(data, size, country))
+			return false;
+		country++;
+	}
+
+	return true;
+}
+
+static int regdb_query_country(const struct fwdb_header *db,
+			       const struct fwdb_country *country)
+{
+	unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2;
+	struct fwdb_collection *coll = (void *)((u8 *)db + ptr);
+	struct ieee80211_regdomain *regdom;
+	unsigned int size_of_regd;
+	unsigned int i;
+
+	size_of_regd =
+		sizeof(struct ieee80211_regdomain) +
+		coll->n_rules * sizeof(struct ieee80211_reg_rule);
+
+	regdom = kzalloc(size_of_regd, GFP_KERNEL);
+	if (!regdom)
+		return -ENOMEM;
+
+	regdom->n_reg_rules = coll->n_rules;
+	regdom->alpha2[0] = country->alpha2[0];
+	regdom->alpha2[1] = country->alpha2[1];
+	regdom->dfs_region = coll->dfs_region;
+
+	for (i = 0; i < regdom->n_reg_rules; i++) {
+		__be16 *rules_ptr = (void *)((u8 *)coll + ALIGN(coll->len, 2));
+		unsigned int rule_ptr = be16_to_cpu(rules_ptr[i]) << 2;
+		struct fwdb_rule *rule = (void *)((u8 *)db + rule_ptr);
+		struct ieee80211_reg_rule *rrule = &regdom->reg_rules[i];
+
+		rrule->freq_range.start_freq_khz = be32_to_cpu(rule->start);
+		rrule->freq_range.end_freq_khz = be32_to_cpu(rule->end);
+		rrule->freq_range.max_bandwidth_khz = be32_to_cpu(rule->max_bw);
+
+		rrule->power_rule.max_antenna_gain = 0;
+		rrule->power_rule.max_eirp = be16_to_cpu(rule->max_eirp);
+
+		rrule->flags = 0;
+		if (rule->flags & FWDB_FLAG_NO_OFDM)
+			rrule->flags |= NL80211_RRF_NO_OFDM;
+		if (rule->flags & FWDB_FLAG_NO_OUTDOOR)
+			rrule->flags |= NL80211_RRF_NO_OUTDOOR;
+		if (rule->flags & FWDB_FLAG_DFS)
+			rrule->flags |= NL80211_RRF_DFS;
+		if (rule->flags & FWDB_FLAG_NO_IR)
+			rrule->flags |= NL80211_RRF_NO_IR;
+		if (rule->flags & FWDB_FLAG_AUTO_BW)
+			rrule->flags |= NL80211_RRF_AUTO_BW;
+
+		rrule->dfs_cac_ms = 0;
+
+		/* handle optional data */
+		if (rule->len >= offsetofend(struct fwdb_rule, cac_timeout))
+			rrule->dfs_cac_ms =
+				1000 * be16_to_cpu(rule->cac_timeout);
+	}
+
+	return reg_schedule_apply(regdom);
+}
+
+static int query_regdb(const char *alpha2)
+{
+	const struct fwdb_header *hdr = regdb;
+	const struct fwdb_country *country;
+
+	if (IS_ERR(regdb))
+		return PTR_ERR(regdb);
+
+	country = &hdr->country[0];
+	while (country->coll_ptr) {
+		if (alpha2_equal(alpha2, country->alpha2))
+			return regdb_query_country(regdb, country);
+		country++;
+	}
+
+	return -ENODATA;
+}
+
+static void regdb_fw_cb(const struct firmware *fw, void *context)
+{
+	void *db;
+
+	if (!fw) {
+		pr_info("failed to load regulatory.db\n");
+		if (fwregdb_attempts-- == 0)
+			regdb = ERR_PTR(-ENODATA);
+		goto restore;
+	}
+
+	if (!valid_regdb(fw->data, fw->size)) {
+		pr_info("loaded regulatory.db is malformed\n");
+		release_firmware(fw);
+		regdb = ERR_PTR(-EINVAL);
+		goto restore;
+	}
+
+	db = kmemdup(fw->data, fw->size, GFP_KERNEL);
+	release_firmware(fw);
+
+	if (!db)
+		goto restore;
+	regdb = db;
+
+	if (query_regdb(context))
+		goto restore;
+	goto free;
+ restore:
+	rtnl_lock();
+	restore_regulatory_settings(true);
+	rtnl_unlock();
+ free:
+	kfree(context);
+}
+
+static int query_regdb_file(const char *alpha2)
+{
+	if (regdb)
+		return query_regdb(alpha2);
+
+	alpha2 = kmemdup(alpha2, 2, GFP_KERNEL);
+	if (!alpha2)
+		return -ENOMEM;
+
+	return request_firmware_nowait(THIS_MODULE, true, "regulatory.db",
+				       &reg_pdev->dev, GFP_KERNEL,
+				       (void *)alpha2, regdb_fw_cb);
+}
+
 static bool reg_query_database(struct regulatory_request *request)
 {
 	/* query internal regulatory database (if it exists) */
 	if (reg_query_builtin(request->alpha2) == 0)
 		return true;
 
+	if (query_regdb_file(request->alpha2) == 0)
+		return true;
+
 	if (call_crda(request->alpha2) == 0)
 		return true;
 
@@ -3360,4 +3609,7 @@ void regulatory_exit(void)
 		list_del(&reg_request->list);
 		kfree(reg_request);
 	}
+
+	if (!IS_ERR_OR_NULL(regdb))
+		kfree(regdb);
 }
-- 
2.14.2

^ permalink raw reply related

* [PATCH v2 2/4] cfg80211: support reloading regulatory database
From: Johannes Berg @ 2017-10-09  9:50 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20171009095018.5289-1-johannes@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

If the regulatory database is loaded, and then updated, it may
be necessary to reload it. Add an nl80211 command to do this.

Note that this just reloads the database, it doesn't re-apply
the rules from it immediately.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/uapi/linux/nl80211.h |  4 +++
 net/wireless/nl80211.c       | 11 ++++++
 net/wireless/reg.c           | 80 +++++++++++++++++++++++++++++++++-----------
 net/wireless/reg.h           |  6 ++++
 4 files changed, 81 insertions(+), 20 deletions(-)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 95832ce03a44..f882fe1f9709 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -990,6 +990,8 @@
  *	&NL80211_CMD_CONNECT or &NL80211_CMD_ROAM. If the 4 way handshake failed
  *	&NL80211_CMD_DISCONNECT should be indicated instead.
  *
+ * @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1194,6 +1196,8 @@ enum nl80211_commands {
 
 	NL80211_CMD_PORT_AUTHORIZED,
 
+	NL80211_CMD_RELOAD_REGDB,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 5129342151e6..67a03f2885a4 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -5678,6 +5678,11 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
 	}
 }
 
+static int nl80211_reload_regdb(struct sk_buff *skb, struct genl_info *info)
+{
+	return reg_reload_regdb();
+}
+
 static int nl80211_get_mesh_config(struct sk_buff *skb,
 				   struct genl_info *info)
 {
@@ -12708,6 +12713,12 @@ static const struct genl_ops nl80211_ops[] = {
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
 	},
+	{
+		.cmd = NL80211_CMD_RELOAD_REGDB,
+		.doit = nl80211_reload_regdb,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+	},
 	{
 		.cmd = NL80211_CMD_GET_MESH_CONFIG,
 		.doit = nl80211_get_mesh_config,
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 3187a941b7bf..6b444898919b 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -782,6 +782,8 @@ static int query_regdb(const char *alpha2)
 	const struct fwdb_header *hdr = regdb;
 	const struct fwdb_country *country;
 
+	ASSERT_RTNL();
+
 	if (IS_ERR(regdb))
 		return PTR_ERR(regdb);
 
@@ -797,42 +799,48 @@ static int query_regdb(const char *alpha2)
 
 static void regdb_fw_cb(const struct firmware *fw, void *context)
 {
+	int set_error = 0;
+	bool restore = true;
 	void *db;
 
 	if (!fw) {
 		pr_info("failed to load regulatory.db\n");
 		if (fwregdb_attempts-- == 0)
-			regdb = ERR_PTR(-ENODATA);
-		goto restore;
-	}
-
-	if (!valid_regdb(fw->data, fw->size)) {
+			set_error = -ENODATA;
+	} else if (!valid_regdb(fw->data, fw->size)) {
 		pr_info("loaded regulatory.db is malformed\n");
-		release_firmware(fw);
-		regdb = ERR_PTR(-EINVAL);
-		goto restore;
+		set_error = -EINVAL;
 	}
 
-	db = kmemdup(fw->data, fw->size, GFP_KERNEL);
-	release_firmware(fw);
+	rtnl_lock();
+	if (WARN_ON(regdb && !IS_ERR(regdb))) {
+		/* just restore and free new db */
+	} else if (set_error) {
+		regdb = ERR_PTR(set_error);
+	} else if (fw) {
+		db = kmemdup(fw->data, fw->size, GFP_KERNEL);
+		if (db) {
+			regdb = db;
+			restore = context && query_regdb(context);
+		} else {
+			restore = true;
+		}
+	}
 
-	if (!db)
-		goto restore;
-	regdb = db;
+	if (restore)
+		restore_regulatory_settings(true);
 
-	if (query_regdb(context))
-		goto restore;
-	goto free;
- restore:
-	rtnl_lock();
-	restore_regulatory_settings(true);
 	rtnl_unlock();
- free:
+
 	kfree(context);
+
+	release_firmware(fw);
 }
 
 static int query_regdb_file(const char *alpha2)
 {
+	ASSERT_RTNL();
+
 	if (regdb)
 		return query_regdb(alpha2);
 
@@ -845,6 +853,38 @@ static int query_regdb_file(const char *alpha2)
 				       (void *)alpha2, regdb_fw_cb);
 }
 
+int reg_reload_regdb(void)
+{
+	const struct firmware *fw;
+	void *db;
+	int err;
+
+	err = request_firmware(&fw, "regulatory.db", &reg_pdev->dev);
+	if (err)
+		return err;
+
+	if (!valid_regdb(fw->data, fw->size)) {
+		err = -ENODATA;
+		goto out;
+	}
+
+	db = kmemdup(fw->data, fw->size, GFP_KERNEL);
+	if (!db) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	rtnl_lock();
+	if (!IS_ERR_OR_NULL(regdb))
+		kfree(regdb);
+	regdb = db;
+	rtnl_unlock();
+
+ out:
+	release_firmware(fw);
+	return err;
+}
+
 static bool reg_query_database(struct regulatory_request *request)
 {
 	/* query internal regulatory database (if it exists) */
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index ca7fedf2e7a1..9529c522611a 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -179,4 +179,10 @@ void regulatory_propagate_dfs_state(struct wiphy *wiphy,
  * @wiphy2 - wiphy it's dfs_region to be checked against that of wiphy1
  */
 bool reg_dfs_domain_same(struct wiphy *wiphy1, struct wiphy *wiphy2);
+
+/**
+ * reg_reload_regdb - reload the regulatory.db firmware file
+ */
+int reg_reload_regdb(void);
+
 #endif  /* __NET_WIRELESS_REG_H */
-- 
2.14.2

^ permalink raw reply related

* [PATCH v2 4/4] cfg80211: implement regdb signature checking
From: Johannes Berg @ 2017-10-09  9:50 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20171009095018.5289-1-johannes@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

Currently CRDA implements the signature checking, and the previous
commits added the ability to load the whole regulatory database
into the kernel.

However, we really can't lose the signature checking, so implement
it in the kernel by loading a detached signature (regulatory.db.p7s)
and check it against built-in keys.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/wireless/Kconfig             |  30 ++++++++++
 net/wireless/Makefile            |  22 +++++++
 net/wireless/certs/sforshee.x509 | Bin 0 -> 680 bytes
 net/wireless/reg.c               | 121 ++++++++++++++++++++++++++++++++++++++-
 net/wireless/reg.h               |   8 +++
 5 files changed, 180 insertions(+), 1 deletion(-)
 create mode 100644 net/wireless/certs/sforshee.x509

diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index f050030055c5..da91bb547db3 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -83,6 +83,36 @@ config CFG80211_CERTIFICATION_ONUS
 	  you are a wireless researcher and are working in a controlled
 	  and approved environment by your local regulatory agency.
 
+config CFG80211_REQUIRE_SIGNED_REGDB
+	bool "require regdb signature" if CFG80211_CERTIFICATION_ONUS
+	default y
+	select SYSTEM_DATA_VERIFICATION
+	help
+	  Require that in addition to the "regulatory.db" file a
+	  "regulatory.db.p7s" can be loaded with a valid PKCS#7
+	  signature for the regulatory.db file made by one of the
+	  keys in the certs/ directory.
+
+config CFG80211_USE_KERNEL_REGDB_KEYS
+	bool "allow regdb keys shipped with the kernel" if CFG80211_CERTIFICATION_ONUS
+	default y
+	depends on CFG80211_REQUIRE_SIGNED_REGDB
+	help
+	  Allow the regulatory database to be signed by one of the keys for
+	  which certificates are part of the kernel sources
+	  (in net/wireless/certs/).
+
+	  This is currently only Seth Forshee's key, who is the regulatory
+	  database maintainer.
+
+config CFG80211_EXTRA_REGDB_KEYDIR
+	string "additional regdb key directory" if CFG80211_CERTIFICATION_ONUS
+	depends on CFG80211_REQUIRE_SIGNED_REGDB
+	help
+	  If selected, point to a directory with DER-encoded X.509
+	  certificates like in the kernel sources (net/wireless/certs/)
+	  that shall be accepted for a signed regulatory database.
+
 config CFG80211_REG_CELLULAR_HINTS
 	bool "cfg80211 regulatory support for cellular base station hints"
 	depends on CFG80211_CERTIFICATION_ONUS
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index 5f20dac5d8c6..219baea57e4e 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -16,3 +16,25 @@ cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
 cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o
 
 CFLAGS_trace.o := -I$(src)
+
+cfg80211-$(CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS) += shipped-certs.o
+ifneq ($(CONFIG_CFG80211_EXTRA_REGDB_KEYDIR),)
+cfg80211-y += extra-certs.o
+endif
+
+$(obj)/shipped-certs.c: $(wildcard $(srctree)/$(src)/certs/*.x509)
+	@echo "  GEN     $@"
+	@echo '#include "reg.h"' > $@
+	@echo 'const u8 shipped_regdb_certs[] = {' >> $@
+	@for f in $^ ; do hexdump -v -e '1/1 "0x%.2x," "\n"' < $$f >> $@ ; done
+	@echo '};' >> $@
+	@echo 'unsigned int shipped_regdb_certs_len = sizeof(shipped_regdb_certs);' >> $@
+
+$(obj)/extra-certs.c: $(CONFIG_CFG80211_EXTRA_REGDB_KEYDIR:"%"=%) \
+		      $(wildcard $(CONFIG_CFG80211_EXTRA_REGDB_KEYDIR:"%"=%)/*.x509)
+	@echo "  GEN     $@"
+	@echo '#include "reg.h"' > $@
+	@echo 'const u8 extra_regdb_certs[] = {' >> $@
+	@for f in $^ ; do test -f $$f && hexdump -v -e '1/1 "0x%.2x," "\n"' < $$f >> $@ || true ; done
+	@echo '};' >> $@
+	@echo 'unsigned int extra_regdb_certs_len = sizeof(extra_regdb_certs);' >> $@
diff --git a/net/wireless/certs/sforshee.x509 b/net/wireless/certs/sforshee.x509
new file mode 100644
index 0000000000000000000000000000000000000000..c6f8f9d6b98839048822ebbe27ecb831614ccf3d
GIT binary patch
literal 680
zcmXqLVp?L*#Mr~c$*`&SzWchL=aw7rvT<s)d9;1!Wn|=LWiSvn6g1#xV-96u=HVz#
z%P%U<NKG|R5a%^CH#9IXGqf}@FgA^n;5RZfG&is`G=d6X*Ve?Sgls$`D+6;ABR>Ps
z1zb!`jEoFh9UjloXt8AeWO+SJ$I(J`P2JMwLe;tnH5qsF?QdR>w3uI$6?BMMOSdlV
zi`-_R0)^-+(~WEkyRD@;#6_|bkA!zm6O;L?a+RC&XNF+Q?^A(17hNT93Al9K{8zT}
zZ-TA_x5m^>y01EB?6?@F_#s&SBUAoMx7m~9H74+{G5eLFTo@kq?abx-wOTi&i(Oyu
zQg3}<RloFf!*K(%OTq8ntdV<e_|a_9oaAGv(e<jO84F)su49Oq6?a2H!l;~GQz%W&
ztoZqK7Dw}q8;i8REYwt}nO4cIec{Hv6FK&ie;<8U5hN%oUG?oz#?0rx-NafRA7A+F
z!6mn=50AtzNc(c@$p5LbOw5c7jL0Dbi~wK=F*39>-}=;a=<fO&7yY)&@jjD1cK%}*
z->vvvRoQQq5|7x<;&pS~YD#Y&_6&F5Z@hi_o39R~2i%lCEQp;`DZKFij>Y=beQfq8
zwmr$x_+%2JY;Sbn*;@WJ=R-@}i!U>_Zs%4CQ>mTLxstDKo_X|~T&9~nCjzn_MSd1z
zd$q}FYs9}@7aPN+-fyz#i1@bZh+cP;`je$EmYhnDSyPmLIA8d%u4(1<uIFE`C>nTO
z{kHgKW!NWvf$y~!0w?Rc|ETrmY6%tMs`ay$*Vg}|u{qP^VMD|2N9%W9Gx#VQ(ylyn
seju}tYb{f1@#??lr<~!nO89FdqAzB=Qc?bNz{Y;&cMH;1idBjL01XcsegFUf

literal 0
HcmV?d00001

diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index bcccd1a905ef..6f2728137749 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -53,6 +53,7 @@
 #include <linux/ctype.h>
 #include <linux/nl80211.h>
 #include <linux/platform_device.h>
+#include <linux/verification.h>
 #include <linux/moduleparam.h>
 #include <linux/firmware.h>
 #include <net/cfg80211.h>
@@ -660,6 +661,115 @@ static bool valid_country(const u8 *data, unsigned int size,
 	return true;
 }
 
+#ifdef CONFIG_CFG80211_REQUIRE_SIGNED_REGDB
+static struct key *builtin_regdb_keys;
+
+static void __init load_keys_from_buffer(const u8 *p, unsigned int buflen)
+{
+	const u8 *end = p + buflen;
+	size_t plen;
+	key_ref_t key;
+
+	while (p < end) {
+		/* Each cert begins with an ASN.1 SEQUENCE tag and must be more
+		 * than 256 bytes in size.
+		 */
+		if (end - p < 4)
+			goto dodgy_cert;
+		if (p[0] != 0x30 &&
+		    p[1] != 0x82)
+			goto dodgy_cert;
+		plen = (p[2] << 8) | p[3];
+		plen += 4;
+		if (plen > end - p)
+			goto dodgy_cert;
+
+		key = key_create_or_update(make_key_ref(builtin_regdb_keys, 1),
+					   "asymmetric", NULL, p, plen,
+					   ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
+					    KEY_USR_VIEW | KEY_USR_READ),
+					   KEY_ALLOC_NOT_IN_QUOTA |
+					   KEY_ALLOC_BUILT_IN |
+					   KEY_ALLOC_BYPASS_RESTRICTION);
+		if (IS_ERR(key)) {
+			pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
+			       PTR_ERR(key));
+		} else {
+			pr_notice("Loaded X.509 cert '%s'\n",
+				  key_ref_to_ptr(key)->description);
+			key_ref_put(key);
+		}
+		p += plen;
+	}
+
+	return;
+
+dodgy_cert:
+	pr_err("Problem parsing in-kernel X.509 certificate list\n");
+}
+
+static int __init load_builtin_regdb_keys(void)
+{
+	builtin_regdb_keys =
+		keyring_alloc(".builtin_regdb_keys",
+			      KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
+			      ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
+			      KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH),
+			      KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
+	if (IS_ERR(builtin_regdb_keys))
+		return PTR_ERR(builtin_regdb_keys);
+
+	pr_notice("Loading compiled-in X.509 certificates for regulatory database\n");
+
+#ifdef CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS
+	load_keys_from_buffer(shipped_regdb_certs, shipped_regdb_certs_len);
+#endif
+#ifdef CFG80211_EXTRA_REGDB_KEYDIR
+	if (CONFIG_CFG80211_EXTRA_REGDB_KEYDIR[0] != '\0')
+		load_keys_from_buffer(extra_regdb_certs, extra_regdb_certs_len);
+#endif
+
+	return 0;
+}
+
+static bool regdb_has_valid_signature(const u8 *data, unsigned int size)
+{
+	const struct firmware *sig;
+	bool result;
+
+	if (request_firmware(&sig, "regulatory.db.p7s", &reg_pdev->dev))
+		return false;
+
+	result = verify_pkcs7_signature(data, size, sig->data, sig->size,
+					builtin_regdb_keys,
+					VERIFYING_UNSPECIFIED_SIGNATURE,
+					NULL, NULL) == 0;
+
+	release_firmware(sig);
+
+	return result;
+}
+
+static void free_regdb_keyring(void)
+{
+	key_put(builtin_regdb_keys);
+}
+#else
+static int load_builtin_regdb_keys(void)
+{
+	return 0;
+}
+
+static bool regdb_has_valid_signature(const u8 *data, unsigned int size)
+{
+	return true;
+}
+
+static void free_regdb_keyring(void)
+{
+}
+#endif /* CONFIG_CFG80211_REQUIRE_SIGNED_REGDB */
+
 static bool valid_regdb(const u8 *data, unsigned int size)
 {
 	const struct fwdb_header *hdr = (void *)data;
@@ -674,6 +784,9 @@ static bool valid_regdb(const u8 *data, unsigned int size)
 	if (hdr->version != cpu_to_be32(FWDB_VERSION))
 		return false;
 
+	if (!regdb_has_valid_signature(data, size))
+		return false;
+
 	country = &hdr->country[0];
 	while ((u8 *)(country + 1) <= data + size) {
 		if (!country->coll_ptr)
@@ -775,7 +888,7 @@ static void regdb_fw_cb(const struct firmware *fw, void *context)
 		if (fwregdb_attempts-- == 0)
 			set_error = -ENODATA;
 	} else if (!valid_regdb(fw->data, fw->size)) {
-		pr_info("loaded regulatory.db is malformed\n");
+		pr_info("loaded regulatory.db is malformed or signature is missing/invalid\n");
 		set_error = -EINVAL;
 	}
 
@@ -3537,6 +3650,10 @@ int __init regulatory_init(void)
 {
 	int err = 0;
 
+	err = load_builtin_regdb_keys();
+	if (err)
+		return err;
+
 	reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0);
 	if (IS_ERR(reg_pdev))
 		return PTR_ERR(reg_pdev);
@@ -3613,4 +3730,6 @@ void regulatory_exit(void)
 
 	if (!IS_ERR_OR_NULL(regdb))
 		kfree(regdb);
+
+	free_regdb_keyring();
 }
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index 9529c522611a..9ceeb5f3a7cb 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -1,5 +1,8 @@
 #ifndef __NET_WIRELESS_REG_H
 #define __NET_WIRELESS_REG_H
+
+#include <net/cfg80211.h>
+
 /*
  * Copyright 2008-2011	Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
  *
@@ -185,4 +188,9 @@ bool reg_dfs_domain_same(struct wiphy *wiphy1, struct wiphy *wiphy2);
  */
 int reg_reload_regdb(void);
 
+extern const u8 shipped_regdb_certs[];
+extern unsigned int shipped_regdb_certs_len;
+extern const u8 extra_regdb_certs[];
+extern unsigned int extra_regdb_certs_len;
+
 #endif  /* __NET_WIRELESS_REG_H */
-- 
2.14.2

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox