Skip to content

Commit 4081a1f

Browse files
ukify: Allow passing path to kernel and initramfs
While building a sealed UKI image we'd want to remove the original kernel + initramfs from the final image and have only the final UKI present. This was not possible before as `bootc container ukify` expected kernel + initramfs to be present in `usr/lib/modules` of container root We now accept a parameter `kernel_dir` which must be of the format `/path/$kernel_ver` for `bootc container ukify` Fixes: #2185 Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
1 parent c879302 commit 4081a1f

3 files changed

Lines changed: 71 additions & 18 deletions

File tree

crates/lib/src/cli.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,13 @@ pub(crate) enum ContainerOpts {
442442
#[clap(long)]
443443
write_dumpfile_to: Option<Utf8PathBuf>,
444444

445+
/// The directory containing the kernel and initramfs.img
446+
/// Must be of the format /parent/$kernel_version
447+
///
448+
/// Ex. /boot/6.18.7-100.fc42.x86_64
449+
#[clap(long)]
450+
kernel_dir: Option<Utf8PathBuf>,
451+
445452
/// Additional arguments to pass to ukify (after `--`).
446453
#[clap(last = true)]
447454
args: Vec<OsString>,
@@ -1902,12 +1909,36 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
19021909
kargs,
19031910
allow_missing_verity,
19041911
write_dumpfile_to,
1912+
kernel_dir,
19051913
args,
19061914
} => {
1915+
let kernel = match kernel_dir {
1916+
Some(kernel_dir) => {
1917+
let kver = kernel_dir
1918+
.components()
1919+
.last()
1920+
.ok_or_else(|| anyhow::anyhow!("Could not determine kernel version"))?;
1921+
1922+
Some(crate::kernel::KernelInternal {
1923+
kernel: crate::kernel::Kernel {
1924+
unified: false,
1925+
version: kver.to_string(),
1926+
},
1927+
k_type: crate::kernel::KernelType::Vmlinuz {
1928+
path: kernel_dir.join("vmlinuz"),
1929+
initramfs: kernel_dir.join("initramfs.img"),
1930+
},
1931+
})
1932+
}
1933+
1934+
None => None,
1935+
};
1936+
19071937
crate::ukify::build_ukify(
19081938
&rootfs,
19091939
&kargs,
19101940
&args,
1941+
kernel,
19111942
allow_missing_verity,
19121943
write_dumpfile_to.as_deref(),
19131944
)

crates/lib/src/ukify.rs

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use fn_error_context::context;
1515

1616
use crate::bootc_composefs::digest::compute_composefs_digest;
1717
use crate::bootc_composefs::status::ComposefsCmdline;
18+
use crate::kernel::KernelInternal;
1819

1920
/// Build a UKI from the given rootfs.
2021
///
@@ -30,6 +31,7 @@ pub(crate) async fn build_ukify(
3031
rootfs: &Utf8Path,
3132
extra_kargs: &[String],
3233
args: &[OsString],
34+
kernel: Option<KernelInternal>,
3335
allow_missing_fsverity: bool,
3436
write_dumpfile_to: Option<&Utf8Path>,
3537
) -> Result<()> {
@@ -52,30 +54,46 @@ pub(crate) async fn build_ukify(
5254
let root = Dir::open_ambient_dir(rootfs, cap_std_ext::cap_std::ambient_authority())
5355
.with_context(|| format!("Opening rootfs {rootfs}"))?;
5456

55-
// Find the kernel
56-
let kernel = crate::kernel::find_kernel(&root)?
57-
.ok_or_else(|| anyhow::anyhow!("No kernel found in {rootfs}"))?;
57+
let kernel_final = match kernel {
58+
Some(ref kernel) => kernel,
59+
None => &crate::kernel::find_kernel(&root)?
60+
.ok_or_else(|| anyhow::anyhow!("No kernel found in {rootfs}"))?,
61+
};
5862

5963
// Extract vmlinuz and initramfs paths, or bail if this is already a UKI
60-
let (vmlinuz_path, initramfs_path) = match kernel.k_type {
64+
let (vmlinuz_path, initramfs_path) = match &kernel_final.k_type {
6165
crate::kernel::KernelType::Vmlinuz { path, initramfs } => (path, initramfs),
6266
crate::kernel::KernelType::Uki { path, .. } => {
6367
anyhow::bail!("Cannot build UKI: rootfs already contains a UKI at {path}");
6468
}
6569
};
6670

6771
// Verify kernel and initramfs exist
68-
if !root
69-
.try_exists(&vmlinuz_path)
70-
.context("Checking for vmlinuz")?
71-
{
72-
anyhow::bail!("Kernel not found at {vmlinuz_path}");
73-
}
74-
if !root
75-
.try_exists(&initramfs_path)
76-
.context("Checking for initramfs")?
77-
{
78-
anyhow::bail!("Initramfs not found at {initramfs_path}");
72+
//
73+
// NOTE: Not using cap_std here as the vmlinuz/initramfs path from
74+
// args can be outside of "rootfs"
75+
if kernel.is_some() {
76+
if !vmlinuz_path.exists() {
77+
anyhow::bail!("Kernel not found at {vmlinuz_path}");
78+
}
79+
80+
if !initramfs_path.exists() {
81+
anyhow::bail!("Initramfs not found at {initramfs_path}");
82+
}
83+
} else {
84+
if !root
85+
.try_exists(&vmlinuz_path)
86+
.context("Checking for vmlinuz")?
87+
{
88+
anyhow::bail!("Kernel not found at {vmlinuz_path}");
89+
}
90+
91+
if !root
92+
.try_exists(&initramfs_path)
93+
.context("Checking for initramfs")?
94+
{
95+
anyhow::bail!("Initramfs not found at {initramfs_path}");
96+
}
7997
}
8098

8199
// Compute the composefs digest
@@ -105,7 +123,7 @@ pub(crate) async fn build_ukify(
105123
.arg("--initrd")
106124
.arg(&initramfs_path)
107125
.arg("--uname")
108-
.arg(&kernel.kernel.version)
126+
.arg(&kernel_final.kernel.version)
109127
.arg("--cmdline")
110128
.arg(&cmdline_str)
111129
.arg("--os-release")
@@ -134,7 +152,7 @@ mod tests {
134152
let tempdir = tempfile::tempdir().unwrap();
135153
let path = Utf8Path::from_path(tempdir.path()).unwrap();
136154

137-
let result = build_ukify(path, &[], &[], false, None).await;
155+
let result = build_ukify(path, &[], &[], None, false, None).await;
138156
assert!(result.is_err());
139157
let err = format!("{:#}", result.unwrap_err());
140158
assert!(
@@ -156,7 +174,7 @@ mod tests {
156174
)
157175
.unwrap();
158176

159-
let result = build_ukify(path, &[], &[], false, None).await;
177+
let result = build_ukify(path, &[], &[], None, false, None).await;
160178
assert!(result.is_err());
161179
let err = format!("{:#}", result.unwrap_err());
162180
assert!(

docs/src/man/bootc-container-ukify.8.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ Any additional arguments after `--` are passed through to ukify unchanged.
3535

3636
Write a dumpfile to this path
3737

38+
**--kernel-dir**=*KERNEL_DIR*
39+
40+
The directory containing the kernel and initramfs.img Must be of the format /parent/$kernel_version
41+
3842
<!-- END GENERATED OPTIONS -->
3943

4044
# EXAMPLES

0 commit comments

Comments
 (0)