From 02a6621a19b47ea29d68a8b57bec975e1675b167 Mon Sep 17 00:00:00 2001 From: Audiobuzz Date: Fri, 10 Jul 2026 09:57:34 +0000 Subject: [PATCH] image: SELinux allow fleet-agent to read chrony tracking.log under enforcing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tracking.log approach (4ca0b6d) works in permissive but is blocked under enforcing: chrony's log is labeled chronyd_var_log_t, confined by the shipped policy to chronyd_t despite the 0644 mode. Verified on comet-beacon-54 — a non-root read succeeds permissive, but under enforcing even a STIG-confined admin (staff_t) gets Permission denied (ls -Z on the file is itself blocked). The agent runs unconfined_service_t (confirmed via ps -eZ) and is denied the same way. Ship a minimal read-only allow module (files/stig/fleet-agent-chronylog.te): allow unconfined_service_t chronyd_var_log_t:file { open read getattr } + dir search to reach it. No write, no other chrony access, and no domain transition (the agent reads a file; it does not exec chronyc) — narrower than the abandoned nnp-transition module. Built + semodule -i'd in 2c-STIG alongside the existing chrony_dhcp_dispatcher / fapolicyd_tmpfs modules. docs/stig-deviations #16. Needs a workstation image rebuild + reboot; same policy-store-rebuild reproducibility re-check as #14/#15. --- diskless.pkr.hcl | 14 ++++++++++++ docs/stig-deviations.md | 32 ++++++++++++++++++++++++++ files/stig/fleet-agent-chronylog.te | 35 +++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 files/stig/fleet-agent-chronylog.te diff --git a/diskless.pkr.hcl b/diskless.pkr.hcl index 9bf6639..eb35a47 100644 --- a/diskless.pkr.hcl +++ b/diskless.pkr.hcl @@ -910,6 +910,20 @@ build { "semodule -i /tmp/fapolicyd_tmpfs.pp", "rm -f /tmp/fapolicyd_tmpfs.mod /tmp/fapolicyd_tmpfs.pp", "semodule -l | grep -q '^fapolicyd_tmpfs' && echo '==> SELinux module fapolicyd_tmpfs installed' || { echo 'ERROR: fapolicyd_tmpfs module not installed' >&2; exit 1; }", + # SELinux: let the fleet-agent READ chrony's tracking log. The agent + # (unconfined_service_t) reports clock health by reading + # /var/log/chrony/tracking.log (type chronyd_var_log_t), which the shipped + # policy confines to chronyd_t despite the 0644 mode -> denied under enforcing + # (seen on comet-beacon-54). A minimal read-only allow (no write, no domain + # transition). Installed unconditionally like the modules above (inert without + # the agent). checkpolicy ensured above. Same policy-store-rebuild + # reproducibility caveat as chrony/fapolicyd. docs/stig-deviations.md #16. + "echo '==> supplemental: SELinux module fleet_agent_chronylog (fleet-agent reads chrony tracking.log)'", + "checkmodule -M -m -o /tmp/fleet_agent_chronylog.mod /tmp/stig/fleet-agent-chronylog.te", + "semodule_package -o /tmp/fleet_agent_chronylog.pp -m /tmp/fleet_agent_chronylog.mod", + "semodule -i /tmp/fleet_agent_chronylog.pp", + "rm -f /tmp/fleet_agent_chronylog.mod /tmp/fleet_agent_chronylog.pp", + "semodule -l | grep -q '^fleet_agent_chronylog' && echo '==> SELinux module fleet_agent_chronylog installed' || { echo 'ERROR: fleet_agent_chronylog 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 5f019e8..0a346a3 100644 --- a/docs/stig-deviations.md +++ b/docs/stig-deviations.md @@ -248,6 +248,38 @@ surface rather than detecting abuse of it. Requires a write primitive to a root- path either way (already-privileged context), which is fapolicyd's defense-in-depth threat model — not an unprivileged bypass. +## 16. Local SELinux policy module `fleet_agent_chronylog` (added 2026-07-10) + +Not a STIG-rule waiver — a **minimal local read-only `allow` module** so the +`fleet-agent` telemetry client can read chrony's tracking log under enforcing +SELinux. Source: `files/stig/fleet-agent-chronylog.te`; built + `semodule -i`'d in +the 2c-STIG provisioner (after #15). + +**The rules:** `allow unconfined_service_t chronyd_var_log_t:file { open read +getattr };` (+ `dir { search getattr open }` to reach the file). + +**Why:** `fleet-agent` reports clock health (source/stratum/offset) by reading +`/var/log/chrony/tracking.log` — deliberately a FILE read rather than a query to +chronyd's command interface, which the hardened agent can't use (owner-write-only +unix socket; STIG's `cmdport 0` closes the UDP port). But chrony's log dir + files +are labeled `chronyd_var_log_t`, which the shipped policy confines to `chronyd_t` + +log-admin roles. So although the file is mode `0644`, under enforcing the agent +(`unconfined_service_t`) is **denied** by type enforcement — DAC allows, TE does +not. Verified 2026-07-10 on `comet-beacon-54`: with SELinux **permissive** a +non-root read of `tracking.log` succeeds; flip to **enforcing** and even a +STIG-confined admin (`staff_t`) gets `Permission denied` (`ls -Z` on the file is +itself blocked) — the signature of a type-enforcement block, not a DAC one. + +**Scope:** read-only (`open`/`read`/`getattr`) on one log type + dir search to +reach it. No write, no other chrony access, and — unlike the earlier abandoned +approach — **no domain transition** (the agent reads a file; it does not exec +`chronyc`). This replaces the never-shipped `fleet_agent_chronyc` nnp-transition +module (that whole command-socket path was dropped for reading the log instead). +**BENCH-VERIFY:** (a) the manager's Monitor chrony row populates on an enforcing +boot; (b) no other chrony-log AVC (extend here if one appears); (c) +**reproducibility** — `semodule -i` rebuilds the policy store, re-check verity hash +stability (same concern as #14/#15). Only shipped when `enable_stig=true`. + ## Things that are NOT deviations (kept / enforced) - **SELinux enforcing** (`selinux --enforcing`; labels preserved into the erofs). diff --git a/files/stig/fleet-agent-chronylog.te b/files/stig/fleet-agent-chronylog.te new file mode 100644 index 0000000..1ed8ff4 --- /dev/null +++ b/files/stig/fleet-agent-chronylog.te @@ -0,0 +1,35 @@ +# Raw module-policy syntax (compiled with `checkmodule -M -m`), NOT the refpolicy +# `policy_module()` m4 macro — that macro is only expanded by the refpolicy +# Makefile and checkmodule rejects it. See chrony-dhcp-dispatcher.te for the why. +module fleet_agent_chronylog 1.0.0; + +######################################## +# Let the fleet-agent READ chrony's tracking log under enforcing SELinux. +# +# fleet-agent (telemetry) reports clock health (source/stratum/offset) by reading +# /var/log/chrony/tracking.log (chronyd appends a line per clock update; enabled +# via `log tracking`). The agent runs as unconfined_service_t. chrony's log dir + +# files are labeled chronyd_var_log_t, and the shipped policy confines that type +# to chronyd_t + log-admin roles — so although the file is mode 0644, under +# enforcing the read is DENIED by type enforcement (DAC allows, TE does not). +# Verified 2026-07-10 on comet-beacon-54: with SELinux enforcing even a +# STIG-confined admin login (staff_t) gets "Permission denied" reading it, though +# a permissive-mode read succeeds — the tell-tale of a type-enforcement block. +# +# This grants ONLY read (open/read/getattr) on the chrony log type plus dir search +# to reach the file — no write, no other chrony access, and NO domain transition +# (the agent reads a file; it does not exec chronyc). Minimal + auditable; +# justified in docs/stig-deviations.md #16. BENCH-VERIFY: the manager's Monitor +# chrony row populates on an enforcing boot; extend here only if a related chrony +# log AVC appears. Same policy-store-rebuild reproducibility caveat as #14/#15. +######################################## + +require { + type unconfined_service_t; + type chronyd_var_log_t; + class dir { search getattr open }; + class file { open read getattr }; +} + +allow unconfined_service_t chronyd_var_log_t:dir { search getattr open }; +allow unconfined_service_t chronyd_var_log_t:file { open read getattr };