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


Steffen Klassert says:

====================
pull request (net): ipsec 2020-05-29

1) Several fixes for ESP gro/gso in transport and beet mode when
   IPv6 extension headers are present. From Xin Long.

2) Fix a wrong comment on XFRMA_OFFLOAD_DEV.
   From Antony Antony.

3) Fix sk_destruct callback handling on ESP in TCP encapsulation.
   From Sabrina Dubroca.

4) Fix a use after free in xfrm_output_gso when used with vxlan.
   From Xin Long.

5) Fix secpath handling of VTI when used wiuth IPCOMP.
   From Xin Long.

6) Fix an oops when deleting a x-netns xfrm interface.
   From Nicolas Dichtel.

7) Fix a possible warning on policy updates. We had a case where it was
   possible to add two policies with the same lookup keys.
   From Xin Long.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 7c6d2ecb f6a23d85
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ struct espintcp_ctx {
	struct espintcp_msg partial;
	void (*saved_data_ready)(struct sock *sk);
	void (*saved_write_space)(struct sock *sk);
	void (*saved_destruct)(struct sock *sk);
	struct work_struct work;
	bool tx_running;
};
+1 −1
Original line number Diff line number Diff line
@@ -304,7 +304,7 @@ enum xfrm_attr_type_t {
	XFRMA_PROTO,		/* __u8 */
	XFRMA_ADDRESS_FILTER,	/* struct xfrm_address_filter */
	XFRMA_PAD,
	XFRMA_OFFLOAD_DEV,	/* struct xfrm_state_offload */
	XFRMA_OFFLOAD_DEV,	/* struct xfrm_user_offload */
	XFRMA_SET_MARK,		/* __u32 */
	XFRMA_SET_MARK_MASK,	/* __u32 */
	XFRMA_IF_ID,		/* __u32 */
+18 −12
Original line number Diff line number Diff line
@@ -63,11 +63,9 @@ static struct sk_buff *esp4_gro_receive(struct list_head *head,
		sp->olen++;

		xo = xfrm_offload(skb);
		if (!xo) {
			xfrm_state_put(x);
		if (!xo)
			goto out_reset;
	}
	}

	xo->flags |= XFRM_GRO;

@@ -139,18 +137,26 @@ static struct sk_buff *xfrm4_beet_gso_segment(struct xfrm_state *x,
	struct xfrm_offload *xo = xfrm_offload(skb);
	struct sk_buff *segs = ERR_PTR(-EINVAL);
	const struct net_offload *ops;
	int proto = xo->proto;
	u8 proto = xo->proto;

	skb->transport_header += x->props.header_len;

	if (x->sel.family != AF_INET6) {
		if (proto == IPPROTO_BEETPH) {
		struct ip_beet_phdr *ph = (struct ip_beet_phdr *)skb->data;
			struct ip_beet_phdr *ph =
				(struct ip_beet_phdr *)skb->data;

			skb->transport_header += ph->hdrlen * 8;
			proto = ph->nexthdr;
	} else if (x->sel.family != AF_INET6) {
		} else {
			skb->transport_header -= IPV4_BEET_PHMAXLEN;
	} else if (proto == IPPROTO_TCP) {
		}
	} else {
		__be16 frag;

		skb->transport_header +=
			ipv6_skip_exthdr(skb, 0, &proto, &frag);
		if (proto == IPPROTO_TCP)
			skb_shinfo(skb)->gso_type |= SKB_GSO_TCPV4;
	}

+22 −1
Original line number Diff line number Diff line
@@ -93,7 +93,28 @@ static int vti_rcv_proto(struct sk_buff *skb)

static int vti_rcv_tunnel(struct sk_buff *skb)
{
	return vti_rcv(skb, ip_hdr(skb)->saddr, true);
	struct ip_tunnel_net *itn = net_generic(dev_net(skb->dev), vti_net_id);
	const struct iphdr *iph = ip_hdr(skb);
	struct ip_tunnel *tunnel;

	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
				  iph->saddr, iph->daddr, 0);
	if (tunnel) {
		struct tnl_ptk_info tpi = {
			.proto = htons(ETH_P_IP),
		};

		if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
			goto drop;
		if (iptunnel_pull_header(skb, 0, tpi.proto, false))
			goto drop;
		return ip_tunnel_rcv(tunnel, skb, &tpi, NULL, false);
	}

	return -EINVAL;
drop:
	kfree_skb(skb);
	return 0;
}

static int vti_rcv_cb(struct sk_buff *skb, int err)
+25 −12
Original line number Diff line number Diff line
@@ -85,11 +85,9 @@ static struct sk_buff *esp6_gro_receive(struct list_head *head,
		sp->olen++;

		xo = xfrm_offload(skb);
		if (!xo) {
			xfrm_state_put(x);
		if (!xo)
			goto out_reset;
	}
	}

	xo->flags |= XFRM_GRO;

@@ -123,9 +121,16 @@ static void esp6_gso_encap(struct xfrm_state *x, struct sk_buff *skb)
	struct ip_esp_hdr *esph;
	struct ipv6hdr *iph = ipv6_hdr(skb);
	struct xfrm_offload *xo = xfrm_offload(skb);
	int proto = iph->nexthdr;
	u8 proto = iph->nexthdr;

	skb_push(skb, -skb_network_offset(skb));

	if (x->outer_mode.encap == XFRM_MODE_TRANSPORT) {
		__be16 frag;

		ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &proto, &frag);
	}

	esph = ip_esp_hdr(skb);
	*skb_mac_header(skb) = IPPROTO_ESP;

@@ -166,23 +171,31 @@ static struct sk_buff *xfrm6_beet_gso_segment(struct xfrm_state *x,
	struct xfrm_offload *xo = xfrm_offload(skb);
	struct sk_buff *segs = ERR_PTR(-EINVAL);
	const struct net_offload *ops;
	int proto = xo->proto;
	u8 proto = xo->proto;

	skb->transport_header += x->props.header_len;

	if (x->sel.family != AF_INET6) {
		skb->transport_header -=
			(sizeof(struct ipv6hdr) - sizeof(struct iphdr));

		if (proto == IPPROTO_BEETPH) {
		struct ip_beet_phdr *ph = (struct ip_beet_phdr *)skb->data;
			struct ip_beet_phdr *ph =
				(struct ip_beet_phdr *)skb->data;

			skb->transport_header += ph->hdrlen * 8;
			proto = ph->nexthdr;
		} else {
			skb->transport_header -= IPV4_BEET_PHMAXLEN;
		}

	if (x->sel.family != AF_INET6) {
		skb->transport_header -=
			(sizeof(struct ipv6hdr) - sizeof(struct iphdr));

		if (proto == IPPROTO_TCP)
			skb_shinfo(skb)->gso_type |= SKB_GSO_TCPV6;
	} else {
		__be16 frag;

		skb->transport_header +=
			ipv6_skip_exthdr(skb, 0, &proto, &frag);
	}

	__skb_pull(skb, skb_transport_offset(skb));
Loading