Close prepared-lower identity and reclaim races
This commit is contained in:
parent
5458460717
commit
0dfd7767b5
1 changed files with 142 additions and 30 deletions
|
|
@ -95,6 +95,7 @@ struct Descriptor {
|
|||
}
|
||||
|
||||
pub(crate) struct VerifiedLayout {
|
||||
pub(crate) manifest_digest: [u8; 32],
|
||||
layers: Vec<Descriptor>,
|
||||
diff_ids: Vec<String>,
|
||||
}
|
||||
|
|
@ -130,6 +131,7 @@ pub(crate) fn verify_layout(layout: &Path, limits: PreparationLimits) -> Result<
|
|||
verify_blob_digest(layout, layer, limits.max_layer_blob_bytes)?;
|
||||
}
|
||||
Ok(VerifiedLayout {
|
||||
manifest_digest: parse_sha256(&descriptor.digest)?,
|
||||
layers: manifest.layers,
|
||||
diff_ids: config.rootfs.diff_ids,
|
||||
})
|
||||
|
|
@ -147,41 +149,24 @@ pub(crate) fn apply_layout(
|
|||
let mut usage = Usage::default();
|
||||
for (index, (descriptor, diff_id)) in verified.layers.iter().zip(&verified.diff_ids).enumerate()
|
||||
{
|
||||
let spool_name = format!(".layer-{index}.tar");
|
||||
let spool_output = File::from(openat2(
|
||||
let spool = File::from(openat2(
|
||||
rootfs,
|
||||
&spool_name,
|
||||
OFlags::WRONLY | OFlags::CREATE | OFlags::EXCL | OFlags::CLOEXEC | OFlags::NOFOLLOW,
|
||||
".",
|
||||
OFlags::RDWR | OFlags::TMPFILE | OFlags::CLOEXEC,
|
||||
Mode::from_raw_mode(0o600),
|
||||
secure_resolve(),
|
||||
)?);
|
||||
let observed = decompress_layer(
|
||||
&blob_path(layout, &descriptor.digest)?,
|
||||
&descriptor.media_type,
|
||||
spool_output,
|
||||
spool.try_clone()?,
|
||||
limits.max_uncompressed_layer_bytes,
|
||||
)?;
|
||||
if &observed != diff_id {
|
||||
let _ = unlinkat(rootfs, &spool_name, AtFlags::empty());
|
||||
bail!("layer {index} diff-ID mismatch");
|
||||
}
|
||||
let spool = File::from(openat2(
|
||||
rootfs,
|
||||
&spool_name,
|
||||
OFlags::RDONLY | OFlags::CLOEXEC | OFlags::NOFOLLOW,
|
||||
Mode::empty(),
|
||||
secure_resolve(),
|
||||
)?);
|
||||
let result = validate_tar(&spool, id_map, limits, &mut usage)
|
||||
.and_then(|()| state.apply(&spool, rootfs));
|
||||
if let Err(error) = result {
|
||||
let _ = unlinkat(rootfs, &spool_name, AtFlags::empty());
|
||||
return Err(error);
|
||||
}
|
||||
match unlinkat(rootfs, &spool_name, AtFlags::empty()) {
|
||||
Ok(()) | Err(rustix::io::Errno::NOENT) => {}
|
||||
Err(error) => return Err(error.into()),
|
||||
}
|
||||
validate_tar(&spool, id_map, limits, &mut usage)?;
|
||||
state.apply(&spool, rootfs)?;
|
||||
}
|
||||
state.finish(rootfs)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue