diff options
author | Hannes Frederic Sowa <hannes@stressinduktion.org> | 2015-01-23 12:01:26 +0100 |
---|---|---|
committer | Andreas Blaesius <skate4life@gmx.de> | 2016-10-12 23:23:48 +0200 |
commit | 6d219535a3a7b1869a44d9ed93875b57a8053010 (patch) | |
tree | c0a8fbd582ccae098e9e8a11e8d77cb2beb66c04 /net | |
parent | 5c4d7219e24ad84b4c31caa713db890be6eb895a (diff) | |
download | kernel_samsung_espresso10-6d219535a3a7b1869a44d9ed93875b57a8053010.zip kernel_samsung_espresso10-6d219535a3a7b1869a44d9ed93875b57a8053010.tar.gz kernel_samsung_espresso10-6d219535a3a7b1869a44d9ed93875b57a8053010.tar.bz2 |
ipv4: try to cache dst_entries which would cause a redirect
Not caching dst_entries which cause redirects could be exploited by hosts
on the same subnet, causing a severe DoS attack. This effect aggravated
since commit f88649721268999 ("ipv4: fix dst race in sk_dst_get()").
Lookups causing redirects will be allocated with DST_NOCACHE set which
will force dst_release to free them via RCU. Unfortunately waiting for
RCU grace period just takes too long, we can end up with >1M dst_entries
waiting to be released and the system will run OOM. rcuos threads cannot
catch up under high softirq load.
Attaching the flag to emit a redirect later on to the specific skb allows
us to cache those dst_entries thus reducing the pressure on allocation
and deallocation.
This issue was discovered by Marcelo Leitner.
Cc: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Marcelo Leitner <mleitner@redhat.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: David S. Miller <davem@davemloft.net>
Conflicts:
include/net/ip.h
net/ipv4/route.c
Change-Id: I53e4b500a4db2f5fece937a42a3bd810b2640c44
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/ip_forward.c | 3 | ||||
-rw-r--r-- | net/ipv4/route.c | 5 |
2 files changed, 6 insertions, 2 deletions
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index 29a07b6..0ee2d50 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -107,7 +107,8 @@ int ip_forward(struct sk_buff *skb) * We now generate an ICMP HOST REDIRECT giving the route * we calculated. */ - if (rt->rt_flags&RTCF_DOREDIRECT && !opt->srr && !skb_sec_path(skb)) + if (IPCB(skb)->flags & IPSKB_DOREDIRECT && !opt->srr && + !skb_sec_path(skb)) ip_rt_send_redirect(skb); skb->priority = rt_tos2priority(iph->tos); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 43838f5..ac2632f 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2123,9 +2123,10 @@ static int __mkroute_input(struct sk_buff *skb, flags |= RTCF_DIRECTSRC; if (out_dev == in_dev && err && + skb->protocol == htons(ETH_P_IP) && (IN_DEV_SHARED_MEDIA(out_dev) || inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) - flags |= RTCF_DOREDIRECT; + IPCB(skb)->flags |= IPSKB_DOREDIRECT; if (skb->protocol != htons(ETH_P_IP)) { /* Not IP (i.e. ARP). Do not create route, if it is @@ -2954,6 +2955,8 @@ static int rt_fill_info(struct net *net, r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED; if (rt->rt_flags & RTCF_NOTIFY) r->rtm_flags |= RTM_F_NOTIFY; + if (IPCB(skb)->flags & IPSKB_DOREDIRECT) + r->rtm_flags |= RTCF_DOREDIRECT; NLA_PUT_BE32(skb, RTA_DST, rt->rt_dst); |