Skip to content

fix: reject corrupt blob reads - #80

Merged
wchwawa merged 3 commits into
mainfrom
fix/blob-integrity-20261026
Oct 26, 2026
Merged

wchwawa merged 3 commits into
mainfrom
fix/blob-integrity-20261026

Conversation

@wchwawa

@wchwawa wchwawa commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

TLDR

Reject damaged file-backed blob reads and respect the authenticated extent of compact records.

Problem

A changed byte in an active blob could reach a reader without a storage error. This is a private security follow-up; no public issue was opened under SECURITY.md.

Consequences

A caller could consume a wrong value, and bytes outside a compact record's extent could come from a reused slot.

Example

A read of a damaged page now returns NodeCorrupt. A range read beyond a compact record's extent returns zeros rather than old slot bytes.

Solution

Bind per-page checksums to each published blob slot, make the checksum record durable before its manifest mapping, and verify reads before returning them. Existing version 6 stores migrate on writable open. Large Linux batches verify independent blobs on separate workers while preserving result order.

Gain

Persistent blob damage is reported at the read boundary. Compact records from the 0.8 line remain readable without exposing their unpersisted tail.

Tradeoffs

CRC detects accidental damage, not an attacker who can rewrite storage metadata. Damage already present during legacy migration cannot be authenticated. Version 6 read-only opens need a prior writable migration. The 0.8 backport's synthetic dense-frame benchmark shows material checksum overhead; 0.9.2 product performance is not qualified. This PR remains Draft.

Validation

  • Final source: macOS file-store tests 52/52; Linux/arm64 Docker io-uring file-store tests 58/58, including a 40-blob damaged-page batch.
  • cargo fmt --all -- --check, cargo clippy --workspace --all-targets --locked -- -D warnings on macOS, and Linux io-uring Clippy passed. git diff --check passed.
  • A checkpointed 0.8.8 store was read by this 0.9.2 line. The full CI run passed on the exact pushed head, including macOS and Ubuntu tests, coverage, lint, docs, MSRV, fuzz, benchmarks, and the smoke soak.
  • The Linux Docker run used relaxed seccomp for io-uring. These tests do not establish NoKV-wide recovery, fault, or latency qualification.

The current NoKV dependency uses published Holt 0.8.7. The matching 0.8.8 backport is #81.

Signed-off-by: wchwawa <wch19961116@gmail.com>
Signed-off-by: wchwawa <wch19961116@gmail.com>
Compact records from the 0.8 line must never expose bytes beyond their authenticated extent. Read that prefix, clear the rest, and verify independent blobs in parallel for large Linux batches while preserving per-blob results.

Signed-off-by: wchwawa <wch19961116@gmail.com>
@wchwawa
wchwawa marked this pull request as ready for review October 26, 2026 22:54
@wchwawa
wchwawa merged commit 8e7d8d7 into main Oct 26, 2026
25 checks passed
@wchwawa
wchwawa deleted the fix/blob-integrity-20261026 branch October 26, 2026 22:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant