66
77use std:: path:: Path ;
88
9- use anyhow:: Result ;
9+ use anyhow:: { Context , Result } ;
10+ use bootc_kernel_cmdline:: utf8:: Cmdline ;
1011use camino:: Utf8PathBuf ;
1112use cap_std_ext:: cap_std:: fs:: Dir ;
1213use cap_std_ext:: dirext:: CapStdExtDirExt ;
1314use serde:: Serialize ;
1415
1516use crate :: bootc_composefs:: boot:: EFI_LINUX ;
17+ use crate :: bootc_composefs:: status:: ComposefsCmdline ;
18+ use crate :: composefs_consts:: COMPOSEFS_CMDLINE ;
1619
1720/// Information about the kernel in a container image.
1821#[ derive( Debug , Serialize ) ]
@@ -31,8 +34,11 @@ pub(crate) struct Kernel {
3134/// UKI kernels only have the single PE binary, whereas
3235/// traditional "vmlinuz" kernels have distinct kernel and
3336/// initramfs.
34- pub ( crate ) enum KernelPath {
35- Uki ( Utf8PathBuf ) ,
37+ pub ( crate ) enum KernelType {
38+ Uki {
39+ path : Utf8PathBuf ,
40+ allow_missing_fsverity : bool ,
41+ } ,
3642 Vmlinuz {
3743 path : Utf8PathBuf ,
3844 initramfs : Utf8PathBuf ,
@@ -47,7 +53,7 @@ pub(crate) enum KernelPath {
4753/// to get the "public" form where needed.
4854pub ( crate ) struct KernelInternal {
4955 pub ( crate ) kernel : Kernel ,
50- pub ( crate ) path : KernelPath ,
56+ pub ( crate ) k_type : KernelType ,
5157}
5258
5359impl From < KernelInternal > for Kernel {
@@ -67,12 +73,48 @@ pub(crate) fn find_kernel(root: &Dir) -> Result<Option<KernelInternal>> {
6773 // First, try to find a UKI
6874 if let Some ( uki_path) = find_uki_path ( root) ? {
6975 let version = uki_path. file_stem ( ) . unwrap_or ( uki_path. as_str ( ) ) . to_owned ( ) ;
76+
77+ let uki = root. read ( & uki_path) . context ( "Reading UKI" ) ?;
78+
79+ // Best effort to check for composefs=?verity in the UKI cmdline
80+ let cmdline = composefs_boot:: uki:: get_section ( & uki, ".cmdline" ) ;
81+
82+ let allow_missing_fsverity = match cmdline {
83+ Some ( Ok ( cmdline) ) => {
84+ let cmdline_str = std:: str:: from_utf8 ( cmdline) ?;
85+
86+ let cmdline = Cmdline :: from ( cmdline_str) ;
87+
88+ match cmdline. find ( COMPOSEFS_CMDLINE ) {
89+ Some ( param) => ComposefsCmdline :: new ( & param) . allow_missing_fsverity ,
90+
91+ // The cmdline might be in an addon, so don't allow missing verity
92+ None => false ,
93+ }
94+ }
95+
96+ Some ( Err ( uki_error) ) => match uki_error {
97+ composefs_boot:: uki:: UkiError :: MissingSection ( _) => {
98+ // TODO(Johan-Liebert1): Check this when we have full UKI Addons support
99+ // The cmdline might be in an addon, so don't allow missing verity
100+ false
101+ }
102+
103+ e => anyhow:: bail!( "Failed to read UKI cmdline: {e:?}" ) ,
104+ } ,
105+
106+ None => false ,
107+ } ;
108+
70109 return Ok ( Some ( KernelInternal {
71110 kernel : Kernel {
72111 version,
73112 unified : true ,
74113 } ,
75- path : KernelPath :: Uki ( uki_path) ,
114+ k_type : KernelType :: Uki {
115+ path : uki_path,
116+ allow_missing_fsverity,
117+ } ,
76118 } ) ) ;
77119 }
78120
@@ -89,7 +131,7 @@ pub(crate) fn find_kernel(root: &Dir) -> Result<Option<KernelInternal>> {
89131 version,
90132 unified : false ,
91133 } ,
92- path : KernelPath :: Vmlinuz {
134+ k_type : KernelType :: Vmlinuz {
93135 path : vmlinuz,
94136 initramfs,
95137 } ,
@@ -156,8 +198,8 @@ mod tests {
156198 let kernel_internal = find_kernel ( & tempdir) ?. expect ( "should find kernel" ) ;
157199 assert_eq ! ( kernel_internal. kernel. version, "6.12.0-100.fc41.x86_64" ) ;
158200 assert ! ( !kernel_internal. kernel. unified) ;
159- match & kernel_internal. path {
160- KernelPath :: Vmlinuz { path, initramfs } => {
201+ match & kernel_internal. k_type {
202+ KernelType :: Vmlinuz { path, initramfs } => {
161203 assert_eq ! (
162204 path. as_str( ) ,
163205 "usr/lib/modules/6.12.0-100.fc41.x86_64/vmlinuz"
@@ -167,7 +209,7 @@ mod tests {
167209 "usr/lib/modules/6.12.0-100.fc41.x86_64/initramfs.img"
168210 ) ;
169211 }
170- KernelPath :: Uki ( _ ) => panic ! ( "Expected Vmlinuz, got Uki" ) ,
212+ KernelType :: Uki { .. } => panic ! ( "Expected Vmlinuz, got Uki" ) ,
171213 }
172214 Ok ( ( ) )
173215 }
@@ -181,11 +223,11 @@ mod tests {
181223 let kernel_internal = find_kernel ( & tempdir) ?. expect ( "should find kernel" ) ;
182224 assert_eq ! ( kernel_internal. kernel. version, "fedora-6.12.0" ) ;
183225 assert ! ( kernel_internal. kernel. unified) ;
184- match & kernel_internal. path {
185- KernelPath :: Uki ( path) => {
226+ match & kernel_internal. k_type {
227+ KernelType :: Uki { path, .. } => {
186228 assert_eq ! ( path. as_str( ) , "boot/EFI/Linux/fedora-6.12.0.efi" ) ;
187229 }
188- KernelPath :: Vmlinuz { .. } => panic ! ( "Expected Uki, got Vmlinuz" ) ,
230+ KernelType :: Vmlinuz { .. } => panic ! ( "Expected Uki, got Vmlinuz" ) ,
189231 }
190232 Ok ( ( ) )
191233 }
0 commit comments