Skip to content
This repository has been archived by the owner on Nov 7, 2024. It is now read-only.

Require matching architecture for bootable images #656

Merged
merged 1 commit into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion lib/src/container/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ use containers_image_proxy::{ImageProxy, OpenedImage};
use flate2::Compression;
use fn_error_context::context;
use futures_util::TryFutureExt;
use oci_spec::image::{self as oci_image, Descriptor, History, ImageConfiguration, ImageManifest};
use oci_spec::image::{
self as oci_image, Arch, Descriptor, History, ImageConfiguration, ImageManifest,
};
use ostree::prelude::{Cast, FileEnumeratorExt, FileExt, ToVariant};
use ostree::{gio, glib};
use std::collections::{BTreeSet, HashMap};
Expand Down Expand Up @@ -584,6 +586,11 @@ impl ImageImporter {
if !bootable {
anyhow::bail!("Target image does not have {bootable_key} label");
}
let container_arch = config.architecture();
let target_arch = &Arch::default();
if container_arch != target_arch {
anyhow::bail!("Image has architecture {container_arch}; expected {target_arch}");
}
}

let (commit_layer, component_layers, remaining_layers) =
Expand Down
21 changes: 17 additions & 4 deletions lib/src/integrationtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ use cap_std_ext::cap_std;
use containers_image_proxy::oci_spec;
use fn_error_context::context;
use gio::prelude::*;
use oci_spec::image as oci_image;
use ocidir::GzipLayerWriter;
use ocidir::{
oci_spec::image::{Arch, Platform},
GzipLayerWriter,
};
use ostree::gio;
use xshell::cmd;

Expand Down Expand Up @@ -46,6 +48,7 @@ pub fn generate_derived_oci(
Ok(())
},
tag,
None,
)
}

Expand All @@ -56,6 +59,7 @@ pub fn generate_derived_oci_from_tar<F>(
src: impl AsRef<Utf8Path>,
f: F,
tag: Option<&str>,
arch: Option<Arch>,
) -> Result<()>
where
F: FnOnce(&mut GzipLayerWriter) -> Result<()>,
Expand All @@ -67,6 +71,10 @@ where
let mut manifest = src.read_manifest()?;
let mut config: oci_spec::image::ImageConfiguration = src.read_json_blob(manifest.config())?;

if let Some(arch) = arch.as_ref() {
config.set_architecture(arch.clone());
}

let mut bw = src.create_gzip_layer(None)?;
f(&mut bw)?;
let new_layer = bw.complete()?;
Expand All @@ -92,10 +100,15 @@ where
let new_config_desc = src.write_config(config)?;
manifest.set_config(new_config_desc);

let mut platform = Platform::default();
if let Some(arch) = arch.as_ref() {
platform.set_architecture(arch.clone());
}

if let Some(tag) = tag {
src.insert_manifest(manifest, Some(tag), oci_image::Platform::default())?;
src.insert_manifest(manifest, Some(tag), platform)?;
} else {
src.replace_with_single_manifest(manifest, oci_image::Platform::default())?;
src.replace_with_single_manifest(manifest, platform)?;
}
Ok(())
}
Expand Down
52 changes: 52 additions & 0 deletions lib/tests/it/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use cap_std::fs::{Dir, DirBuilder, DirBuilderExt};
use cap_std_ext::cap_std;
use containers_image_proxy::oci_spec;
use containers_image_proxy::oci_spec::image::ImageManifest;
use ocidir::oci_spec::image::Arch;
use once_cell::sync::Lazy;
use ostree_ext::chunking::ObjectMetaSized;
use ostree_ext::container::{store, ManifestDiff};
Expand Down Expand Up @@ -768,6 +769,55 @@ fn validate_chunked_structure(oci_path: &Utf8Path) -> Result<()> {
Ok(())
}

#[tokio::test]
async fn test_container_arch_mismatch() -> Result<()> {
let fixture = Fixture::new_v1()?;

let imgref = fixture.export_container().await.unwrap().0;

// Build a derived image
let derived_path = &fixture.path.join("derived.oci");
let srcpath = imgref.name.as_str();
oci_clone(srcpath, derived_path).await.unwrap();
ostree_ext::integrationtest::generate_derived_oci_from_tar(
derived_path,
|w| {
let mut layer_tar = tar::Builder::new(w);
let mut h = tar::Header::new_gnu();
h.set_uid(0);
h.set_gid(0);
h.set_size(0);
h.set_mode(0o755);
h.set_entry_type(tar::EntryType::Directory);
layer_tar.append_data(
&mut h.clone(),
"etc/mips-operating-system",
&mut std::io::empty(),
)?;
layer_tar.into_inner()?;
Ok(())
},
None,
Some(Arch::Mips64le),
)?;

let derived_imgref = OstreeImageReference {
sigverify: SignatureSource::ContainerPolicyAllowInsecure,
imgref: ImageReference {
transport: Transport::OciDir,
name: derived_path.to_string(),
},
};
let mut imp =
store::ImageImporter::new(fixture.destrepo(), &derived_imgref, Default::default()).await?;
imp.require_bootable();
imp.set_ostree_version(2023, 11);
let r = imp.prepare().await;
assert_err_contains(r, "Image has architecture mips64le");

Ok(())
}

#[tokio::test]
async fn test_container_chunked() -> Result<()> {
let nlayers = LAYERS_V0_LEN - 1;
Expand Down Expand Up @@ -1118,6 +1168,7 @@ async fn test_container_etc_hardlinked() -> Result<()> {
Ok(())
},
None,
None,
)?;

let derived_imgref = OstreeImageReference {
Expand Down Expand Up @@ -1534,6 +1585,7 @@ async fn test_container_write_derive_sysroot_hardlink() -> Result<()> {
Ok::<_, anyhow::Error>(())
},
None,
None,
)?;
let derived_ref = &OstreeImageReference {
sigverify: SignatureSource::ContainerPolicyAllowInsecure,
Expand Down
Loading