From 2568af12c3cf96a8b28082e6188dba94441b21c1 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Tue, 19 Dec 2023 00:56:07 +0100 Subject: [PATCH] iptables-legacy: Fix for mandatory lock waiting 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 Cc: howardjohn@google.com Cc: Antonio Ojea Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1728 Fixes: 07e2107ef0cbc ("xshared: Implement xtables lock timeout using signals") Signed-off-by: Phil Sutter (cherry picked from commit 63ab5b8906f6913a14d38ec231f21daa760339a9) --- .../shell/testcases/iptables/0010-wait_0 | 55 +++++++++++++++++++ iptables/xshared.c | 4 +- 2 files changed, 57 insertions(+), 2 deletions(-) create mode 100755 iptables/tests/shell/testcases/iptables/0010-wait_0 diff --git a/iptables/tests/shell/testcases/iptables/0010-wait_0 b/iptables/tests/shell/testcases/iptables/0010-wait_0 new file mode 100755 index 0000000000000..4481f966ce435 --- /dev/null +++ b/iptables/tests/shell/testcases/iptables/0010-wait_0 @@ -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 diff --git a/iptables/xshared.c b/iptables/xshared.c index 5f75a0a57a023..690502c457dd0 100644 --- a/iptables/xshared.c +++ b/iptables/xshared.c @@ -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) {