]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
iptables-legacy: Fix for mandatory lock waiting
authorPhil Sutter <phil@nwl.cc>
Mon, 18 Dec 2023 23:56:07 +0000 (00:56 +0100)
committerPhil Sutter <phil@nwl.cc>
Thu, 21 Dec 2023 13:33:47 +0000 (14:33 +0100)
Parameter 'wait' passed to xtables_lock() signals three modes of
operation, depending on its value:

 0: --wait not specified, do not wait if lock is busy
-1: --wait specified without value, wait indefinitely until lock becomes
    free
>0: Wait for 'wait' seconds for lock to become free, abort otherwise

Since fixed commit, the first two cases were treated the same apart from
calling alarm(0), but that is a nop if no alarm is pending. Fix the code
by requesting a non-blocking flock() in the second case. While at it,
restrict the alarm setup to the third case only.

Cc: Jethro Beekman <jethro@fortanix.com>
Cc: howardjohn@google.com
Cc: Antonio Ojea <antonio.ojea.garcia@gmail.com>
Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1728
Fixes: 07e2107ef0cbc ("xshared: Implement xtables lock timeout using signals")
Signed-off-by: Phil Sutter <phil@nwl.cc>
iptables/tests/shell/testcases/iptables/0010-wait_0 [new file with mode: 0755]
iptables/xshared.c

diff --git a/iptables/tests/shell/testcases/iptables/0010-wait_0 b/iptables/tests/shell/testcases/iptables/0010-wait_0
new file mode 100755 (executable)
index 0000000..4481f96
--- /dev/null
@@ -0,0 +1,55 @@
+#!/bin/bash
+
+case "$XT_MULTI" in
+*xtables-legacy-multi)
+       ;;
+*)
+       echo skip $XT_MULTI
+       exit 0
+       ;;
+esac
+
+coproc RESTORE { $XT_MULTI iptables-restore; }
+echo "*filter" >&${RESTORE[1]}
+
+
+$XT_MULTI iptables -A FORWARD -j ACCEPT &
+ipt_pid=$!
+
+waitpid -t 1 $ipt_pid
+[[ $? -eq 3 ]] && {
+       echo "process waits when it should not"
+       exit 1
+}
+wait $ipt_pid
+[[ $? -eq 0 ]] && {
+       echo "process exited 0 despite busy lock"
+       exit 1
+}
+
+t0=$(date +%s)
+$XT_MULTI iptables -w 3 -A FORWARD -j ACCEPT
+t1=$(date +%s)
+[[ $((t1 - t0)) -ge 3 ]] || {
+       echo "wait time not expired"
+       exit 1
+}
+
+$XT_MULTI iptables -w -A FORWARD -j ACCEPT &
+ipt_pid=$!
+
+waitpid -t 3 $ipt_pid
+[[ $? -eq 3 ]] || {
+       echo "no indefinite wait"
+       exit 1
+}
+kill $ipt_pid
+waitpid -t 3 $ipt_pid
+[[ $? -eq 3 ]] && {
+       echo "killed waiting iptables call did not exit in time"
+       exit 1
+}
+
+kill $RESTORE_PID
+wait
+exit 0
index 5cae62b45cdf4bea8af931f9fdefb785d3fbbb47..43fa929df76763af0c7d1818f96cae890d6f7609 100644 (file)
@@ -270,7 +270,7 @@ static int xtables_lock(int wait)
                return XT_LOCK_FAILED;
        }
 
-       if (wait != -1) {
+       if (wait > 0) {
                sigact_alarm.sa_handler = alarm_ignore;
                sigact_alarm.sa_flags = SA_RESETHAND;
                sigemptyset(&sigact_alarm.sa_mask);
@@ -278,7 +278,7 @@ static int xtables_lock(int wait)
                alarm(wait);
        }
 
-       if (flock(fd, LOCK_EX) == 0)
+       if (flock(fd, LOCK_EX | (wait ? 0 : LOCK_NB)) == 0)
                return fd;
 
        if (errno == EINTR) {