Skip to content

v0.20.1

Latest

Choose a tag to compare

@github-actions github-actions released this 05 Sep 23:01
v0.20.1
6a9627b

What's new in v0.20.1

v0.20.1 is about a daemon that would not start again. 0.20.0 began refusing an incident archive whose mode had gained a group or world bit, on the reasoning that a file a hostile local user pre-created is not one to append detail and templates to. On Kubernetes the platform sets that bit itself, on a file the daemon owns, and the refusal turned into a CrashLoopBackOff that nothing in the product could undo.

The bit the platform sets, on a file the daemon owns

Mounting a volume under an fsGroup adds g+rw to the files already on it. The chart's default podSecurityContext carries fsGroup: 65534 and its values.yaml advises putting archive_path on the PVC, so the recommended deployment reached this on its first restart. An archive the daemon had created at 0600 came back at 0660, the daemon exited before it ever reached a write, and every restart met the same mode, so only a chmod from outside got it back. The daemon that had captured incidents was the one that would not come back.

The guard now tells the two cases apart by acting rather than asking. An fchmod on the handle already opened without following symlinks takes the group and world bits off. It succeeds for the file's owner and fails for anyone else, so an archive the daemon owns is tightened back to 0600 and one owned by another user is still refused, with the offending mode named in the message. That split is what makes it safe: the kubelet changes the group of the files it finds and never their owner, so the archive stays the daemon's to tighten, while a file planted by another user is exactly the one the fchmod cannot touch.

The ack store never met this, its startup compaction rewriting its file at 0600 on every launch, which is also why its own refusal stands unchanged.

Verified against a cluster rather than a temporary directory: a daemon put back into the failure, an incident archive left at 0660 by an fsGroup mount, came up on its own with the file back at 0600 and its content untouched, where 0.20.0 stayed in CrashLoopBackOff on the same state.

The window archive was the one file left readable

[daemon.archive] path and the files it rotates into were created at the process umask, 0022 in a container, so they landed at 0644. They hold the whole window Report, every finding, endpoint and normalized SQL shape, and the chart puts them on the same volume as the ack store, which has refused a weak mode since it existed. The SQL is normalized, so no literal and no secret is in there, but the shape of a fleet is what a co-resident attacker reads next, and the same function already reasons about one when it closes the symlink race on rotation.

They are created 0600 now. Creation only, deliberately: a file already on disk keeps the mode its operator gave it, since tightening one the daemon may not own is how the incident archive above failed to start.

Upgrade impact

  • A daemon stuck on incident archive has mode 660, refusing to append starts again on this release, with no manual chmod first. If you already worked around it by widening the mode yourself, the daemon now narrows the file back to 0600 on startup.
  • 0.20.0 said a weakened archive or ack file is refused at startup. That still holds for a file the daemon does not own. A file it does own is tightened back to 0600 instead of failing the daemon.
  • New window archives are created 0600 where they were 0644. Files already on disk keep their mode, so a reader running under another account carries on until you chmod 600 them yourself.
  • No configuration key is added or removed, no route, metric or wire format changes, the acknowledgment signatures and the detection verdicts are untouched, and MSRV stays 1.97.1.

Full detail in CHANGELOG.md.

Verifying this release

# Binary integrity via SLSA Build L3 attestation
gh attestation verify perf-sentinel-linux-amd64 \
  --repo robintra/perf-sentinel

# A periodic disclosure produced by this binary
perf-sentinel verify-hash --report perf-sentinel-report.json \
  --expected-identity "https://github.com/robintra/perf-sentinel/.github/workflows/release.yml@refs/tags/v0.20.1" \
  --expected-issuer "https://token.actions.githubusercontent.com" \
  --verify-binary ./perf-sentinel-linux-amd64

gh CLI 2.49 or newer required for gh attestation verify.