Netdev List
 help / color / mirror / Atom feed
* Re: linux-next: manual merge of the net tree with Linus' tree
From: Mintz, Yuval @ 2016-10-17 11:41 UTC (permalink / raw)
  To: Stephen Rothwell, David Miller, Networking
  Cc: linux-next@vger.kernel.org, linux-kernel@vger.kernel.org,
	Amrani, Ram, Doug Ledford
In-Reply-To: <20161016081317.229c5c47@canb.auug.org.au>

> Today's linux-next merge of the net tree got a conflict in:

>   drivers/net/ethernet/qlogic/Kconfig

> between commit:

>   2e0cbc4dd077 ("qedr: Add RoCE driver framework")

> from Linus' tree and commit:

>   0189efb8f4f8 ("qed*: Fix Kconfig dependencies with INFINIBAND_QEDR")

> from the net tree.

> I fixed it up (see below) and can carry the fix as necessary. This
> is now fixed as far as linux-next is concerned, but any non trivial
> conflicts should be mentioned to your upstream maintainer when your tree
> is submitted for merging.  

My bad; I've sent the fix to 'net' and was not aware that the
qedr submission was already accepted in linux-rdma.

> I also added this merge fix patch:

> From: Stephen Rothwell <sfr@canb.auug.org.au>
> Date: Sun, 16 Oct 2016 08:09:42 +1100
> Subject: [PATCH] qed*: merge fix for CONFIG_INFINIBAND_QEDR Kconfig move

> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
> ---
>  drivers/infiniband/hw/qedr/Kconfig | 1 +
>  1 file changed, 1 insertion(+)

> diff --git a/drivers/infiniband/hw/qedr/Kconfig b/drivers/infiniband/hw/qedr/Kconfig
> index 7c06d85568d4..6c9f3923e838 100644
> --- a/drivers/infiniband/hw/qedr/Kconfig
> +++ b/drivers/infiniband/hw/qedr/Kconfig
> @@ -2,6 +2,7 @@ config INFINIBAND_QEDR
>          tristate "QLogic RoCE driver"
>          depends on 64BIT && QEDE
>          select QED_LL2
> +       select QED_RDMA
>          ---help---
>            This driver provides low-level InfiniBand over Ethernet
>            support for QLogic QED host channel adapters (HCAs).
> -- 
> 2.8.1

Looks good; Thanks.

^ permalink raw reply

* Re: [patch net-next RFC 4/6] Introduce sample tc action
From: Jamal Hadi Salim @ 2016-10-17 10:10 UTC (permalink / raw)
  To: Roopa Prabhu, Jiri Pirko
  Cc: netdev, davem, yotamg, idosch, eladr, nogahf, ogerlitz,
	geert+renesas, stephen, xiyou.wangcong, linux
In-Reply-To: <58025A90.9010608@cumulusnetworks.com>


Some comments:
IIUC, the main struggle seems to be whether the redirect to dummy0
is useful or not? i.e instead of just letting the packets go up the
stack on eth1?
It seems like sflowd needs to read off eth1 via packet socket?
To be backward compatible - supporting that approach seems sensible.

Note:
There is a clear efficiency benefit of both using IFE encoding and
redirecting to dummy0.
1) Redirecting to dummy0 implies you dont need to exercise a bpf
filter around every packet that comes off eth1.
I understand there are probably not millions of pps for this case;
but in a non-offloaded cases it could be millions pps.
And in case of sampling over many ethx devices, you can redirect
samples from many other ethx devices.
So making dummy0 the sflow device is a win.
2) Encaping an IFE header implies a much more efficient bpf filter
(IFE ethertype is an excellent discriminator for bpf).

Additional benefit is as mentioned before - redirecting to a device
means you can send it remotely over ethernet to a more powerful
machine without having to cross kernel-userspace. Redirecting instead
of mirroring to tuntap is also an interesting option.

More comments below (on the sflow person's comment - dont seem him
on the Cc):

On 16-10-15 12:34 PM, Roopa Prabhu wrote:
> On 10/12/16, 5:41 AM, Jiri Pirko wrote:
>> From: Yotam Gigi <yotam.gi@gmail.com>


>> +
>> +struct sample_packet_metadata {
>> +	int sample_size;
>> +	int orig_size;
>> +	int ifindex;
>> +};
>> +
> This metadata does not look extensible.. can it be made to ?
>

Sure it can...

> With sflow in context, you need a pair of ifindex numbers to encode ingress and egress ports.

What is the use case for both?
> Ideally you would also include a sequence number and a count of the total number of packets
 > that were candidates for sampling.

Sequence number may make sense (they will help show a gap if something
gets dropped). But i am not sure about the stats consuming such space.
Stats are something that can be queried (tc stats should have a record
of how many bytes/packets )

>The OVS implementation is a good example, the metadata includes all the actions applied
>to the packet in the kernel data path.
>

Again not sure what the use case would be (and why waste such space
especially when you are sending over the wire with such details).

>> +	rcu_read_lock();
>> +	retval = READ_ONCE(s->tcf_action);
>> +
>> +	if (++s->packet_counter % s->rate == 0) {
>
> The sampling function isn’t random
>
> if (++s->packet_counter % s->rate == 0) {
>
> This is unsuitable for sFlow, which is specific about the random sampling function required.
>BPF, OVS, and the
> ULOG statistics module include efficient kernel based random sampling functions that could be used instead.
>

If i understood correctly, the above is a fallback sampling algorithm.
In the case of the spectrum it already does the sampling in the ASIC
so there is no need to repeat it in software.
Agreed that in that case the sampling approach is not sufficiently
random.

cheers,
jamal

^ permalink raw reply

* Re: [PATCH v4] mac80211: move extra crypto data off the stack
From: Ard Biesheuvel @ 2016-10-17 10:02 UTC (permalink / raw)
  To: Johannes Berg
  Cc: <linux-wireless@vger.kernel.org>, Sergey Senozhatsky,
	<netdev@vger.kernel.org>, Herbert Xu
In-Reply-To: <1476698041.19992.19.camel@sipsolutions.net>



> On 17 Oct 2016, at 10:54, Johannes Berg <johannes@sipsolutions.net> wrote:
> 
> 
>>> Well, if your other patch to make it OK to be on-stack would be
>>> applied instead, this wouldn't make much sense either :)
>>> 
>> 
>> Yes but that one only fixes ccm not gcm
> 
> Yes, but we can do the same for GCM, no?
> 

No, not really. ccm happens to use aes with the same key for the mac and the encryption. gcm uses an another algo entirely for the mac

>>> In this particular patch, we could reduce the size of the struct,
>>> but I
>>> don't actually think it'll make a difference to go from 48 to 36
>>> bytes,
>>> given alignment etc., so I think I'll just leave it as is.
>>> 
>> 
>> I understand you are in a hurry, but this is unlikely to be the only
>> such issue. I will propose an 'auxdata' feature for the crypto api
>> that can be used here, but also for any other occurrence where client
>> data assoiciated with the request can no longer be allocated on the
>> stack
> 
> No objections. I'll merge this anyway today I think, reverting is easy
> later.
> 

ok fair enough

^ permalink raw reply

* Re: net/ipv6: potential deadlock in do_ipv6_setsockopt
From: Baozeng Ding @ 2016-10-17  9:54 UTC (permalink / raw)
  To: Cong Wang; +Cc: Linux Kernel Network Developers
In-Reply-To: <CAM_iQpWKfkkYzF6yb9fGQsieGwok196kqGtRNVVS_ULxZghyew@mail.gmail.com>

Applied the patch to my test tree. I will tell you the result a few days later. Thank you.

On 2016/10/17 2:50, Cong Wang wrote:
> On Sun, Oct 16, 2016 at 6:34 AM, Baozeng Ding <sploving1@gmail.com> wrote:
>>  Possible unsafe locking scenario:
>>
>>        CPU0                    CPU1
>>        ----                    ----
>>   lock([  165.136033] sk_lock-AF_INET6
>> );
>>                                lock([  165.136033] rtnl_mutex
>> );
>>                                lock([  165.136033] sk_lock-AF_INET6
>> );
>>   lock([  165.136033] rtnl_mutex
>> );
>>
>>  *** DEADLOCK ***
> 
> This is caused by the conditional rtnl locking in do_ipv6_setsockopt().
> It looks like we miss the case of IPV6_ADDRFORM.
> 
> Please try the attached patch.
> 

^ permalink raw reply

* Re: [PATCH v4] mac80211: move extra crypto data off the stack
From: Johannes Berg @ 2016-10-17  9:54 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: <linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
	Sergey Senozhatsky,
	<netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
	Herbert Xu
In-Reply-To: <67161BCC-596E-4DDE-A58E-9195BB5570C2-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>


> > Well, if your other patch to make it OK to be on-stack would be
> > applied instead, this wouldn't make much sense either :)
> > 
> 
> Yes but that one only fixes ccm not gcm

Yes, but we can do the same for GCM, no?

> > In this particular patch, we could reduce the size of the struct,
> > but I
> > don't actually think it'll make a difference to go from 48 to 36
> > bytes,
> > given alignment etc., so I think I'll just leave it as is.
> > 
> 
> I understand you are in a hurry, but this is unlikely to be the only
> such issue. I will propose an 'auxdata' feature for the crypto api
> that can be used here, but also for any other occurrence where client
> data assoiciated with the request can no longer be allocated on the
> stack

No objections. I'll merge this anyway today I think, reverting is easy
later.

johannes

^ permalink raw reply

* Re: [PATCH v4] mac80211: move extra crypto data off the stack
From: Ard Biesheuvel @ 2016-10-17  9:52 UTC (permalink / raw)
  To: Johannes Berg
  Cc: <linux-wireless@vger.kernel.org>, Sergey Senozhatsky,
	<netdev@vger.kernel.org>, Herbert Xu
In-Reply-To: <1476696918.19992.15.camel@sipsolutions.net>



> On 17 Oct 2016, at 10:35, Johannes Berg <johannes@sipsolutions.net> wrote:
> 
>> On Mon, 2016-10-17 at 10:30 +0100, Ard Biesheuvel wrote:
>> 
>> Yes. But as I replied, setting the req size is not supported atm,
>> although it is reasonable to demand a way to allocate additional data
>> in the request specifically for this issue. So let's proceed with the
>> aead_request_alloc/free patch, but I would like to propose something
>> on the API side to address this particular issue
> 
> Well, if your other patch to make it OK to be on-stack would be applied
> instead, this wouldn't make much sense either :)
> 

Yes but that one only fixes ccm not gcm

> In this particular patch, we could reduce the size of the struct, but I
> don't actually think it'll make a difference to go from 48 to 36 bytes,
> given alignment etc., so I think I'll just leave it as is.
> 

I understand you are in a hurry, but this is unlikely to be the only such issue. I will propose an 'auxdata' feature for the crypto api that can be used here, but also for any other occurrence where client data assoiciated with the request can no longer be allocated on the stack

^ permalink raw reply

* Re: [PATCH v4] mac80211: move extra crypto data off the stack
From: Ard Biesheuvel @ 2016-10-17  9:49 UTC (permalink / raw)
  To: Johannes Berg
  Cc: <linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
	Sergey Senozhatsky,
	<netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
	Herbert Xu
In-Reply-To: <1476696918.19992.15.camel-cdvu00un1VgdHxzADdlk8Q@public.gmane.org>



> On 17 Oct 2016, at 10:35, Johannes Berg <johannes-cdvu00un1VgdHxzADdlk8Q@public.gmane.org> wrote:
> 
>> On Mon, 2016-10-17 at 10:30 +0100, Ard Biesheuvel wrote:
>> 
>> Yes. But as I replied, setting the req size is not supported atm,
>> although it is reasonable to demand a way to allocate additional data
>> in the request specifically for this issue. So let's proceed with the
>> aead_request_alloc/free patch, but I would like to propose something
>> on the API side to address this particular issue
> 
> Well, if your other patch to make it OK to be on-stack would be applied
> instead, this wouldn't make much sense either :)
> 
> In this particular patch, we could reduce the size of the struct, but I
> don't actually think it'll make a difference to go from 48 to 36 bytes,
> given alignment etc., so I think I'll just leave it as is.
> 
> johannes

^ permalink raw reply

* Re: [PATCH] mac80211_hwsim: suggest nl80211 instead of wext driver in documentation
From: Johannes Berg @ 2016-10-17  9:39 UTC (permalink / raw)
  To: Linus Lüssing, linux-wireless, Jouni Malinen
  Cc: David S . Miller, Jonathan Corbet, netdev, linux-kernel,
	linux-doc
In-Reply-To: <20161016223933.9484-1-linus.luessing@c0d3.blue>

On Mon, 2016-10-17 at 00:39 +0200, Linus Lüssing wrote:
> For mac80211_hwsim interfaces, suggest to use wpa_supplicant with the
> more modern, netlink based driver instead of wext.

Makes sense, applied.

> Actually, I wasn't even able to make a connection with the
> configuration
> files and information provided in
> Documentation/networking/mac80211_hwsim/{README,hostapd.conf/wpa_supp
> licant.conf}
> 
This less so, we even have a few test cases we run regularly, but I
don't know. Maybe there's something special in those configuration
files that we don't test for otherwise.

johannes

^ permalink raw reply

* Re: [PATCH v4] mac80211: move extra crypto data off the stack
From: Johannes Berg @ 2016-10-17  9:35 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: <linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
	Sergey Senozhatsky,
	<netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
	Herbert Xu
In-Reply-To: <CAKv+Gu_ZH9hO_xbVfOfk90CxFJ6ZTz3PKWB1v23LRVzpBrb=oQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On Mon, 2016-10-17 at 10:30 +0100, Ard Biesheuvel wrote:

> Yes. But as I replied, setting the req size is not supported atm,
> although it is reasonable to demand a way to allocate additional data
> in the request specifically for this issue. So let's proceed with the
> aead_request_alloc/free patch, but I would like to propose something
> on the API side to address this particular issue

Well, if your other patch to make it OK to be on-stack would be applied
instead, this wouldn't make much sense either :)

In this particular patch, we could reduce the size of the struct, but I
don't actually think it'll make a difference to go from 48 to 36 bytes,
given alignment etc., so I think I'll just leave it as is.

johannes

^ permalink raw reply

* [PATCH iproute2 2/2] tc filters: fix filters to display handle when deleted even when no option
From: Jamal Hadi Salim @ 2016-10-17  9:34 UTC (permalink / raw)
  To: stephen; +Cc: netdev, daniel, xiyou.wangcong, mrv, Jamal Hadi Salim
In-Reply-To: <1476696885-22214-1-git-send-email-jhs@emojatatu.com>

From: Jamal Hadi Salim <jhs@mojatatu.com>

Fix a few stylistic things that hurt my eyes while at it.

Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
 tc/f_basic.c    |  6 +++---
 tc/f_bpf.c      |  6 +++---
 tc/f_cgroup.c   |  7 +++----
 tc/f_flow.c     |  4 ++--
 tc/f_flower.c   |  5 +++--
 tc/f_fw.c       | 38 ++++++++++++++++++++++----------------
 tc/f_matchall.c |  6 +++---
 tc/f_route.c    | 29 ++++++++++++++++++-----------
 tc/f_rsvp.c     | 28 ++++++++++++++++++----------
 tc/f_tcindex.c  |  4 +++-
 tc/f_u32.c      |  9 ++++-----
 11 files changed, 82 insertions(+), 60 deletions(-)

diff --git a/tc/f_basic.c b/tc/f_basic.c
index d663668..317dca1 100644
--- a/tc/f_basic.c
+++ b/tc/f_basic.c
@@ -112,14 +112,14 @@ static int basic_print_opt(struct filter_util *qu, FILE *f,
 {
 	struct rtattr *tb[TCA_BASIC_MAX+1];
 
+	if (handle)
+		fprintf(f, "handle 0x%x ", handle);
+
 	if (opt == NULL)
 		return 0;
 
 	parse_rtattr_nested(tb, TCA_BASIC_MAX, opt);
 
-	if (handle)
-		fprintf(f, "handle 0x%x ", handle);
-
 	if (tb[TCA_BASIC_CLASSID]) {
 		SPRINT_BUF(b1);
 		fprintf(f, "flowid %s ",
diff --git a/tc/f_bpf.c b/tc/f_bpf.c
index 5c97c86..a7dd2f2 100644
--- a/tc/f_bpf.c
+++ b/tc/f_bpf.c
@@ -152,14 +152,14 @@ static int bpf_print_opt(struct filter_util *qu, FILE *f,
 {
 	struct rtattr *tb[TCA_BPF_MAX + 1];
 
+	if (handle)
+		fprintf(f, "handle 0x%x ", handle);
+
 	if (opt == NULL)
 		return 0;
 
 	parse_rtattr_nested(tb, TCA_BPF_MAX, opt);
 
-	if (handle)
-		fprintf(f, "handle 0x%x ", handle);
-
 	if (tb[TCA_BPF_CLASSID]) {
 		SPRINT_BUF(b1);
 		fprintf(f, "flowid %s ",
diff --git a/tc/f_cgroup.c b/tc/f_cgroup.c
index ecf9909..ae798db 100644
--- a/tc/f_cgroup.c
+++ b/tc/f_cgroup.c
@@ -85,14 +85,13 @@ static int cgroup_print_opt(struct filter_util *qu, FILE *f,
 {
 	struct rtattr *tb[TCA_CGROUP_MAX+1];
 
+	if (handle)
+		fprintf(f, "handle 0x%x ", handle);
+
 	if (opt == NULL)
 		return 0;
 
 	parse_rtattr_nested(tb, TCA_CGROUP_MAX, opt);
-
-	if (handle)
-		fprintf(f, "handle 0x%x ", handle);
-
 	if (tb[TCA_CGROUP_EMATCHES])
 		print_ematch(f, tb[TCA_CGROUP_EMATCHES]);
 
diff --git a/tc/f_flow.c b/tc/f_flow.c
index 09ddcaa..5a9948f 100644
--- a/tc/f_flow.c
+++ b/tc/f_flow.c
@@ -272,13 +272,13 @@ static int flow_print_opt(struct filter_util *fu, FILE *f, struct rtattr *opt,
 	unsigned int i;
 	__u32 mask = ~0, val = 0;
 
+	fprintf(f, "handle 0x%x ", handle);
+
 	if (opt == NULL)
 		return -EINVAL;
 
 	parse_rtattr_nested(tb, TCA_FLOW_MAX, opt);
 
-	fprintf(f, "handle 0x%x ", handle);
-
 	if (tb[TCA_FLOW_MODE]) {
 		__u32 mode = rta_getattr_u32(tb[TCA_FLOW_MODE]);
 
diff --git a/tc/f_flower.c b/tc/f_flower.c
index 791ade7..2f566ec 100644
--- a/tc/f_flower.c
+++ b/tc/f_flower.c
@@ -456,13 +456,14 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
 	__be16 eth_type = 0;
 	__u8 ip_proto = 0xff;
 
+	if (handle)
+		fprintf(f, "handle 0x%x ", handle);
+
 	if (!opt)
 		return 0;
 
 	parse_rtattr_nested(tb, TCA_FLOWER_MAX, opt);
 
-	if (handle)
-		fprintf(f, "handle 0x%x ", handle);
 
 	if (tb[TCA_FLOWER_CLASSID]) {
 		SPRINT_BUF(b1);
diff --git a/tc/f_fw.c b/tc/f_fw.c
index 29c9854..f779c16 100644
--- a/tc/f_fw.c
+++ b/tc/f_fw.c
@@ -115,37 +115,42 @@ static int fw_parse_opt(struct filter_util *qu, char *handle, int argc, char **a
 	return 0;
 }
 
-static int fw_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __u32 handle)
+static int fw_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt,
+			__u32 handle)
 {
 	struct rtattr *tb[TCA_FW_MAX+1];
+	__u32 mark = 0, mask = 0;
 
-	if (opt == NULL)
-		return 0;
+	if (opt) {
+		parse_rtattr_nested(tb, TCA_FW_MAX, opt);
+		if (tb[TCA_FW_MASK]) {
+		   __u32 tmask = rta_getattr_u32(tb[TCA_FW_MASK]);
 
-	parse_rtattr_nested(tb, TCA_FW_MAX, opt);
+		   if (tmask != 0xFFFFFFFF)
+			   mask = tmask;
+		}
+	}
 
-	if (handle || tb[TCA_FW_MASK]) {
-		__u32 mark = 0, mask = 0;
+	if (mask)
+		fprintf(f, "handle 0x%x/0x%x ", mark, mask);
+	else
+		fprintf(f, "handle 0x%x ", handle);
 
-		if (handle)
-			mark = handle;
-		if (tb[TCA_FW_MASK] &&
-		    (mask = rta_getattr_u32(tb[TCA_FW_MASK])) != 0xFFFFFFFF)
-			fprintf(f, "handle 0x%x/0x%x ", mark, mask);
-		else
-			fprintf(f, "handle 0x%x ", handle);
-	}
+	if (opt == NULL)
+		return 0;
 
 	if (tb[TCA_FW_CLASSID]) {
 		SPRINT_BUF(b1);
-		fprintf(f, "classid %s ", sprint_tc_classid(rta_getattr_u32(tb[TCA_FW_CLASSID]), b1));
+		fprintf(f, "classid %s ",
+			sprint_tc_classid(rta_getattr_u32(tb[TCA_FW_CLASSID]),
+					  b1));
 	}
 
 	if (tb[TCA_FW_POLICE])
 		tc_print_police(f, tb[TCA_FW_POLICE]);
+
 	if (tb[TCA_FW_INDEV]) {
 		struct rtattr *idev = tb[TCA_FW_INDEV];
-
 		fprintf(f, "input dev %s ", rta_getattr_str(idev));
 	}
 
@@ -153,6 +158,7 @@ static int fw_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __u
 		fprintf(f, "\n");
 		tc_print_action(f, tb[TCA_FW_ACT]);
 	}
+
 	return 0;
 }
 
diff --git a/tc/f_matchall.c b/tc/f_matchall.c
index 04e524e..006eb70 100644
--- a/tc/f_matchall.c
+++ b/tc/f_matchall.c
@@ -116,14 +116,14 @@ static int matchall_print_opt(struct filter_util *qu, FILE *f,
 {
 	struct rtattr *tb[TCA_MATCHALL_MAX+1];
 
+	if (handle)
+		fprintf(f, "handle 0x%x ", handle);
+
 	if (opt == NULL)
 		return 0;
 
 	parse_rtattr_nested(tb, TCA_MATCHALL_MAX, opt);
 
-	if (handle)
-		fprintf(f, "handle 0x%x ", handle);
-
 	if (tb[TCA_MATCHALL_CLASSID]) {
 		SPRINT_BUF(b1);
 		fprintf(f, "flowid %s ",
diff --git a/tc/f_route.c b/tc/f_route.c
index 5c600b9..5d1ea17 100644
--- a/tc/f_route.c
+++ b/tc/f_route.c
@@ -34,7 +34,8 @@ static void explain(void)
 	fprintf(stderr, "\nNOTE: CLASSID is parsed as hexadecimal input.\n");
 }
 
-static int route_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n)
+static int route_parse_opt(struct filter_util *qu, char *handle, int argc,
+			   char **argv, struct nlmsghdr *n)
 {
 	struct tcmsg *t = NLMSG_DATA(n);
 	struct rtattr *tail;
@@ -139,32 +140,38 @@ static int route_parse_opt(struct filter_util *qu, char *handle, int argc, char
 	return 0;
 }
 
-static int route_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __u32 handle)
+static int route_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt,
+			   __u32 handle)
 {
 	struct rtattr *tb[TCA_ROUTE4_MAX+1];
 
 	SPRINT_BUF(b1);
 
-	if (opt == NULL)
-		return 0;
-
-	parse_rtattr_nested(tb, TCA_ROUTE4_MAX, opt);
-
 	if (handle)
 		fprintf(f, "fh 0x%08x ", handle);
 	if (handle&0x7F00)
 		fprintf(f, "order %d ", (handle>>8)&0x7F);
+	if (opt == NULL)
+		return 0;
+
+	parse_rtattr_nested(tb, TCA_ROUTE4_MAX, opt);
 
 	if (tb[TCA_ROUTE4_CLASSID]) {
 		SPRINT_BUF(b1);
-		fprintf(f, "flowid %s ", sprint_tc_classid(rta_getattr_u32(tb[TCA_ROUTE4_CLASSID]), b1));
+		fprintf(f, "flowid %s ",
+			sprint_tc_classid(rta_getattr_u32(tb[TCA_ROUTE4_CLASSID]), b1));
 	}
 	if (tb[TCA_ROUTE4_TO])
-		fprintf(f, "to %s ", rtnl_rtrealm_n2a(rta_getattr_u32(tb[TCA_ROUTE4_TO]), b1, sizeof(b1)));
+		fprintf(f, "to %s ",
+			rtnl_rtrealm_n2a(rta_getattr_u32(tb[TCA_ROUTE4_TO]),
+					 b1, sizeof(b1)));
 	if (tb[TCA_ROUTE4_FROM])
-		fprintf(f, "from %s ", rtnl_rtrealm_n2a(rta_getattr_u32(tb[TCA_ROUTE4_FROM]), b1, sizeof(b1)));
+		fprintf(f, "from %s ",
+			rtnl_rtrealm_n2a(rta_getattr_u32(tb[TCA_ROUTE4_FROM]),
+					 b1, sizeof(b1)));
 	if (tb[TCA_ROUTE4_IIF])
-		fprintf(f, "fromif %s", ll_index_to_name(*(int *)RTA_DATA(tb[TCA_ROUTE4_IIF])));
+		fprintf(f, "fromif %s",
+			ll_index_to_name(*(int *)RTA_DATA(tb[TCA_ROUTE4_IIF])));
 	if (tb[TCA_ROUTE4_POLICE])
 		tc_print_police(f, tb[TCA_ROUTE4_POLICE]);
 	if (tb[TCA_ROUTE4_ACT])
diff --git a/tc/f_rsvp.c b/tc/f_rsvp.c
index 94bfbef..fae70cc 100644
--- a/tc/f_rsvp.c
+++ b/tc/f_rsvp.c
@@ -325,20 +325,21 @@ static char *sprint_spi(struct tc_rsvp_gpi *pi, int dir, char *buf)
 	return buf;
 }
 
-static int rsvp_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __u32 handle)
+static int rsvp_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt,
+			  __u32 handle)
 {
 	int family = strcmp(qu->id, "rsvp") == 0 ? AF_INET : AF_INET6;
 	struct rtattr *tb[TCA_RSVP_MAX+1];
 	struct tc_rsvp_pinfo *pinfo = NULL;
 
+	if (handle)
+		fprintf(f, "fh 0x%08x ", handle);
+
 	if (opt == NULL)
 		return 0;
 
 	parse_rtattr_nested(tb, TCA_RSVP_MAX, opt);
 
-	if (handle)
-		fprintf(f, "fh 0x%08x ", handle);
-
 	if (tb[TCA_RSVP_PINFO]) {
 		if (RTA_PAYLOAD(tb[TCA_RSVP_PINFO])  < sizeof(*pinfo))
 			return -1;
@@ -349,9 +350,12 @@ static int rsvp_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, _
 	if (tb[TCA_RSVP_CLASSID]) {
 		SPRINT_BUF(b1);
 		if (!pinfo || pinfo->tunnelhdr == 0)
-			fprintf(f, "flowid %s ", sprint_tc_classid(rta_getattr_u32(tb[TCA_RSVP_CLASSID]), b1));
+			fprintf(f, "flowid %s ",
+				sprint_tc_classid(rta_getattr_u32(tb[TCA_RSVP_CLASSID]), b1));
 		else
-			fprintf(f, "tunnel %d skip %d ", rta_getattr_u32(tb[TCA_RSVP_CLASSID]), pinfo->tunnelhdr);
+			fprintf(f, "tunnel %d skip %d ",
+				rta_getattr_u32(tb[TCA_RSVP_CLASSID]),
+				pinfo->tunnelhdr);
 	} else if (pinfo && pinfo->tunnelhdr)
 		fprintf(f, "tunnel [BAD] skip %d ", pinfo->tunnelhdr);
 
@@ -359,7 +363,8 @@ static int rsvp_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, _
 		char buf[128];
 
 		fprintf(f, "session ");
-		if (inet_ntop(family, RTA_DATA(tb[TCA_RSVP_DST]), buf, sizeof(buf)) == 0)
+		if (inet_ntop(family, RTA_DATA(tb[TCA_RSVP_DST]), buf,
+			      sizeof(buf)) == 0)
 			fprintf(f, " [INVALID DADDR] ");
 		else
 			fprintf(f, "%s", buf);
@@ -371,14 +376,16 @@ static int rsvp_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, _
 	} else {
 		if (pinfo && pinfo->dpi.mask) {
 			SPRINT_BUF(b2);
-			fprintf(f, "session [NONE]%s ", sprint_spi(&pinfo->dpi, 1, b2));
+			fprintf(f, "session [NONE]%s ",
+				sprint_spi(&pinfo->dpi, 1, b2));
 		} else
 			fprintf(f, "session NONE ");
 	}
 
 	if (pinfo && pinfo->protocol) {
 		SPRINT_BUF(b1);
-		fprintf(f, "ipproto %s ", inet_proto_n2a(pinfo->protocol, b1, sizeof(b1)));
+		fprintf(f, "ipproto %s ", inet_proto_n2a(pinfo->protocol, b1,
+							 sizeof(b1)));
 	}
 	if (pinfo && pinfo->tunnelid)
 		fprintf(f, "tunnelid %d ", pinfo->tunnelid);
@@ -386,7 +393,8 @@ static int rsvp_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, _
 		char buf[128];
 
 		fprintf(f, "sender ");
-		if (inet_ntop(family, RTA_DATA(tb[TCA_RSVP_SRC]), buf, sizeof(buf)) == 0) {
+		if (inet_ntop(family, RTA_DATA(tb[TCA_RSVP_SRC]), buf,
+			      sizeof(buf)) == 0) {
 			fprintf(f, "[BAD]");
 		} else {
 			fprintf(f, " %s", buf);
diff --git a/tc/f_tcindex.c b/tc/f_tcindex.c
index 32bccb0..8b6f0e8 100644
--- a/tc/f_tcindex.c
+++ b/tc/f_tcindex.c
@@ -123,12 +123,14 @@ static int tcindex_print_opt(struct filter_util *qu, FILE *f,
 {
 	struct rtattr *tb[TCA_TCINDEX_MAX+1];
 
+	if (handle != ~0)
+		fprintf(f, "handle 0x%04x ", handle);
+
 	if (opt == NULL)
 		return 0;
 
 	parse_rtattr_nested(tb, TCA_TCINDEX_MAX, opt);
 
-	if (handle != ~0) fprintf(f, "handle 0x%04x ", handle);
 	if (tb[TCA_TCINDEX_HASH]) {
 		__u16 hash;
 
diff --git a/tc/f_u32.c b/tc/f_u32.c
index 0ad7ed2..3b107cc 100644
--- a/tc/f_u32.c
+++ b/tc/f_u32.c
@@ -1210,16 +1210,15 @@ static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt,
 	struct tc_u32_sel *sel = NULL;
 	struct tc_u32_pcnt *pf = NULL;
 
-	if (opt == NULL)
-		return 0;
-
-	parse_rtattr_nested(tb, TCA_U32_MAX, opt);
-
 	if (handle) {
 		SPRINT_BUF(b1);
 		fprintf(f, "fh %s ", sprint_u32_handle(handle, b1));
 	}
 
+	if (opt == NULL)
+		return 0;
+
+	parse_rtattr_nested(tb, TCA_U32_MAX, opt);
 	if (TC_U32_NODE(handle))
 		fprintf(f, "order %d ", TC_U32_NODE(handle));
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH iproute2 1/2] tc filters: display handle in events when a filter is deleted
From: Jamal Hadi Salim @ 2016-10-17  9:34 UTC (permalink / raw)
  To: stephen; +Cc: netdev, daniel, xiyou.wangcong, mrv, Jamal Hadi Salim

From: Jamal Hadi Salim <jhs@mojatatu.com>

An event being displayed via "tc mon" should display the filter handle.
The filter handle is a required parameter when deleting a filter and
therefore the delete event should mimic/mirror the command sent.
A simple test, run tc monitor on one window, on another try adding
a filter:
..
sudo $TC filter add dev $ETH parent ffff: protocol ip pref 1 \
u32 match ip protocol 1 0xff \
flowid 1:1 \
action ok
..

.. get its handle by dumping ...
sudo $TC -s filter ls dev $ETH parent ffff: protocol ip
... find out the handle (say it was 800::800)
... go delete it..
sudo $TC filter del dev $ETH handle 800::800 parent ffff: \
protocol ip prio 1 u32

now see tc monitor reporting it without handle. After this patch
with a handle.

Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
 tc/tc_filter.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tc/tc_filter.c b/tc/tc_filter.c
index 2413cef..4efc44f 100644
--- a/tc/tc_filter.c
+++ b/tc/tc_filter.c
@@ -253,12 +253,13 @@ int print_filter(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 	}
 	fprintf(fp, "%s ", rta_getattr_str(tb[TCA_KIND]));
 	q = get_filter_kind(RTA_DATA(tb[TCA_KIND]));
-	if (tb[TCA_OPTIONS]) {
+	if (tb[TCA_OPTIONS] || n->nlmsg_type == RTM_DELTFILTER) {
 		if (q)
 			q->print_fopt(q, fp, tb[TCA_OPTIONS], t->tcm_handle);
 		else
 			fprintf(fp, "[cannot parse parameters]");
 	}
+
 	fprintf(fp, "\n");
 
 	if (show_stats && (tb[TCA_STATS] || tb[TCA_STATS2])) {
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH v4] mac80211: move extra crypto data off the stack
From: Ard Biesheuvel @ 2016-10-17  9:30 UTC (permalink / raw)
  To: Johannes Berg
  Cc: <linux-wireless@vger.kernel.org>, Sergey Senozhatsky,
	<netdev@vger.kernel.org>, Herbert Xu
In-Reply-To: <1476696226.19992.13.camel@sipsolutions.net>

On 17 October 2016 at 10:23, Johannes Berg <johannes@sipsolutions.net> wrote:
>
>> Apologies for going back and forth on this, but it appears there may
>> be another way to deal with this.
>>
>> First of all, we only need this handling for the authenticated data,
>
> Are you sure b_0/j_0 aren't needed? We pass those
> to aead_request_set_crypt(), and I wasn't sure what that really did
> internally, perhaps like the internal data.
>

They are the IV[], which is a fixed length parameter of the algorithm.
In contrast, the AAD[] could be of arbitrary length (from the POV of
the crypto API) so it uses scatterlists.

> Testing with that on the stack does seem to work, in fact.
>
> Surely we need zero for GMAC though, since we also put that into the sg
> list. Thus for GMAC we definitely need 20+16 bytes, and since I round
> up to a cacheline (at least on SMP) it doesn't really matter that we
> could get 36 instead of the 48 I have now.
>
>> and only for CCM and GCM, not CMAC (which does not use scatterlists
>> at all, it simply calls the AES cipher directly)
>
> I didn't modify CMAC, I think, only GMAC, which also uses scatterlists.
>

Ah ok, I misread the patch.

>> So that leaves a fixed 20 bytes for GCM and fixed 32 bytes for CCM,
>
> and 36 for GMAC :)

Yes. But as I replied, setting the req size is not supported atm,
although it is reasonable to demand a way to allocate additional data
in the request specifically for this issue. So let's proceed with the
aead_request_alloc/free patch, but I would like to propose something
on the API side to address this particular issue

^ permalink raw reply

* Re: [PATCH 10/10] mm: replace access_process_vm() write parameter with gup_flags
From: Jesper Nilsson @ 2016-10-17  9:23 UTC (permalink / raw)
  To: Lorenzo Stoakes
  Cc: linux-mm, linux-mips, linux-fbdev, Jan Kara, kvm, linux-sh,
	Dave Hansen, dri-devel, netdev, sparclinux, linux-ia64,
	linux-s390, linux-samsung-soc, linux-scsi, linux-rdma, x86,
	Hugh Dickins, linux-media, Rik van Riel, intel-gfx,
	adi-buildroot-devel, ceph-devel, linux-arm-kernel,
	linux-cris-kernel, Linus Torvalds, linuxppc-dev, linux-kernel,
	linux-security-module, linux-alpha
In-Reply-To: <20161013002020.3062-11-lstoakes@gmail.com>

On Thu, Oct 13, 2016 at 01:20:20AM +0100, Lorenzo Stoakes wrote:
> This patch removes the write parameter from access_process_vm() and replaces it
> with a gup_flags parameter as use of this function previously _implied_
> FOLL_FORCE, whereas after this patch callers explicitly pass this flag.
> 
> We make this explicit as use of FOLL_FORCE can result in surprising behaviour
> (and hence bugs) within the mm subsystem.
> 
> Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
> ---
>  arch/cris/arch-v32/kernel/ptrace.c |  4 ++--

For the CRIS part:

Acked-by: Jesper Nilsson <jesper.nilsson@axis.com>

/^JN - Jesper Nilsson
-- 
               Jesper Nilsson -- jesper.nilsson@axis.com

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* Re: [PATCH v4] mac80211: move extra crypto data off the stack
From: Johannes Berg @ 2016-10-17  9:23 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: <linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
	Sergey Senozhatsky,
	<netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
	Herbert Xu
In-Reply-To: <CAKv+Gu-aZhCBvnEQoZUZLDPXCrvgxO1pSd=6EHz+tMB+dFz5hg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>


> Apologies for going back and forth on this, but it appears there may
> be another way to deal with this.
> 
> First of all, we only need this handling for the authenticated data,

Are you sure b_0/j_0 aren't needed? We pass those
to aead_request_set_crypt(), and I wasn't sure what that really did
internally, perhaps like the internal data.

Testing with that on the stack does seem to work, in fact.

Surely we need zero for GMAC though, since we also put that into the sg
list. Thus for GMAC we definitely need 20+16 bytes, and since I round
up to a cacheline (at least on SMP) it doesn't really matter that we
could get 36 instead of the 48 I have now.

> and only for CCM and GCM, not CMAC (which does not use scatterlists
> at all, it simply calls the AES cipher directly)

I didn't modify CMAC, I think, only GMAC, which also uses scatterlists.

> So that leaves a fixed 20 bytes for GCM and fixed 32 bytes for CCM,

and 36 for GMAC :)

johannes

^ permalink raw reply

* Re: [PATCH 06/10] mm: replace get_user_pages() write/force parameters with gup_flags
From: Jesper Nilsson @ 2016-10-17  9:22 UTC (permalink / raw)
  To: Lorenzo Stoakes
  Cc: linux-mm, linux-mips, linux-fbdev, Jan Kara, kvm, linux-sh,
	Dave Hansen, dri-devel, netdev, sparclinux, linux-ia64,
	linux-s390, linux-samsung-soc, linux-scsi, linux-rdma, x86,
	Hugh Dickins, linux-media, Rik van Riel, intel-gfx,
	adi-buildroot-devel, ceph-devel, linux-arm-kernel,
	linux-cris-kernel, Linus Torvalds, linuxppc-dev, linux-kernel,
	linux-security-module, linux-alpha
In-Reply-To: <20161013002020.3062-7-lstoakes@gmail.com>

On Thu, Oct 13, 2016 at 01:20:16AM +0100, Lorenzo Stoakes wrote:
> This patch removes the write and force parameters from get_user_pages() and
> replaces them with a gup_flags parameter to make the use of FOLL_FORCE explicit
> in callers as use of this flag can result in surprising behaviour (and hence
> bugs) within the mm subsystem.
> 
> Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
> ---
>  arch/cris/arch-v32/drivers/cryptocop.c                 |  4 +---

For the CRIS part:

Acked-by: Jesper Nilsson <jesper.nilsson@axis.com>

/^JN - Jesper Nilsson
-- 
               Jesper Nilsson -- jesper.nilsson@axis.com

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* Re: [PATCH v4] mac80211: move extra crypto data off the stack
From: Ard Biesheuvel @ 2016-10-17  9:17 UTC (permalink / raw)
  To: Johannes Berg
  Cc: <linux-wireless@vger.kernel.org>, Sergey Senozhatsky,
	<netdev@vger.kernel.org>, Herbert Xu, Johannes Berg
In-Reply-To: <CAKv+Gu-aZhCBvnEQoZUZLDPXCrvgxO1pSd=6EHz+tMB+dFz5hg@mail.gmail.com>

On 17 October 2016 at 10:14, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> On 17 October 2016 at 09:33, Johannes Berg <johannes@sipsolutions.net> wrote:
>> From: Johannes Berg <johannes.berg@intel.com>
>>
>> As the stack can (on x86-64) now be virtually mapped rather than
>> using "normal" kernel memory, Sergey noticed mac80211 isn't using
>> the SG APIs correctly by putting on-stack buffers into SG tables.
>> This leads to kernel crashes.
>>
>> Fix this by allocating the extra fields dynamically on the fly as
>> needed, using a kmem cache.
>>
>> I used per-CPU memory in a previous iteration of this patch, but
>> Ard Biesheuvel pointed out that was also vmalloc'ed on some
>> architectures.
>>
>> Reported-by: Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
>> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
>
> Apologies for going back and forth on this, but it appears there may
> be another way to deal with this.
>
> First of all, we only need this handling for the authenticated data,
> and only for CCM and GCM, not CMAC (which does not use scatterlists at
> all, it simply calls the AES cipher directly)
>
> So that leaves a fixed 20 bytes for GCM and fixed 32 bytes for CCM,
> which we could allocate along with the AEAD request, e..g.,
>
> """
> diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
> index 8e898a6e8de8..c0c33e6ad94e 100644
> --- a/net/mac80211/aes_ccm.c
> +++ b/net/mac80211/aes_ccm.c
> @@ -24,13 +24,17 @@ int ieee80211_aes_ccm_encrypt(struct crypto_aead
> *tfm, u8 *b_0, u8 *aad,
>  {
>         struct scatterlist sg[3];
>         struct aead_request *aead_req;
> +       u8 *__aad;
>
>         aead_req = aead_request_alloc(tfm, GFP_ATOMIC);
>         if (!aead_req)
>                 return -ENOMEM;
>
> +       __aad = (u8 *)aead_req + crypto_aead_reqsize(tfm);
> +       memcpy(__aad, aad, 2 * AES_BLOCK_SIZE);
> +
>         sg_init_table(sg, 3);
> -       sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
> +       sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad));
>         sg_set_buf(&sg[1], data, data_len);
>         sg_set_buf(&sg[2], mic, mic_len);
>
> @@ -49,6 +53,7 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead
> *tfm, u8 *b_0, u8 *aad,
>  {
>         struct scatterlist sg[3];
>         struct aead_request *aead_req;
> +       u8 *__aad;
>         int err;
>
>         if (data_len == 0)
> @@ -58,8 +63,11 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead
> *tfm, u8 *b_0, u8 *aad,
>         if (!aead_req)
>                 return -ENOMEM;
>
> +       __aad = (u8 *)aead_req + crypto_aead_reqsize(tfm);
> +       memcpy(__aad, aad, 2 * AES_BLOCK_SIZE);
> +
>         sg_init_table(sg, 3);
> -       sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
> +       sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad));
>         sg_set_buf(&sg[1], data, data_len);
>         sg_set_buf(&sg[2], mic, mic_len);
>
> @@ -90,6 +98,8 @@ struct crypto_aead
> *ieee80211_aes_key_setup_encrypt(const u8 key[],
>         if (err)
>                 goto free_aead;
>
> +       crypto_aead_set_reqsize(tfm,
> +                               crypto_aead_reqsize(tfm) + 2 * AES_BLOCK_SIZE));
>         return tfm;
>

Darn, it seems crypto_aead_set_reqsize() is internal to the crypto API ... :-(

^ permalink raw reply

* Re: [PATCH v4] mac80211: move extra crypto data off the stack
From: Ard Biesheuvel @ 2016-10-17  9:14 UTC (permalink / raw)
  To: Johannes Berg
  Cc: <linux-wireless@vger.kernel.org>, Sergey Senozhatsky,
	<netdev@vger.kernel.org>, Herbert Xu, Johannes Berg
In-Reply-To: <1476693195-14071-1-git-send-email-johannes@sipsolutions.net>

On 17 October 2016 at 09:33, Johannes Berg <johannes@sipsolutions.net> wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> As the stack can (on x86-64) now be virtually mapped rather than
> using "normal" kernel memory, Sergey noticed mac80211 isn't using
> the SG APIs correctly by putting on-stack buffers into SG tables.
> This leads to kernel crashes.
>
> Fix this by allocating the extra fields dynamically on the fly as
> needed, using a kmem cache.
>
> I used per-CPU memory in a previous iteration of this patch, but
> Ard Biesheuvel pointed out that was also vmalloc'ed on some
> architectures.
>
> Reported-by: Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>

Apologies for going back and forth on this, but it appears there may
be another way to deal with this.

First of all, we only need this handling for the authenticated data,
and only for CCM and GCM, not CMAC (which does not use scatterlists at
all, it simply calls the AES cipher directly)

So that leaves a fixed 20 bytes for GCM and fixed 32 bytes for CCM,
which we could allocate along with the AEAD request, e..g.,

"""
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
index 8e898a6e8de8..c0c33e6ad94e 100644
--- a/net/mac80211/aes_ccm.c
+++ b/net/mac80211/aes_ccm.c
@@ -24,13 +24,17 @@ int ieee80211_aes_ccm_encrypt(struct crypto_aead
*tfm, u8 *b_0, u8 *aad,
 {
        struct scatterlist sg[3];
        struct aead_request *aead_req;
+       u8 *__aad;

        aead_req = aead_request_alloc(tfm, GFP_ATOMIC);
        if (!aead_req)
                return -ENOMEM;

+       __aad = (u8 *)aead_req + crypto_aead_reqsize(tfm);
+       memcpy(__aad, aad, 2 * AES_BLOCK_SIZE);
+
        sg_init_table(sg, 3);
-       sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
+       sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad));
        sg_set_buf(&sg[1], data, data_len);
        sg_set_buf(&sg[2], mic, mic_len);

@@ -49,6 +53,7 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead
*tfm, u8 *b_0, u8 *aad,
 {
        struct scatterlist sg[3];
        struct aead_request *aead_req;
+       u8 *__aad;
        int err;

        if (data_len == 0)
@@ -58,8 +63,11 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead
*tfm, u8 *b_0, u8 *aad,
        if (!aead_req)
                return -ENOMEM;

+       __aad = (u8 *)aead_req + crypto_aead_reqsize(tfm);
+       memcpy(__aad, aad, 2 * AES_BLOCK_SIZE);
+
        sg_init_table(sg, 3);
-       sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
+       sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad));
        sg_set_buf(&sg[1], data, data_len);
        sg_set_buf(&sg[2], mic, mic_len);

@@ -90,6 +98,8 @@ struct crypto_aead
*ieee80211_aes_key_setup_encrypt(const u8 key[],
        if (err)
                goto free_aead;

+       crypto_aead_set_reqsize(tfm,
+                               crypto_aead_reqsize(tfm) + 2 * AES_BLOCK_SIZE));
        return tfm;

 free_aead:
"""

^ permalink raw reply related

* Re: Need help with mdiobus_register and phy
From: Zefir Kurtisi @ 2016-10-17  9:05 UTC (permalink / raw)
  To: Timur Tabi, Andrew Lunn; +Cc: Florian Fainelli, netdev
In-Reply-To: <58027540.6080604@codeaurora.org>

On 10/15/2016 08:28 PM, Timur Tabi wrote:
> Andrew Lunn wrote:
>> 1) Take the SerDes power down out of the suspend code for the at803x.
>>
>> 2) Assume MII_PHYID1/2 registers are not guaranteed to be available
>> when the PHY is powered down. So get_phy_id should first read
>> MII_BMCR. If it gets 0xffff, assume there is no PHY there. If the
>> PDOWN bit is set, power up the PHY. Then reading the ID registers.
> 
> Before we take approach #1, I'd like to hear from the developer of that patch,
> Zefir.  According to him, that patch is necessary to fix a bug. I don't know if
> that bug exists only on his system, though.
> 

Hi,

the problem we observed was that in SGMII mode after a suspend/resume cycle the
PHY link states get out of sync (e.g. gianfar reports link up, at803x down) and
power cycling the SerDes was a reliable way to get them re-synchronized again.

This obviously worked for some time after March 2016 and must have stopped only
recently (maybe additional PHY suspends were added).

Anyway, since the SGMII reset is required, instead of reverting the patch in full
I suggest to move the SGMII power down from at803x_suspend() and do a SerDes power
cycle in at803x_resume(). Could you please test if the patch below fixes the problem?


Thanks,
Zefir
---



Subject: [PATCH] at803x: don't power down SerDes on suspend

Powering down SerDes renders registers inaccessible
and with that re-initializing a suspended PHY fails.

Instead of powering down SerDes at suspend(), leave
it as is and power-cycle it on resume().

Signed-off-by: Zefir Kurtisi <zefir.kurtisi@neratec.com>
---
 drivers/net/phy/at803x.c | 14 +++-----------
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index f279a89..282ffbb 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -225,16 +225,6 @@ static int at803x_suspend(struct phy_device *phydev)

 	phy_write(phydev, MII_BMCR, value);

-	if (phydev->interface != PHY_INTERFACE_MODE_SGMII)
-		goto done;
-
-	/* also power-down SGMII interface */
-	ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG);
-	phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr & ~AT803X_BT_BX_REG_SEL);
-	phy_write(phydev, MII_BMCR, phy_read(phydev, MII_BMCR) | BMCR_PDOWN);
-	phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr | AT803X_BT_BX_REG_SEL);
-
-done:
 	mutex_unlock(&phydev->lock);

 	return 0;
@@ -254,9 +244,11 @@ static int at803x_resume(struct phy_device *phydev)
 	if (phydev->interface != PHY_INTERFACE_MODE_SGMII)
 		goto done;

-	/* also power-up SGMII interface */
+	/* reset SGMII interface for re-synchronization */
 	ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG);
 	phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr & ~AT803X_BT_BX_REG_SEL);
+	phy_write(phydev, MII_BMCR, phy_read(phydev, MII_BMCR) | BMCR_PDOWN);
+
 	value = phy_read(phydev, MII_BMCR) & ~(BMCR_PDOWN | BMCR_ISOLATE);
 	phy_write(phydev, MII_BMCR, value);
 	phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr | AT803X_BT_BX_REG_SEL);
-- 
2.7.4

^ permalink raw reply related

* introduce IPV6_PKTINFO_L2 socket-option?
From: Alexander Aring @ 2016-10-17  8:33 UTC (permalink / raw)
  To: Network Development
  Cc: linux-wpan-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Michael Richardson, Martin Gergeleit, Linux Bluetooth,
	Jukka Rissanen, kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org


Hi all,

I am currently writing some userspace UDP Software for 6LoWPAN
subsystem. It will use UDP IPv6 sockets, the 6LoWPAN adaptation will be
done at kernelspace.

My problem is currently the following:

I need per recvmsg(2) the used source link-layer address for the
incoming UDP packet which used a multicast destination address.

There is currently no solution to get such information. Michael
Richardson told about IPV6_RECVPKTINFO and then we thought about to
introduce an IPV6_PKTINFO_L2 to get such information.

If somebody know already a solution how to get L2 information from
userspace IPv6 SOCK_DGRAM socket, I would be happy if somebody told me
the solution. :-)

The idea about IPV6_PKTINFO_L2 is to put L2 information in there which
depends on netdev type (on 6LoWPAN it even depends on sub netdev type of
6LoWPAN netdev type - sub netdev type will represent the used link-layer).

Now, here comes some design question...

What we put into the IPV6_PKTINFO_L2 which is an attribute of the control
messages. The socket-option IPV6_PKTINFO_L2 will turn it on/off only
like all others.

If we only need it for recvmsg(2) then maybe we could simple offer the
mac-header - which maybe works on all skb's by accessing skb_mac_header
and skb->mac_len. (btw: on 6LoWPAN this is currently broken and I need
to fix it). It works only if all IPv6 capable subsystem sets these
attributes and don't overwrite the mac space with other data (that's the
bug we have in 6LoWPAN).

The point is... it's useful also for sendmsg. Example: 802.15.4 6LoWPAN
can use two type of mac address: short or extended. On sendmsg you could
say which one you prefer to use for the L2 source/destination address
information. I heard from Michael, this is necessary on some protocols
to prefer extended than short. Currently we use short if short is
available, because it will produce less payload - which is very fine as
default handling. But sometimes you must have control over that.

Another option to implement this is a flag for a neighbour in ndisc
cache, but this works for destination L2 address then and per-neighbour
and not per sendmsg(2), so all running processes for the interface will
be manipulated by that. I think this is not an good option.

What I am thinking of is to have the control message attribute defined
per netdev type (in case of 6LoWPAN even link-layer 6LoWPAN netdev type)
and each link-layer can add what they want to have there. E.g.

struct in6_pktinfo_l2_802154 {
        /* sendmsg and recvmsg */
        __u8    src[MAX_ADDR_LEN];
        __u8    dst[MAX_ADDR_LEN];

        /* recvmsg */
        __u8    lqi;
};

The lqi is here some 802.15.4 L2 information about link quality. Some
another idea to add there, makes only sense for recvmsg and need to be
some average if fragmentation was done there. If the link-layer doesn't
support such handling -EOPNOTSUPP for setting the socket-option on will
be returned.

The src and dst address could maybe the same on all link-layers and
that's why we could split this attribute maybe in two attributes for
control message:

struct in6_pktinfo_l2 {
        /* sendmsg and recvmsg */
        __u8    src[MAX_ADDR_LEN];
        __u8    dst[MAX_ADDR_LEN];
};

struct in6_pktinfo_l2_802154 {
        /* recvmsg */
        __u8    lqi;
};

and introduce some IPV6_PKTINFO_L2 and IPV6_PKTINFO_L2_802154_LQI socket
option to enable/disable these attributes. The addresses which will be
placed into src and dst depends on used link-layer which need to be
evaluated somehow before.

I currently must implement the getting of source l2 address information
and I will try to implement it. For sendmsg side I need to figure out
how to get the information from socket interface through 6LoWPAN
implementation - maybe adding new attribute in sk_buff? Don't know yet.

I also want some mainline solution and I don't know if this is the right
way to implement it to have an acceptable solution for mainline. That's
why I start this discussion and hope I get some new inputs here.

- Alex

^ permalink raw reply

* [PATCH v4] mac80211: move extra crypto data off the stack
From: Johannes Berg @ 2016-10-17  8:33 UTC (permalink / raw)
  To: linux-wireless-u79uwXL29TY76Z2rM5mHXA
  Cc: Ard Biesheuvel, Sergey Senozhatsky, netdev-u79uwXL29TY76Z2rM5mHXA,
	herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q, Johannes Berg

From: Johannes Berg <johannes.berg-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

As the stack can (on x86-64) now be virtually mapped rather than
using "normal" kernel memory, Sergey noticed mac80211 isn't using
the SG APIs correctly by putting on-stack buffers into SG tables.
This leads to kernel crashes.

Fix this by allocating the extra fields dynamically on the fly as
needed, using a kmem cache.

I used per-CPU memory in a previous iteration of this patch, but
Ard Biesheuvel pointed out that was also vmalloc'ed on some
architectures.

Reported-by: Sergey Senozhatsky <sergey.senozhatsky.work-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Johannes Berg <johannes.berg-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 net/mac80211/aes_cmac.c    |   5 +-
 net/mac80211/aes_cmac.h    |   2 +
 net/mac80211/aes_gmac.c    |   9 ++-
 net/mac80211/aes_gmac.h    |   5 +-
 net/mac80211/ieee80211_i.h |   7 ++
 net/mac80211/main.c        |   8 +++
 net/mac80211/wpa.c         | 173 ++++++++++++++++++++++++++++++++++++---------
 7 files changed, 166 insertions(+), 43 deletions(-)

diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c
index bdf0790d89cc..ebb8c2dc9928 100644
--- a/net/mac80211/aes_cmac.c
+++ b/net/mac80211/aes_cmac.c
@@ -20,7 +20,6 @@
 
 #define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */
 #define CMAC_TLEN_256 16 /* CMAC TLen = 128 bits (16 octets) */
-#define AAD_LEN 20
 
 
 static void gf_mulx(u8 *pad)
@@ -101,7 +100,7 @@ void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad,
 
 	memset(zero, 0, CMAC_TLEN);
 	addr[0] = aad;
-	len[0] = AAD_LEN;
+	len[0] = CMAC_AAD_LEN;
 	addr[1] = data;
 	len[1] = data_len - CMAC_TLEN;
 	addr[2] = zero;
@@ -119,7 +118,7 @@ void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad,
 
 	memset(zero, 0, CMAC_TLEN_256);
 	addr[0] = aad;
-	len[0] = AAD_LEN;
+	len[0] = CMAC_AAD_LEN;
 	addr[1] = data;
 	len[1] = data_len - CMAC_TLEN_256;
 	addr[2] = zero;
diff --git a/net/mac80211/aes_cmac.h b/net/mac80211/aes_cmac.h
index 3702041f44fd..6645f8963278 100644
--- a/net/mac80211/aes_cmac.h
+++ b/net/mac80211/aes_cmac.h
@@ -11,6 +11,8 @@
 
 #include <linux/crypto.h>
 
+#define CMAC_AAD_LEN 20
+
 struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[],
 						   size_t key_len);
 void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad,
diff --git a/net/mac80211/aes_gmac.c b/net/mac80211/aes_gmac.c
index 6951af9715c0..86892e2e3c8c 100644
--- a/net/mac80211/aes_gmac.c
+++ b/net/mac80211/aes_gmac.c
@@ -19,13 +19,12 @@
 
 #define GMAC_MIC_LEN 16
 #define GMAC_NONCE_LEN 12
-#define AAD_LEN 20
 
 int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
-		       const u8 *data, size_t data_len, u8 *mic)
+		       const u8 *data, size_t data_len, u8 *mic, u8 *zero)
 {
 	struct scatterlist sg[4];
-	u8 zero[GMAC_MIC_LEN], iv[AES_BLOCK_SIZE];
+	u8 iv[AES_BLOCK_SIZE];
 	struct aead_request *aead_req;
 
 	if (data_len < GMAC_MIC_LEN)
@@ -37,7 +36,7 @@ int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
 
 	memset(zero, 0, GMAC_MIC_LEN);
 	sg_init_table(sg, 4);
-	sg_set_buf(&sg[0], aad, AAD_LEN);
+	sg_set_buf(&sg[0], aad, GMAC_AAD_LEN);
 	sg_set_buf(&sg[1], data, data_len - GMAC_MIC_LEN);
 	sg_set_buf(&sg[2], zero, GMAC_MIC_LEN);
 	sg_set_buf(&sg[3], mic, GMAC_MIC_LEN);
@@ -47,7 +46,7 @@ int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
 	iv[AES_BLOCK_SIZE - 1] = 0x01;
 
 	aead_request_set_crypt(aead_req, sg, sg, 0, iv);
-	aead_request_set_ad(aead_req, AAD_LEN + data_len);
+	aead_request_set_ad(aead_req, GMAC_AAD_LEN + data_len);
 
 	crypto_aead_encrypt(aead_req);
 	aead_request_free(aead_req);
diff --git a/net/mac80211/aes_gmac.h b/net/mac80211/aes_gmac.h
index d328204d73a8..f06833c9095f 100644
--- a/net/mac80211/aes_gmac.h
+++ b/net/mac80211/aes_gmac.h
@@ -11,10 +11,13 @@
 
 #include <linux/crypto.h>
 
+#define GMAC_MIC_LEN 16
+#define GMAC_AAD_LEN 20
+
 struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[],
 						 size_t key_len);
 int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
-		       const u8 *data, size_t data_len, u8 *mic);
+		       const u8 *data, size_t data_len, u8 *mic, u8 *zero);
 void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm);
 
 #endif /* AES_GMAC_H */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 34c2add2c455..a63593f6b645 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1128,6 +1128,13 @@ enum mac80211_scan_state {
 	SCAN_ABORT,
 };
 
+struct ieee80211_crypto_bufs {
+	u8 buf1[32];
+	u8 buf2[16];
+} ____cacheline_aligned_in_smp;
+
+extern struct kmem_cache *ieee80211_crypto_bufs_cache;
+
 struct ieee80211_local {
 	/* embed the driver visible part.
 	 * don't cast (use the static inlines below), but we keep
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 1075ac24c8c5..c6303a8a12d2 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -33,6 +33,8 @@
 #include "led.h"
 #include "debugfs.h"
 
+struct kmem_cache *ieee80211_crypto_bufs_cache;
+
 void ieee80211_configure_filter(struct ieee80211_local *local)
 {
 	u64 mc;
@@ -1234,6 +1236,10 @@ static int __init ieee80211_init(void)
 	BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) +
 		     IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb));
 
+	ieee80211_crypto_bufs_cache = KMEM_CACHE(ieee80211_crypto_bufs, 0);
+	if (!ieee80211_crypto_bufs_cache)
+		return -ENOMEM;
+
 	ret = rc80211_minstrel_init();
 	if (ret)
 		return ret;
@@ -1264,6 +1270,8 @@ static void __exit ieee80211_exit(void)
 
 	ieee80211_iface_exit();
 
+	kmem_cache_destroy(ieee80211_crypto_bufs_cache);
+
 	rcu_barrier();
 }
 
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 2e366438f8ef..ee9105d57545 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -405,8 +405,6 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb,
 	u8 *pos;
 	u8 pn[6];
 	u64 pn64;
-	u8 aad[2 * AES_BLOCK_SIZE];
-	u8 b_0[AES_BLOCK_SIZE];
 
 	if (info->control.hw_key &&
 	    !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
@@ -456,13 +454,34 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb,
 	ccmp_pn2hdr(pos, pn, key->conf.keyidx);
 
 	/* hwaccel - with software CCMP header */
-	if (info->control.hw_key)
-		return 0;
+	if (unlikely(!info->control.hw_key)) {
+		struct ieee80211_crypto_bufs *bufs;
+		int err;
+		u8 *aad;
+		u8 *b_0;
+
+		bufs = kmem_cache_alloc(ieee80211_crypto_bufs_cache,
+					GFP_ATOMIC);
+		if (!bufs)
+			return -ENOMEM;
+
+		BUILD_BUG_ON(sizeof(bufs->buf1) < 2 * AES_BLOCK_SIZE);
+		BUILD_BUG_ON(sizeof(bufs->buf2) < AES_BLOCK_SIZE);
+
+		aad = bufs->buf1;
+		b_0 = bufs->buf2;
+
+		pos += IEEE80211_CCMP_HDR_LEN;
+		ccmp_special_blocks(skb, pn, b_0, aad);
+		err = ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad,
+						pos, len,
+						skb_put(skb, mic_len),
+						mic_len);
+		kmem_cache_free(ieee80211_crypto_bufs_cache, bufs);
+		return err;
+	}
 
-	pos += IEEE80211_CCMP_HDR_LEN;
-	ccmp_special_blocks(skb, pn, b_0, aad);
-	return ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
-					 skb_put(skb, mic_len), mic_len);
+	return 0;
 }
 
 
@@ -532,16 +551,33 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx,
 		}
 
 		if (!(status->flag & RX_FLAG_DECRYPTED)) {
-			u8 aad[2 * AES_BLOCK_SIZE];
-			u8 b_0[AES_BLOCK_SIZE];
+			struct ieee80211_crypto_bufs *bufs;
+			int err;
+			u8 *aad;
+			u8 *b_0;
+
+			bufs = kmem_cache_alloc(ieee80211_crypto_bufs_cache,
+						GFP_ATOMIC);
+			if (!bufs)
+				return -ENOMEM;
+
+			BUILD_BUG_ON(sizeof(bufs->buf1) < 2 * AES_BLOCK_SIZE);
+			BUILD_BUG_ON(sizeof(bufs->buf2) < AES_BLOCK_SIZE);
+
+			aad = bufs->buf1;
+			b_0 = bufs->buf2;
+
 			/* hardware didn't decrypt/verify MIC */
 			ccmp_special_blocks(skb, pn, b_0, aad);
 
-			if (ieee80211_aes_ccm_decrypt(
+			err = ieee80211_aes_ccm_decrypt(
 				    key->u.ccmp.tfm, b_0, aad,
 				    skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
 				    data_len,
-				    skb->data + skb->len - mic_len, mic_len))
+				    skb->data + skb->len - mic_len, mic_len);
+			kmem_cache_free(ieee80211_crypto_bufs_cache, bufs);
+
+			if (err)
 				return RX_DROP_UNUSABLE;
 		}
 
@@ -637,8 +673,6 @@ static int gcmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 	u8 *pos;
 	u8 pn[6];
 	u64 pn64;
-	u8 aad[2 * AES_BLOCK_SIZE];
-	u8 j_0[AES_BLOCK_SIZE];
 
 	if (info->control.hw_key &&
 	    !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
@@ -689,13 +723,34 @@ static int gcmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 	gcmp_pn2hdr(pos, pn, key->conf.keyidx);
 
 	/* hwaccel - with software GCMP header */
-	if (info->control.hw_key)
-		return 0;
+	if (unlikely(!info->control.hw_key)) {
+		struct ieee80211_crypto_bufs *bufs;
+		int err;
+		u8 *aad;
+		u8 *j_0;
+		u8 *mic = skb_put(skb, IEEE80211_GCMP_MIC_LEN);
+
+		bufs = kmem_cache_alloc(ieee80211_crypto_bufs_cache,
+					GFP_ATOMIC);
+		if (!bufs)
+			return -ENOMEM;
+
+		BUILD_BUG_ON(sizeof(bufs->buf1) < 2 * AES_BLOCK_SIZE);
+		BUILD_BUG_ON(sizeof(bufs->buf2) < AES_BLOCK_SIZE);
+
+		aad = bufs->buf1;
+		j_0 = bufs->buf2;
+
+		pos += IEEE80211_GCMP_HDR_LEN;
+		gcmp_special_blocks(skb, pn, j_0, aad);
+		err = ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad,
+						pos, len, mic);
+		kmem_cache_free(ieee80211_crypto_bufs_cache, bufs);
+
+		return err;
+	}
 
-	pos += IEEE80211_GCMP_HDR_LEN;
-	gcmp_special_blocks(skb, pn, j_0, aad);
-	return ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len,
-					 skb_put(skb, IEEE80211_GCMP_MIC_LEN));
+	return 0;
 }
 
 ieee80211_tx_result
@@ -760,17 +815,34 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx)
 		}
 
 		if (!(status->flag & RX_FLAG_DECRYPTED)) {
-			u8 aad[2 * AES_BLOCK_SIZE];
-			u8 j_0[AES_BLOCK_SIZE];
+			struct ieee80211_crypto_bufs *bufs;
+			int err;
+			u8 *aad;
+			u8 *j_0;
+
+			bufs = kmem_cache_alloc(ieee80211_crypto_bufs_cache,
+						GFP_ATOMIC);
+			if (!bufs)
+				return -ENOMEM;
+
+			BUILD_BUG_ON(sizeof(bufs->buf1) < 2 * AES_BLOCK_SIZE);
+			BUILD_BUG_ON(sizeof(bufs->buf2) < AES_BLOCK_SIZE);
+
+			aad = bufs->buf1;
+			j_0 = bufs->buf2;
+
 			/* hardware didn't decrypt/verify MIC */
 			gcmp_special_blocks(skb, pn, j_0, aad);
 
-			if (ieee80211_aes_gcm_decrypt(
+			err = ieee80211_aes_gcm_decrypt(
 				    key->u.gcmp.tfm, j_0, aad,
 				    skb->data + hdrlen + IEEE80211_GCMP_HDR_LEN,
 				    data_len,
 				    skb->data + skb->len -
-				    IEEE80211_GCMP_MIC_LEN))
+				    IEEE80211_GCMP_MIC_LEN);
+			kmem_cache_free(ieee80211_crypto_bufs_cache, bufs);
+
+			if (err)
 				return RX_DROP_UNUSABLE;
 		}
 
@@ -1119,9 +1191,12 @@ ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx)
 	struct ieee80211_key *key = tx->key;
 	struct ieee80211_mmie_16 *mmie;
 	struct ieee80211_hdr *hdr;
-	u8 aad[20];
 	u64 pn64;
 	u8 nonce[12];
+	struct ieee80211_crypto_bufs *bufs;
+	int err;
+	u8 *aad;
+	u8 *zero;
 
 	if (WARN_ON(skb_queue_len(&tx->skbs) != 1))
 		return TX_DROP;
@@ -1136,6 +1211,16 @@ ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx)
 	if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
 		return TX_DROP;
 
+	bufs = kmem_cache_alloc(ieee80211_crypto_bufs_cache, GFP_ATOMIC);
+	if (!bufs)
+		return TX_DROP;
+
+	BUILD_BUG_ON(sizeof(bufs->buf1) < GMAC_AAD_LEN);
+	BUILD_BUG_ON(sizeof(bufs->buf2) < GMAC_MIC_LEN);
+
+	aad = bufs->buf1;
+	zero = bufs->buf2;
+
 	mmie = (struct ieee80211_mmie_16 *)skb_put(skb, sizeof(*mmie));
 	mmie->element_id = WLAN_EID_MMIE;
 	mmie->length = sizeof(*mmie) - 2;
@@ -1153,11 +1238,13 @@ ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx)
 	bip_ipn_swap(nonce + ETH_ALEN, mmie->sequence_number);
 
 	/* MIC = AES-GMAC(IGTK, AAD || Management Frame Body || MMIE, 128) */
-	if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce,
-			       skb->data + 24, skb->len - 24, mmie->mic) < 0)
-		return TX_DROP;
+	err = ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce,
+				 skb->data + 24, skb->len - 24, mmie->mic,
+				 zero);
 
-	return TX_CONTINUE;
+	kmem_cache_free(ieee80211_crypto_bufs_cache, bufs);
+
+	return err < 0 ? TX_DROP : TX_CONTINUE;
 }
 
 ieee80211_rx_result
@@ -1167,7 +1254,7 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx)
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 	struct ieee80211_key *key = rx->key;
 	struct ieee80211_mmie_16 *mmie;
-	u8 aad[20], mic[16], ipn[6], nonce[12];
+	u8 mic[16], ipn[6], nonce[12];
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 
 	if (!ieee80211_is_mgmt(hdr->frame_control))
@@ -1192,16 +1279,34 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx)
 	}
 
 	if (!(status->flag & RX_FLAG_DECRYPTED)) {
+		struct ieee80211_crypto_bufs *bufs;
+		int err;
+		u8 *aad;
+		u8 *zero;
+
+		bufs = kmem_cache_alloc(ieee80211_crypto_bufs_cache,
+					GFP_ATOMIC);
+		if (!bufs)
+			return RX_DROP_UNUSABLE;
+
+		BUILD_BUG_ON(sizeof(bufs->buf1) < GMAC_AAD_LEN);
+		BUILD_BUG_ON(sizeof(bufs->buf2) < GMAC_MIC_LEN);
+
+		aad = bufs->buf1;
+		zero = bufs->buf2;
+
 		/* hardware didn't decrypt/verify MIC */
 		bip_aad(skb, aad);
 
 		memcpy(nonce, hdr->addr2, ETH_ALEN);
 		memcpy(nonce + ETH_ALEN, ipn, 6);
 
-		if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce,
-				       skb->data + 24, skb->len - 24,
-				       mic) < 0 ||
-		    memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) {
+		err = ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce,
+					 skb->data + 24, skb->len - 24,
+					 mic, zero);
+		kmem_cache_free(ieee80211_crypto_bufs_cache, bufs);
+
+		if (err < 0 || memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) {
 			key->u.aes_gmac.icverrors++;
 			return RX_DROP_UNUSABLE;
 		}
-- 
2.8.1

^ permalink raw reply related

* Re: [PATCH net-next 2/2] net: phy: Add Fast Link Failure - 2 set driver for Microsemi PHYs.
From: Raju Lakkaraju @ 2016-10-17  8:13 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: netdev, devicetree, f.fainelli, Allan.Nielsen
In-Reply-To: <20161014120228.GF5822@lunn.ch>

Hi Andrew,

Thank you for code review and comments.

On Fri, Oct 14, 2016 at 02:02:28PM +0200, Andrew Lunn wrote:
> EXTERNAL EMAIL
> 
> 
> > On Fri, Oct 14, 2016 at 05:10:33PM +0530, Raju Lakkaraju wrote:
> > From: Raju Lakkaraju <Raju.Lakkaraju@microsemi.com>
> >
> > VSC8531 Fast Link Failure 2 feature enables the PHY to indicate the
> > onset of a potential link failure in < 100 usec for 100BASE-TX
> > operation. FLF2 is supported through the MDINT (active low) pin.
> 
> Is the MDINT pin specific to this feature, or a general interrupt pin?
> 

MDINT pin is general interrupt. MDINT pin share the interrupt with
FLF2 along with another 13 interrupts.

> Device tree is used to describe the hardware. It should not really
> describe software or configuration. But the borders are a bit
> fluffly. Signal edge rates is near to hardware. This is a lot more
> towards configuration. So i'm not sure a device tree property is the
> correct way to describe this.
> 
> This is also a feature i know other PHYs support. The Marvell PHY has
> a "Metro Ethernet" extension which allows it to report link failures
> for 1000BASE-T in 10, 20 or 40ms, instead of the usual 750ms. So we
> need a generic solution other PHYs can implement.
> 
> As with cable testing, i think it should be an ethtool option.

I agree with you.
I thought this is one time initialization either enable or disable.
if customer need this feature, they can enable in DT.
Do you want me to implement through IOCTL instead of Device tree?
Do you have any other suggestions?

> 
>    Andrew

---
Thanks,
Raju.

^ permalink raw reply

* Re: [PATCH v3] mac80211: move struct aead_req off the stack
From: Ard Biesheuvel @ 2016-10-17  8:10 UTC (permalink / raw)
  To: Johannes Berg
  Cc: <linux-wireless@vger.kernel.org>, Sergey Senozhatsky,
	<netdev@vger.kernel.org>, Herbert Xu, Johannes Berg
In-Reply-To: <1476691431-27693-1-git-send-email-johannes@sipsolutions.net>

On 17 October 2016 at 09:03, Johannes Berg <johannes@sipsolutions.net> wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> Some crypto implementations (such as the generic CCM wrapper in crypto/)
> use scatterlists to map fields of private data in their struct aead_req.
> This means these data structures cannot live in the vmalloc area, which
> means that they cannot live on the stack (with CONFIG_VMAP_STACK.)
>
> This currently occurs only with the generic software implementation, but
> the private data and usage is implementation specific, so move the whole
> data structures off the stack into heap by allocating every time we need
> to use them.
>
> This pattern already exists in the IPsec ESP driver, but in the future,
> we may want/need to improve upon this, e.g. by using a slab cache.
>
> (Based on Ard's patch, but that was missing error handling and GCM/GMAC)
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> ---
> v3: remove superfluous aead_request_set_tfm() calls

Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

> ---
>  net/mac80211/aes_ccm.c  | 36 +++++++++++++++++++-----------------
>  net/mac80211/aes_ccm.h  |  6 +++---
>  net/mac80211/aes_gcm.c  | 33 +++++++++++++++++----------------
>  net/mac80211/aes_gcm.h  |  4 ++--
>  net/mac80211/aes_gmac.c | 11 +++++------
>  net/mac80211/wpa.c      | 12 ++++--------
>  6 files changed, 50 insertions(+), 52 deletions(-)
>
> diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
> index 7663c28ba353..8e898a6e8de8 100644
> --- a/net/mac80211/aes_ccm.c
> +++ b/net/mac80211/aes_ccm.c
> @@ -18,29 +18,29 @@
>  #include "key.h"
>  #include "aes_ccm.h"
>
> -void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
> -                              u8 *data, size_t data_len, u8 *mic,
> -                              size_t mic_len)
> +int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
> +                             u8 *data, size_t data_len, u8 *mic,
> +                             size_t mic_len)
>  {
>         struct scatterlist sg[3];
> +       struct aead_request *aead_req;
>
> -       char aead_req_data[sizeof(struct aead_request) +
> -                          crypto_aead_reqsize(tfm)]
> -               __aligned(__alignof__(struct aead_request));
> -       struct aead_request *aead_req = (void *) aead_req_data;
> -
> -       memset(aead_req, 0, sizeof(aead_req_data));
> +       aead_req = aead_request_alloc(tfm, GFP_ATOMIC);
> +       if (!aead_req)
> +               return -ENOMEM;
>
>         sg_init_table(sg, 3);
>         sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
>         sg_set_buf(&sg[1], data, data_len);
>         sg_set_buf(&sg[2], mic, mic_len);
>
> -       aead_request_set_tfm(aead_req, tfm);
>         aead_request_set_crypt(aead_req, sg, sg, data_len, b_0);
>         aead_request_set_ad(aead_req, sg[0].length);
>
>         crypto_aead_encrypt(aead_req);
> +       aead_request_free(aead_req);
> +
> +       return 0;
>  }
>
>  int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
> @@ -48,26 +48,28 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
>                               size_t mic_len)
>  {
>         struct scatterlist sg[3];
> -       char aead_req_data[sizeof(struct aead_request) +
> -                          crypto_aead_reqsize(tfm)]
> -               __aligned(__alignof__(struct aead_request));
> -       struct aead_request *aead_req = (void *) aead_req_data;
> +       struct aead_request *aead_req;
> +       int err;
>
>         if (data_len == 0)
>                 return -EINVAL;
>
> -       memset(aead_req, 0, sizeof(aead_req_data));
> +       aead_req = aead_request_alloc(tfm, GFP_ATOMIC);
> +       if (!aead_req)
> +               return -ENOMEM;
>
>         sg_init_table(sg, 3);
>         sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
>         sg_set_buf(&sg[1], data, data_len);
>         sg_set_buf(&sg[2], mic, mic_len);
>
> -       aead_request_set_tfm(aead_req, tfm);
>         aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0);
>         aead_request_set_ad(aead_req, sg[0].length);
>
> -       return crypto_aead_decrypt(aead_req);
> +       err = crypto_aead_decrypt(aead_req);
> +       aead_request_free(aead_req);
> +
> +       return err;
>  }
>
>  struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
> diff --git a/net/mac80211/aes_ccm.h b/net/mac80211/aes_ccm.h
> index 6a73d1e4d186..03e21b0995e3 100644
> --- a/net/mac80211/aes_ccm.h
> +++ b/net/mac80211/aes_ccm.h
> @@ -15,9 +15,9 @@
>  struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
>                                                     size_t key_len,
>                                                     size_t mic_len);
> -void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
> -                              u8 *data, size_t data_len, u8 *mic,
> -                              size_t mic_len);
> +int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
> +                             u8 *data, size_t data_len, u8 *mic,
> +                             size_t mic_len);
>  int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
>                               u8 *data, size_t data_len, u8 *mic,
>                               size_t mic_len);
> diff --git a/net/mac80211/aes_gcm.c b/net/mac80211/aes_gcm.c
> index 3afe361fd27c..831054c6c756 100644
> --- a/net/mac80211/aes_gcm.c
> +++ b/net/mac80211/aes_gcm.c
> @@ -15,55 +15,56 @@
>  #include "key.h"
>  #include "aes_gcm.h"
>
> -void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
> -                              u8 *data, size_t data_len, u8 *mic)
> +int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
> +                             u8 *data, size_t data_len, u8 *mic)
>  {
>         struct scatterlist sg[3];
> +       struct aead_request *aead_req;
>
> -       char aead_req_data[sizeof(struct aead_request) +
> -                          crypto_aead_reqsize(tfm)]
> -               __aligned(__alignof__(struct aead_request));
> -       struct aead_request *aead_req = (void *)aead_req_data;
> -
> -       memset(aead_req, 0, sizeof(aead_req_data));
> +       aead_req = aead_request_alloc(tfm, GFP_ATOMIC);
> +       if (!aead_req)
> +               return -ENOMEM;
>
>         sg_init_table(sg, 3);
>         sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
>         sg_set_buf(&sg[1], data, data_len);
>         sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN);
>
> -       aead_request_set_tfm(aead_req, tfm);
>         aead_request_set_crypt(aead_req, sg, sg, data_len, j_0);
>         aead_request_set_ad(aead_req, sg[0].length);
>
>         crypto_aead_encrypt(aead_req);
> +       aead_request_free(aead_req);
> +       return 0;
>  }
>
>  int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
>                               u8 *data, size_t data_len, u8 *mic)
>  {
>         struct scatterlist sg[3];
> -       char aead_req_data[sizeof(struct aead_request) +
> -                          crypto_aead_reqsize(tfm)]
> -               __aligned(__alignof__(struct aead_request));
> -       struct aead_request *aead_req = (void *)aead_req_data;
> +       struct aead_request *aead_req;
> +       int err;
>
>         if (data_len == 0)
>                 return -EINVAL;
>
> -       memset(aead_req, 0, sizeof(aead_req_data));
> +       aead_req = aead_request_alloc(tfm, GFP_ATOMIC);
> +       if (!aead_req)
> +               return -ENOMEM;
>
>         sg_init_table(sg, 3);
>         sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
>         sg_set_buf(&sg[1], data, data_len);
>         sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN);
>
> -       aead_request_set_tfm(aead_req, tfm);
>         aead_request_set_crypt(aead_req, sg, sg,
>                                data_len + IEEE80211_GCMP_MIC_LEN, j_0);
>         aead_request_set_ad(aead_req, sg[0].length);
>
> -       return crypto_aead_decrypt(aead_req);
> +       err = crypto_aead_decrypt(aead_req);
> +       aead_request_free(aead_req);
> +
> +       return err;
>  }
>
>  struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[],
> diff --git a/net/mac80211/aes_gcm.h b/net/mac80211/aes_gcm.h
> index 1347fda6b76a..b36503cd7716 100644
> --- a/net/mac80211/aes_gcm.h
> +++ b/net/mac80211/aes_gcm.h
> @@ -11,8 +11,8 @@
>
>  #include <linux/crypto.h>
>
> -void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
> -                              u8 *data, size_t data_len, u8 *mic);
> +int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
> +                             u8 *data, size_t data_len, u8 *mic);
>  int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
>                               u8 *data, size_t data_len, u8 *mic);
>  struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[],
> diff --git a/net/mac80211/aes_gmac.c b/net/mac80211/aes_gmac.c
> index 3ddd927aaf30..6951af9715c0 100644
> --- a/net/mac80211/aes_gmac.c
> +++ b/net/mac80211/aes_gmac.c
> @@ -25,16 +25,15 @@ int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
>                        const u8 *data, size_t data_len, u8 *mic)
>  {
>         struct scatterlist sg[4];
> -       char aead_req_data[sizeof(struct aead_request) +
> -                          crypto_aead_reqsize(tfm)]
> -               __aligned(__alignof__(struct aead_request));
> -       struct aead_request *aead_req = (void *)aead_req_data;
>         u8 zero[GMAC_MIC_LEN], iv[AES_BLOCK_SIZE];
> +       struct aead_request *aead_req;
>
>         if (data_len < GMAC_MIC_LEN)
>                 return -EINVAL;
>
> -       memset(aead_req, 0, sizeof(aead_req_data));
> +       aead_req = aead_request_alloc(tfm, GFP_ATOMIC);
> +       if (!aead_req)
> +               return -ENOMEM;
>
>         memset(zero, 0, GMAC_MIC_LEN);
>         sg_init_table(sg, 4);
> @@ -47,11 +46,11 @@ int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
>         memset(iv + GMAC_NONCE_LEN, 0, sizeof(iv) - GMAC_NONCE_LEN);
>         iv[AES_BLOCK_SIZE - 1] = 0x01;
>
> -       aead_request_set_tfm(aead_req, tfm);
>         aead_request_set_crypt(aead_req, sg, sg, 0, iv);
>         aead_request_set_ad(aead_req, AAD_LEN + data_len);
>
>         crypto_aead_encrypt(aead_req);
> +       aead_request_free(aead_req);
>
>         return 0;
>  }
> diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
> index b48c1e13e281..2e366438f8ef 100644
> --- a/net/mac80211/wpa.c
> +++ b/net/mac80211/wpa.c
> @@ -461,10 +461,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb,
>
>         pos += IEEE80211_CCMP_HDR_LEN;
>         ccmp_special_blocks(skb, pn, b_0, aad);
> -       ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
> -                                 skb_put(skb, mic_len), mic_len);
> -
> -       return 0;
> +       return ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
> +                                        skb_put(skb, mic_len), mic_len);
>  }
>
>
> @@ -696,10 +694,8 @@ static int gcmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
>
>         pos += IEEE80211_GCMP_HDR_LEN;
>         gcmp_special_blocks(skb, pn, j_0, aad);
> -       ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len,
> -                                 skb_put(skb, IEEE80211_GCMP_MIC_LEN));
> -
> -       return 0;
> +       return ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len,
> +                                        skb_put(skb, IEEE80211_GCMP_MIC_LEN));
>  }
>
>  ieee80211_tx_result
> --
> 2.8.1
>

^ permalink raw reply

* Re: [PATCH v3] mac80211: move extra crypto data off the stack
From: Johannes Berg @ 2016-10-17  8:04 UTC (permalink / raw)
  To: linux-wireless-u79uwXL29TY76Z2rM5mHXA
  Cc: Ard Biesheuvel, Sergey Senozhatsky, netdev-u79uwXL29TY76Z2rM5mHXA,
	herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q
In-Reply-To: <1476691342-22347-1-git-send-email-johannes-cdvu00un1VgdHxzADdlk8Q@public.gmane.org>

[snip]

Sorry, this went out by mistake.

johannes

^ permalink raw reply

* [PATCH v3] mac80211: move struct aead_req off the stack
From: Johannes Berg @ 2016-10-17  8:03 UTC (permalink / raw)
  To: linux-wireless
  Cc: Ard Biesheuvel, Sergey Senozhatsky, netdev, herbert,
	Johannes Berg

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

Some crypto implementations (such as the generic CCM wrapper in crypto/)
use scatterlists to map fields of private data in their struct aead_req.
This means these data structures cannot live in the vmalloc area, which
means that they cannot live on the stack (with CONFIG_VMAP_STACK.)

This currently occurs only with the generic software implementation, but
the private data and usage is implementation specific, so move the whole
data structures off the stack into heap by allocating every time we need
to use them.

This pattern already exists in the IPsec ESP driver, but in the future,
we may want/need to improve upon this, e.g. by using a slab cache.

(Based on Ard's patch, but that was missing error handling and GCM/GMAC)

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
v3: remove superfluous aead_request_set_tfm() calls
---
 net/mac80211/aes_ccm.c  | 36 +++++++++++++++++++-----------------
 net/mac80211/aes_ccm.h  |  6 +++---
 net/mac80211/aes_gcm.c  | 33 +++++++++++++++++----------------
 net/mac80211/aes_gcm.h  |  4 ++--
 net/mac80211/aes_gmac.c | 11 +++++------
 net/mac80211/wpa.c      | 12 ++++--------
 6 files changed, 50 insertions(+), 52 deletions(-)

diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
index 7663c28ba353..8e898a6e8de8 100644
--- a/net/mac80211/aes_ccm.c
+++ b/net/mac80211/aes_ccm.c
@@ -18,29 +18,29 @@
 #include "key.h"
 #include "aes_ccm.h"
 
-void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
-			       u8 *data, size_t data_len, u8 *mic,
-			       size_t mic_len)
+int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+			      u8 *data, size_t data_len, u8 *mic,
+			      size_t mic_len)
 {
 	struct scatterlist sg[3];
+	struct aead_request *aead_req;
 
-	char aead_req_data[sizeof(struct aead_request) +
-			   crypto_aead_reqsize(tfm)]
-		__aligned(__alignof__(struct aead_request));
-	struct aead_request *aead_req = (void *) aead_req_data;
-
-	memset(aead_req, 0, sizeof(aead_req_data));
+	aead_req = aead_request_alloc(tfm, GFP_ATOMIC);
+	if (!aead_req)
+		return -ENOMEM;
 
 	sg_init_table(sg, 3);
 	sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
 	sg_set_buf(&sg[1], data, data_len);
 	sg_set_buf(&sg[2], mic, mic_len);
 
-	aead_request_set_tfm(aead_req, tfm);
 	aead_request_set_crypt(aead_req, sg, sg, data_len, b_0);
 	aead_request_set_ad(aead_req, sg[0].length);
 
 	crypto_aead_encrypt(aead_req);
+	aead_request_free(aead_req);
+
+	return 0;
 }
 
 int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
@@ -48,26 +48,28 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
 			      size_t mic_len)
 {
 	struct scatterlist sg[3];
-	char aead_req_data[sizeof(struct aead_request) +
-			   crypto_aead_reqsize(tfm)]
-		__aligned(__alignof__(struct aead_request));
-	struct aead_request *aead_req = (void *) aead_req_data;
+	struct aead_request *aead_req;
+	int err;
 
 	if (data_len == 0)
 		return -EINVAL;
 
-	memset(aead_req, 0, sizeof(aead_req_data));
+	aead_req = aead_request_alloc(tfm, GFP_ATOMIC);
+	if (!aead_req)
+		return -ENOMEM;
 
 	sg_init_table(sg, 3);
 	sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
 	sg_set_buf(&sg[1], data, data_len);
 	sg_set_buf(&sg[2], mic, mic_len);
 
-	aead_request_set_tfm(aead_req, tfm);
 	aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0);
 	aead_request_set_ad(aead_req, sg[0].length);
 
-	return crypto_aead_decrypt(aead_req);
+	err = crypto_aead_decrypt(aead_req);
+	aead_request_free(aead_req);
+
+	return err;
 }
 
 struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
diff --git a/net/mac80211/aes_ccm.h b/net/mac80211/aes_ccm.h
index 6a73d1e4d186..03e21b0995e3 100644
--- a/net/mac80211/aes_ccm.h
+++ b/net/mac80211/aes_ccm.h
@@ -15,9 +15,9 @@
 struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
 						    size_t key_len,
 						    size_t mic_len);
-void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
-			       u8 *data, size_t data_len, u8 *mic,
-			       size_t mic_len);
+int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+			      u8 *data, size_t data_len, u8 *mic,
+			      size_t mic_len);
 int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
 			      u8 *data, size_t data_len, u8 *mic,
 			      size_t mic_len);
diff --git a/net/mac80211/aes_gcm.c b/net/mac80211/aes_gcm.c
index 3afe361fd27c..831054c6c756 100644
--- a/net/mac80211/aes_gcm.c
+++ b/net/mac80211/aes_gcm.c
@@ -15,55 +15,56 @@
 #include "key.h"
 #include "aes_gcm.h"
 
-void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
-			       u8 *data, size_t data_len, u8 *mic)
+int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
+			      u8 *data, size_t data_len, u8 *mic)
 {
 	struct scatterlist sg[3];
+	struct aead_request *aead_req;
 
-	char aead_req_data[sizeof(struct aead_request) +
-			   crypto_aead_reqsize(tfm)]
-		__aligned(__alignof__(struct aead_request));
-	struct aead_request *aead_req = (void *)aead_req_data;
-
-	memset(aead_req, 0, sizeof(aead_req_data));
+	aead_req = aead_request_alloc(tfm, GFP_ATOMIC);
+	if (!aead_req)
+		return -ENOMEM;
 
 	sg_init_table(sg, 3);
 	sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
 	sg_set_buf(&sg[1], data, data_len);
 	sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN);
 
-	aead_request_set_tfm(aead_req, tfm);
 	aead_request_set_crypt(aead_req, sg, sg, data_len, j_0);
 	aead_request_set_ad(aead_req, sg[0].length);
 
 	crypto_aead_encrypt(aead_req);
+	aead_request_free(aead_req);
+	return 0;
 }
 
 int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
 			      u8 *data, size_t data_len, u8 *mic)
 {
 	struct scatterlist sg[3];
-	char aead_req_data[sizeof(struct aead_request) +
-			   crypto_aead_reqsize(tfm)]
-		__aligned(__alignof__(struct aead_request));
-	struct aead_request *aead_req = (void *)aead_req_data;
+	struct aead_request *aead_req;
+	int err;
 
 	if (data_len == 0)
 		return -EINVAL;
 
-	memset(aead_req, 0, sizeof(aead_req_data));
+	aead_req = aead_request_alloc(tfm, GFP_ATOMIC);
+	if (!aead_req)
+		return -ENOMEM;
 
 	sg_init_table(sg, 3);
 	sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
 	sg_set_buf(&sg[1], data, data_len);
 	sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN);
 
-	aead_request_set_tfm(aead_req, tfm);
 	aead_request_set_crypt(aead_req, sg, sg,
 			       data_len + IEEE80211_GCMP_MIC_LEN, j_0);
 	aead_request_set_ad(aead_req, sg[0].length);
 
-	return crypto_aead_decrypt(aead_req);
+	err = crypto_aead_decrypt(aead_req);
+	aead_request_free(aead_req);
+
+	return err;
 }
 
 struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[],
diff --git a/net/mac80211/aes_gcm.h b/net/mac80211/aes_gcm.h
index 1347fda6b76a..b36503cd7716 100644
--- a/net/mac80211/aes_gcm.h
+++ b/net/mac80211/aes_gcm.h
@@ -11,8 +11,8 @@
 
 #include <linux/crypto.h>
 
-void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
-			       u8 *data, size_t data_len, u8 *mic);
+int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
+			      u8 *data, size_t data_len, u8 *mic);
 int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
 			      u8 *data, size_t data_len, u8 *mic);
 struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[],
diff --git a/net/mac80211/aes_gmac.c b/net/mac80211/aes_gmac.c
index 3ddd927aaf30..6951af9715c0 100644
--- a/net/mac80211/aes_gmac.c
+++ b/net/mac80211/aes_gmac.c
@@ -25,16 +25,15 @@ int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
 		       const u8 *data, size_t data_len, u8 *mic)
 {
 	struct scatterlist sg[4];
-	char aead_req_data[sizeof(struct aead_request) +
-			   crypto_aead_reqsize(tfm)]
-		__aligned(__alignof__(struct aead_request));
-	struct aead_request *aead_req = (void *)aead_req_data;
 	u8 zero[GMAC_MIC_LEN], iv[AES_BLOCK_SIZE];
+	struct aead_request *aead_req;
 
 	if (data_len < GMAC_MIC_LEN)
 		return -EINVAL;
 
-	memset(aead_req, 0, sizeof(aead_req_data));
+	aead_req = aead_request_alloc(tfm, GFP_ATOMIC);
+	if (!aead_req)
+		return -ENOMEM;
 
 	memset(zero, 0, GMAC_MIC_LEN);
 	sg_init_table(sg, 4);
@@ -47,11 +46,11 @@ int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
 	memset(iv + GMAC_NONCE_LEN, 0, sizeof(iv) - GMAC_NONCE_LEN);
 	iv[AES_BLOCK_SIZE - 1] = 0x01;
 
-	aead_request_set_tfm(aead_req, tfm);
 	aead_request_set_crypt(aead_req, sg, sg, 0, iv);
 	aead_request_set_ad(aead_req, AAD_LEN + data_len);
 
 	crypto_aead_encrypt(aead_req);
+	aead_request_free(aead_req);
 
 	return 0;
 }
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index b48c1e13e281..2e366438f8ef 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -461,10 +461,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb,
 
 	pos += IEEE80211_CCMP_HDR_LEN;
 	ccmp_special_blocks(skb, pn, b_0, aad);
-	ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
-				  skb_put(skb, mic_len), mic_len);
-
-	return 0;
+	return ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
+					 skb_put(skb, mic_len), mic_len);
 }
 
 
@@ -696,10 +694,8 @@ static int gcmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 
 	pos += IEEE80211_GCMP_HDR_LEN;
 	gcmp_special_blocks(skb, pn, j_0, aad);
-	ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len,
-				  skb_put(skb, IEEE80211_GCMP_MIC_LEN));
-
-	return 0;
+	return ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len,
+					 skb_put(skb, IEEE80211_GCMP_MIC_LEN));
 }
 
 ieee80211_tx_result
-- 
2.8.1

^ permalink raw reply related

* [PATCH v3] mac80211: move extra crypto data off the stack
From: Johannes Berg @ 2016-10-17  8:02 UTC (permalink / raw)
  To: linux-wireless
  Cc: Ard Biesheuvel, Sergey Senozhatsky, netdev, herbert,
	Johannes Berg

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

As the stack can (on x86-64) now be virtually mapped rather than
using "normal" kernel memory, Sergey noticed mac80211 isn't using
the SG APIs correctly by putting on-stack buffers into SG tables.
This leads to kernel crashes.

Fix this by allocating a bit of per-CPU memory for the extra data
that encryption/decryption/verification needs, instead of having
it stored on the stack.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/aes_ccm.c     |  2 --
 net/mac80211/aes_cmac.c    |  5 ++-
 net/mac80211/aes_cmac.h    |  2 ++
 net/mac80211/aes_gcm.c     |  2 --
 net/mac80211/aes_gmac.c    | 10 +++---
 net/mac80211/aes_gmac.h    |  5 ++-
 net/mac80211/ieee80211_i.h |  7 ++++
 net/mac80211/main.c        |  8 +++++
 net/mac80211/wpa.c         | 86 +++++++++++++++++++++++++++++++++++++---------
 9 files changed, 97 insertions(+), 30 deletions(-)

diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
index 5c9fe00be6cc..8e898a6e8de8 100644
--- a/net/mac80211/aes_ccm.c
+++ b/net/mac80211/aes_ccm.c
@@ -34,7 +34,6 @@ int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
 	sg_set_buf(&sg[1], data, data_len);
 	sg_set_buf(&sg[2], mic, mic_len);
 
-	aead_request_set_tfm(aead_req, tfm);
 	aead_request_set_crypt(aead_req, sg, sg, data_len, b_0);
 	aead_request_set_ad(aead_req, sg[0].length);
 
@@ -64,7 +63,6 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
 	sg_set_buf(&sg[1], data, data_len);
 	sg_set_buf(&sg[2], mic, mic_len);
 
-	aead_request_set_tfm(aead_req, tfm);
 	aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0);
 	aead_request_set_ad(aead_req, sg[0].length);
 
diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c
index bdf0790d89cc..ebb8c2dc9928 100644
--- a/net/mac80211/aes_cmac.c
+++ b/net/mac80211/aes_cmac.c
@@ -20,7 +20,6 @@
 
 #define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */
 #define CMAC_TLEN_256 16 /* CMAC TLen = 128 bits (16 octets) */
-#define AAD_LEN 20
 
 
 static void gf_mulx(u8 *pad)
@@ -101,7 +100,7 @@ void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad,
 
 	memset(zero, 0, CMAC_TLEN);
 	addr[0] = aad;
-	len[0] = AAD_LEN;
+	len[0] = CMAC_AAD_LEN;
 	addr[1] = data;
 	len[1] = data_len - CMAC_TLEN;
 	addr[2] = zero;
@@ -119,7 +118,7 @@ void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad,
 
 	memset(zero, 0, CMAC_TLEN_256);
 	addr[0] = aad;
-	len[0] = AAD_LEN;
+	len[0] = CMAC_AAD_LEN;
 	addr[1] = data;
 	len[1] = data_len - CMAC_TLEN_256;
 	addr[2] = zero;
diff --git a/net/mac80211/aes_cmac.h b/net/mac80211/aes_cmac.h
index 3702041f44fd..6645f8963278 100644
--- a/net/mac80211/aes_cmac.h
+++ b/net/mac80211/aes_cmac.h
@@ -11,6 +11,8 @@
 
 #include <linux/crypto.h>
 
+#define CMAC_AAD_LEN 20
+
 struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[],
 						   size_t key_len);
 void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad,
diff --git a/net/mac80211/aes_gcm.c b/net/mac80211/aes_gcm.c
index aa8eb2718bc1..831054c6c756 100644
--- a/net/mac80211/aes_gcm.c
+++ b/net/mac80211/aes_gcm.c
@@ -30,7 +30,6 @@ int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
 	sg_set_buf(&sg[1], data, data_len);
 	sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN);
 
-	aead_request_set_tfm(aead_req, tfm);
 	aead_request_set_crypt(aead_req, sg, sg, data_len, j_0);
 	aead_request_set_ad(aead_req, sg[0].length);
 
@@ -58,7 +57,6 @@ int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
 	sg_set_buf(&sg[1], data, data_len);
 	sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN);
 
-	aead_request_set_tfm(aead_req, tfm);
 	aead_request_set_crypt(aead_req, sg, sg,
 			       data_len + IEEE80211_GCMP_MIC_LEN, j_0);
 	aead_request_set_ad(aead_req, sg[0].length);
diff --git a/net/mac80211/aes_gmac.c b/net/mac80211/aes_gmac.c
index 15cfcebf0884..86892e2e3c8c 100644
--- a/net/mac80211/aes_gmac.c
+++ b/net/mac80211/aes_gmac.c
@@ -19,13 +19,12 @@
 
 #define GMAC_MIC_LEN 16
 #define GMAC_NONCE_LEN 12
-#define AAD_LEN 20
 
 int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
-		       const u8 *data, size_t data_len, u8 *mic)
+		       const u8 *data, size_t data_len, u8 *mic, u8 *zero)
 {
 	struct scatterlist sg[4];
-	u8 zero[GMAC_MIC_LEN], iv[AES_BLOCK_SIZE];
+	u8 iv[AES_BLOCK_SIZE];
 	struct aead_request *aead_req;
 
 	if (data_len < GMAC_MIC_LEN)
@@ -37,7 +36,7 @@ int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
 
 	memset(zero, 0, GMAC_MIC_LEN);
 	sg_init_table(sg, 4);
-	sg_set_buf(&sg[0], aad, AAD_LEN);
+	sg_set_buf(&sg[0], aad, GMAC_AAD_LEN);
 	sg_set_buf(&sg[1], data, data_len - GMAC_MIC_LEN);
 	sg_set_buf(&sg[2], zero, GMAC_MIC_LEN);
 	sg_set_buf(&sg[3], mic, GMAC_MIC_LEN);
@@ -46,9 +45,8 @@ int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
 	memset(iv + GMAC_NONCE_LEN, 0, sizeof(iv) - GMAC_NONCE_LEN);
 	iv[AES_BLOCK_SIZE - 1] = 0x01;
 
-	aead_request_set_tfm(aead_req, tfm);
 	aead_request_set_crypt(aead_req, sg, sg, 0, iv);
-	aead_request_set_ad(aead_req, AAD_LEN + data_len);
+	aead_request_set_ad(aead_req, GMAC_AAD_LEN + data_len);
 
 	crypto_aead_encrypt(aead_req);
 	aead_request_free(aead_req);
diff --git a/net/mac80211/aes_gmac.h b/net/mac80211/aes_gmac.h
index d328204d73a8..f06833c9095f 100644
--- a/net/mac80211/aes_gmac.h
+++ b/net/mac80211/aes_gmac.h
@@ -11,10 +11,13 @@
 
 #include <linux/crypto.h>
 
+#define GMAC_MIC_LEN 16
+#define GMAC_AAD_LEN 20
+
 struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[],
 						 size_t key_len);
 int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
-		       const u8 *data, size_t data_len, u8 *mic);
+		       const u8 *data, size_t data_len, u8 *mic, u8 *zero);
 void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm);
 
 #endif /* AES_GMAC_H */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 34c2add2c455..d68aae40b8d5 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1128,6 +1128,13 @@ enum mac80211_scan_state {
 	SCAN_ABORT,
 };
 
+struct ieee80211_crypto_bufs {
+	u8 buf1[32];
+	u8 buf2[16];
+};
+
+extern struct ieee80211_crypto_bufs __percpu *ieee80211_crypto_bufs;
+
 struct ieee80211_local {
 	/* embed the driver visible part.
 	 * don't cast (use the static inlines below), but we keep
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 1075ac24c8c5..6175cde94c53 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -33,6 +33,8 @@
 #include "led.h"
 #include "debugfs.h"
 
+struct ieee80211_crypto_bufs __percpu *ieee80211_crypto_bufs;
+
 void ieee80211_configure_filter(struct ieee80211_local *local)
 {
 	u64 mc;
@@ -1234,6 +1236,10 @@ static int __init ieee80211_init(void)
 	BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) +
 		     IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb));
 
+	ieee80211_crypto_bufs = alloc_percpu(struct ieee80211_crypto_bufs);
+	if (!ieee80211_crypto_bufs)
+		return -ENOMEM;
+
 	ret = rc80211_minstrel_init();
 	if (ret)
 		return ret;
@@ -1264,6 +1270,8 @@ static void __exit ieee80211_exit(void)
 
 	ieee80211_iface_exit();
 
+	free_percpu(ieee80211_crypto_bufs);
+
 	rcu_barrier();
 }
 
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 2e366438f8ef..3a83a6763664 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -405,8 +405,13 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb,
 	u8 *pos;
 	u8 pn[6];
 	u64 pn64;
-	u8 aad[2 * AES_BLOCK_SIZE];
-	u8 b_0[AES_BLOCK_SIZE];
+	struct ieee80211_crypto_bufs *bufs =
+		this_cpu_ptr(ieee80211_crypto_bufs);
+	u8 *aad = bufs->buf1;
+	u8 *b_0 = bufs->buf2;
+
+	BUILD_BUG_ON(sizeof(bufs->buf1) < 2 * AES_BLOCK_SIZE);
+	BUILD_BUG_ON(sizeof(bufs->buf2) < AES_BLOCK_SIZE);
 
 	if (info->control.hw_key &&
 	    !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
@@ -532,8 +537,14 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx,
 		}
 
 		if (!(status->flag & RX_FLAG_DECRYPTED)) {
-			u8 aad[2 * AES_BLOCK_SIZE];
-			u8 b_0[AES_BLOCK_SIZE];
+			struct ieee80211_crypto_bufs *bufs =
+				this_cpu_ptr(ieee80211_crypto_bufs);
+			u8 *aad = bufs->buf1;
+			u8 *b_0 = bufs->buf2;
+
+			BUILD_BUG_ON(sizeof(bufs->buf1) < 2 * AES_BLOCK_SIZE);
+			BUILD_BUG_ON(sizeof(bufs->buf2) < AES_BLOCK_SIZE);
+
 			/* hardware didn't decrypt/verify MIC */
 			ccmp_special_blocks(skb, pn, b_0, aad);
 
@@ -637,8 +648,13 @@ static int gcmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 	u8 *pos;
 	u8 pn[6];
 	u64 pn64;
-	u8 aad[2 * AES_BLOCK_SIZE];
-	u8 j_0[AES_BLOCK_SIZE];
+	struct ieee80211_crypto_bufs *bufs =
+		this_cpu_ptr(ieee80211_crypto_bufs);
+	u8 *aad = bufs->buf1;
+	u8 *j_0 = bufs->buf2;
+
+	BUILD_BUG_ON(sizeof(bufs->buf1) < 2 * AES_BLOCK_SIZE);
+	BUILD_BUG_ON(sizeof(bufs->buf2) < AES_BLOCK_SIZE);
 
 	if (info->control.hw_key &&
 	    !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
@@ -760,8 +776,14 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx)
 		}
 
 		if (!(status->flag & RX_FLAG_DECRYPTED)) {
-			u8 aad[2 * AES_BLOCK_SIZE];
-			u8 j_0[AES_BLOCK_SIZE];
+			struct ieee80211_crypto_bufs *bufs =
+				this_cpu_ptr(ieee80211_crypto_bufs);
+			u8 *aad = bufs->buf1;
+			u8 *j_0 = bufs->buf2;
+
+			BUILD_BUG_ON(sizeof(bufs->buf1) < 2 * AES_BLOCK_SIZE);
+			BUILD_BUG_ON(sizeof(bufs->buf2) < AES_BLOCK_SIZE);
+
 			/* hardware didn't decrypt/verify MIC */
 			gcmp_special_blocks(skb, pn, j_0, aad);
 
@@ -931,8 +953,12 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
 	struct ieee80211_tx_info *info;
 	struct ieee80211_key *key = tx->key;
 	struct ieee80211_mmie *mmie;
-	u8 aad[20];
 	u64 pn64;
+	struct ieee80211_crypto_bufs *bufs =
+		this_cpu_ptr(ieee80211_crypto_bufs);
+	u8 *aad = bufs->buf1;
+
+	BUILD_BUG_ON(sizeof(bufs->buf1) < CMAC_AAD_LEN);
 
 	if (WARN_ON(skb_queue_len(&tx->skbs) != 1))
 		return TX_DROP;
@@ -975,8 +1001,12 @@ ieee80211_crypto_aes_cmac_256_encrypt(struct ieee80211_tx_data *tx)
 	struct ieee80211_tx_info *info;
 	struct ieee80211_key *key = tx->key;
 	struct ieee80211_mmie_16 *mmie;
-	u8 aad[20];
 	u64 pn64;
+	struct ieee80211_crypto_bufs *bufs =
+		this_cpu_ptr(ieee80211_crypto_bufs);
+	u8 *aad = bufs->buf1;
+
+	BUILD_BUG_ON(sizeof(bufs->buf1) < CMAC_AAD_LEN);
 
 	if (WARN_ON(skb_queue_len(&tx->skbs) != 1))
 		return TX_DROP;
@@ -1018,8 +1048,13 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx)
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 	struct ieee80211_key *key = rx->key;
 	struct ieee80211_mmie *mmie;
-	u8 aad[20], mic[8], ipn[6];
+	u8 mic[8], ipn[6];
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ieee80211_crypto_bufs *bufs =
+		this_cpu_ptr(ieee80211_crypto_bufs);
+	u8 *aad = bufs->buf1;
+
+	BUILD_BUG_ON(sizeof(bufs->buf1) < CMAC_AAD_LEN);
 
 	if (!ieee80211_is_mgmt(hdr->frame_control))
 		return RX_CONTINUE;
@@ -1068,8 +1103,13 @@ ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx)
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 	struct ieee80211_key *key = rx->key;
 	struct ieee80211_mmie_16 *mmie;
-	u8 aad[20], mic[16], ipn[6];
+	u8 mic[16], ipn[6];
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	struct ieee80211_crypto_bufs *bufs =
+		this_cpu_ptr(ieee80211_crypto_bufs);
+	u8 *aad = bufs->buf1;
+
+	BUILD_BUG_ON(sizeof(bufs->buf1) < CMAC_AAD_LEN);
 
 	if (!ieee80211_is_mgmt(hdr->frame_control))
 		return RX_CONTINUE;
@@ -1119,9 +1159,15 @@ ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx)
 	struct ieee80211_key *key = tx->key;
 	struct ieee80211_mmie_16 *mmie;
 	struct ieee80211_hdr *hdr;
-	u8 aad[20];
 	u64 pn64;
 	u8 nonce[12];
+	struct ieee80211_crypto_bufs *bufs =
+		this_cpu_ptr(ieee80211_crypto_bufs);
+	u8 *aad = bufs->buf1;
+	u8 *zero = bufs->buf2;
+
+	BUILD_BUG_ON(sizeof(bufs->buf1) < GMAC_AAD_LEN);
+	BUILD_BUG_ON(sizeof(bufs->buf2) < GMAC_MIC_LEN);
 
 	if (WARN_ON(skb_queue_len(&tx->skbs) != 1))
 		return TX_DROP;
@@ -1154,7 +1200,8 @@ ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx)
 
 	/* MIC = AES-GMAC(IGTK, AAD || Management Frame Body || MMIE, 128) */
 	if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce,
-			       skb->data + 24, skb->len - 24, mmie->mic) < 0)
+			       skb->data + 24, skb->len - 24, mmie->mic,
+			       zero) < 0)
 		return TX_DROP;
 
 	return TX_CONTINUE;
@@ -1167,8 +1214,15 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx)
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 	struct ieee80211_key *key = rx->key;
 	struct ieee80211_mmie_16 *mmie;
-	u8 aad[20], mic[16], ipn[6], nonce[12];
+	u8 mic[16], ipn[6], nonce[12];
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	struct ieee80211_crypto_bufs *bufs =
+		this_cpu_ptr(ieee80211_crypto_bufs);
+	u8 *aad = bufs->buf1;
+	u8 *zero = bufs->buf2;
+
+	BUILD_BUG_ON(sizeof(bufs->buf1) < GMAC_AAD_LEN);
+	BUILD_BUG_ON(sizeof(bufs->buf2) < GMAC_MIC_LEN);
 
 	if (!ieee80211_is_mgmt(hdr->frame_control))
 		return RX_CONTINUE;
@@ -1200,7 +1254,7 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx)
 
 		if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce,
 				       skb->data + 24, skb->len - 24,
-				       mic) < 0 ||
+				       mic, zero) < 0 ||
 		    memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) {
 			key->u.aes_gmac.icverrors++;
 			return RX_DROP_UNUSABLE;
-- 
2.8.1

^ 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