Package: openntpd
Version: 1:7.9p1-5
Severity: normal
Tags: patch
Control: found -1 1:6.2p3-4.2

Dear Maintainer,

When DNS does not answer, "/etc/init.d/openntpd restart" (and force-reload, which the if-up.d hook runs) can stop ntpd and not start it again. After
that, "start" prints "Already running." and returns 0, but no ntpd runs.

Cause: stop and restart run

    start-stop-daemon --stop --oknodo --quiet --retry=TERM/30/KILL/5 --user root --exec $DAEMON

which waits only for the root parent. The "dns engine" child runs as _ntpd, and in my tests with DNS blocked it outlived the parent. The next "start-stop-daemon --start" has no --user, finds the dns engine, starts nothing and returns 1; restart exits 1 (set -e), which the if-up.d hook ignores ("|| true"). "start" uses status_of_proc, which finds the dns engine too. (#773569 added --retry to this line; --user root stayed.)

What I ran: a sid minbase chroot with openntpd 1:7.9p1-5 and the default config, on a host running sysvinit (so no systemctl redirect), with the host's own ntpd stopped. In a private mount namespace, the chroot's /etc/resolv.conf pointed to 192.0.2.1 (TEST-NET-1); I did not trace the lookups themselves. Each trial started ntpd as the init script does, waited 3 or 18 s, ran "/etc/init.d/openntpd restart" and checked
2 s later. First trial (ps columns: pid, ppid, user, command):

    before:   2898069 2898060 root   /usr/sbin/ntpd -f /etc/openntpd/ntpd.conf
              2898071 2898069 _ntpd  ntpd: ntp engine
              2898072 2898071 _ntpd  ntpd: dns engine
    restart:  rc=1, output "Restarting openntpd: "
    after:    2898072       1 _ntpd  ntpd: dns engine
    ntpctl -s status: "ntpctl: connect: /run/openntpd/ntpd.sock: Connection refused"     start:    rc=0, output "Starting openntpd: Already running."; still no ntpd

Results, 10 trials per version (5 single restarts, 5 pairs of concurrent restarts): - unpatched, 1:7.9p1-5 (sid) and 1:6.2p3-4.2+b1 (bookworm, same setup without the chroot): 10 of 10 left only the dns engine running;
- patched as below, bookworm: 5 of 5 single restarts left one ntpd.

With working DNS, the unpatched script restarted correctly 30 of 30 times on bookworm.

Patch: drop --user root, so stop also waits for the _ntpd children.

--- a/debian/openntpd.init
+++ b/debian/openntpd.init
@@ -45,13 +45,13 @@

 stop)
     echo -n "Stopping $DESC: "
-    start-stop-daemon --stop --oknodo --quiet --retry=TERM/30/KILL/5 --user root --exec $DAEMON +    start-stop-daemon --stop --oknodo --quiet --retry=TERM/30/KILL/5 --exec $DAEMON
     echo "$NAME."
     ;;

 restart | force-reload)
     echo -n "Restarting $DESC: "
-    start-stop-daemon --stop --oknodo --quiet --retry=TERM/30/KILL/5 --user root --exec $DAEMON +    start-stop-daemon --stop --oknodo --quiet --retry=TERM/30/KILL/5 --exec $DAEMON
     start-stop-daemon --start --quiet --exec $DAEMON -- $DAEMON_OPTS
     echo "$NAME."
     ;;

Costs of this patch, measured on bookworm only:
- Slow restart while DNS does not answer: 45 s, where the unpatched restart returned at once. My hosts start ntpd with -s, which accounts for at most 15 s, so the timing fits stop reaching the 30 s TERM timeout and sending KILL; I did not trace the signals. The if-up.d hook runs force-reload, so ifup waits as long (cf. #898159). - Concurrent restarts: 3 of 5 pairs left TWO ntpd running. I now serialize the script locally with flock(1), after PATH=:

    LOCK=/run/openntpd.lock
    (umask 077; : >>$LOCK)
    [ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -o -w 120 $LOCK "$0" "$@" || :

  With a lock, 14 of 14 pairs left one ntpd (3 on sid with these lines, 11 on bookworm with earlier variants). I have seen concurrent hook runs only with a locally modified hook, so the package may not need it.

Not tested: systemd. openntpd.service sets no KillMode, so the default (control-group) should stop the dns engine too.

I found this because ntpd was found stopped on several of my bookworm hosts after the if-up.d hook had restarted it. Slow DNS in those cases is
unproven; the test above forces it.

I used AI assistants for the investigation and this draft; I carefully reviewed the report.

Regards,
Teodor Milkov

Reply via email to