#1151260 openntpd: init script restart can leave ntpd stopped while start says "Already running."

Package:
openntpd
Source:
openntpd
Description:
OpenBSD NTP daemon
Submitter:
Teodor Milkov
Date:
2026-10-19 09:37:02 UTC
Severity:
normal
Tags:
#1151260#5
Date:
2026-10-19 08:51:59 UTC
From:
To:
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