From 835ae7bc247ffcb3ea984bdb498fb927ebb5d2cf Mon Sep 17 00:00:00 2001 From: Audiobuzz Date: Fri, 3 Jul 2026 01:16:26 +0000 Subject: [PATCH] stig: ship SELinux allow module for chrony DHCP-NTP dispatcher (stop chronyd AVC) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The NM dispatcher 10-chrony-dhcp-ntp runs `chronyc reload sources` to load DHCP option-42 NTP servers. That chronyc runs in the confined custom-dispatcher domain (NetworkManager_dispatcher_custom_t), so its reply socket carries that label and the shipped policy has no rule for chronyd_t to sendto it. Under enforcing, chronyd does the reload but its ack is denied — chronyc reports failure and the AVC floods the SIEM (seen 2026-07-03; permissive=1 only because the box was booted enforcing=0). Ship a minimal local allow module (files/stig/chrony-dhcp-dispatcher.te): allow chronyd_t NetworkManager_dispatcher_custom_t:unix_dgram_socket sendto; Built + semodule -i'd in the 2c-STIG provisioner (checkpolicy installed if absent), with an install assertion. `allow` not `dontaudit` — it also lets the reload ack succeed so chronyc returns cleanly. Documented as docs/stig-deviations.md #14 (not a rule waiver — a local functional allow). BENCH-VERIFY: enforcing boot shows no AVC, chronyc reload returns 0, a DHCP-handed NTP server appears in `chronyc sources`; and re-check verity-hash reproducibility (semodule rebuilds the policy store, like the semanage step). --- diskless.pkr.hcl | 14 ++++++++++++++ docs/stig-deviations.md | 29 ++++++++++++++++++++++++++++ files/stig/chrony-dhcp-dispatcher.te | 21 ++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 files/stig/chrony-dhcp-dispatcher.te diff --git a/diskless.pkr.hcl b/diskless.pkr.hcl index 68454f8..4e5fc87 100644 --- a/diskless.pkr.hcl +++ b/diskless.pkr.hcl @@ -716,6 +716,20 @@ build { "evaluated=$(grep -oE '(pass|fixed|fail)' /root/stig-arf.xml | wc -l)", "[ \"$evaluated\" -gt 0 ] || { echo 'ERROR: STIG scan evaluated 0 rules (all notapplicable/notselected) — SSG datastream/CPE mismatch for this distro. Hardening did NOT run; aborting.' >&2; exit 1; }", "echo \"==> STIG scan evaluated $evaluated rules (pass/fixed/fail)\"", + # SELinux: allow chronyd to reply to the chronyc our NM dispatcher runs for + # DHCP option-42 NTP (10-chrony-dhcp-ntp -> `chronyc reload sources`). The + # dispatcher's confined domain (NetworkManager_dispatcher_custom_t) labels + # chronyc's reply socket, and the shipped policy denies chronyd_t sendto to + # it -> AVC flood + failed reload under enforcing. Ship a minimal allow + # module (docs/stig-deviations.md). NB: rebuilds the policy store — include + # in the reproducibility check alongside semanage (verity hash stability). + "echo '==> supplemental: SELinux module chrony_dhcp_dispatcher (chronyd reply to NM-dispatcher chronyc)'", + "command -v checkmodule >/dev/null 2>&1 || dnf install -y checkpolicy", + "checkmodule -M -m -o /tmp/chrony_dhcp_dispatcher.mod /tmp/stig/chrony-dhcp-dispatcher.te", + "semodule_package -o /tmp/chrony_dhcp_dispatcher.pp -m /tmp/chrony_dhcp_dispatcher.mod", + "semodule -i /tmp/chrony_dhcp_dispatcher.pp", + "rm -f /tmp/chrony_dhcp_dispatcher.mod /tmp/chrony_dhcp_dispatcher.pp", + "semodule -l | grep -q '^chrony_dhcp_dispatcher' && echo '==> SELinux module chrony_dhcp_dispatcher installed' || { echo 'ERROR: chrony_dhcp_dispatcher module not installed' >&2; exit 1; }", "rm -rf /tmp/stig", "echo '==> STIG remediation complete (report at /root/stig-report.html, ARF at /root/stig-arf.xml)'", ] diff --git a/docs/stig-deviations.md b/docs/stig-deviations.md index f6024f4..b229d0e 100644 --- a/docs/stig-deviations.md +++ b/docs/stig-deviations.md @@ -138,6 +138,35 @@ down (kiosk autologin to a single locked browser; no getty shell on tty1; `debug_shell` is lab-only and never shipped). If a future deployment wants the hotkey disabled (e.g. a physically exposed terminal), re-select both rule IDs. +## 14. Local SELinux policy module `chrony_dhcp_dispatcher` (added 2026-07-03) + +Not a STIG-rule waiver — a **minimal local `allow` module** shipped to keep a +legitimate function working under enforcing SELinux. Source: +`files/stig/chrony-dhcp-dispatcher.te`; built + `semodule -i`'d in the 2c-STIG +provisioner. + +**The one rule:** `allow chronyd_t NetworkManager_dispatcher_custom_t:unix_dgram_socket sendto;` + +**Why:** the NM dispatcher script `10-chrony-dhcp-ntp` loads DHCP option-42 NTP +servers by running `chronyc reload sources`. That `chronyc` runs in the confined +custom-dispatcher domain (`NetworkManager_dispatcher_custom_t`), so its reply +socket carries that label; the shipped policy has no rule for `chronyd_t` to +`sendto` it. Under enforcing, chronyd processes the reload but its **ack is +denied** — `chronyc` reports failure and the AVC floods the SIEM (seen +2026-07-03). An **`allow`** (not `dontaudit`) is used deliberately: it both stops +the noise and lets the reload ack succeed, so `chronyc` returns cleanly. + +**Scope:** one direction, one class/perm, two well-known types. It grants no +network/file access and nothing beyond the chronyd↔dispatcher reply the DHCP-NTP +path needs. **BENCH-VERIFY:** (a) on an *enforcing* boot the AVC is gone and +`chronyc reload sources` from the dispatcher returns 0 (confirm a DHCP-handed NTP +server appears in `chronyc sources`); (b) no follow-on AVC (extend the `.te` if +one shows); (c) **reproducibility** — `semodule -i` rebuilds the policy store, so +re-check the verity hash is stable across two builds (same concern as the +`semanage` step, #12/sudo elevation). NB: only shipped when `enable_stig=true` +(the module install lives in the STIG-gated provisioner); a non-STIG *enforcing* +build would still see the AVC. + ## Things that are NOT deviations (kept / enforced) - **SELinux enforcing** (`selinux --enforcing`; labels preserved into the erofs). diff --git a/files/stig/chrony-dhcp-dispatcher.te b/files/stig/chrony-dhcp-dispatcher.te new file mode 100644 index 0000000..1ad644e --- /dev/null +++ b/files/stig/chrony-dhcp-dispatcher.te @@ -0,0 +1,21 @@ +policy_module(chrony_dhcp_dispatcher, 1.0.0) + +######################################## +# Let chronyd reply to the chronyc that our NetworkManager dispatcher script +# runs. files/etc/NetworkManager/dispatcher.d/10-chrony-dhcp-ntp loads DHCP +# option-42 NTP servers with `chronyc reload sources`. That chronyc runs in the +# confined custom-dispatcher domain (NetworkManager_dispatcher_custom_t), so its +# reply socket is labeled with that domain, and the shipped policy has no rule +# for chronyd_t -> that socket. Result (enforcing): chronyd processes the reload +# but its ack `sendto` is DENIED — chronyc reports failure and the AVC floods the +# SIEM. This one allow closes it. Minimal + auditable; justified in +# docs/stig-deviations.md. If a follow-on AVC appears on the bench, extend here. +######################################## + +require { + type chronyd_t; + type NetworkManager_dispatcher_custom_t; + class unix_dgram_socket sendto; +} + +allow chronyd_t NetworkManager_dispatcher_custom_t:unix_dgram_socket sendto;