From 00b4422fe363cc7cadc51c50c5a0c3c510f0fa14 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Wed, 9 Nov 2016 10:25:05 -0800 Subject: netfilter: Update nf_send_reset6 to consider L3 domain nf_send_reset6 is not considering the L3 domain and lookups are sent to the wrong table. For example consider the following output rule: ip6tables -A OUTPUT -p tcp --dport 12345 -j REJECT --reject-with tcp-reset using perf to analyze lookups via the fib6_table_lookup tracepoint shows: swapper 0 [001] 248.787816: fib6:fib6_table_lookup: table 255 oif 0 iif 1 src 2100:1::3 dst 2100:1: ffffffff81439cdc perf_trace_fib6_table_lookup ([kernel.kallsyms]) ffffffff814c1ce3 trace_fib6_table_lookup ([kernel.kallsyms]) ffffffff814c3e89 ip6_pol_route ([kernel.kallsyms]) ffffffff814c40d5 ip6_pol_route_output ([kernel.kallsyms]) ffffffff814e7b6f fib6_rule_action ([kernel.kallsyms]) ffffffff81437f60 fib_rules_lookup ([kernel.kallsyms]) ffffffff814e7c79 fib6_rule_lookup ([kernel.kallsyms]) ffffffff814c2541 ip6_route_output_flags ([kernel.kallsyms]) 528 nf_send_reset6 ([nf_reject_ipv6]) The lookup is directed to table 255 rather than the table associated with the device via the L3 domain. Update nf_send_reset6 to pull the L3 domain from the dst currently attached to the skb. Signed-off-by: David Ahern Signed-off-by: Pablo Neira Ayuso --- net/ipv6/netfilter/nf_reject_ipv6.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net/ipv6') diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c index a5400223fd74..10090400c72f 100644 --- a/net/ipv6/netfilter/nf_reject_ipv6.c +++ b/net/ipv6/netfilter/nf_reject_ipv6.c @@ -156,6 +156,7 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook) fl6.daddr = oip6h->saddr; fl6.fl6_sport = otcph->dest; fl6.fl6_dport = otcph->source; + fl6.flowi6_oif = l3mdev_master_ifindex(skb_dst(oldskb)->dev); security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6)); dst = ip6_route_output(net, NULL, &fl6); if (dst->error) { -- cgit From 9b57da0630c9fd36ed7a20fc0f98dc82cc0777fa Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 29 Nov 2016 02:17:34 +0100 Subject: netfilter: ipv6: nf_defrag: drop mangled skb on ream error Dmitry Vyukov reported GPF in network stack that Andrey traced down to negative nh offset in nf_ct_frag6_queue(). Problem is that all network headers before fragment header are pulled. Normal ipv6 reassembly will drop the skb when errors occur further down the line. netfilter doesn't do this, and instead passed the original fragment along. That was also fine back when netfilter ipv6 defrag worked with cloned fragments, as the original, pristine fragment was passed on. So we either have to undo the pull op, or discard such fragments. Since they're malformed after all (e.g. overlapping fragment) it seems preferrable to just drop them. Same for temporary errors -- it doesn't make sense to accept (and perhaps forward!) only some fragments of same datagram. Fixes: 029f7f3b8701cc7ac ("netfilter: ipv6: nf_defrag: avoid/free clone operations") Reported-by: Dmitry Vyukov Debugged-by: Andrey Konovalov Diagnosed-by: Eric Dumazet Signed-off-by: Florian Westphal Acked-by: Eric Dumazet Signed-off-by: Pablo Neira Ayuso --- net/ipv6/netfilter/nf_conntrack_reasm.c | 4 ++-- net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'net/ipv6') diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index e4347aeb2e65..9948b5ce52da 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -576,11 +576,11 @@ int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user) /* Jumbo payload inhibits frag. header */ if (ipv6_hdr(skb)->payload_len == 0) { pr_debug("payload len = 0\n"); - return -EINVAL; + return 0; } if (find_prev_fhdr(skb, &prevhdr, &nhoff, &fhoff) < 0) - return -EINVAL; + return 0; if (!pskb_may_pull(skb, fhoff + sizeof(*fhdr))) return -ENOMEM; diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c index f7aab5ab93a5..f06b0471f39f 100644 --- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c @@ -69,7 +69,7 @@ static unsigned int ipv6_defrag(void *priv, if (err == -EINPROGRESS) return NF_STOLEN; - return NF_ACCEPT; + return err == 0 ? NF_ACCEPT : NF_DROP; } static struct nf_hook_ops ipv6_defrag_ops[] = { -- cgit