]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 20 May 2018 07:47:49 +0000 (09:47 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 20 May 2018 07:47:49 +0000 (09:47 +0200)
added patches:
netfilter-nf_tables-can-t-fail-after-linking-rule-into-active-rule-list.patch

queue-4.9/netfilter-nf_tables-can-t-fail-after-linking-rule-into-active-rule-list.patch [new file with mode: 0644]
queue-4.9/series

diff --git a/queue-4.9/netfilter-nf_tables-can-t-fail-after-linking-rule-into-active-rule-list.patch b/queue-4.9/netfilter-nf_tables-can-t-fail-after-linking-rule-into-active-rule-list.patch
new file mode 100644 (file)
index 0000000..aafe74c
--- /dev/null
@@ -0,0 +1,110 @@
+From 569ccae68b38654f04b6842b034aa33857f605fe Mon Sep 17 00:00:00 2001
+From: Florian Westphal <fw@strlen.de>
+Date: Tue, 10 Apr 2018 09:30:27 +0200
+Subject: netfilter: nf_tables: can't fail after linking rule into active rule list
+
+From: Florian Westphal <fw@strlen.de>
+
+commit 569ccae68b38654f04b6842b034aa33857f605fe upstream.
+
+rules in nftables a free'd using kfree, but protected by rcu, i.e. we
+must wait for a grace period to elapse.
+
+Normal removal patch does this, but nf_tables_newrule() doesn't obey
+this rule during error handling.
+
+It calls nft_trans_rule_add() *after* linking rule, and, if that
+fails to allocate memory, it unlinks the rule and then kfree() it --
+this is unsafe.
+
+Switch order -- first add rule to transaction list, THEN link it
+to public list.
+
+Note: nft_trans_rule_add() uses GFP_KERNEL; it will not fail so this
+is not a problem in practice (spotted only during code review).
+
+Fixes: 0628b123c96d12 ("netfilter: nfnetlink: add batch support and use it from nf_tables")
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/netfilter/nf_tables_api.c |   59 ++++++++++++++++++++++--------------------
+ 1 file changed, 32 insertions(+), 27 deletions(-)
+
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -2200,41 +2200,46 @@ static int nf_tables_newrule(struct net
+       }
+       if (nlh->nlmsg_flags & NLM_F_REPLACE) {
+-              if (nft_is_active_next(net, old_rule)) {
+-                      trans = nft_trans_rule_add(&ctx, NFT_MSG_DELRULE,
+-                                                 old_rule);
+-                      if (trans == NULL) {
+-                              err = -ENOMEM;
+-                              goto err2;
+-                      }
+-                      nft_deactivate_next(net, old_rule);
+-                      chain->use--;
+-                      list_add_tail_rcu(&rule->list, &old_rule->list);
+-              } else {
++              if (!nft_is_active_next(net, old_rule)) {
+                       err = -ENOENT;
+                       goto err2;
+               }
+-      } else if (nlh->nlmsg_flags & NLM_F_APPEND)
+-              if (old_rule)
+-                      list_add_rcu(&rule->list, &old_rule->list);
+-              else
+-                      list_add_tail_rcu(&rule->list, &chain->rules);
+-      else {
+-              if (old_rule)
+-                      list_add_tail_rcu(&rule->list, &old_rule->list);
+-              else
+-                      list_add_rcu(&rule->list, &chain->rules);
+-      }
++              trans = nft_trans_rule_add(&ctx, NFT_MSG_DELRULE,
++                                         old_rule);
++              if (trans == NULL) {
++                      err = -ENOMEM;
++                      goto err2;
++              }
++              nft_deactivate_next(net, old_rule);
++              chain->use--;
++
++              if (nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE, rule) == NULL) {
++                      err = -ENOMEM;
++                      goto err2;
++              }
+-      if (nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE, rule) == NULL) {
+-              err = -ENOMEM;
+-              goto err3;
++              list_add_tail_rcu(&rule->list, &old_rule->list);
++      } else {
++              if (nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE, rule) == NULL) {
++                      err = -ENOMEM;
++                      goto err2;
++              }
++
++              if (nlh->nlmsg_flags & NLM_F_APPEND) {
++                      if (old_rule)
++                              list_add_rcu(&rule->list, &old_rule->list);
++                      else
++                              list_add_tail_rcu(&rule->list, &chain->rules);
++               } else {
++                      if (old_rule)
++                              list_add_tail_rcu(&rule->list, &old_rule->list);
++                      else
++                              list_add_rcu(&rule->list, &chain->rules);
++              }
+       }
+       chain->use++;
+       return 0;
+-err3:
+-      list_del_rcu(&rule->list);
+ err2:
+       nf_tables_rule_destroy(&ctx, rule);
+ err1:
index a8f9d676f12f2ff3177bb0430011538af4fa2413..b67130faf847e3e11b175187b048a6c7167cc1b7 100644 (file)
@@ -13,3 +13,4 @@ kvm-arm-arm64-vgic-its-protect-kvm_read_guest-calls-with-srcu-lock.patch
 powerpc-don-t-preempt_disable-in-show_cpuinfo.patch
 signals-avoid-unnecessary-taking-of-sighand-siglock.patch
 tracing-x86-xen-remove-zero-data-size-trace-events-trace_xen_mmu_flush_tlb-_all.patch
+netfilter-nf_tables-can-t-fail-after-linking-rule-into-active-rule-list.patch