From 2f5608b4897ff99afbb1c2425a94df035031c1a2 Mon Sep 17 00:00:00 2001
From: Eric Garver <e@erig.me>
Date: Mon, 3 Dec 2018 12:40:41 -0500
Subject: [PATCH 043/127] nftables: fix panic mode not filtering output packets

This simplifies policy in the nftables backend by filtering only on the
prerouting and output hooks. The others hooks are unnecessary since
we're using a higher precedence.

Also fixes an issue when re-enabling panic mode multiple times. Due to
rule de-duplication the policy drop rule was not being re-added.

Fixes: rhbz 1579740
Fixes: a0f683dfef2c ("nftables: fix policy")
---
 src/firewall/core/nftables.py | 36 +++++++++--------------------------
 1 file changed, 9 insertions(+), 27 deletions(-)

diff --git a/src/firewall/core/nftables.py b/src/firewall/core/nftables.py
index 69236a96..44cd4f9e 100644
--- a/src/firewall/core/nftables.py
+++ b/src/firewall/core/nftables.py
@@ -314,38 +314,20 @@ class nftables(object):
         # packets while initially starting and for panic mode. As such, using
         # hooks with a higher priority than our base chains is sufficient.
         #
-        table_chains = []
-        for table in list(IPTABLES_TO_NFT_HOOK.keys()):
-            for chain in IPTABLES_TO_NFT_HOOK[table]:
-                table_chains.append((table, chain))
-
         table_name = TABLE_NAME + "_" + "policy_drop"
 
-        def _policy_drop_helper(table, chain, family, rules):
-            _chain = "%s_%s" % (table, chain)
-            _hook = IPTABLES_TO_NFT_HOOK[table][chain][0]
-            # add hooks with priority -1, only contain drop rule
-            _priority = IPTABLES_TO_NFT_HOOK[table][chain][1] - 1
-            _add_chain = "add chain %s %s %s '{ type filter hook %s priority %d ; }'" % \
-                         (family, table_name, _chain, _hook, _priority)
-            rules.append(splitArgs(_add_chain))
-            rules.append(["add", "rule", family, table_name, _chain, "drop"])
-
         rules = []
         if policy == "DROP":
-            for family in ["inet", "ip", "ip6"]:
-                rules.append(["add", "table", family, table_name])
-
-            for table,chain in table_chains:
-                if table == "nat":
-                    # nat requires two families
-                    for family in ["ip", "ip6"]:
-                        _policy_drop_helper(table, chain, family, rules)
-                else:
-                    _policy_drop_helper(table, chain, "inet", rules)
+            rules.append(["add", "table", "inet", table_name])
+
+            # To drop everything we need to use the "raw" priority. These occur
+            # before conntrack, mangle, nat, etc
+            for hook in ["prerouting", "output"]:
+                _add_chain = "add chain inet %s %s_%s '{ type filter hook %s priority %d ; policy drop ; }'" % \
+                             (table_name, "raw", hook, hook, -300 + NFT_HOOK_OFFSET - 1)
+                rules.append(splitArgs(_add_chain))
         elif policy == "ACCEPT":
-            for family in ["inet", "ip", "ip6"]:
-                rules.append(["delete", "table", family, table_name])
+            rules.append(["delete", "table", "inet", table_name])
         else:
             FirewallError(UNKNOWN_ERROR, "not implemented")
 
-- 
2.19.1

