Skip to content

Conversation

@dobrac
Copy link
Contributor

@dobrac dobrac commented Nov 25, 2025

Note

Introduce BLAKE3-based rootfs checksums with optional verification, refactor direct/NBD providers and cache export to a unified diff metadata builder, and wire verification into sandbox lifecycle.

  • Rootfs/Providers:
    • Add Provider.Verify and wire into sandbox create/resume; pass full config to providers.
    • Refactor DirectProvider to mmap the rootfs file, stream diff via header.NewDiffMetadataBuilder, and optionally attach computed checksums.
    • Enhance NBDProvider to compute and optionally verify BLAKE3 checksums (per-block and aggregate); include checksums in exported diffs.
  • Checksums:
    • Add BLAKE3 dependency and checksum utilities (CalculateChecksumsReader).
    • Extend header.Header and header.DiffMetadata with Checksums; propagate through ToDiffHeader.
  • Block Cache:
    • Replace manual dirty/empty bitset handling with DiffMetadataBuilder in ExportToDiff; remove MarkAllAsDirty.
  • Sandbox/Build:
    • Integrate rootfs verification; enforce empty-block validation when base build blocks are nil.
    • Improve phase logging and pass builder logger to phases.Run; simplify base phase by removing provision symlink.
  • Misc:
    • Add ROOTFS_CHECKSUM_VERIFICATION flag to config.
    • Improve socket wait error to include context cause.

Written by Cursor Bugbot for commit 160574d. This will update automatically on new commits. Configure here.

@dobrac dobrac force-pushed the fix/rootfs-direct-provider branch 6 times, most recently from 7fc7ee9 to 6110ab9 Compare November 26, 2025 14:10
@dobrac dobrac changed the title fix: rootfs direct provider chore: refactor rootfs direct provider and add checksums Nov 26, 2025
@dobrac dobrac force-pushed the fix/rootfs-direct-provider branch from 6110ab9 to 5f6a4fa Compare November 26, 2025 17:21
@dobrac dobrac marked this pull request as ready for review November 27, 2025 08:59
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// We will use this to handle base builds that are already diffs.
// The passed slice p must start as empty, otherwise we would need to copy the empty values there.
if *buildID == uuid.Nil {
isEmpty, err := header.IsEmptyBlock(p[n:int64(n)+readLength], int64(b.header.Metadata.BlockSize))
Copy link
Contributor Author

@dobrac dobrac Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this might not be needed, it's just check to be sure that the block is empty

}
if !isEmpty {
return 0, fmt.Errorf("block is not empty")
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Empty block check fails for non-blockSize reads

The IsEmptyBlock function compares the input slice against a pre-allocated empty buffer of exactly blockSize bytes using bytes.Equal. However, the slice passed here has length readLength (from p[n:int64(n)+readLength]), which can differ from blockSize when reads span multiple mappings or aren't block-aligned. When readLength != blockSize, bytes.Equal will return false due to the length mismatch, incorrectly reporting non-empty blocks and causing spurious errors even when the slice contains all zeros.

Fix in Cursor Fix in Web

Comment on lines +114 to +116
if wrongCount > 10 {
return fmt.Errorf("too many block checksum mismatches")
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is just a optimization?

}
}

if !bytes.Equal(checksums.Checksum[:], headerChecksums.Checksum[:]) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you even need to do this if you do block checksums check?

Comment on lines +177 to +183
m, err := builder.Build()
if err != nil {
return nil, fmt.Errorf("error building diff metadata: %w", err)
}

return m, nil
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can do the same as in the Cache, also Build() can't return error, so that can be also simplified

Suggested change
m, err := builder.Build()
if err != nil {
return nil, fmt.Errorf("error building diff metadata: %w", err)
}
return m, nil
}
return builder.Build()
}

@dobrac dobrac marked this pull request as draft December 1, 2025 15:17
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.

3 participants