Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 05 Jul 2026 17:59:44 +0000
From:      bugzilla-noreply@freebsd.org
To:        bugs@FreeBSD.org
Subject:   [Bug 296542] local_unbound silently loses all syslog logging after a syslogd restart (chroot has no log socket)
Message-ID:  <bug-296542-227@https.bugs.freebsd.org/bugzilla/>

index | next in thread | raw e-mail

https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=296542

            Bug ID: 296542
           Summary: local_unbound silently loses all syslog logging after
                    a syslogd restart (chroot has no log socket)
           Product: Base System
           Version: 15.1-RELEASE
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Many People
          Priority: ---
         Component: bin
          Assignee: bugs@FreeBSD.org
          Reporter: xistence@0x58.com

`local_unbound` as configured by `local-unbound-setup(8)` runs chrooted to
`/var/unbound` (the setup script defaults `chrootdir="${workdir}"`,
`usr.sbin/unbound/setup/local-unbound-setup.sh` `set_chrootdir()`), and logs
via `syslog(3)` (unbound's `use-syslog` defaults to yes). The syslog
connection is established before the chroot, so logging works — until
`syslogd` is restarted. At that point the connected datagram socket to the
(now unlinked) `/var/run/log` goes stale; libc's automatic reconnect
(`lib/libc/gen/syslog.c`, "syslogd was restarted. In this case make one
(only) attempt to reconnect") resolves `_PATH_LOG` **inside the chroot**,
where no socket exists, and the `LOG_CONS` console fallback is equally
unreachable. Every subsequent message from unbound is silently dropped until
the daemon is restarted. There is no error visible anywhere.

The base system already ships the machinery to fix this —
`libexec/rc/rc.d/syslogd` builds extra `-l` listen sockets from
`altlog_proglist` + `${prog}_chrootdir` (rc.conf(5)) — but nothing wires
`local_unbound` into it, and `/etc/defaults/rc.conf` ships
`altlog_proglist=""`.

## Steps to reproduce (stock config, `local_unbound_enable=YES`)

```sh
# healthy: unbound logs (connection made pre-chroot at daemon start)
service local_unbound restart && sleep 1
grep -c 'Restart of unbound' /var/log/messages   # -> n

service syslogd restart && sleep 1

# broken: this reload logs "Restart of unbound ..." at notice level,
# but nothing arrives
service local_unbound reload && sleep 2
grep -c 'Restart of unbound' /var/log/messages   # -> still n

# only a daemon restart recovers (new pre-chroot connection)
service local_unbound restart && sleep 1
grep -c 'Restart of unbound' /var/log/messages   # -> n+1
```

Observed on a live resolver: after a syslogd restart, `procstat -f <pid>`
shows unbound's `root` vnode at `/var/unbound`, and reload/validation
messages never reach `/var/log/messages`.

## Verified workaround (uses existing rc machinery)

```sh
mkdir -p /var/unbound/var/run     # rc.d/syslogd does not create the dir
sysrc altlog_proglist="local_unbound" local_unbound_chrootdir="/var/unbound"
service syslogd restart
service local_unbound restart     # once, to recover the current process
```

After this, syslogd listens on `/var/unbound/var/run/log`
(`srw-rw-rw- root unbound`), and libc's in-chroot reconnect succeeds:
verified that unbound messages flow again immediately after further syslogd
restarts. (Per libc's one-shot reconnect semantics, the single message that
races a restart can still be lost — same as for any non-chrooted daemon.)

## Suggested fix

Wire the existing pieces together out of the box, e.g.:

1. `/etc/defaults/rc.conf`: `local_unbound_chrootdir="/var/unbound"`, and
   include `local_unbound` in the default `altlog_proglist` (the
   `rc.d/syslogd` loop already gates each entry on `checkyesno
   ${_l}_enable`, so it is a no-op unless local_unbound is enabled); and
2. have `rc.d/syslogd` (or `rc.d/local_unbound` via a precmd) create
   `${_ldir}/var/run` before adding the socket, since the directory does not
   exist in a fresh `local-unbound-setup` tree.

Alternatively `local-unbound-setup(8)` could emit the two rc.conf knobs when
it decides to chroot.

## Test evidence environment

All tests on FreeBSD 15.1-RELEASE-p1 amd64 (pkgbase), unbound 1.25.1
(FreeBSD-local-unbound pkg), default `local-unbound-setup` configuration.
truss excerpt of libc reconnect inside the casper service (healthy path,
for contrast):

```
sendto(4,"<13>1 2026-07-05T13:46:27...",90,0,NULL,0) ERR#54 'Connection reset
by peer'
socket(PF_LOCAL,SOCK_DGRAM|SOCK_CLOEXEC,0)  = 4
connect(4,{ AF_UNIX "/var/run/log" },106)   = 0
sendto(4,"<13>1 2026-07-05T13:46:27...",90,0,NULL,0) = 90
```

The chrooted unbound never reaches the successful `connect()` because the
path resolves inside `/var/unbound`.

-- 
You are receiving this mail because:
You are the assignee for the bug.

home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-296542-227>