Ncat 7.991 propagates SIGTERM to its caller's process group
Ncat 7.991 introduced a regression in listen mode: terminating Ncat can also terminate the shell or test runner that launched it.
This was introduced by eb31283031d476776cc9b2c261d73c9f6da53688 (Catch and propagate termination signals to children with -k).
The new signal handler propagates the received signal using:
kill(0, signum);kill(0, ...) signals every process in Ncat's current process group, not just Ncat's children. Ncat inherits its launcher's process group and does not create a separate one, so this can signal its parent shell and the surrounding test runner. The handler is also active for a listener that does not use -k.
We encountered this in the OVN system test suite. A test starts:
ncat -4 -l -u -p 1234 -d 0.1 -c catWhen the test cleanup sends SIGTERM to that Ncat process, Ncat broadcasts SIGTERM to the shared process group. This kills the Autotest runner, and the suite exits with status 143.
The following script is a deterministic reproducer on Linux. It uses setsid to contain the propagated signal, waits for a Unix socket to prove that Ncat is listening, and then terminates Ncat.
#!/bin/sh
set -eu
if [ "${1:-}" != --inner ]; then
# Isolate the test so a buggy Ncat cannot signal the invoking shell.
exec setsid --fork --wait sh "$0" --inner "$1"
fi
ncat=$2
socket="${TMPDIR:-/tmp}/ncat-sigterm-test.$$.sock"
pid=
cleanup() {
test -z "$pid" || kill -KILL "$pid" 2>/dev/null || true
rm -f "$socket"
}
trap cleanup EXIT
trap 'echo "FAIL: Ncat signalled its launcher"; exit 1' TERM
"$ncat" -l -U "$socket" </dev/null >/dev/null 2>&1 &
pid=$!
# Do not send SIGTERM until Ncat has entered listen mode.
i=0
while test ! -S "$socket"; do
kill -0 "$pid" 2>/dev/null || {
echo "ERROR: Ncat exited before listening"
exit 2
}
i=$((i + 1))
test "$i" -lt 100 || {
echo "ERROR: Ncat did not start listening"
exit 2
}
sleep 0.01
done
# Ncat 7.991 propagates this signal to the launcher through kill(0, ...).
kill -TERM "$pid"
if wait "$pid"; then
status=0
else
status=$?
fi
pid=
sleep 0.05
echo "PASS: launcher survived; Ncat status $status"Run it with the path to the Ncat binary:
$ sh ncat-sigterm-process-group-test.sh /path/to/ncatResults from released versions:
Ncat 7.99:
PASS: launcher survived; Ncat status 143
Ncat 7.991:
FAIL: Ncat signalled its launcherTherefore this worked with Ncat 7.99 and regressed in Ncat 7.991 after the referenced commit.
Source: nmap/nmap