cubelinux: an addressed image is readable without a log
merged_digest answered "no log" before it looked at the layout, so a bare v3/v4 image fell through to the packed walk — which starts at the v2 header length and reads index entries as record frames. A bare addressed image with no log beside it therefore read as a one-record store with an empty value. An addressed image is a complete store on its own: its index holds every record and says where each one is, so a log is an addition rather than a requirement. A packed image is not, which is why "no log" still means what it meant for v1/v2. Found by verify-image-read the moment userspace started writing v4: while every userspace image was v2 the fallback happened to be the right walk. The kernel's own v4 images always had a log header beside them, so no other gate could have caught it.
This commit is contained in:
@@ -1047,7 +1047,17 @@ fn build_merged(image: &[u8], log: &[u8], header: &Header) -> Result<(Merged, u6
|
||||
/// to it. Returns `Err("no-log")` when there is none, so the caller can fall back to reading
|
||||
/// the image by itself.
|
||||
fn merged_digest(image: &[u8], log: &[u8], header: &Header) -> Result<Line, &'static str> {
|
||||
if log.len() < WAL_HEADER_LEN || &log[0..4] != WAL_MAGIC {
|
||||
// An addressed image is a complete store on its own: its index holds every record and says
|
||||
// where each one is, so a log is an *addition* rather than a requirement. A packed image is
|
||||
// not — without a log there is nothing this path adds over the image's own order, which is why
|
||||
// it answers "no log" and lets the caller walk the records it can see.
|
||||
//
|
||||
// Requiring a log here regardless of layout is what made a bare v3/v4 image read as a *packed*
|
||||
// one: the caller fell through to a walk that starts at the v2 header length and reads index
|
||||
// entries as record frames. It went unnoticed while every userspace-written image was v2, which
|
||||
// is exactly the kind of bug that a migration finds and a unit test does not.
|
||||
let addressed = header.version == VERSION_V3 || header.version == VERSION_V4;
|
||||
if !addressed && (log.len() < WAL_HEADER_LEN || &log[0..4] != WAL_MAGIC) {
|
||||
return Err("no-log");
|
||||
}
|
||||
let (mut merged, applied) = build_merged(image, log, header)?;
|
||||
|
||||
Reference in New Issue
Block a user