diff options
author | David S. Miller <davem@davemloft.net> | 2018-04-21 23:06:14 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-04-21 23:06:14 +0300 |
commit | 0638eb573cde5888c0886c7f35da604e5db209a6 (patch) | |
tree | 482fdfb31458861648701b908a46450d455fc470 /include | |
parent | 1b80f86ed6b0e98a7e3d1e7d547f66163aa8a1af (diff) | |
parent | 8ae869714ba377c93d5dc546b97c0aeaba90b3c9 (diff) | |
download | linux-0638eb573cde5888c0886c7f35da604e5db209a6.tar.xz |
Merge branch 'ipv6-Another-followup-to-the-fib6_info-change'
David Ahern says:
====================
net/ipv6: Another followup to the fib6_info change
Last one - for this week.
Patches 1, 2 and 7 are more cleanup patches - removing dead code,
moving code from a header to near its single caller, and updating
function name.
Patches 3-5 do some refactoring leading up to patch 6 which fixes
a NULL dereference. I have only managed to trigger a panic once, so
I can not definitively confirm it addresses the problem but it seems
pretty clear that it is a race on removing a 'from' reference on
an rt6_info and another path using that 'from' value to do
cookie checking.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r-- | include/net/ip6_fib.h | 41 |
1 files changed, 12 insertions, 29 deletions
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index 642211174692..1af450d4e923 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -174,7 +174,7 @@ struct fib6_info { struct rt6_info { struct dst_entry dst; - struct fib6_info *from; + struct fib6_info __rcu *from; struct rt6key rt6i_dst; struct rt6key rt6i_src; @@ -223,39 +223,17 @@ static inline bool fib6_check_expired(const struct fib6_info *f6i) return false; } -static inline void rt6_clean_expires(struct rt6_info *rt) -{ - rt->rt6i_flags &= ~RTF_EXPIRES; - rt->dst.expires = 0; -} - -static inline void rt6_set_expires(struct rt6_info *rt, unsigned long expires) -{ - rt->dst.expires = expires; - rt->rt6i_flags |= RTF_EXPIRES; -} - -static inline void rt6_update_expires(struct rt6_info *rt0, int timeout) -{ - if (!(rt0->rt6i_flags & RTF_EXPIRES) && rt0->from) - rt0->dst.expires = rt0->from->expires; - - dst_set_expires(&rt0->dst, timeout); - rt0->rt6i_flags |= RTF_EXPIRES; -} - /* Function to safely get fn->sernum for passed in rt * and store result in passed in cookie. * Return true if we can get cookie safely * Return false if not */ -static inline bool rt6_get_cookie_safe(const struct fib6_info *f6i, - u32 *cookie) +static inline bool fib6_get_cookie_safe(const struct fib6_info *f6i, + u32 *cookie) { struct fib6_node *fn; bool status = false; - rcu_read_lock(); fn = rcu_dereference(f6i->fib6_node); if (fn) { @@ -265,17 +243,22 @@ static inline bool rt6_get_cookie_safe(const struct fib6_info *f6i, status = true; } - rcu_read_unlock(); return status; } static inline u32 rt6_get_cookie(const struct rt6_info *rt) { + struct fib6_info *from; u32 cookie = 0; - if (rt->rt6i_flags & RTF_PCPU || - (unlikely(!list_empty(&rt->rt6i_uncached)) && rt->from)) - rt6_get_cookie_safe(rt->from, &cookie); + rcu_read_lock(); + + from = rcu_dereference(rt->from); + if (from && (rt->rt6i_flags & RTF_PCPU || + unlikely(!list_empty(&rt->rt6i_uncached)))) + fib6_get_cookie_safe(from, &cookie); + + rcu_read_unlock(); return cookie; } |