]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
iptables-restore: free the table lock when skipping a table
authorJoel Goguen <contact+netfilter@jgoguen.ca>
Wed, 11 Jul 2018 23:32:20 +0000 (16:32 -0700)
committerFlorian Westphal <fw@strlen.de>
Thu, 26 Jul 2018 13:04:29 +0000 (15:04 +0200)
Currently, when running `iptables-restore --table=X`, where `X` is not the first
table in the rules dump, the restore will fail when parsing the second table:

- a lock is acquird when parsing the first table name
- the table name does not match the parameter to `--table` so processing
  continues until the next table
- when processing the next table a lock is acquired, which fails because a lock
  is already held

Another app is currently holding the xtables lock. Perhaps you want to use the -w option?

This will release the lock as soon as it's decided the current table won't be
used.

Signed-off-by: Joel Goguen <contact+netfilter@jgoguen.ca>
Signed-off-by: Florian Westphal <fw@strlen.de>
iptables/ip6tables-restore.c
iptables/iptables-restore.c
iptables/tests/shell/testcases/ipt-restore/0001load-specific-table_0 [new file with mode: 0755]
iptables/tests/shell/testcases/ipt-restore/dumps/ip6tables.dump [new file with mode: 0644]
iptables/tests/shell/testcases/ipt-restore/dumps/iptables.dump [new file with mode: 0644]

index cc50bb4f557ebb3630b27e3cf70f5c8467a44d70..d36f92da45e181efa562dd86999884bdfc07f91d 100644 (file)
@@ -325,8 +325,13 @@ int ip6tables_restore_main(int argc, char *argv[])
                        strncpy(curtable, table, XT_TABLE_MAXNAMELEN);
                        curtable[XT_TABLE_MAXNAMELEN] = '\0';
 
-                       if (tablename != NULL && strcmp(tablename, table) != 0)
+                       if (tablename != NULL && strcmp(tablename, table) != 0) {
+                               if (lock >= 0) {
+                                       xtables_unlock(lock);
+                                       lock = XT_LOCK_NOT_ACQUIRED;
+                               }
                                continue;
+                       }
                        if (handle)
                                ops->free(handle);
 
index d5603fcec4f9b5c5d2a2a09d46456a598621773b..142ddb825ce6dde9489a29ef24b59462e13016cb 100644 (file)
@@ -323,8 +323,13 @@ iptables_restore_main(int argc, char *argv[])
                        strncpy(curtable, table, XT_TABLE_MAXNAMELEN);
                        curtable[XT_TABLE_MAXNAMELEN] = '\0';
 
-                       if (tablename && (strcmp(tablename, table) != 0))
+                       if (tablename && (strcmp(tablename, table) != 0)) {
+                               if (lock >= 0) {
+                                       xtables_unlock(lock);
+                                       lock = XT_LOCK_NOT_ACQUIRED;
+                               }
                                continue;
+                       }
                        if (handle)
                                ops->free(handle);
 
diff --git a/iptables/tests/shell/testcases/ipt-restore/0001load-specific-table_0 b/iptables/tests/shell/testcases/ipt-restore/0001load-specific-table_0
new file mode 100755 (executable)
index 0000000..ce3bef3
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+RET=0
+tmpfile=""
+
+set -x
+
+clean_tempfile()
+{
+       if [ -n "${tmpfile}" ]; then
+               rm -f "${tmpfile}"
+       fi
+}
+
+trap clean_tempfile EXIT
+
+tmpfile=$(mktemp) || exit 1
+
+do_simple()
+{
+       iptables="${1}"
+       table="${2}"
+       dumpfile="$(dirname "${0}")/dumps/${iptables}.dump"
+
+       "$XT_MULTI" "${iptables}-restore" --table="${table}" <"${dumpfile}"; rv=$?
+
+       if [ "${rv}" -ne 0 ]; then
+               RET=1
+       fi
+}
+
+do_simple "iptables" "filter"
+do_simple "iptables" "mangle"
+do_simple "iptables" "raw"
+do_simple "iptables" "nat"
+do_simple "ip6tables" "filter"
+do_simple "ip6tables" "mangle"
+do_simple "ip6tables" "raw"
+do_simple "ip6tables" "nat"
+
+exit "${RET}"
diff --git a/iptables/tests/shell/testcases/ipt-restore/dumps/ip6tables.dump b/iptables/tests/shell/testcases/ipt-restore/dumps/ip6tables.dump
new file mode 100644 (file)
index 0000000..4ac4f88
--- /dev/null
@@ -0,0 +1,30 @@
+*nat
+:PREROUTING ACCEPT [0:0]
+:INPUT ACCEPT [0:0]
+:OUTPUT ACCEPT [8:656]
+:POSTROUTING ACCEPT [8:656]
+COMMIT
+
+*mangle
+:PREROUTING ACCEPT [794:190738]
+:INPUT ACCEPT [794:190738]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [991:170303]
+:POSTROUTING ACCEPT [991:170303]
+COMMIT
+
+*raw
+:PREROUTING ACCEPT [794:190738]
+:OUTPUT ACCEPT [991:170303]
+COMMIT
+
+*filter
+:INPUT DROP [0:0]
+:FORWARD DROP [0:0]
+:OUTPUT ACCEPT [991:170303]
+-A INPUT -i lo -j ACCEPT
+-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
+-A INPUT -p ipv6-icmp -j ACCEPT
+-A OUTPUT -p tcp -m tcp --dport 137 -j REJECT --reject-with icmp6-port-unreachable
+-A OUTPUT -p udp -m udp --dport 137 -j REJECT --reject-with icmp6-port-unreachable
+COMMIT
diff --git a/iptables/tests/shell/testcases/ipt-restore/dumps/iptables.dump b/iptables/tests/shell/testcases/ipt-restore/dumps/iptables.dump
new file mode 100644 (file)
index 0000000..6e4e42d
--- /dev/null
@@ -0,0 +1,30 @@
+*nat
+:PREROUTING ACCEPT [1:89]
+:INPUT ACCEPT [0:0]
+:OUTPUT ACCEPT [351:24945]
+:POSTROUTING ACCEPT [351:24945]
+COMMIT
+
+*mangle
+:PREROUTING ACCEPT [3270:1513114]
+:INPUT ACCEPT [3270:1513114]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [3528:1087907]
+:POSTROUTING ACCEPT [3546:1090751]
+COMMIT
+
+*raw
+:PREROUTING ACCEPT [3270:1513114]
+:OUTPUT ACCEPT [3528:1087907]
+COMMIT
+
+*filter
+:INPUT DROP [37:4057]
+:FORWARD DROP [0:0]
+:OUTPUT ACCEPT [3528:1087907]
+-A INPUT -i lo -j ACCEPT
+-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
+-A INPUT -p icmp -j ACCEPT
+-A OUTPUT -p tcp -m tcp --dport 137 -j REJECT --reject-with icmp-port-unreachable
+-A OUTPUT -p udp -m udp --dport 137 -j REJECT --reject-with icmp-port-unreachable
+COMMIT