From d6990976af7c5d8f55903bfb4289b6fb030bf754 Mon Sep 17 00:00:00 2001 From: Eyal Birger Date: Thu, 7 Jun 2018 10:11:02 +0300 Subject: vti6: fix PMTU caching and reporting on xmit When setting the skb->dst before doing the MTU check, the route PMTU caching and reporting is done on the new dst which is about to be released. Instead, PMTU handling should be done using the original dst. This is aligned with IPv4 VTI. Fixes: ccd740cbc6 ("vti6: Add pmtu handling to vti6_xmit.") Signed-off-by: Eyal Birger Signed-off-by: Steffen Klassert --- net/ipv6/ip6_vti.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'net/ipv6') diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index b7f28deddaea..c72ae3a4fe09 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -480,10 +480,6 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) goto tx_err_dst_release; } - skb_scrub_packet(skb, !net_eq(t->net, dev_net(dev))); - skb_dst_set(skb, dst); - skb->dev = skb_dst(skb)->dev; - mtu = dst_mtu(dst); if (!skb->ignore_df && skb->len > mtu) { skb_dst_update_pmtu(skb, mtu); @@ -498,9 +494,14 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) htonl(mtu)); } - return -EMSGSIZE; + err = -EMSGSIZE; + goto tx_err_dst_release; } + skb_scrub_packet(skb, !net_eq(t->net, dev_net(dev))); + skb_dst_set(skb, dst); + skb->dev = skb_dst(skb)->dev; + err = dst_output(t->net, skb->sk, skb); if (net_xmit_eval(err) == 0) { struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats); -- cgit v1.2.3 From 7284fdf39a912322ce97de2d30def3c6068a418c Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Wed, 27 Jun 2018 11:49:28 +0800 Subject: esp6: fix memleak on error path in esp6_input This ought to be an omission in e6194923237 ("esp: Fix memleaks on error paths."). The memleak on error path in esp6_input is similar to esp_input of esp4. Fixes: e6194923237 ("esp: Fix memleaks on error paths.") Fixes: 3f29770723f ("ipsec: check return value of skb_to_sgvec always") Signed-off-by: Zhen Lei Signed-off-by: Steffen Klassert --- net/ipv6/esp6.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'net/ipv6') diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 97513f35bcc5..88a7579c23bd 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -669,8 +669,10 @@ skip_cow: sg_init_table(sg, nfrags); ret = skb_to_sgvec(skb, sg, 0, skb->len); - if (unlikely(ret < 0)) + if (unlikely(ret < 0)) { + kfree(tmp); goto out; + } skb->ip_summed = CHECKSUM_NONE; -- cgit v1.2.3 From df18b50448fab1dff093731dfd0e25e77e1afcd1 Mon Sep 17 00:00:00 2001 From: Sabrina Dubroca Date: Mon, 30 Jul 2018 16:23:10 +0200 Subject: net/ipv6: fix metrics leak Since commit d4ead6b34b67 ("net/ipv6: move metrics from dst to rt6_info"), ipv6 metrics are shared and refcounted. rt6_set_from() assigns the rt->from pointer and increases the refcount on from's metrics. This reference is never released. Introduce the fib6_metrics_release() helper and use it to release the metrics. Fixes: d4ead6b34b67 ("net/ipv6: move metrics from dst to rt6_info") Signed-off-by: Sabrina Dubroca Signed-off-by: David S. Miller --- net/ipv6/ip6_fib.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'net/ipv6') diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index d212738e9d10..211a2d437b56 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -167,11 +167,22 @@ struct fib6_info *fib6_info_alloc(gfp_t gfp_flags) return f6i; } +static void fib6_metrics_release(struct fib6_info *f6i) +{ + struct dst_metrics *m; + + if (!f6i) + return; + + m = f6i->fib6_metrics; + if (m != &dst_default_metrics && refcount_dec_and_test(&m->refcnt)) + kfree(m); +} + void fib6_info_destroy_rcu(struct rcu_head *head) { struct fib6_info *f6i = container_of(head, struct fib6_info, rcu); struct rt6_exception_bucket *bucket; - struct dst_metrics *m; WARN_ON(f6i->fib6_node); @@ -201,9 +212,7 @@ void fib6_info_destroy_rcu(struct rcu_head *head) if (f6i->fib6_nh.nh_dev) dev_put(f6i->fib6_nh.nh_dev); - m = f6i->fib6_metrics; - if (m != &dst_default_metrics && refcount_dec_and_test(&m->refcnt)) - kfree(m); + fib6_metrics_release(f6i); kfree(f6i); } @@ -887,6 +896,7 @@ static void fib6_drop_pcpu_from(struct fib6_info *f6i, from = rcu_dereference_protected(pcpu_rt->from, lockdep_is_held(&table->tb6_lock)); + fib6_metrics_release(from); rcu_assign_pointer(pcpu_rt->from, NULL); fib6_info_release(from); } -- cgit v1.2.3 From e6aed040eafb4ce1881bbc59a225f6b27d250396 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 1 Aug 2018 21:32:30 -0700 Subject: Revert "net/ipv6: fix metrics leak" This reverts commit df18b50448fab1dff093731dfd0e25e77e1afcd1. This change causes other problems and use-after-free situations as found by syzbot. Signed-off-by: David S. Miller --- net/ipv6/ip6_fib.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'net/ipv6') diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 211a2d437b56..d212738e9d10 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -167,22 +167,11 @@ struct fib6_info *fib6_info_alloc(gfp_t gfp_flags) return f6i; } -static void fib6_metrics_release(struct fib6_info *f6i) -{ - struct dst_metrics *m; - - if (!f6i) - return; - - m = f6i->fib6_metrics; - if (m != &dst_default_metrics && refcount_dec_and_test(&m->refcnt)) - kfree(m); -} - void fib6_info_destroy_rcu(struct rcu_head *head) { struct fib6_info *f6i = container_of(head, struct fib6_info, rcu); struct rt6_exception_bucket *bucket; + struct dst_metrics *m; WARN_ON(f6i->fib6_node); @@ -212,7 +201,9 @@ void fib6_info_destroy_rcu(struct rcu_head *head) if (f6i->fib6_nh.nh_dev) dev_put(f6i->fib6_nh.nh_dev); - fib6_metrics_release(f6i); + m = f6i->fib6_metrics; + if (m != &dst_default_metrics && refcount_dec_and_test(&m->refcnt)) + kfree(m); kfree(f6i); } @@ -896,7 +887,6 @@ static void fib6_drop_pcpu_from(struct fib6_info *f6i, from = rcu_dereference_protected(pcpu_rt->from, lockdep_is_held(&table->tb6_lock)); - fib6_metrics_release(from); rcu_assign_pointer(pcpu_rt->from, NULL); fib6_info_release(from); } -- cgit v1.2.3