summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-04-21 23:06:14 +0300
committerDavid S. Miller <davem@davemloft.net>2018-04-21 23:06:14 +0300
commit0638eb573cde5888c0886c7f35da604e5db209a6 (patch)
tree482fdfb31458861648701b908a46450d455fc470 /include
parent1b80f86ed6b0e98a7e3d1e7d547f66163aa8a1af (diff)
parent8ae869714ba377c93d5dc546b97c0aeaba90b3c9 (diff)
downloadlinux-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.h41
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;
}