* Re: [PATCH 3/8] tools: Sync tools/include/uapi/linux/bpf.h with the kernel
From: Wangnan (F) @ 2016-10-17 1:48 UTC (permalink / raw)
To: Eric Leblond, netdev; +Cc: linux-kernel, ast
In-Reply-To: <20161016211834.11732-4-eric@regit.org>
On 2016/10/17 5:18, Eric Leblond wrote:
> Signed-off-by: Eric Leblond <eric@regit.org>
Commit message is required.
Thank you.
> ---
> tools/include/uapi/linux/bpf.h | 52 ++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 52 insertions(+)
>
> diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
> index 9e5fc16..570287f 100644
> --- a/tools/include/uapi/linux/bpf.h
> +++ b/tools/include/uapi/linux/bpf.h
> @@ -95,6 +95,8 @@ enum bpf_prog_type {
> BPF_PROG_TYPE_SCHED_ACT,
> BPF_PROG_TYPE_TRACEPOINT,
> BPF_PROG_TYPE_XDP,
> + BPF_PROG_TYPE_PERF_EVENT,
> + __MAX_BPF_PROG_TYPE,
> };
>
> #define BPF_PSEUDO_MAP_FD 1
> @@ -375,6 +377,56 @@ enum bpf_func_id {
> */
> BPF_FUNC_probe_write_user,
>
> + /**
> + * bpf_current_task_under_cgroup(map, index) - Check cgroup2 membership of current task
> + * @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type
> + * @index: index of the cgroup in the bpf_map
> + * Return:
> + * == 0 current failed the cgroup2 descendant test
> + * == 1 current succeeded the cgroup2 descendant test
> + * < 0 error
> + */
> + BPF_FUNC_current_task_under_cgroup,
> +
> + /**
> + * bpf_skb_change_tail(skb, len, flags)
> + * The helper will resize the skb to the given new size,
> + * to be used f.e. with control messages.
> + * @skb: pointer to skb
> + * @len: new skb length
> + * @flags: reserved
> + * Return: 0 on success or negative error
> + */
> + BPF_FUNC_skb_change_tail,
> +
> + /**
> + * bpf_skb_pull_data(skb, len)
> + * The helper will pull in non-linear data in case the
> + * skb is non-linear and not all of len are part of the
> + * linear section. Only needed for read/write with direct
> + * packet access.
> + * @skb: pointer to skb
> + * @len: len to make read/writeable
> + * Return: 0 on success or negative error
> + */
> + BPF_FUNC_skb_pull_data,
> +
> + /**
> + * bpf_csum_update(skb, csum)
> + * Adds csum into skb->csum in case of CHECKSUM_COMPLETE.
> + * @skb: pointer to skb
> + * @csum: csum to add
> + * Return: csum on success or negative error
> + */
> + BPF_FUNC_csum_update,
> +
> + /**
> + * bpf_set_hash_invalid(skb)
> + * Invalidate current skb>hash.
> + * @skb: pointer to skb
> + */
> + BPF_FUNC_set_hash_invalid,
> +
> __BPF_FUNC_MAX_ID,
> };
>
^ permalink raw reply
* Re: [PATCH 4/8] tools lib bpf: export function to set type
From: Wangnan (F) @ 2016-10-17 1:56 UTC (permalink / raw)
To: Eric Leblond, netdev; +Cc: linux-kernel, ast
In-Reply-To: <20161016211834.11732-5-eric@regit.org>
On 2016/10/17 5:18, Eric Leblond wrote:
> Current API was not allowing the user to set a type like socket
> filter. To avoid a setter function for each type, the patch simply
> exports a set function that takes the type in parameter.
>
> Signed-off-by: Eric Leblond <eric@regit.org>
> ---
> tools/lib/bpf/libbpf.c | 19 +++++++++----------
> tools/lib/bpf/libbpf.h | 3 +++
> 2 files changed, 12 insertions(+), 10 deletions(-)
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 90932f1..7cd341e 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -1336,26 +1336,25 @@ int bpf_program__nth_fd(struct bpf_program *prog, int n)
> return fd;
> }
>
> -static void bpf_program__set_type(struct bpf_program *prog,
> - enum bpf_prog_type type)
> +int bpf_program__set_type(struct bpf_program *prog, unsigned int type)
> {
> + if (!prog)
> + return -EINVAL;
> + if (type >= __MAX_BPF_PROG_TYPE)
> + return -EINVAL;
> +
> prog->type = type;
> + return 0;
> }
>
> int bpf_program__set_tracepoint(struct bpf_program *prog)
> {
> - if (!prog)
> - return -EINVAL;
> - bpf_program__set_type(prog, BPF_PROG_TYPE_TRACEPOINT);
> - return 0;
> + return bpf_program__set_type(prog, BPF_PROG_TYPE_TRACEPOINT);
> }
>
> int bpf_program__set_kprobe(struct bpf_program *prog)
> {
> - if (!prog)
> - return -EINVAL;
> - bpf_program__set_type(prog, BPF_PROG_TYPE_KPROBE);
> - return 0;
> + return bpf_program__set_type(prog, BPF_PROG_TYPE_KPROBE);
> }
>
> static bool bpf_program__is_type(struct bpf_program *prog,
> diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
> index e40c8d3..a18783b 100644
> --- a/tools/lib/bpf/libbpf.h
> +++ b/tools/lib/bpf/libbpf.h
> @@ -173,6 +173,9 @@ int bpf_program__set_kprobe(struct bpf_program *prog);
> bool bpf_program__is_tracepoint(struct bpf_program *prog);
> bool bpf_program__is_kprobe(struct bpf_program *prog);
>
> +int bpf_program__set_type(struct bpf_program *prog,
> + unsigned int type);
> +
Although you don't include uapi/linux/bpf.h in this patch, logically
you add this dependency.
Please continously add bpf_program__set_socket_filter() and
bpf_program__is_socket_filter() like what we do for tracepoint.
This way libbpf.h is indenpendent from kernel header.
We can use macro in both .h and .c.
Thank you.
^ permalink raw reply
* Re: [PATCH 6/8] tools lib bpf: improve warning
From: Wangnan (F) @ 2016-10-17 2:17 UTC (permalink / raw)
To: Eric Leblond, netdev; +Cc: linux-kernel, ast
In-Reply-To: <20161016211834.11732-7-eric@regit.org>
On 2016/10/17 5:18, Eric Leblond wrote:
> Signed-off-by: Eric Leblond <eric@regit.org>
Please add some commit messages.
Thank you.
> ---
> tools/lib/bpf/libbpf.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 7cd341e..1fe4532 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -802,7 +802,8 @@ bpf_object__create_maps(struct bpf_object *obj)
> size_t j;
> int err = *pfd;
>
> - pr_warning("failed to create map: %s\n",
> + pr_warning("failed to create map (name: '%s'): %s\n",
> + obj->maps[i].name,
> strerror(errno));
> for (j = 0; j < i; j++)
> zclose(obj->maps[j].fd);
^ permalink raw reply
* Re: [PATCH 5/8] tools lib bpf: add missing functions
From: Wangnan (F) @ 2016-10-17 2:16 UTC (permalink / raw)
To: Eric Leblond, netdev; +Cc: linux-kernel, ast
In-Reply-To: <20161016211834.11732-6-eric@regit.org>
On 2016/10/17 5:18, Eric Leblond wrote:
> Some functions were missing in the library to be able to use it
> in the case where the userspace is handling the maps in kernel.
>
> The patch also renames functions to have a homogeneous naming
> convention.
>
> Signed-off-by: Eric Leblond <eric@regit.org>
> ---
> tools/lib/bpf/bpf.c | 35 ++++++++++++++++++++++++++++++++++-
> tools/lib/bpf/bpf.h | 2 --
> tools/lib/bpf/libbpf.h | 5 +++++
> 3 files changed, 39 insertions(+), 3 deletions(-)
>
> diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
> index 4212ed6..c0e07bd 100644
> --- a/tools/lib/bpf/bpf.c
> +++ b/tools/lib/bpf/bpf.c
> @@ -25,6 +25,7 @@
> #include <asm/unistd.h>
> #include <linux/bpf.h>
> #include "bpf.h"
> +#include "libbpf.h"
>
> /*
> * When building perf, unistd.h is overrided. __NR_bpf is
> @@ -97,7 +98,7 @@ int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns,
> return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
> }
>
> -int bpf_map_update_elem(int fd, void *key, void *value,
> +int bpf_map__update_elem(int fd, void *key, void *value,
> u64 flags)
Please don't use '__' style API here. It is easily be confused with
bpf_map__*() in libbpf.h. They are APIs at different level.
bpf_map__*() are APIs for 'struct bpf_map's, they are object introduced
by libbpf, defined in libbpf.h. bpf_map_*() APIs operate on fd, they are
objects defined by kernel. bpf_map_*() APIs are declared in bpf.h.
In libbpf, bpf.h directly operates on kernel objects (fd), APIs in it
are named bpf_map_*(); libbpf.h operates on 'struct bpf_map' object,
APIs in it are named using bpf_map__*(). libbpf.h and bpf.h are independent
with each other.
> {
> union bpf_attr attr;
> @@ -110,3 +111,35 @@ int bpf_map_update_elem(int fd, void *key, void *value,
>
> return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
> }
> +
> +int bpf_map__lookup_elem(int fd, void *key, void *value)
> +{
> + union bpf_attr attr = {
> + .map_fd = fd,
> + .key = ptr_to_u64(key),
> + .value = ptr_to_u64(value),
> + };
> +
> + return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
> +}
> +
> +int bpf_map__delete_elem(int fd, void *key)
> +{
> + union bpf_attr attr = {
> + .map_fd = fd,
> + .key = ptr_to_u64(key),
> + };
> +
> + return sys_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
> +}
> +
> +int bpf_map__get_next_key(int fd, void *key, void *next_key)
> +{
> + union bpf_attr attr = {
> + .map_fd = fd,
> + .key = ptr_to_u64(key),
> + .next_key = ptr_to_u64(next_key),
> + };
> +
> + return sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
> +}
> diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
> index e8ba540..5ca834a 100644
> --- a/tools/lib/bpf/bpf.h
> +++ b/tools/lib/bpf/bpf.h
> @@ -33,6 +33,4 @@ int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns,
> u32 kern_version, char *log_buf,
> size_t log_buf_sz);
>
> -int bpf_map_update_elem(int fd, void *key, void *value,
> - u64 flags);
> #endif
> diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
> index a18783b..dfb46d0 100644
> --- a/tools/lib/bpf/libbpf.h
> +++ b/tools/lib/bpf/libbpf.h
> @@ -207,6 +207,11 @@ bpf_map__next(struct bpf_map *map, struct bpf_object *obj);
> int bpf_map__fd(struct bpf_map *map);
> const struct bpf_map_def *bpf_map__def(struct bpf_map *map);
> const char *bpf_map__name(struct bpf_map *map);
> +int bpf_map__update_elem(int fd, void *key, void *value,
> + uint64_t flags);
> +int bpf_map__lookup_elem(int fd, void *key, void *value);
> +int bpf_map__delete_elem(int fd, void *key);
> +int bpf_map__get_next_key(int fd, void *key, void *next_key);
As what we have discussed, the newly introduced functions should be added
in bpf.h.
Thank you.
^ permalink raw reply
* Re: [PATCH 7/8] tools lib bpf: fix maps resolution
From: Wangnan (F) @ 2016-10-17 2:23 UTC (permalink / raw)
To: Eric Leblond, netdev; +Cc: linux-kernel, ast
In-Reply-To: <20161016211834.11732-8-eric@regit.org>
On 2016/10/17 5:18, Eric Leblond wrote:
> It is not correct to assimilate the elf data of the maps section
> to an array of map definition. In fact the sizes differ. The
> offset provided in the symbol section has to be used instead.
>
> This patch fixes a bug causing a elf with two maps not to load
> correctly.
Could you please give an example so we can understand why
section 'maps' is not an array?
Thank you.
^ permalink raw reply
* [PATCH] net: Require exact match for TCP socket lookups if dif is l3mdev
From: David Ahern @ 2016-10-17 3:02 UTC (permalink / raw)
To: netdev; +Cc: eric.dumazet, David Ahern
Currently, socket lookups for l3mdev (vrf) use cases can match a socket
that is bound to a port but not a device (ie., a global socket). If the
sysctl tcp_l3mdev_accept is not set this leads to ack packets going out
based on the main table even though the packet came in from an L3 domain.
The end result is that the connection does not establish creating
confusion for users since the service is running and a socket shows in
ss output. Fix by requiring an exact dif to sk_bound_dev_if match if the
skb came through an interface enslaved to an l3mdev device and the
tcp_l3mdev_accept is not set.
skb's through an l3mdev interface are marked by setting a flag in
inet{6}_skb_parm. The IPv6 variant is already set; this patch adds the
flag for IPv4. Using an skb flag avoids a device lookup on the dif. The
flag is set in the VRF driver using the IP{6}CB macros. For IPv4, the
inet_skb_parm struct is moved in the cb per commit 971f10eca186, so the
match function in the TCP stack needs to use TCP_SKB_CB. For IPv6, the
move is done after the socket lookup, so IP6CB is used.
The flags field in inet_skb_parm struct needs to be increased to add
another flag. There is currently a 1-byte hole following the flags,
so it can be expanded to u16 without increasing the size of the struct.
Fixes: 193125dbd8eb ("net: Introduce VRF device driver")
Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
---
v4
- renamed existing skb_l3mdev_slave to ipv6_l3mdev_skb
- renamed ipv4 version ipv4_l3mdev_skb
v3
- changed the match functions to pull the skb flag from TCP_SKB_CB
rather than IPCB for IPv4 per changes from 971f10eca186. match
function is moved to tcp.h as a consequence.
- made flags a u16 versus __u16 for consistency with frag_max_size
- updated commit message
v2
- reordered the checks in inet_exact_dif_match per Eric's comment
- changed the l3mdev determination from looking up the dif to using
a flag set on the skb which is much faster
drivers/net/vrf.c | 2 ++
include/linux/ipv6.h | 17 ++++++++++++++---
include/net/ip.h | 8 +++++++-
include/net/tcp.h | 13 ++++++++++++-
net/ipv4/inet_hashtables.c | 8 +++++---
net/ipv6/inet6_hashtables.c | 7 ++++---
6 files changed, 44 insertions(+), 11 deletions(-)
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 85c271c70d42..820de6a9ddde 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -956,6 +956,7 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
if (skb->pkt_type == PACKET_LOOPBACK) {
skb->dev = vrf_dev;
skb->skb_iif = vrf_dev->ifindex;
+ IP6CB(skb)->flags |= IP6SKB_L3SLAVE;
skb->pkt_type = PACKET_HOST;
goto out;
}
@@ -996,6 +997,7 @@ static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev,
{
skb->dev = vrf_dev;
skb->skb_iif = vrf_dev->ifindex;
+ IPCB(skb)->flags |= IPSKB_L3SLAVE;
/* loopback traffic; do not push through packet taps again.
* Reset pkt_type for upper layers to process skb
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 7e9a789be5e0..ca1ad9ebbc92 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -123,12 +123,12 @@ struct inet6_skb_parm {
};
#if defined(CONFIG_NET_L3_MASTER_DEV)
-static inline bool skb_l3mdev_slave(__u16 flags)
+static inline bool ipv6_l3mdev_skb(__u16 flags)
{
return flags & IP6SKB_L3SLAVE;
}
#else
-static inline bool skb_l3mdev_slave(__u16 flags)
+static inline bool ipv6_l3mdev_skb(__u16 flags)
{
return false;
}
@@ -139,11 +139,22 @@ static inline bool skb_l3mdev_slave(__u16 flags)
static inline int inet6_iif(const struct sk_buff *skb)
{
- bool l3_slave = skb_l3mdev_slave(IP6CB(skb)->flags);
+ bool l3_slave = ipv6_l3mdev_skb(IP6CB(skb)->flags);
return l3_slave ? skb->skb_iif : IP6CB(skb)->iif;
}
+/* can not be used in TCP layer after tcp_v6_fill_cb */
+static inline bool inet6_exact_dif_match(struct net *net, struct sk_buff *skb)
+{
+#if defined(CONFIG_NET_L3_MASTER_DEV)
+ if (!net->ipv4.sysctl_tcp_l3mdev_accept &&
+ ipv6_l3mdev_skb(IP6CB(skb)->flags))
+ return true;
+#endif
+ return false;
+}
+
struct tcp6_request_sock {
struct tcp_request_sock tcp6rsk_tcp;
};
diff --git a/include/net/ip.h b/include/net/ip.h
index bc43c0fcae12..c9d07988911e 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -38,7 +38,7 @@ struct sock;
struct inet_skb_parm {
int iif;
struct ip_options opt; /* Compiled IP options */
- unsigned char flags;
+ u16 flags;
#define IPSKB_FORWARDED BIT(0)
#define IPSKB_XFRM_TUNNEL_SIZE BIT(1)
@@ -48,10 +48,16 @@ struct inet_skb_parm {
#define IPSKB_DOREDIRECT BIT(5)
#define IPSKB_FRAG_PMTU BIT(6)
#define IPSKB_FRAG_SEGS BIT(7)
+#define IPSKB_L3SLAVE BIT(8)
u16 frag_max_size;
};
+static inline bool ipv4_l3mdev_skb(u16 flags)
+{
+ return !!(flags & IPSKB_L3SLAVE);
+}
+
static inline unsigned int ip_hdrlen(const struct sk_buff *skb)
{
return ip_hdr(skb)->ihl * 4;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index f83b7f220a65..5b82d4d94834 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -794,12 +794,23 @@ struct tcp_skb_cb {
*/
static inline int tcp_v6_iif(const struct sk_buff *skb)
{
- bool l3_slave = skb_l3mdev_slave(TCP_SKB_CB(skb)->header.h6.flags);
+ bool l3_slave = ipv6_l3mdev_skb(TCP_SKB_CB(skb)->header.h6.flags);
return l3_slave ? skb->skb_iif : TCP_SKB_CB(skb)->header.h6.iif;
}
#endif
+/* TCP_SKB_CB reference means this can not be used from early demux */
+static inline bool inet_exact_dif_match(struct net *net, struct sk_buff *skb)
+{
+#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
+ if (!net->ipv4.sysctl_tcp_l3mdev_accept &&
+ ipv4_l3mdev_skb(TCP_SKB_CB(skb)->header.h4.flags))
+ return true;
+#endif
+ return false;
+}
+
/* Due to TSO, an SKB can be composed of multiple actual
* packets. To keep these tracked properly, we use this.
*/
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 77c20a489218..ca97835bfec4 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -25,6 +25,7 @@
#include <net/inet_hashtables.h>
#include <net/secure_seq.h>
#include <net/ip.h>
+#include <net/tcp.h>
#include <net/sock_reuseport.h>
static u32 inet_ehashfn(const struct net *net, const __be32 laddr,
@@ -172,7 +173,7 @@ EXPORT_SYMBOL_GPL(__inet_inherit_port);
static inline int compute_score(struct sock *sk, struct net *net,
const unsigned short hnum, const __be32 daddr,
- const int dif)
+ const int dif, bool exact_dif)
{
int score = -1;
struct inet_sock *inet = inet_sk(sk);
@@ -186,7 +187,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
return -1;
score += 4;
}
- if (sk->sk_bound_dev_if) {
+ if (sk->sk_bound_dev_if || exact_dif) {
if (sk->sk_bound_dev_if != dif)
return -1;
score += 4;
@@ -215,11 +216,12 @@ struct sock *__inet_lookup_listener(struct net *net,
unsigned int hash = inet_lhashfn(net, hnum);
struct inet_listen_hashbucket *ilb = &hashinfo->listening_hash[hash];
int score, hiscore = 0, matches = 0, reuseport = 0;
+ bool exact_dif = inet_exact_dif_match(net, skb);
struct sock *sk, *result = NULL;
u32 phash = 0;
sk_for_each_rcu(sk, &ilb->head) {
- score = compute_score(sk, net, hnum, daddr, dif);
+ score = compute_score(sk, net, hnum, daddr, dif, exact_dif);
if (score > hiscore) {
reuseport = sk->sk_reuseport;
if (reuseport) {
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 00cf28ad4565..2fd0374a35b1 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -96,7 +96,7 @@ EXPORT_SYMBOL(__inet6_lookup_established);
static inline int compute_score(struct sock *sk, struct net *net,
const unsigned short hnum,
const struct in6_addr *daddr,
- const int dif)
+ const int dif, bool exact_dif)
{
int score = -1;
@@ -109,7 +109,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
return -1;
score++;
}
- if (sk->sk_bound_dev_if) {
+ if (sk->sk_bound_dev_if || exact_dif) {
if (sk->sk_bound_dev_if != dif)
return -1;
score++;
@@ -131,11 +131,12 @@ struct sock *inet6_lookup_listener(struct net *net,
unsigned int hash = inet_lhashfn(net, hnum);
struct inet_listen_hashbucket *ilb = &hashinfo->listening_hash[hash];
int score, hiscore = 0, matches = 0, reuseport = 0;
+ bool exact_dif = inet6_exact_dif_match(net, skb);
struct sock *sk, *result = NULL;
u32 phash = 0;
sk_for_each(sk, &ilb->head) {
- score = compute_score(sk, net, hnum, daddr, dif);
+ score = compute_score(sk, net, hnum, daddr, dif, exact_dif);
if (score > hiscore) {
reuseport = sk->sk_reuseport;
if (reuseport) {
--
2.1.4
^ permalink raw reply related
* [RFC PATCH v3 1/2] L2TP:Adjust intf MTU,factor underlay L3,overlay L2
From: R. Parameswaran @ 2016-10-17 4:05 UTC (permalink / raw)
To: James Chapman
Cc: R Parameswaran, kleptog, netdev, davem, linux-kernel, nprachan,
Robert Shearman, dfawcus, stephen, acme, lboccass, bhong
In-Reply-To: <52890af4-38d6-6aa7-a9e0-69be60fe89fa@katalix.com>
[v3: Picked up review comments from James Chapman, added a
function to compute ip header + ip option overhead on a socket, and factored
it into L2TP change-set, RFC, would like early feedback on name and
placement, and logic of new function while I test this]
>From 30c4b3900d09deb912fc6ce4af3c19e870f84e14 Mon Sep 17 00:00:00 2001
From: "R. Parameswaran" <rparames@brocade.com>
Date: Sun, 16 Oct 2016 20:19:38 -0700
In existing kernel code, when setting up the L2TP interface, all of the
tunnel encapsulation headers are not taken into account when setting
up the MTU on the L2TP logical interface device. Due to this, the
packets created by the applications on top of the L2TP layer are larger
than they ought to be, relative to the underlay MTU, which leads to
needless fragmentation once the L2TP packet is encapsulated in an outer IP
packet.
Specifically, the MTU calculation does not take into account the (outer)
IP header imposed on the encapsulated L2TP packet, and the Layer 2 header
imposed on the inner L2TP packet prior to encapsulation. The patch posted
here takes care of these.
Existing code also seems to assume an Ethernet (non-jumbo) underlay. The
patch uses the PMTU mechanism and the dst entry in the L2TP tunnel socket
to directly pull up the underlay MTU (as the baseline number on top of
which the encapsulation headers are factored in). Ethernet MTU is
assumed as a fallback only if this fails.
Picked up review comments from James Chapman, added a function
to compute ip header + ip option overhead on a socket, and factored it
into L2TP change-set.
Signed-off-by: nprachan@brocade.com,
Signed-off-by: bhong@brocade.com,
Signed-off-by: rshearma@brocade.com,
Signed-off-by: dfawcus@brocade.com
---
include/linux/net.h | 3 +++
net/socket.c | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 40 insertions(+)
diff --git a/include/linux/net.h b/include/linux/net.h
index cd0c8bd..2c8b092 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -298,6 +298,9 @@ int kernel_sendpage(struct socket *sock, struct page *page, int offset,
int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg);
int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how);
+/* Following routine returns the IP overhead imposed by a socket. */
+u32 kernel_sock_ip_overhead(struct sock *sk);
+
#define MODULE_ALIAS_NETPROTO(proto) \
MODULE_ALIAS("net-pf-" __stringify(proto))
diff --git a/net/socket.c b/net/socket.c
index 5a9bf5e..d5e79c2 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -3293,3 +3293,40 @@ int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
return sock->ops->shutdown(sock, how);
}
EXPORT_SYMBOL(kernel_sock_shutdown);
+
+/*
+ * This routine returns the IP overhead imposed by a socket i.e.
+ * the length of the underlying IP header, depending on whether
+ * this is an IPv4 or IPv6 socket and the length from IP options turned
+ * on at the socket.
+ */
+u32 kernel_sock_ip_overhead(struct sock *sk)
+{
+ u32 overhead = 0;
+ if (!sk)
+ goto done;
+ if (sk->sk_family == AF_INET) {
+ struct ip_options_rcu *opt = NULL;
+ struct inet_sock *inet = inet_sk(sk);
+ overhead += sizeof(struct iphdr);
+ if (inet)
+ opt = rcu_dereference_protected(inet->inet_opt,
+ sock_owned_by_user(sk));
+ if (opt)
+ overhead += opt->opt.optlen;
+ }
+ else if (sk->sk_family == AF_INET6) {
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct ipv6_txoptions *opt = NULL;
+ overhead += sizeof(struct ipv6hdr);
+ if (np)
+ opt = rcu_dereference_protected(np->opt,
+ sock_owned_by_user(sk));
+ if (opt)
+ overhead += (opt->opt_flen + opt->opt_nflen);
+ }
+
+done:
+ return overhead;
+}
+EXPORT_SYMBOL_GPL(kernel_sock_ip_overhead);
--
2.1.4
----
On Tue, 11 Oct 2016, James Chapman wrote:
>
> I think keep it simple. A function to return the size of the IP header
> associated with any IP socket, not necessarily a tunnel socket. Don't
> mix in any MTU derivation logic or UDP header size etc.
>
> Post code early as an RFC. You're more likely to get review feedback
> from others.
>
>
>
>
^ permalink raw reply related
* [PATCH net-next] ila: Don't use dest cache when gateway is set
From: Tom Herbert @ 2016-10-17 4:25 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
If the gateway is set on an ILA route we don't need to bother with using
the destination cache in the ILA route. Translation does not change the
routing in this case so we can stick with orig_output in the lwstate
output function.
Tested: Ran netperf with and without gateway for LWT route.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
net/ipv6/ila/ila_lwt.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c
index d0a98d9..9fafba6 100644
--- a/net/ipv6/ila/ila_lwt.c
+++ b/net/ipv6/ila/ila_lwt.c
@@ -36,6 +36,7 @@ static inline struct ila_params *ila_params_lwtunnel(
static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct dst_entry *orig_dst = skb_dst(skb);
+ struct rt6_info *rt = (struct rt6_info *)orig_dst;
struct ila_lwt *ilwt = ila_lwt_lwtunnel(orig_dst->lwtstate);
struct dst_entry *dst;
int err = -EINVAL;
@@ -46,6 +47,13 @@ static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb)
ila_update_ipv6_locator(skb, ila_params_lwtunnel(orig_dst->lwtstate),
true);
+ if (rt->rt6i_flags & (RTF_GATEWAY | RTF_CACHE)) {
+ /* Already have a next hop address in route, no need for
+ * dest cache route.
+ */
+ return orig_dst->lwtstate->orig_output(net, sk, skb);
+ }
+
dst = dst_cache_get(&ilwt->dst_cache);
if (unlikely(!dst)) {
struct ipv6hdr *ip6h = ipv6_hdr(skb);
--
2.9.3
^ permalink raw reply related
* [RFC PATCH v3 2/2] L2TP:Adjust intf MTU,factor underlay L3,overlay L2
From: R. Parameswaran @ 2016-10-17 5:20 UTC (permalink / raw)
To: James Chapman
Cc: R Parameswaran, kleptog, netdev, davem, linux-kernel, nprachan,
Robert Shearman, dfawcus, stephen, acme, lboccass, bhong
In-Reply-To: <52890af4-38d6-6aa7-a9e0-69be60fe89fa@katalix.com>
[v3: Picked up review comments from James Chapman, added a
function to compute ip header + ip option overhead on a socket, and factored
it into L2TP change-set, RFC, would like early feedback on name and
placement of new function while I test this.
Part 2/2: Changes in l2tp_eth.c, using the new API from part 1]
>From f4066da53e781ef167055c1e89ca1a7819215a40 Mon Sep 17 00:00:00 2001
From: "R. Parameswaran" <rparames@brocade.com>
Date: Sun, 16 Oct 2016 20:27:20 -0700
In existing kernel code, when setting up the L2TP interface, all of the
tunnel encapsulation headers are not taken into account when setting
up the MTU on the L2TP logical interface device. Due to this, the
packets created by the applications on top of the L2TP layer are larger
than they ought to be, relative to the underlay MTU, which leads to
needless fragmentation once the L2TP packet is encapsulated in an outer IP
packet.
Specifically, the MTU calculation does not take into account the (outer)
IP header imposed on the encapsulated L2TP packet, and the Layer 2 header
imposed on the inner L2TP packet prior to encapsulation. The patch posted
here takes care of these.
Existing code also seems to assume an Ethernet (non-jumbo) underlay. The
patch uses the PMTU mechanism and the dst entry in the L2TP tunnel socket
to directly pull up the underlay MTU (as the baseline number on top of
which the encapsulation headers are factored in). Ethernet MTU is
assumed as a fallback only if this fails.
Picked up review comments from James Chapman, added a function
to compute ip header + ip option overhead on a socket, and factored it
into L2TP change-set.
Signed-off-by: nprachan@brocade.com,
Signed-off-by: bhong@brocade.com,
Signed-off-by: rshearma@brocade.com,
Signed-off-by: dfawcus@brocade.com
---
net/l2tp/l2tp_eth.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 47 insertions(+), 4 deletions(-)
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c
index 965f7e3..75eb5d3 100644
--- a/net/l2tp/l2tp_eth.c
+++ b/net/l2tp/l2tp_eth.c
@@ -30,6 +30,9 @@
#include <net/xfrm.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/udp.h>
#include "l2tp_core.h"
@@ -206,6 +209,49 @@ static void l2tp_eth_show(struct seq_file *m, void *arg)
}
#endif
+static void l2tp_eth_adjust_mtu(struct l2tp_tunnel *tunnel,
+ struct l2tp_session *session,
+ struct net_device *dev)
+{
+ unsigned int overhead = 0;
+ struct dst_entry *dst;
+ u32 l3_overhead = 0;
+
+ if (session->mtu != 0) {
+ dev->mtu = session->mtu;
+ dev->needed_headroom += session->hdr_len;
+ if (tunnel->encap == L2TP_ENCAPTYPE_UDP)
+ dev->needed_headroom += sizeof(struct udphdr);
+ return;
+ }
+ overhead = session->hdr_len;
+ l3_overhead = kernel_sock_ip_overhead(tunnel->sock);
+ if (!tunnel->sock || (l3_overhead == 0)) {
+ /* L3 Overhead couldn't be identified, dev mtu stays at 1500 */
+ return;
+ }
+ /* Adjust MTU, factor overhead - underlay L3, overlay L2 hdr*/
+ overhead += ETH_HLEN + l3_overhead;
+ /* Additionally, if the encap is UDP, account for UDP header size */
+ if (tunnel->encap == L2TP_ENCAPTYPE_UDP)
+ overhead += sizeof(struct udphdr);
+ /* If PMTU discovery was enabled, use discovered MTU on L2TP device */
+ dst = sk_dst_get(tunnel->sock);
+ if (dst) {
+ /* dst_mtu will use PMTU if found, else fallback to intf MTU */
+ u32 pmtu = dst_mtu(dst);
+
+ if (pmtu != 0)
+ dev->mtu = pmtu;
+ dst_release(dst);
+ }
+ session->mtu = dev->mtu - overhead;
+ dev->mtu = session->mtu;
+ dev->needed_headroom += session->hdr_len;
+ if (tunnel->encap == L2TP_ENCAPTYPE_UDP)
+ dev->needed_headroom += sizeof(struct udphdr);
+}
+
static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg)
{
struct net_device *dev;
@@ -255,11 +301,8 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p
}
dev_net_set(dev, net);
- if (session->mtu == 0)
- session->mtu = dev->mtu - session->hdr_len;
- dev->mtu = session->mtu;
- dev->needed_headroom += session->hdr_len;
+ l2tp_eth_adjust_mtu(tunnel, session, dev);
priv = netdev_priv(dev);
priv->dev = dev;
priv->session = session;
--
2.1.4
----
>
> I think keep it simple. A function to return the size of the IP header
> associated with any IP socket, not necessarily a tunnel socket. Don't
> mix in any MTU derivation logic or UDP header size etc.
>
> Post code early as an RFC. You're more likely to get review feedback
> from others.
>
>
>
>
^ permalink raw reply related
* [PATCH 1/2] dwc_eth_qos: do not clear pause flags from phy_device->supported
From: Niklas Cassel @ 2016-10-17 6:25 UTC (permalink / raw)
To: larper, netdev; +Cc: linux-kernel, Niklas Cassel
From: Niklas Cassel <niklas.cassel@axis.com>
phy_device->supported is originally set by the PHY driver.
The ethernet driver should filter phy_device->supported to only contain
flags supported by the IP.
The IP supports setting rx and tx flow control independently,
therefore SUPPORTED_Pause and SUPPORTED_Asym_Pause should not be cleared.
If the flags are cleared, pause frames cannot be enabled (even if they
are supported by the PHY).
Signed-off-by: Niklas Cassel <niklas.cassel@axis.com>
Signed-off-by: Lars Persson <larper@axis.com>
---
drivers/net/ethernet/synopsys/dwc_eth_qos.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/synopsys/dwc_eth_qos.c b/drivers/net/ethernet/synopsys/dwc_eth_qos.c
index c9891eac9775..93a3a919f723 100644
--- a/drivers/net/ethernet/synopsys/dwc_eth_qos.c
+++ b/drivers/net/ethernet/synopsys/dwc_eth_qos.c
@@ -985,7 +985,8 @@ static int dwceqos_mii_probe(struct net_device *ndev)
"phydev %p, phydev->phy_id 0xa%x, phydev->addr 0x%x\n",
phydev, phydev->phy_id, phydev->addr);
- phydev->supported &= PHY_GBIT_FEATURES;
+ phydev->supported &= PHY_GBIT_FEATURES | SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause;
lp->link = 0;
lp->speed = 0;
--
2.1.4
^ permalink raw reply related
* [PATCH 2/2] dwc_eth_qos: enable flow control by default
From: Niklas Cassel @ 2016-10-17 6:26 UTC (permalink / raw)
To: larper, netdev; +Cc: linux-kernel, Niklas Cassel
From: Niklas Cassel <niklas.cassel@axis.com>
Allow autoneg to enable flow control by default.
The behavior when autoneg is off has not changed.
Signed-off-by: Niklas Cassel <niklas.cassel@axis.com>
Signed-off-by: Lars Persson <larper@axis.com>
---
drivers/net/ethernet/synopsys/dwc_eth_qos.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/synopsys/dwc_eth_qos.c b/drivers/net/ethernet/synopsys/dwc_eth_qos.c
index 93a3a919f723..8e39295427c0 100644
--- a/drivers/net/ethernet/synopsys/dwc_eth_qos.c
+++ b/drivers/net/ethernet/synopsys/dwc_eth_qos.c
@@ -992,6 +992,7 @@ static int dwceqos_mii_probe(struct net_device *ndev)
lp->speed = 0;
lp->duplex = DUPLEX_UNKNOWN;
lp->phy_dev = phydev;
+ lp->flowcontrol.autoneg = AUTONEG_ENABLE;
if (netif_msg_probe(lp)) {
netdev_dbg(lp->ndev, "phy_addr 0x%x, phy_id 0x%08x\n",
--
2.1.4
^ permalink raw reply related
* [PATCH] ethtool: add register dump support for fjes driver
From: Taku Izumi @ 2016-10-17 7:04 UTC (permalink / raw)
To: linville, netdev; +Cc: Taku
From: Taku <izumi.taku@jp.fujitsu.com>
This patch adds the register dump format for FUJITSU Extended
Network device like the following:
# ethtool -d es0
0x0000: OWNER_EPID (Owner EPID) 0x00000001
0x0004: MAX_EP (Maximum EP) 0x00000008
0x0010: DCTL (Device Control) 0x00000000
0x0020: CR (Command request) 0x80000002
0x0024: CS (Command status) 0x80000002
0x0028: SHSTSAL (Share status address Low) 0xE8215304
0x002C: SHSTSAH (Share status address High) 0x00000007
0x0034: REQBL (Request Buffer length) 0x00008028
0x0038: REQBAL (Request Buffer Address Low) 0xEB0A0000
0x003C: REQBAH (Request Buffer Address High) 0x00000007
0x0044: RESPBL (Response Buffer Length) 0x00000018
0x0048: RESPBAL (Response Buffer Address Low) 0xE41E1220
0x004C: RESPBAH (Response Buffer Address High) 0x00000007
0x0080: IS (Interrupt status) 0x00000000
0x0084: IMS (Interrupt mask set) 0x7FE00000
0x0088: IMC (Interrupt mask clear) 0x001F0000
0x008C: IG (Interrupt generator) 0x00010000
0x0090: ICTL (Interrupt control) 0x00000000
Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
---
Makefile.am | 2 +-
ethtool.c | 1 +
fjes.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
internal.h | 2 ++
4 files changed, 93 insertions(+), 1 deletion(-)
create mode 100644 fjes.c
diff --git a/Makefile.am b/Makefile.am
index de2db2e..edbda57 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,7 +14,7 @@ ethtool_SOURCES += \
pcnet32.c realtek.c tg3.c marvell.c vioc.c \
smsc911x.c at76c50x-usb.c sfc.c stmmac.c \
sff-common.c sff-common.h sfpid.c sfpdiag.c \
- ixgbevf.c tse.c vmxnet3.c qsfp.c qsfp.h
+ ixgbevf.c tse.c vmxnet3.c qsfp.c qsfp.h fjes.c
endif
TESTS = test-cmdline test-features
diff --git a/ethtool.c b/ethtool.c
index 49ac94e..75299c6 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -1136,6 +1136,7 @@ static const struct {
{ "et131x", et131x_dump_regs },
{ "altera_tse", altera_tse_dump_regs },
{ "vmxnet3", vmxnet3_dump_regs },
+ { "fjes", fjes_dump_regs },
#endif
};
diff --git a/fjes.c b/fjes.c
new file mode 100644
index 0000000..52f7c28
--- /dev/null
+++ b/fjes.c
@@ -0,0 +1,89 @@
+/* Copyright (c) 2016 FUJITSU LIMITED */
+#include <stdio.h>
+#include "internal.h"
+
+int fjes_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+{
+ u32 *regs_buff = (u32 *)regs->data;
+
+ if (regs->version != 1)
+ return -1;
+
+ /* Information registers */
+ fprintf(stdout,
+ "0x0000: OWNER_EPID (Owner EPID) 0x%08X\n",
+ regs_buff[0]);
+
+ fprintf(stdout,
+ "0x0004: MAX_EP (Maximum EP) 0x%08X\n",
+ regs_buff[1]);
+
+ /* Device Control registers */
+ fprintf(stdout,
+ "0x0010: DCTL (Device Control) 0x%08X\n",
+ regs_buff[4]);
+
+ /* Command Control registers */
+ fprintf(stdout,
+ "0x0020: CR (Command request) 0x%08X\n",
+ regs_buff[8]);
+
+ fprintf(stdout,
+ "0x0024: CS (Command status) 0x%08X\n",
+ regs_buff[9]);
+
+ fprintf(stdout,
+ "0x0028: SHSTSAL (Share status address Low) 0x%08X\n",
+ regs_buff[10]);
+
+ fprintf(stdout,
+ "0x002C: SHSTSAH (Share status address High) 0x%08X\n",
+ regs_buff[11]);
+
+ fprintf(stdout,
+ "0x0034: REQBL (Request Buffer length) 0x%08X\n",
+ regs_buff[13]);
+
+ fprintf(stdout,
+ "0x0038: REQBAL (Request Buffer Address Low) 0x%08X\n",
+ regs_buff[14]);
+
+ fprintf(stdout,
+ "0x003C: REQBAH (Request Buffer Address High) 0x%08X\n",
+ regs_buff[15]);
+
+ fprintf(stdout,
+ "0x0044: RESPBL (Response Buffer Length) 0x%08X\n",
+ regs_buff[17]);
+
+ fprintf(stdout,
+ "0x0048: RESPBAL (Response Buffer Address Low) 0x%08X\n",
+ regs_buff[18]);
+
+ fprintf(stdout,
+ "0x004C: RESPBAH (Response Buffer Address High) 0x%08X\n",
+ regs_buff[19]);
+
+ /* Interrupt Control registers */
+ fprintf(stdout,
+ "0x0080: IS (Interrupt status) 0x%08X\n",
+ regs_buff[32]);
+
+ fprintf(stdout,
+ "0x0084: IMS (Interrupt mask set) 0x%08X\n",
+ regs_buff[33]);
+
+ fprintf(stdout,
+ "0x0088: IMC (Interrupt mask clear) 0x%08X\n",
+ regs_buff[34]);
+
+ fprintf(stdout,
+ "0x008C: IG (Interrupt generator) 0x%08X\n",
+ regs_buff[35]);
+
+ fprintf(stdout,
+ "0x0090: ICTL (Interrupt control) 0x%08X\n",
+ regs_buff[36]);
+
+ return 0;
+}
diff --git a/internal.h b/internal.h
index 3c08b74..4e658ea 100644
--- a/internal.h
+++ b/internal.h
@@ -348,4 +348,6 @@ void sff8472_show_all(const __u8 *id);
/* QSFP Optics diagnostics */
void sff8636_show_all(const __u8 *id, __u32 eeprom_len);
+/* FUJITSU Extended Socket network device */
+int fjes_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
#endif /* ETHTOOL_INTERNAL_H__ */
--
1.9.1
^ permalink raw reply related
* [PATCH] net: hip04: Remove superfluous ether_setup after alloc_etherdev
From: Tobias Klauser @ 2016-10-17 7:22 UTC (permalink / raw)
To: Yisen Zhuang, Salil Mehta; +Cc: netdev
There is no need to call ether_setup after alloc_ethdev since it was
already called there.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
---
drivers/net/ethernet/hisilicon/hip04_eth.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c
index 3c99ca420f57..854befde0a08 100644
--- a/drivers/net/ethernet/hisilicon/hip04_eth.c
+++ b/drivers/net/ethernet/hisilicon/hip04_eth.c
@@ -897,7 +897,6 @@ static int hip04_mac_probe(struct platform_device *pdev)
INIT_WORK(&priv->tx_timeout_task, hip04_tx_timeout_task);
- ether_setup(ndev);
ndev->netdev_ops = &hip04_netdev_ops;
ndev->ethtool_ops = &hip04_ethtool_ops;
ndev->watchdog_timeo = TX_TIMEOUT;
--
2.9.0
^ permalink raw reply related
* Re: [PATCH] crypto: ccm - avoid scatterlist for MAC encryption
From: Johannes Berg @ 2016-10-17 7:28 UTC (permalink / raw)
To: Ard Biesheuvel, luto, sergey.senozhatsky.work, netdev, herbert,
davem, linux-wireless, linux-kernel, j
In-Reply-To: <1476551776-8099-1-git-send-email-ard.biesheuvel@linaro.org>
On Sat, 2016-10-15 at 18:16 +0100, Ard Biesheuvel wrote:
> The CCM code goes out of its way to perform the CTR encryption of the
> MAC using the subordinate CTR driver. To this end, it tweaks the
> input and output scatterlists so the aead_req 'odata' and/or
> 'auth_tag' fields [which may live on the stack] are prepended to the
> CTR payload. This involves calling sg_set_buf() on addresses which
> are not direct mapped, which is not supported.
> Since the calculation of the MAC keystream involves a single call
> into the cipher, to which we have a handle already given that the
> CBC-MAC calculation uses it as well, just calculate the MAC keystream
> directly, and record it in the aead_req private context so we can
> apply it to the MAC in cypto_ccm_auth_mac(). This greatly simplifies
> the scatterlist manipulation, and no longer requires scatterlists to
> refer to buffers that may live on the stack.
No objection from me, Herbert?
I'm getting a bit nervous though - I'd rather have any fix first so
people get things working again - so maybe I'll apply your other patch
and mine first, and then we can replace yours by this later.
johannes
^ permalink raw reply
* Re: [PATCH net-next 1/2] net: phy: Add Speed downshift set driver for Microsemi PHYs.
From: Raju Lakkaraju @ 2016-10-17 7:31 UTC (permalink / raw)
To: Andrew Lunn; +Cc: netdev, devicetree, f.fainelli, Allan.Nielsen
In-Reply-To: <20161014121232.GH5822@lunn.ch>
Hi Andrew,
Thank you for code review and comments.
On Fri, Oct 14, 2016 at 02:12:32PM +0200, Andrew Lunn wrote:
> EXTERNAL EMAIL
>
>
> On Fri, Oct 14, 2016 at 05:10:32PM +0530, Raju Lakkaraju wrote:
> > From: Raju Lakkaraju <Raju.Lakkaraju@microsemi.com>
> >
> > For operation in cabling environments that are incompatible with
> > 1000BAST-T, VSC8531 device provides an automatic link speed
> > downshift operation. When enabled, the device automatically changes
> > its 1000BAST-T auto-negotiation to the next slower speed after
> > a configured number of failed attempts at 1000BAST-T.
> > This feature is useful in setting up in networks using older cable
> > installations that include only pairs A and B, and not pairs C and D.
>
> Any reason not to just turn this on by default when auto-neg is
> enabled?
>
Downshift can enable by default when auto-neg enabled. This is good idea.
But we would like to provide option to customer can choose whether this
feature need to enable or disable and also configure failure attempts.
Do you have any other suggestion how to configure failure attempts?
> Andrew
---
Thanks,
Raju.
^ permalink raw reply
* Re: [PATCH] crypto: ccm - avoid scatterlist for MAC encryption
From: Ard Biesheuvel @ 2016-10-17 7:37 UTC (permalink / raw)
To: Johannes Berg
Cc: Andy Lutomirski, Sergey Senozhatsky,
<netdev@vger.kernel.org>, Herbert Xu, David S. Miller,
<linux-wireless@vger.kernel.org>,
linux-kernel@vger.kernel.org, Jouni Malinen
In-Reply-To: <1476689310.19992.1.camel@sipsolutions.net>
On 17 October 2016 at 08:28, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Sat, 2016-10-15 at 18:16 +0100, Ard Biesheuvel wrote:
>> The CCM code goes out of its way to perform the CTR encryption of the
>> MAC using the subordinate CTR driver. To this end, it tweaks the
>> input and output scatterlists so the aead_req 'odata' and/or
>> 'auth_tag' fields [which may live on the stack] are prepended to the
>> CTR payload. This involves calling sg_set_buf() on addresses which
>> are not direct mapped, which is not supported.
>
>> Since the calculation of the MAC keystream involves a single call
>> into the cipher, to which we have a handle already given that the
>> CBC-MAC calculation uses it as well, just calculate the MAC keystream
>> directly, and record it in the aead_req private context so we can
>> apply it to the MAC in cypto_ccm_auth_mac(). This greatly simplifies
>> the scatterlist manipulation, and no longer requires scatterlists to
>> refer to buffers that may live on the stack.
>
> No objection from me, Herbert?
>
> I'm getting a bit nervous though - I'd rather have any fix first so
> people get things working again - so maybe I'll apply your other patch
> and mine first, and then we can replace yours by this later.
>
Could we get a statement first whether it is supported to allocate
aead_req (and other crypto req structures) on the stack? If not, then
we have our work cut out for us. But if it is, I'd rather we didn't
apply the kzalloc/kfree patch, since it is just a workaround for the
broken generic CCM driver, for which a fix is already available.
Also, regarding your __percpu patch: those are located in the vmalloc
area as well, at least on arm64, and likely other architectures too.
^ permalink raw reply
* Re: hello
From: Alexander Alemayhu @ 2016-10-17 7:47 UTC (permalink / raw)
To: maowenan; +Cc: netdev
In-Reply-To: <194bc755-9984-2df7-c7d5-632d58c84d05@huawei.com>
On Fri, Oct 14, 2016 at 05:18:10PM +0800, maowenan wrote:
> i want to subscribe this mail, thank you very much.
>
Try sending subscribe netdev to majordomo@vger.kernel.org
^ permalink raw reply
* Re: [PATCH] crypto: ccm - avoid scatterlist for MAC encryption
From: Johannes Berg @ 2016-10-17 7:47 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Andy Lutomirski, Sergey Senozhatsky,
<netdev@vger.kernel.org>, Herbert Xu, David S. Miller,
<linux-wireless@vger.kernel.org>,
linux-kernel@vger.kernel.org, Jouni Malinen
In-Reply-To: <CAKv+Gu_P-6sHW3t7tp1N+3v9ZGqWcQrzMZkASY5g=QR76KN4wg@mail.gmail.com>
On Mon, 2016-10-17 at 08:37 +0100, Ard Biesheuvel wrote:
>
> Could we get a statement first whether it is supported to allocate
> aead_req (and other crypto req structures) on the stack?
Well, we haven't heard from Herbert :)
> If not, then
> we have our work cut out for us. But if it is, I'd rather we didn't
> apply the kzalloc/kfree patch, since it is just a workaround for the
> broken generic CCM driver, for which a fix is already available.
Yeah but I can't apply it. I just fixed up your kzalloc patch to also
handle GCM and GMAC, and to have error checking. Will send it in a
minute.
> Also, regarding your __percpu patch: those are located in the vmalloc
> area as well, at least on arm64, and likely other architectures too.
Crap. Any other bright ideas?
johannes
^ permalink raw reply
* Re: Hello
From: Alexander Alemayhu @ 2016-10-17 7:48 UTC (permalink / raw)
To: yuehaibing; +Cc: netdev
In-Reply-To: <c76dd0ee-c150-f7a5-2da5-42883c420b5b@huawei.com>
On Fri, Oct 14, 2016 at 05:17:36PM +0800, yuehaibing wrote:
> subscribe linux-kernel
>
Try sending subscribe linux-kernel to majordomo@vger.kernel.org
^ permalink raw reply
* [PATCH] mac80211: move struct aead_req off the stack
From: Johannes Berg @ 2016-10-17 7:49 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>
---
net/mac80211/aes_ccm.c | 34 +++++++++++++++++++---------------
net/mac80211/aes_ccm.h | 6 +++---
net/mac80211/aes_gcm.c | 33 +++++++++++++++++++--------------
net/mac80211/aes_gcm.h | 4 ++--
net/mac80211/aes_gmac.c | 12 +++++++-----
net/mac80211/wpa.c | 12 ++++--------
6 files changed, 54 insertions(+), 47 deletions(-)
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
index 7663c28ba353..cd2f10744238 100644
--- a/net/mac80211/aes_ccm.c
+++ b/net/mac80211/aes_ccm.c
@@ -18,18 +18,15 @@
#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 = kzalloc(sizeof(struct aead_request) +
+ crypto_aead_reqsize(tfm), GFP_ATOMIC);
sg_init_table(sg, 3);
sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
@@ -41,6 +38,8 @@ void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
aead_request_set_ad(aead_req, sg[0].length);
crypto_aead_encrypt(aead_req);
+ kfree(aead_req);
+ return 0;
}
int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
@@ -48,15 +47,16 @@ 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 = kzalloc(sizeof(struct aead_request) +
+ crypto_aead_reqsize(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));
@@ -67,7 +67,11 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
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);
+
+ kfree(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..2bd715df512f 100644
--- a/net/mac80211/aes_gcm.c
+++ b/net/mac80211/aes_gcm.c
@@ -15,17 +15,16 @@
#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 = kzalloc(sizeof(struct aead_request) +
+ crypto_aead_reqsize(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));
@@ -37,21 +36,23 @@ void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
aead_request_set_ad(aead_req, sg[0].length);
crypto_aead_encrypt(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 = kzalloc(sizeof(struct aead_request) +
+ crypto_aead_reqsize(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));
@@ -63,7 +64,11 @@ int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
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);
+
+ kfree(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 43ba5ecaaaa3..bb7f7449d3e9 100644
--- a/net/mac80211/aes_gmac.c
+++ b/net/mac80211/aes_gmac.c
@@ -24,16 +24,16 @@ int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
const u8 *data, size_t data_len, u8 *mic, u8 *zero)
{
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 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 = kzalloc(sizeof(struct aead_request) +
+ crypto_aead_reqsize(tfm), GFP_ATOMIC);
+ if (!aead_req)
+ return -ENOMEM;
memset(zero, 0, GMAC_MIC_LEN);
sg_init_table(sg, 4);
@@ -52,6 +52,8 @@ int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
crypto_aead_encrypt(aead_req);
+ kfree(aead_req);
+
return 0;
}
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index c02634c4210c..3a83a6763664 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -466,10 +466,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);
}
@@ -712,10 +710,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
* Re: [PATCH] crypto: ccm - avoid scatterlist for MAC encryption
From: Ard Biesheuvel @ 2016-10-17 7:50 UTC (permalink / raw)
To: Johannes Berg
Cc: Andy Lutomirski, Sergey Senozhatsky,
<netdev@vger.kernel.org>, Herbert Xu, David S. Miller,
<linux-wireless@vger.kernel.org>,
linux-kernel@vger.kernel.org, Jouni Malinen
In-Reply-To: <1476690478.19992.4.camel@sipsolutions.net>
On 17 October 2016 at 08:47, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Mon, 2016-10-17 at 08:37 +0100, Ard Biesheuvel wrote:
>>
>> Could we get a statement first whether it is supported to allocate
>> aead_req (and other crypto req structures) on the stack?
>
> Well, we haven't heard from Herbert :)
>
>> If not, then
>> we have our work cut out for us. But if it is, I'd rather we didn't
>> apply the kzalloc/kfree patch, since it is just a workaround for the
>> broken generic CCM driver, for which a fix is already available.
>
> Yeah but I can't apply it. I just fixed up your kzalloc patch to also
> handle GCM and GMAC, and to have error checking. Will send it in a
> minute.
>
I just realised that patch should probably use
aead_request_alloc/aead_request_free [and drop the memset]. That also
fixes the latent bug where the alignment of the req ctx is not take
into account.
>> Also, regarding your __percpu patch: those are located in the vmalloc
>> area as well, at least on arm64, and likely other architectures too.
>
> Crap. Any other bright ideas?
>
kmem_cache_create() and kmem_cache_alloc()
^ permalink raw reply
* Re: [PATCH] crypto: ccm - avoid scatterlist for MAC encryption
From: Johannes Berg @ 2016-10-17 7:57 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Andy Lutomirski, Sergey Senozhatsky,
<netdev@vger.kernel.org>, Herbert Xu, David S. Miller,
<linux-wireless@vger.kernel.org>,
linux-kernel@vger.kernel.org, Jouni Malinen
In-Reply-To: <CAKv+Gu9EPAF+Oihz0tXCqWURGom-wgSPCMp0dEHHnxqw-pYYJw@mail.gmail.com>
On Mon, 2016-10-17 at 08:50 +0100, Ard Biesheuvel wrote:
> I just realised that patch should probably use
> aead_request_alloc/aead_request_free [and drop the memset]. That also
> fixes the latent bug where the alignment of the req ctx is not take
> into account.
Good point, I'll fix that up.
> >
> > >
> > > Also, regarding your __percpu patch: those are located in the
> > > vmalloc
> > > area as well, at least on arm64, and likely other architectures
> > > too.
> >
> > Crap. Any other bright ideas?
> >
>
> kmem_cache_create() and kmem_cache_alloc()
for the aad/b0/j0/etc? Hmm. Yeah I guess we should do those dynamically
as well then.
johannes
^ permalink raw reply
* Re: linux-4.9-rc1/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c:1561: poor error checking ?
From: Luca Coelho @ 2016-10-17 7:58 UTC (permalink / raw)
To: David Binderman,
johannes.berg-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
emmanuel.grumbach-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
linuxwifi-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
kvalo-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org,
linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <VI1PR08MB1022786893DC435E1A71F3069CD00-Rgw4eRhbCXnvbuUDGEufgykoKrxaZxrJvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
Hi David,
On Mon, 2016-10-17 at 07:40 +0000, David Binderman wrote:
> Hello there,
>
> linux-4.9-rc1/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c:1561]: (style) Checking if unsigned variable 'len' is less than zero.
>
> Source code is
>
> len = min((size_t)le32_to_cpu(rsp->len) << 2,
> iwl_rx_packet_payload_len(hcmd.resp_pkt) - sizeof(*rsp));
> len = min(len - delta, count);
> if (len < 0) {
> ret = -EFAULT;
> goto out;
> }
>
> Suggest improve error checking.
Thanks for reporting! A fix for this is already queued in our internal
tree and will be sent upstream soon.
--
Cheers,
Luca.
^ permalink raw reply
* [PATCH v2] mac80211: move struct aead_req off the stack
From: Johannes Berg @ 2016-10-17 8:01 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>
---
net/mac80211/aes_ccm.c | 34 +++++++++++++++++++---------------
net/mac80211/aes_ccm.h | 6 +++---
net/mac80211/aes_gcm.c | 31 +++++++++++++++++--------------
net/mac80211/aes_gcm.h | 4 ++--
net/mac80211/aes_gmac.c | 10 +++++-----
net/mac80211/wpa.c | 12 ++++--------
6 files changed, 50 insertions(+), 47 deletions(-)
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
index 7663c28ba353..5c9fe00be6cc 100644
--- a/net/mac80211/aes_ccm.c
+++ b/net/mac80211/aes_ccm.c
@@ -18,18 +18,16 @@
#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));
@@ -41,6 +39,9 @@ void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
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,15 +49,15 @@ 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));
@@ -67,7 +68,10 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
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..aa8eb2718bc1 100644
--- a/net/mac80211/aes_gcm.c
+++ b/net/mac80211/aes_gcm.c
@@ -15,17 +15,15 @@
#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));
@@ -37,21 +35,23 @@ void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
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));
@@ -63,7 +63,10 @@ int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
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..15cfcebf0884 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);
@@ -52,6 +51,7 @@ int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
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
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox