]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
drop queue-3.18/ipv6-add-rcu-grace-period-before-freeing-fib6_node.patch
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 18 Sep 2017 06:53:12 +0000 (08:53 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 18 Sep 2017 06:53:12 +0000 (08:53 +0200)
queue-3.18/ipv6-add-rcu-grace-period-before-freeing-fib6_node.patch [deleted file]
queue-3.18/series

diff --git a/queue-3.18/ipv6-add-rcu-grace-period-before-freeing-fib6_node.patch b/queue-3.18/ipv6-add-rcu-grace-period-before-freeing-fib6_node.patch
deleted file mode 100644 (file)
index 7202598..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-From foo@baz Fri Sep 15 17:17:53 PDT 2017
-From: Wei Wang <weiwan@google.com>
-Date: Mon, 21 Aug 2017 09:47:10 -0700
-Subject: ipv6: add rcu grace period before freeing fib6_node
-
-From: Wei Wang <weiwan@google.com>
-
-
-[ Upstream commit c5cff8561d2d0006e972bd114afd51f082fee77c ]
-
-We currently keep rt->rt6i_node pointing to the fib6_node for the route.
-And some functions make use of this pointer to dereference the fib6_node
-from rt structure, e.g. rt6_check(). However, as there is neither
-refcount nor rcu taken when dereferencing rt->rt6i_node, it could
-potentially cause crashes as rt->rt6i_node could be set to NULL by other
-CPUs when doing a route deletion.
-This patch introduces an rcu grace period before freeing fib6_node and
-makes sure the functions that dereference it takes rcu_read_lock().
-
-Note: there is no "Fixes" tag because this bug was there in a very
-early stage.
-
-Signed-off-by: Wei Wang <weiwan@google.com>
-Acked-by: Eric Dumazet <edumazet@google.com>
-Acked-by: Martin KaFai Lau <kafai@fb.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- include/net/ip6_fib.h | 30 +++++++++++++++++++++++++++++-
- net/ipv6/ip6_fib.c    | 20 ++++++++++++++++----
- net/ipv6/route.c      | 14 +++++++++++---
- 3 files changed, 56 insertions(+), 8 deletions(-)
-
-diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
-index a74e2aa40ef4..c17180118897 100644
---- a/include/net/ip6_fib.h
-+++ b/include/net/ip6_fib.h
-@@ -68,6 +68,7 @@ struct fib6_node {
-       __u16                   fn_flags;
-       int                     fn_sernum;
-       struct rt6_info         *rr_ptr;
-+      struct rcu_head         rcu;
- };
- #ifndef CONFIG_IPV6_SUBTREES
-@@ -165,13 +166,40 @@ static inline void rt6_update_expires(struct rt6_info *rt0, int 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 rt6_info *rt,
-+                                     u32 *cookie)
-+{
-+      struct fib6_node *fn;
-+      bool status = false;
-+
-+      rcu_read_lock();
-+      fn = rcu_dereference(rt->rt6i_node);
-+
-+      if (fn) {
-+              *cookie = fn->fn_sernum;
-+              status = true;
-+      }
-+
-+      rcu_read_unlock();
-+      return status;
-+}
-+
- static inline u32 rt6_get_cookie(const struct rt6_info *rt)
- {
-+      u32 cookie = 0;
-+
-       if (rt->rt6i_flags & RTF_PCPU ||
-           (unlikely(rt->dst.flags & DST_NOCACHE) && rt->dst.from))
-               rt = (struct rt6_info *)(rt->dst.from);
--      return rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0;
-+      rt6_get_cookie_safe(rt, &cookie);
-+
-+      return cookie;
- }
- static inline void ip6_rt_put(struct rt6_info *rt)
-diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
-index ff389591a340..ed832b3d9b70 100644
---- a/net/ipv6/ip6_fib.c
-+++ b/net/ipv6/ip6_fib.c
-@@ -148,11 +148,23 @@ static struct fib6_node *node_alloc(void)
-       return fn;
- }
--static void node_free(struct fib6_node *fn)
-+static void node_free_immediate(struct fib6_node *fn)
-+{
-+      kmem_cache_free(fib6_node_kmem, fn);
-+}
-+
-+static void node_free_rcu(struct rcu_head *head)
- {
-+      struct fib6_node *fn = container_of(head, struct fib6_node, rcu);
-+
-       kmem_cache_free(fib6_node_kmem, fn);
- }
-+static void node_free(struct fib6_node *fn)
-+{
-+      call_rcu(&fn->rcu, node_free_rcu);
-+}
-+
- static void rt6_rcu_free(struct rt6_info *rt)
- {
-       call_rcu(&rt->dst.rcu_head, dst_rcu_free);
-@@ -589,9 +601,9 @@ static struct fib6_node *fib6_add_1(struct fib6_node *root,
-               if (!in || !ln) {
-                       if (in)
--                              node_free(in);
-+                              node_free_immediate(in);
-                       if (ln)
--                              node_free(ln);
-+                              node_free_immediate(ln);
-                       return ERR_PTR(-ENOMEM);
-               }
-@@ -1020,7 +1032,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt,
-                                  root, and then (in failure) stale node
-                                  in main tree.
-                                */
--                              node_free(sfn);
-+                              node_free_immediate(sfn);
-                               err = PTR_ERR(sn);
-                               goto failure;
-                       }
-diff --git a/net/ipv6/route.c b/net/ipv6/route.c
-index 5764a84465f8..632987ffc07d 100644
---- a/net/ipv6/route.c
-+++ b/net/ipv6/route.c
-@@ -1267,7 +1267,9 @@ static void rt6_dst_from_metrics_check(struct rt6_info *rt)
- static struct dst_entry *rt6_check(struct rt6_info *rt, u32 cookie)
- {
--      if (!rt->rt6i_node || (rt->rt6i_node->fn_sernum != cookie))
-+      u32 rt_cookie;
-+
-+      if (!rt6_get_cookie_safe(rt, &rt_cookie) || rt_cookie != cookie)
-               return NULL;
-       if (rt6_check_expired(rt))
-@@ -1335,8 +1337,14 @@ static void ip6_link_failure(struct sk_buff *skb)
-               if (rt->rt6i_flags & RTF_CACHE) {
-                       dst_hold(&rt->dst);
-                       ip6_del_rt(rt);
--              } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) {
--                      rt->rt6i_node->fn_sernum = -1;
-+              } else {
-+                      struct fib6_node *fn;
-+
-+                      rcu_read_lock();
-+                      fn = rcu_dereference(rt->rt6i_node);
-+                      if (fn && (rt->rt6i_flags & RTF_DEFAULT))
-+                              fn->fn_sernum = -1;
-+                      rcu_read_unlock();
-               }
-       }
- }
--- 
-2.13.5
-
index 4c237f5aac93c321b3a99918618bf738536ebd2b..d61ef922489809588644f3c4d7bb404401d77959 100644 (file)
@@ -5,4 +5,3 @@ tcp-initialize-rcv_mss-to-tcp_min_mss-instead-of-0.patch
 ipv6-fix-memory-leak-with-multiple-tables-during-netns-destruction.patch
 ipv6-fix-typo-in-fib6_net_exit.patch
 f2fs-check-hot_data-for-roll-forward-recovery.patch
-ipv6-add-rcu-grace-period-before-freeing-fib6_node.patch