Skip to content

Commit

Permalink
Require matching architecture for bootable images
Browse files Browse the repository at this point in the history
  • Loading branch information
cgwalters committed Aug 29, 2024
1 parent 4dcccad commit 2db0f2a
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 5 deletions.
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

0 comments on commit 2db0f2a

Please sign in to comment.