diff options
author | David S. Miller <davem@davemloft.net> | 2018-09-18 20:17:01 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-09-18 20:17:01 -0700 |
commit | 69ba423d35c25ae06fa419ac1d4f6c4e2b74e412 (patch) | |
tree | 196f9e53a53e7aa2c52573c446400640d54f35ad /net | |
parent | 126d6848ef13958e1cb959e96c21d19bc498ade9 (diff) | |
parent | ce7ea4af0838ffd4667ecad4eb5eec7a25342f1e (diff) | |
download | linux-stable-69ba423d35c25ae06fa419ac1d4f6c4e2b74e412.tar.gz linux-stable-69ba423d35c25ae06fa419ac1d4f6c4e2b74e412.tar.bz2 linux-stable-69ba423d35c25ae06fa419ac1d4f6c4e2b74e412.zip |
Merge branch 'ipv6-fix-issues-on-accessing-fib6_metrics'
Wei Wang says:
====================
ipv6: fix issues on accessing fib6_metrics
The latest fix on the memory leak of fib6_metrics still causes
use-after-free.
This patch series first revert the previous fix and propose a new fix
that is more inline with ipv4 logic and is tested to fix the
use-after-free issue reported.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/route.c | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 480a79f47c52..826b14de7dbb 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -364,11 +364,14 @@ EXPORT_SYMBOL(ip6_dst_alloc); static void ip6_dst_destroy(struct dst_entry *dst) { + struct dst_metrics *p = (struct dst_metrics *)DST_METRICS_PTR(dst); struct rt6_info *rt = (struct rt6_info *)dst; struct fib6_info *from; struct inet6_dev *idev; - dst_destroy_metrics_generic(dst); + if (p != &dst_default_metrics && refcount_dec_and_test(&p->refcnt)) + kfree(p); + rt6_uncached_list_del(rt); idev = rt->rt6i_idev; @@ -976,6 +979,10 @@ static void rt6_set_from(struct rt6_info *rt, struct fib6_info *from) rt->rt6i_flags &= ~RTF_EXPIRES; rcu_assign_pointer(rt->from, from); dst_init_metrics(&rt->dst, from->fib6_metrics->metrics, true); + if (from->fib6_metrics != &dst_default_metrics) { + rt->dst._metrics |= DST_METRICS_REFCOUNTED; + refcount_inc(&from->fib6_metrics->refcnt); + } } /* Caller must already hold reference to @ort */ |