diff --git a/drivers/cube/cubelinux_store.rs b/drivers/cube/cubelinux_store.rs index 8cddd6c16..cdc6ac2c1 100644 --- a/drivers/cube/cubelinux_store.rs +++ b/drivers/cube/cubelinux_store.rs @@ -220,6 +220,11 @@ const LOG_ALIGN: usize = 4096; /// Control block magic, distinct from the image's `CUBE` and the log's `CUBW`. const CTL_MAGIC: [u8; 4] = *b"CUBS"; const CTL_VERSION: u8 = 1; +/// The image header's own magic, which a bare packed image begins with. +/// +/// It is read for one decision: a device whose control block does not decode is a packed image only +/// if it says so. Without that question, anything at all was walked as though it were a store. +const IMAGE_MAGIC: &[u8; 4] = b"CUBE"; /// One control copy, and where the two live. const CTL_COPY_LEN: usize = 2048; const CTL_COPY_A: usize = 0; @@ -3014,9 +3019,26 @@ impl Addressed { (Some(x), Some(y)) => core::cmp::max(x, y), (Some(x), None) => x, (None, Some(y)) => y, - // Neither copy decodes: there is no control block, so this is a bare image and the - // walking reader handles it. - (None, None) => return Ok(None), + // Neither copy decodes. That is *not* by itself evidence of a packed image: it is + // evidence that this device does not begin with a control block, and on a device that is + // not a store at all there is nothing to walk. The userspace raw reader has always asked + // that question — its message for this is `not a CUBE store (bad magic)` — and the kernel + // did not, which is the whole of this defect: with nothing behind the read, the walking + // reader served *invented* records, a garbage space with a zero-length value and a cursor + // that kept moving, for as long as the machine was left on. A boot pointed at a store it + // could not read hung instead of saying so. + // + // So the fallback is taken only for something that says it is a packed image: a bare + // packed image begins with the image header's magic. A device with anything else at + // offset 0 is refused here, loudly, which is what a missing or wrong store deserves. + (None, None) => { + let mut head = KVVec::::with_capacity(8, GFP_KERNEL)?; + read_exact_at(file, 0, IMAGE_MAGIC.len(), &mut head, &mut cache.scratch)?; + if head.as_slice() != IMAGE_MAGIC { + return Err(EINVAL); + } + return Ok(None); + } } as u64; let mut opened = Addressed {