Make ID-map artifact identity encoding explicit

This commit is contained in:
ms2k 2026-07-19 05:43:28 +09:00
commit 5376aa90f9

View file

@ -666,7 +666,7 @@ impl Identities {
POLICY_NAME.as_bytes(),
&destination_bytes,
]));
let id_map_bytes = postcard::to_stdvec(&request.id_map)?;
let id_map_bytes = canonical_id_map_bytes(&request.id_map)?;
let id_map = IdMapDigest::new(hash_parts(&[b"lazaret-id-map-v1", &id_map_bytes]));
let artifact_id = PreparedArtifactId::new(hash_parts(&[
b"lazaret-prepared-artifact-v1",
@ -857,6 +857,30 @@ fn sync_tree(directory: &File) -> Result<()> {
Ok(())
}
fn canonical_id_map_bytes(id_map: &IdMap) -> Result<Vec<u8>> {
let capacity = id_map
.uid
.len()
.checked_add(id_map.gid.len())
.and_then(|ranges| ranges.checked_mul(12))
.and_then(|ranges| ranges.checked_add(16))
.context("ID-map encoding length overflow")?;
let mut bytes = Vec::with_capacity(capacity);
for ranges in [&id_map.uid, &id_map.gid] {
bytes.extend_from_slice(
&u64::try_from(ranges.len())
.context("ID-map range count exceeds u64")?
.to_be_bytes(),
);
for range in ranges {
bytes.extend_from_slice(&range.container_id.to_be_bytes());
bytes.extend_from_slice(&range.namespace_id.to_be_bytes());
bytes.extend_from_slice(&range.size.to_be_bytes());
}
}
Ok(bytes)
}
fn hash_parts(parts: &[&[u8]]) -> [u8; 32] {
let mut hasher = Sha256::new();
for part in parts {
@ -910,8 +934,34 @@ fn secure_resolve() -> ResolveFlags {
mod fixed_directory_tests {
use std::os::unix::fs::PermissionsExt;
use crate::layer::IdMapRange;
use super::*;
#[test]
fn id_map_identity_encoding_is_explicit_and_fixed() {
let encoded = canonical_id_map_bytes(&IdMap {
uid: vec![IdMapRange {
container_id: 1,
namespace_id: 2,
size: 3,
}],
gid: vec![IdMapRange {
container_id: 4,
namespace_id: 5,
size: 6,
}],
})
.unwrap();
assert_eq!(
encoded,
[
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6,
]
);
}
#[test]
fn prepared_lower_root_requires_invoking_owner_and_exact_private_mode() {
let directory = tempfile::tempdir().unwrap();