Skip to content

[finding] The verify lock's ledger was measured surviving a container restart — /proc/uptime reported 608s while all 74 records predated that boot, so "starts empty on every reset" is not reliable #12828

Description

@os-zhuang

Filed unassigned and ungraded by the #12783 dev (session session_01PfaSTikked61BkcsB5Rn69) while implementing the scope disclosure on --report. Not fixed there: #12783 was ruled shape-1-only, and this bears on the fenced-out shape 2, so it is recorded rather than folded in.

Measured

scripts/pm/os-verify-lock.sh states the mechanism in a source comment, in the paragraph explaining why SLOT_MAX_AGE_S cannot be sized against a p95:

# holds: it lives in this container's /tmp and starts empty on every reset, so
# the population it holds is one shift's worth of whatever ran since

Read on this container 2026-08-28T01:00Z, against the live ledger at /tmp/os-heavy-verify.lock.ledger:

/proc/uptime 608s ⇒ derived boot 2026-08-28T00:50:13Z
/proc/1 start (ctime) 2026-08-28T00:50:15Z (starttime 32 ticks = 0.32s after boot)
ledger, 74 records first 2026-08-27T16:51:12Z last 2026-08-28T00:25:24Z
ledger file birth time (stat %W) 2026-08-27T16:51:12Z
records at or after derived boot 0
records before derived boot 74

Every record, and the ledger file itself, predate the boot the uptime clock reports — the oldest by 8h11m. The last record was written 25 minutes before that boot.

Controls, in the same command, because a zero is only a reading if the instrument can also return non-zero:

  • positive — a file touched at that moment read as after the derived boot (so the comparison is live);
  • negative — PID 1 started 0.32s after the derived boot, so /proc/uptime and the process tree agree with each other. It is the filesystem that did not restart with them, not the clock that is wrong.

No clock skew is needed to explain the timeline: records up to 00:25, boot at 00:50, now 01:00.

Why it matters

It is an input to the persistence decision, and it points the opposite way from the assumption that shaped it. The triage on #12783 fenced persistence out under two constraints: this file must create nothing that outlives a process and needs reaping, and the ledger must never redden a gate. Both were reasoned against a ledger believed to be reliably per-container and ephemeral. On this host it is neither — the file already outlives every process that writes it, is already unreaped except by LEDGER_MAX_BYTES, and already survived a restart.

That does not make persistence unnecessary. It arguably makes the current situation worse than reliably-ephemeral: a population whose lower bound moves for reasons nobody has characterised is harder to reason about than one that resets predictably. But whoever picks up persistence should start from a measurement of what /tmp actually does here rather than from the sentence above.

⚠️ Note what is not claimed: that /tmp always survives. One container was measured. The finding is that the stated mechanism is not reliable, which is enough to disqualify it as a premise — and enough to disqualify /proc/uptime as a correlate for the ledger's population start, which is why PR #12827 states that floor as the first record's timestamp instead of pairing it with uptime.

Suggested repair (⛔ suggestion, not a ruling)

Correct the source comment to claim only what holds — that the ledger's population begins wherever the file does, for reasons not characterised — or re-measure /tmp's lifetime across restarts and state the real rule. The arithmetic conclusion the paragraph draws (that SLOT_MAX_AGE_S cannot be sized from this ledger) is unaffected either way: it rests on the population being bounded, not on why.

Refs

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions