secure-ntp: label /run/chrony-dhcp so chronyd can read the NTS source under SELinux
Second bench defect after removing the distro 20-chrony-dhcp clobberer (secure-ntp-5a3eaed, comet-beacon-54): the dispatcher wrote the correct `server ntp.fleet.lab iburst nts` line, but chrony loaded ZERO sources -- `chronyc reload sources` returned 200 OK yet authdata/sources stayed empty. Root cause (AVC): chronyd_t was DENIED read on the .sources files because they and /run/chrony-dhcp itself were labeled generic var_run_t; chronyd_t may only read its own chronyd_var_run_t. The dispatcher's `mkdir -p` creates the dir as var_run_t and files inherit it. The distro 20-chrony-dhcp we removed had been restorecon-ing them to the readable label, so removing it exposed a latent labelling gap. Stock RHEL policy already maps /run/chrony-dhcp -> chronyd_var_run_t (a restorecon relabels it and chrony immediately reaches NTS Cook 8). Fix: ship /etc/tmpfiles.d/chrony-dhcp.conf so systemd-tmpfiles pre-creates the dir with that fcontext at sysinit, before any NM event -- the dispatcher's files then inherit chronyd_var_run_t and chronyd can read them. No SELinux allow rules needed (bench-verified: after the fix a real NM event wrote the source as chronyd_var_run_t, no AVC, authdata -> NTS Cook 8). Applies in both secure_ntp modes. Also: the dispatcher now skips `lo` -- it was writing a spurious lo.sources duplicate of the same server (the distro script had skipped loopback). BENCH-VERIFY on the next clean build: a normal boot leaves the source file labeled chronyd_var_run_t (ls -Z), no lo.sources, and authdata reaches NTS/cookies>0 with no manual step.
This commit is contained in:
@@ -27,7 +27,11 @@
|
||||
# /usr/lib/NetworkManager/dispatcher.d/20-chrony-dhcp writing option-42 servers to
|
||||
# the SAME <iface>.sources. NM merges /etc + /usr/lib sorted by name, so it runs
|
||||
# AFTER us and would clobber the NTS line — the provisioner removes it (it defeated
|
||||
# NTS on the bench: chrony fell back to plain NTP). This script supersedes it.
|
||||
# NTS on the bench: chrony fell back to plain NTP). This script supersedes it. It
|
||||
# was ALSO (accidentally) labelling the sources chronyd_var_run_t so chronyd could
|
||||
# read them; we restore that via /etc/tmpfiles.d/chrony-dhcp.conf (see the dir note
|
||||
# below) — without it, under enforcing SELinux chronyd can't read the sources and
|
||||
# loads nothing (bench 2026-07-12).
|
||||
|
||||
MODE="@NTP_MODE@" # nts | dhcp
|
||||
PREFIX="@NTP_PREFIX@" # nts: server name = <PREFIX>.<dhcp-domain>
|
||||
@@ -40,6 +44,15 @@ case "$action" in
|
||||
*) exit 0 ;;
|
||||
esac
|
||||
|
||||
# Loopback carries no DHCP NTP config; acting on it just writes a spurious
|
||||
# lo.sources duplicate of the same server (the distro 20-chrony-dhcp skipped lo —
|
||||
# we must too, or chrony sees two files for one server). Skip it.
|
||||
[ "$interface" = lo ] && exit 0
|
||||
|
||||
# /run/chrony-dhcp is pre-created with the chronyd_var_run_t SELinux label by
|
||||
# /etc/tmpfiles.d/chrony-dhcp.conf at boot, so the files we write below inherit a
|
||||
# label chronyd_t can READ (else, under enforcing, chronyd is denied and loads no
|
||||
# sources — bench 2026-07-12). This mkdir is just a fallback if tmpfiles didn't run.
|
||||
dir=/run/chrony-dhcp
|
||||
file="$dir/${interface}.sources"
|
||||
mkdir -p "$dir"
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# Pre-create chrony's runtime NTP source directory with the CORRECT SELinux label
|
||||
# at boot, before any NetworkManager event fires. The NM dispatcher
|
||||
# (10-chrony-dhcp-ntp) writes <iface>.sources here for chronyd's
|
||||
# `sourcedir /run/chrony-dhcp`.
|
||||
#
|
||||
# Why this exists: the dispatcher's own `mkdir -p /run/chrony-dhcp` creates the dir
|
||||
# as generic `var_run_t`, and the source files inherit it — but `chronyd_t` is only
|
||||
# allowed to read `chronyd_var_run_t`, so under enforcing SELinux chronyd is DENIED
|
||||
# reading them and silently loads ZERO sources (bench 2026-07-12, comet-beacon-54:
|
||||
# NTS never activated — `chronyc authdata` empty; AVC `denied { read } … chronyd_t
|
||||
# … var_run_t`). The stock RHEL policy already maps /run/chrony-dhcp →
|
||||
# `chronyd_var_run_t`, and systemd-tmpfiles applies that fcontext when it creates
|
||||
# the dir here at sysinit (well before the dispatcher runs). Files the dispatcher
|
||||
# then creates inside inherit `chronyd_var_run_t`, so chronyd can read them — no
|
||||
# SELinux allow rules needed (verified on the bench).
|
||||
#
|
||||
# The distro chrony NM dispatcher (/usr/lib/.../20-chrony-dhcp) used to apply this
|
||||
# label via a per-file restorecon; we removed it because it clobbered our NTS source
|
||||
# (see diskless.pkr.hcl + the 10-chrony-dhcp-ntp header), so we restore the labelling
|
||||
# here instead. Needed in BOTH secure_ntp modes (chronyd must read the sourcedir
|
||||
# either way).
|
||||
d /run/chrony-dhcp 0755 root root - -
|
||||
Reference in New Issue
Block a user