Blob Blame History Raw
From 7eff52fa9a7fe21549486e4c92869303f2dc9759 Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Wed, 17 Apr 2019 15:57:22 -0400
Subject: [PATCH 29/73] fix: ipXtables: don't use tables that aren't available

At least for the default ruleset we can avoid failure if some of these
tables are missing. But features that use those missing tables will
still fail if the user attempts to use those features.

Here is a probably incomplete mapping of tables -> features:

  raw:	    helpers, IPv6_rpfilter
  mangle:   rich rule mark action
  nat:	    masquerade, forward ports
  security: none

Of course, direct rules apply to all tables. It is fatal if the "filter"
table is not available.

Fixes: #411
Fixes: #484
(cherry picked from commit c46b0892e1e4a540c959b4c1f6ea87de50d1bcf8)
(cherry picked from commit 1dfbd1b2ba848e281876f7e40b47b8bc18a6d305)
---
 src/firewall/core/ipXtables.py | 104 ++++++++++++++++++---------------
 1 file changed, 56 insertions(+), 48 deletions(-)

diff --git a/src/firewall/core/ipXtables.py b/src/firewall/core/ipXtables.py
index c21dc47457b3..4a9c06242f08 100644
--- a/src/firewall/core/ipXtables.py
+++ b/src/firewall/core/ipXtables.py
@@ -449,6 +449,8 @@ class ip4tables(object):
     def build_flush_rules(self):
         rules = []
         for table in BUILT_IN_CHAINS.keys():
+            if not self.get_available_tables(table):
+                continue
             # Flush firewall rules: -F
             # Delete firewall chains: -X
             # Set counter to zero: -Z
@@ -459,6 +461,8 @@ class ip4tables(object):
     def build_set_policy_rules(self, policy):
         rules = []
         for table in BUILT_IN_CHAINS.keys():
+            if not self.get_available_tables(table):
+                continue
             if table == "nat":
                 continue
             for chain in BUILT_IN_CHAINS[table]:
@@ -505,54 +509,58 @@ class ip4tables(object):
     def build_default_rules(self, log_denied="off"):
         default_rules = {}
 
-        default_rules["security"] = [ ]
-        self.our_chains["security"] = set()
-        for chain in BUILT_IN_CHAINS["security"]:
-            default_rules["security"].append("-N %s_direct" % chain)
-            default_rules["security"].append("-A %s -j %s_direct" % (chain, chain))
-            self.our_chains["security"].add("%s_direct" % chain)
-
-        default_rules["raw"] = [ ]
-        self.our_chains["raw"] = set()
-        for chain in BUILT_IN_CHAINS["raw"]:
-            default_rules["raw"].append("-N %s_direct" % chain)
-            default_rules["raw"].append("-A %s -j %s_direct" % (chain, chain))
-            self.our_chains["raw"].add("%s_direct" % chain)
-
-            if chain == "PREROUTING":
-                default_rules["raw"].append("-N %s_ZONES_SOURCE" % chain)
-                default_rules["raw"].append("-N %s_ZONES" % chain)
-                default_rules["raw"].append("-A %s -j %s_ZONES_SOURCE" % (chain, chain))
-                default_rules["raw"].append("-A %s -j %s_ZONES" % (chain, chain))
-                self.our_chains["raw"].update(set(["%s_ZONES_SOURCE" % chain, "%s_ZONES" % chain]))
-
-        default_rules["mangle"] = [ ]
-        self.our_chains["mangle"] = set()
-        for chain in BUILT_IN_CHAINS["mangle"]:
-            default_rules["mangle"].append("-N %s_direct" % chain)
-            default_rules["mangle"].append("-A %s -j %s_direct" % (chain, chain))
-            self.our_chains["mangle"].add("%s_direct" % chain)
-
-            if chain == "PREROUTING":
-                default_rules["mangle"].append("-N %s_ZONES_SOURCE" % chain)
-                default_rules["mangle"].append("-N %s_ZONES" % chain)
-                default_rules["mangle"].append("-A %s -j %s_ZONES_SOURCE" % (chain, chain))
-                default_rules["mangle"].append("-A %s -j %s_ZONES" % (chain, chain))
-                self.our_chains["mangle"].update(set(["%s_ZONES_SOURCE" % chain, "%s_ZONES" % chain]))
-
-        default_rules["nat"] = [ ]
-        self.our_chains["nat"] = set()
-        for chain in BUILT_IN_CHAINS["nat"]:
-            default_rules["nat"].append("-N %s_direct" % chain)
-            default_rules["nat"].append("-A %s -j %s_direct" % (chain, chain))
-            self.our_chains["nat"].add("%s_direct" % chain)
-
-            if chain in [ "PREROUTING", "POSTROUTING" ]:
-                default_rules["nat"].append("-N %s_ZONES_SOURCE" % chain)
-                default_rules["nat"].append("-N %s_ZONES" % chain)
-                default_rules["nat"].append("-A %s -j %s_ZONES_SOURCE" % (chain, chain))
-                default_rules["nat"].append("-A %s -j %s_ZONES" % (chain, chain))
-                self.our_chains["nat"].update(set(["%s_ZONES_SOURCE" % chain, "%s_ZONES" % chain]))
+        if self.get_available_tables("security"):
+            default_rules["security"] = [ ]
+            self.our_chains["security"] = set()
+            for chain in BUILT_IN_CHAINS["security"]:
+                default_rules["security"].append("-N %s_direct" % chain)
+                default_rules["security"].append("-A %s -j %s_direct" % (chain, chain))
+                self.our_chains["security"].add("%s_direct" % chain)
+
+        if self.get_available_tables("raw"):
+            default_rules["raw"] = [ ]
+            self.our_chains["raw"] = set()
+            for chain in BUILT_IN_CHAINS["raw"]:
+                default_rules["raw"].append("-N %s_direct" % chain)
+                default_rules["raw"].append("-A %s -j %s_direct" % (chain, chain))
+                self.our_chains["raw"].add("%s_direct" % chain)
+
+                if chain == "PREROUTING":
+                    default_rules["raw"].append("-N %s_ZONES_SOURCE" % chain)
+                    default_rules["raw"].append("-N %s_ZONES" % chain)
+                    default_rules["raw"].append("-A %s -j %s_ZONES_SOURCE" % (chain, chain))
+                    default_rules["raw"].append("-A %s -j %s_ZONES" % (chain, chain))
+                    self.our_chains["raw"].update(set(["%s_ZONES_SOURCE" % chain, "%s_ZONES" % chain]))
+
+        if self.get_available_tables("mangle"):
+            default_rules["mangle"] = [ ]
+            self.our_chains["mangle"] = set()
+            for chain in BUILT_IN_CHAINS["mangle"]:
+                default_rules["mangle"].append("-N %s_direct" % chain)
+                default_rules["mangle"].append("-A %s -j %s_direct" % (chain, chain))
+                self.our_chains["mangle"].add("%s_direct" % chain)
+
+                if chain == "PREROUTING":
+                    default_rules["mangle"].append("-N %s_ZONES_SOURCE" % chain)
+                    default_rules["mangle"].append("-N %s_ZONES" % chain)
+                    default_rules["mangle"].append("-A %s -j %s_ZONES_SOURCE" % (chain, chain))
+                    default_rules["mangle"].append("-A %s -j %s_ZONES" % (chain, chain))
+                    self.our_chains["mangle"].update(set(["%s_ZONES_SOURCE" % chain, "%s_ZONES" % chain]))
+
+        if self.get_available_tables("nat"):
+            default_rules["nat"] = [ ]
+            self.our_chains["nat"] = set()
+            for chain in BUILT_IN_CHAINS["nat"]:
+                default_rules["nat"].append("-N %s_direct" % chain)
+                default_rules["nat"].append("-A %s -j %s_direct" % (chain, chain))
+                self.our_chains["nat"].add("%s_direct" % chain)
+
+                if chain in [ "PREROUTING", "POSTROUTING" ]:
+                    default_rules["nat"].append("-N %s_ZONES_SOURCE" % chain)
+                    default_rules["nat"].append("-N %s_ZONES" % chain)
+                    default_rules["nat"].append("-A %s -j %s_ZONES_SOURCE" % (chain, chain))
+                    default_rules["nat"].append("-A %s -j %s_ZONES" % (chain, chain))
+                    self.our_chains["nat"].update(set(["%s_ZONES_SOURCE" % chain, "%s_ZONES" % chain]))
 
         default_rules["filter"] = [
             "-N INPUT_direct",
-- 
2.20.1