diff --git a/04-ISSUES/361-the-control-nodes-agent-account-is-never-judged/01-diagnosis.md b/04-ISSUES/361-the-control-nodes-agent-account-is-never-judged/01-diagnosis.md index 4726fb50..b7906f1c 100644 --- a/04-ISSUES/361-the-control-nodes-agent-account-is-never-judged/01-diagnosis.md +++ b/04-ISSUES/361-the-control-nodes-agent-account-is-never-judged/01-diagnosis.md @@ -60,6 +60,30 @@ example; 36 is chosen because a full walk at idle priority on the control-node i with 26 hours a daily search longer than two hours would leave the account unjudged — and phone linking refused — every day until it finished. +## 2026-10-10 — the independent review, and what it changed + +An independent review of both pull requests asked four questions: can a stale or incomplete search yield "free"; +can the agent account steer the kept files or the walk; does the walk hurt the machine; do the controller and the +engine agree. What it found, and what was done: + +- **A cursor of a name that is not UTF-8 came back changed.** JSON strings replace such bytes, so a resumed walk + skipped every name that sorted between the real cursor and its replacement, and could finish "free" without + having read them. Any account can make such a name. The walk's paths are now kept as their bytes. +- **An ask to search again was lost to a restart**, and the restarted engine carried on the walk that started + before root acted. The ask now forgets the walk under way and stops it keeping progress. +- **A fresh search judged a filesystem it never walked.** A complete search now judges only while it walked every + filesystem a search would walk now; a filesystem mounted since makes the verdict "not judged yet" until walked. +- **A mount point inside a walked filesystem was read before it was known to be another filesystem.** A FUSE + mount root cannot read failed the walk, and a network mount whose server is away could hang it. Every mount + point the kernel lists is now left unread. Mount points are read with all the kernel's escapes. +- **A file found and gone before the package manager was asked failed every resumed search.** The walk looks at + what it found again when it ends, and drops what went or is no longer setuid-root. +- **Outcomes that moved nothing started a search**, and a search asked for could follow a walk of hours at once. + Only created, updated, corrected and removed outcomes count now, and an ask waits an hour from the last + search's end. +- **Not changed, because the mesh cannot do it:** the review asked that a file or archive declared setuid start a + search. The engine writes a file's and an archive's permission bits only, so neither carries a setuid bit. + ## Open, after the fix - **How long the first walk on the control-node takes is not measured.** Until the first complete search, the @@ -68,9 +92,17 @@ every day until it finished. raises the urgent condition, which is right: it is then not known to finish. - **The idle I/O class is honoured only by a disk scheduler that has classes** (BFQ). Under another scheduler the walk still runs at nice 19 but competes for the disk as any reader does. -- **An ask to search again is not kept across a restart.** An apply that moved root's things and a restart - before the next search starts lose the ask; the daily search covers it. The last complete search keeps - judging either way, on the reasoning in the report. +- **An ask to search again is not kept across a restart.** The walk under way is forgotten when it is asked, + so a restarted engine does not carry an older walk on; the ask itself is lost, and the daily search covers it. + The last complete search keeps judging meanwhile, on the reasoning in the report. +- **The agent account can make the search fail, never pass.** A tree deeper than the longest path the kernel + takes, or a directory unreadable to root through FUSE, ends every walk incomplete; a directory of millions of + entries makes the engine hold them all at once. Each is "not judged" — the urgent condition, and linking + refused — never a pass. Reading by directory handle, as `find` did, would close the first. +- **A filesystem mounted only on use** (an automounted boot partition) makes the verdict "not judged yet" each + time it appears unwalked, until a walk covers it. +- **Part of the walk's cost escapes its priority**: Go's garbage collector runs on threads of normal priority, + and a software RAID's own threads do not carry the idle class to the disks. - **ADR 0266 §3 item 10** still says "at most hourly" and "at most 15 minutes". On resolution it gains a progressive insight naming this issue and the values above. - **A later option, not built now:** a fanotify filesystem mark with `FAN_ATTRIB` (Linux 5.1 and later) on