Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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


Steffen Klassert says:

====================
pull request (net): ipsec 2017-06-23

1) Fix xfrm garbage collecting when unregistering a netdevice.
   From Hangbin Liu.

2) Fix NULL pointer derefernce when exiting a network namespace.
   From Hangbin Liu.

3) Fix some error codes in pfkey to prevent a NULL pointer derefernce.
   From Dan Carpenter.

4) Fix NULL pointer derefernce on allocation failure in pfkey.
   From Dan Carpenter.

5) Adjust IPv6 payload_len to include extension headers. Otherwise
   we corrupt the packets when doing ESP GRO on transport mode.
   From Yossi Kuperman.

6) Set nhoff to the proper offset of the IPv6 nexthdr when doing ESP GRO.
   From Yossi Kuperman.

Please pull or let me know if there are problems.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 0ccc22f4 ca3a1b85
Loading
Loading
Loading
Loading
+2 −5
Original line number Diff line number Diff line
@@ -1850,8 +1850,9 @@ static inline struct xfrm_offload *xfrm_offload(struct sk_buff *skb)
}
#endif

#ifdef CONFIG_XFRM_OFFLOAD
void __net_init xfrm_dev_init(void);

#ifdef CONFIG_XFRM_OFFLOAD
int validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features);
int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
		       struct xfrm_user_offload *xuo);
@@ -1877,10 +1878,6 @@ static inline void xfrm_dev_state_free(struct xfrm_state *x)
	}
}
#else
static inline void __net_init xfrm_dev_init(void)
{
}

static inline int validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features)
{
	return 0;
+25 −0
Original line number Diff line number Diff line
@@ -30,6 +30,25 @@
#include <net/ipv6.h>
#include <linux/icmpv6.h>

static __u16 esp6_nexthdr_esp_offset(struct ipv6hdr *ipv6_hdr, int nhlen)
{
	int off = sizeof(struct ipv6hdr);
	struct ipv6_opt_hdr *exthdr;

	if (likely(ipv6_hdr->nexthdr == NEXTHDR_ESP))
		return offsetof(struct ipv6hdr, nexthdr);

	while (off < nhlen) {
		exthdr = (void *)ipv6_hdr + off;
		if (exthdr->nexthdr == NEXTHDR_ESP)
			return off;

		off += ipv6_optlen(exthdr);
	}

	return 0;
}

static struct sk_buff **esp6_gro_receive(struct sk_buff **head,
					 struct sk_buff *skb)
{
@@ -38,6 +57,7 @@ static struct sk_buff **esp6_gro_receive(struct sk_buff **head,
	struct xfrm_state *x;
	__be32 seq;
	__be32 spi;
	int nhoff;
	int err;

	skb_pull(skb, offset);
@@ -72,6 +92,11 @@ static struct sk_buff **esp6_gro_receive(struct sk_buff **head,

	xo->flags |= XFRM_GRO;

	nhoff = esp6_nexthdr_esp_offset(ipv6_hdr(skb), offset);
	if (!nhoff)
		goto out;

	IP6CB(skb)->nhoff = nhoff;
	XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
	XFRM_SPI_SKB_CB(skb)->family = AF_INET6;
	XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
+1 −1
Original line number Diff line number Diff line
@@ -43,8 +43,8 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async)
		return 1;
#endif

	ipv6_hdr(skb)->payload_len = htons(skb->len);
	__skb_push(skb, skb->data - skb_network_header(skb));
	ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));

	if (xo && (xo->flags & XFRM_GRO)) {
		skb_mac_header_rebuild(skb);
+15 −4
Original line number Diff line number Diff line
@@ -1157,6 +1157,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
			goto out;
	}

	err = -ENOBUFS;
	key = ext_hdrs[SADB_EXT_KEY_AUTH - 1];
	if (sa->sadb_sa_auth) {
		int keysize = 0;
@@ -1168,8 +1169,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
		if (key)
			keysize = (key->sadb_key_bits + 7) / 8;
		x->aalg = kmalloc(sizeof(*x->aalg) + keysize, GFP_KERNEL);
		if (!x->aalg)
		if (!x->aalg) {
			err = -ENOMEM;
			goto out;
		}
		strcpy(x->aalg->alg_name, a->name);
		x->aalg->alg_key_len = 0;
		if (key) {
@@ -1188,8 +1191,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
				goto out;
			}
			x->calg = kmalloc(sizeof(*x->calg), GFP_KERNEL);
			if (!x->calg)
			if (!x->calg) {
				err = -ENOMEM;
				goto out;
			}
			strcpy(x->calg->alg_name, a->name);
			x->props.calgo = sa->sadb_sa_encrypt;
		} else {
@@ -1203,8 +1208,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
			if (key)
				keysize = (key->sadb_key_bits + 7) / 8;
			x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL);
			if (!x->ealg)
			if (!x->ealg) {
				err = -ENOMEM;
				goto out;
			}
			strcpy(x->ealg->alg_name, a->name);
			x->ealg->alg_key_len = 0;
			if (key) {
@@ -1249,8 +1256,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
		struct xfrm_encap_tmpl *natt;

		x->encap = kmalloc(sizeof(*x->encap), GFP_KERNEL);
		if (!x->encap)
		if (!x->encap) {
			err = -ENOMEM;
			goto out;
		}

		natt = x->encap;
		n_type = ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1];
@@ -2755,6 +2764,8 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, const struct sad
	int err, err2;

	err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, true);
	if (!err)
		xfrm_garbage_collect(net);
	err2 = unicast_flush_resp(sk, hdr);
	if (err || err2) {
		if (err == -ESRCH) /* empty table - old silent behavior */
+1 −2
Original line number Diff line number Diff line
@@ -4,8 +4,7 @@

obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \
		      xfrm_input.o xfrm_output.o \
		      xfrm_sysctl.o xfrm_replay.o
obj-$(CONFIG_XFRM_OFFLOAD) += xfrm_device.o
		      xfrm_sysctl.o xfrm_replay.o xfrm_device.o
obj-$(CONFIG_XFRM_STATISTICS) += xfrm_proc.o
obj-$(CONFIG_XFRM_ALGO) += xfrm_algo.o
obj-$(CONFIG_XFRM_USER) += xfrm_user.o
Loading