Commit 4f125e14 by PLN (Algolia)

fix(protect): the installer was not idempotent, so the fix did not take

Reinstalled after adding CAP_DAC_OVERRIDE and nothing changed: the unit on disk
was correct, daemon-reload had run, NeedDaemonReload said no — and the running
process still held the old three capabilities, same PID and start time as before
the install.

`systemctl enable --now` starts a STOPPED unit and does nothing to a RUNNING
one. So every re-install silently kept the previous daemon, with the previous
unit's capabilities and the previous script's inode, while printing success.

- restart instead of enable --now (it holds no ports and makes no sound)
- assert the LIVE /proc capability set after restart, and say plainly that
  protection is decoration until that line reads ok

Third layer of one lesson tonight: a correct file on disk is not a correct
process in memory.
parent 22a045be
...@@ -36,12 +36,43 @@ install -o root -g root -m 0755 "$SRC_DIR/parvagues-protect.sh" "$BIN" ...@@ -36,12 +36,43 @@ install -o root -g root -m 0755 "$SRC_DIR/parvagues-protect.sh" "$BIN"
install -o root -g root -m 0644 "$SRC_DIR/parvagues-protect.service" "$UNIT" install -o root -g root -m 0644 "$SRC_DIR/parvagues-protect.service" "$UNIT"
systemctl daemon-reload systemctl daemon-reload
systemctl enable --now parvagues-protect.service systemctl enable parvagues-protect.service
# `enable --now` starts a STOPPED unit and does nothing to a RUNNING one, so a
# re-install left the previous daemon alive holding the previous unit's
# capabilities and the previous script's inode — the installer printed success
# while nothing it had just written was in effect. That is how the missing
# CAP_DAC_OVERRIDE survived being fixed (2026-09-06): correct file on disk,
# stale process in memory, same PID and start time as before the install.
# Always restart; this daemon holds no ports and makes no sound, so a restart
# costs nothing.
systemctl restart parvagues-protect.service
sleep 3 sleep 3
echo echo
systemctl --no-pager --lines=8 status parvagues-protect.service || true systemctl --no-pager --lines=8 status parvagues-protect.service || true
echo echo
# Assert the RUNNING process holds what the unit asked for. A correct file on
# disk is not a correct process in memory, and that gap is this installer's one
# historical failure mode — so check the live /proc, not our own good intentions.
echo "--- daemon capabilities (must include cap_dac_override) ---"
if command -v capsh >/dev/null 2>&1; then
pid=$(systemctl show -p MainPID --value parvagues-protect.service)
eff=$(sed -n 's/^CapEff:[[:space:]]*//p' "/proc/$pid/status" 2>/dev/null || true)
have=$(capsh --decode="${eff:-0}" 2>/dev/null | sed -n 's/^0x[0-9a-f]*=//p' || true)
case ",${have}," in
*,cap_dac_override,*)
echo "ok pid $pid: ${have}" ;;
*)
echo "FAIL pid $pid holds [${have:-none}] — cap_dac_override is MISSING, so the" >&2
echo " daemon cannot open another user's /proc/<pid>/oom_score_adj (mode 0644," >&2
echo " owned by the process owner) and every write will return EACCES while" >&2
echo " id -u still says 0. Protection is decoration until this line says ok." >&2 ;;
esac
else
echo "skip capsh not installed (libcap2-bin) — cannot verify the live capability set"
fi
echo
echo "--- current protection ---" echo "--- current protection ---"
"$BIN" --check || true "$BIN" --check || true
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment