]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 16 Sep 2017 01:28:24 +0000 (18:28 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 16 Sep 2017 01:28:24 +0000 (18:28 -0700)
added patches:
f2fs-check-hot_data-for-roll-forward-recovery.patch
ipv6-add-rcu-grace-period-before-freeing-fib6_node.patch

queue-3.18/f2fs-check-hot_data-for-roll-forward-recovery.patch [new file with mode: 0644]
queue-3.18/ipv6-add-rcu-grace-period-before-freeing-fib6_node.patch [new file with mode: 0644]
queue-3.18/series

diff --git a/queue-3.18/f2fs-check-hot_data-for-roll-forward-recovery.patch b/queue-3.18/f2fs-check-hot_data-for-roll-forward-recovery.patch
new file mode 100644 (file)
index 0000000..99b0284
--- /dev/null
@@ -0,0 +1,31 @@
+From 125c9fb1ccb53eb2ea9380df40f3c743f3fb2fed Mon Sep 17 00:00:00 2001
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+Date: Sat, 12 Aug 2017 21:33:23 -0700
+Subject: f2fs: check hot_data for roll-forward recovery
+
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+
+commit 125c9fb1ccb53eb2ea9380df40f3c743f3fb2fed upstream.
+
+We need to check HOT_DATA to truncate any previous data block when doing
+roll-forward recovery.
+
+Reviewed-by: Chao Yu <yuchao0@huawei.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/f2fs/recovery.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/f2fs/recovery.c
++++ b/fs/f2fs/recovery.c
+@@ -263,7 +263,7 @@ static int check_index_in_prev_nodes(str
+               return 0;
+       /* Get the previous summary */
+-      for (i = CURSEG_WARM_DATA; i <= CURSEG_COLD_DATA; i++) {
++      for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
+               struct curseg_info *curseg = CURSEG_I(sbi, i);
+               if (curseg->segno == segno) {
+                       sum = curseg->sum_blk->entries[blkoff];
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
new file mode 100644 (file)
index 0000000..7202598
--- /dev/null
@@ -0,0 +1,172 @@
+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 4d9a0f0fef2abab7442b12d1e8b45c3416600c55..4c237f5aac93c321b3a99918618bf738536ebd2b 100644 (file)
@@ -4,3 +4,5 @@ revert-net-phy-correctly-process-phy_halted-in-phy_stop_machine.patch
 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