@@ -62,19 +62,47 @@ impl From<ImageSignature> for ostree_container::SignatureSource {
6262 }
6363}
6464
65+ /// A parsed composefs command line
66+ pub ( crate ) struct ComposefsCmdline {
67+ #[ allow( dead_code) ]
68+ pub insecure : bool ,
69+ pub digest : Box < str > ,
70+ }
71+
72+ impl ComposefsCmdline {
73+ pub ( crate ) fn new ( s : & str ) -> Self {
74+ let ( insecure, digest_str) = s
75+ . strip_prefix ( '?' )
76+ . map ( |v| ( true , v) )
77+ . unwrap_or_else ( || ( false , s) ) ;
78+ ComposefsCmdline {
79+ insecure,
80+ digest : digest_str. into ( ) ,
81+ }
82+ }
83+ }
84+
85+ impl std:: fmt:: Display for ComposefsCmdline {
86+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
87+ let insecure = if self . insecure { "?" } else { "" } ;
88+ write ! ( f, "{}={}{}" , COMPOSEFS_CMDLINE , insecure, self . digest)
89+ }
90+ }
91+
6592/// Detect if we have composefs=<digest> in /proc/cmdline
66- pub ( crate ) fn composefs_booted ( ) -> Result < Option < & ' static str > > {
67- static CACHED_DIGEST_VALUE : OnceLock < Option < String > > = OnceLock :: new ( ) ;
93+ pub ( crate ) fn composefs_booted ( ) -> Result < Option < & ' static ComposefsCmdline > > {
94+ static CACHED_DIGEST_VALUE : OnceLock < Option < ComposefsCmdline > > = OnceLock :: new ( ) ;
6895 if let Some ( v) = CACHED_DIGEST_VALUE . get ( ) {
69- return Ok ( v. as_deref ( ) ) ;
96+ return Ok ( v. as_ref ( ) ) ;
7097 }
7198 let cmdline = crate :: kernel_cmdline:: Cmdline :: from_proc ( ) ?;
7299 let Some ( kv) = cmdline. find_str ( COMPOSEFS_CMDLINE ) else {
73100 return Ok ( None ) ;
74101 } ;
75102 let Some ( v) = kv. value else { return Ok ( None ) } ;
76- let r = CACHED_DIGEST_VALUE . get_or_init ( || Some ( v. to_owned ( ) ) ) ;
77- Ok ( r. as_deref ( ) )
103+ let v = ComposefsCmdline :: new ( v) ;
104+ let r = CACHED_DIGEST_VALUE . get_or_init ( || Some ( v) ) ;
105+ Ok ( r. as_ref ( ) )
78106}
79107
80108/// Fixme lower serializability into ostree-ext
@@ -460,13 +488,9 @@ async fn boot_entry_from_composefs_deployment(
460488
461489#[ context( "Getting composefs deployment status" ) ]
462490pub ( crate ) async fn composefs_deployment_status ( ) -> Result < Host > {
463- let cmdline = crate :: kernel_cmdline:: Cmdline :: from_proc ( ) ?;
464- let composefs_arg = cmdline
465- . find_str ( COMPOSEFS_CMDLINE )
491+ let composefs_state = composefs_booted ( ) ?
466492 . ok_or_else ( || anyhow:: anyhow!( "Failed to find composefs parameter in kernel cmdline" ) ) ?;
467- let booted_image_verity = composefs_arg
468- . value
469- . ok_or_else ( || anyhow:: anyhow!( "Missing value for composefs" ) ) ?;
493+ let composefs_digest = & composefs_state. digest ;
470494
471495 let sysroot = cap_std:: fs:: Dir :: open_ambient_dir ( "/sysroot" , cap_std:: ambient_authority ( ) )
472496 . context ( "Opening sysroot" ) ?;
@@ -531,7 +555,7 @@ pub(crate) async fn composefs_deployment_status() -> Result<Host> {
531555 }
532556 } ;
533557
534- if depl. file_name ( ) == booted_image_verity {
558+ if depl. file_name ( ) == composefs_digest . as_ref ( ) {
535559 host. spec . image = boot_entry. image . as_ref ( ) . map ( |x| x. image . clone ( ) ) ;
536560 host. status . booted = Some ( boot_entry) ;
537561 continue ;
@@ -562,7 +586,7 @@ pub(crate) async fn composefs_deployment_status() -> Result<Host> {
562586 . options
563587 . as_ref ( )
564588 . ok_or ( anyhow:: anyhow!( "options key not found in bls config" ) ) ?
565- . contains ( composefs_arg . as_ref ( ) ) ;
589+ . contains ( composefs_digest . as_ref ( ) ) ;
566590 }
567591
568592 BootType :: Uki => {
@@ -573,7 +597,7 @@ pub(crate) async fn composefs_deployment_status() -> Result<Host> {
573597 . ok_or ( anyhow:: anyhow!( "First boot entry not found" ) ) ?
574598 . body
575599 . chainloader
576- . contains ( composefs_arg . as_ref ( ) )
600+ . contains ( composefs_digest . as_ref ( ) )
577601 }
578602 } ;
579603
@@ -1082,4 +1106,15 @@ mod tests {
10821106 assert ! ( w. contains( "Commit:" ) ) ;
10831107 assert ! ( w. contains( "Soft-reboot:" ) ) ;
10841108 }
1109+
1110+ #[ test]
1111+ fn test_composefs_parsing ( ) {
1112+ const DIGEST : & str = "8b7df143d91c716ecfa5fc1730022f6b421b05cedee8fd52b1fc65a96030ad52" ;
1113+ let v = ComposefsCmdline :: new ( DIGEST ) ;
1114+ assert ! ( !v. insecure) ;
1115+ assert_eq ! ( v. digest. as_ref( ) , DIGEST ) ;
1116+ let v = ComposefsCmdline :: new ( & format ! ( "?{}" , DIGEST ) ) ;
1117+ assert ! ( v. insecure) ;
1118+ assert_eq ! ( v. digest. as_ref( ) , DIGEST ) ;
1119+ }
10851120}
0 commit comments