summaryrefslogtreecommitdiffstats
path: root/net/ipv6/xfrm6_input.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2017-12-15 16:40:44 +1100
committerSteffen Klassert <steffen.klassert@secunet.com>2017-12-19 08:23:21 +0100
commitacf568ee859f098279eadf551612f103afdacb4e (patch)
tree2ca6509d139079ad95e37bdfb94bf570fc094a6d /net/ipv6/xfrm6_input.c
parentd2950278d2d04ff5314abeb38d9c59c4e7c0ee53 (diff)
downloadlinux-acf568ee859f098279eadf551612f103afdacb4e.tar.gz
linux-acf568ee859f098279eadf551612f103afdacb4e.tar.bz2
linux-acf568ee859f098279eadf551612f103afdacb4e.zip
xfrm: Reinject transport-mode packets through tasklet
This is an old bugbear of mine: https://www.mail-archive.com/netdev@vger.kernel.org/msg03894.html By crafting special packets, it is possible to cause recursion in our kernel when processing transport-mode packets at levels that are only limited by packet size. The easiest one is with DNAT, but an even worse one is where UDP encapsulation is used in which case you just have to insert an UDP encapsulation header in between each level of recursion. This patch avoids this problem by reinjecting tranport-mode packets through a tasklet. Fixes: b05e106698d9 ("[IPV4/6]: Netfilter IPsec input hooks") Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net/ipv6/xfrm6_input.c')
-rw-r--r--net/ipv6/xfrm6_input.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index fe04e23af986..841f4a07438e 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -32,6 +32,14 @@ int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi,
}
EXPORT_SYMBOL(xfrm6_rcv_spi);
+static int xfrm6_transport_finish2(struct net *net, struct sock *sk,
+ struct sk_buff *skb)
+{
+ if (xfrm_trans_queue(skb, ip6_rcv_finish))
+ __kfree_skb(skb);
+ return -1;
+}
+
int xfrm6_transport_finish(struct sk_buff *skb, int async)
{
struct xfrm_offload *xo = xfrm_offload(skb);
@@ -56,7 +64,7 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async)
NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING,
dev_net(skb->dev), NULL, skb, skb->dev, NULL,
- ip6_rcv_finish);
+ xfrm6_transport_finish2);
return -1;
}