@@ -63,19 +63,47 @@ impl From<ImageSignature> for ostree_container::SignatureSource {
6363 }
6464}
6565
66+ /// A parsed composefs command line
67+ pub ( crate ) struct ComposefsCmdline {
68+ #[ allow( dead_code) ]
69+ pub insecure : bool ,
70+ pub digest : Box < str > ,
71+ }
72+
73+ impl ComposefsCmdline {
74+ pub ( crate ) fn new ( s : & str ) -> Self {
75+ let ( insecure, digest_str) = s
76+ . strip_prefix ( '?' )
77+ . map ( |v| ( true , v) )
78+ . unwrap_or_else ( || ( false , s) ) ;
79+ ComposefsCmdline {
80+ insecure,
81+ digest : digest_str. into ( ) ,
82+ }
83+ }
84+ }
85+
86+ impl std:: fmt:: Display for ComposefsCmdline {
87+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
88+ let insecure = if self . insecure { "?" } else { "" } ;
89+ write ! ( f, "{}={}{}" , COMPOSEFS_CMDLINE , insecure, self . digest)
90+ }
91+ }
92+
6693/// Detect if we have composefs=<digest> in /proc/cmdline
67- pub ( crate ) fn composefs_booted ( ) -> Result < Option < & ' static str > > {
68- static CACHED_DIGEST_VALUE : OnceLock < Option < String > > = OnceLock :: new ( ) ;
94+ pub ( crate ) fn composefs_booted ( ) -> Result < Option < & ' static ComposefsCmdline > > {
95+ static CACHED_DIGEST_VALUE : OnceLock < Option < ComposefsCmdline > > = OnceLock :: new ( ) ;
6996 if let Some ( v) = CACHED_DIGEST_VALUE . get ( ) {
70- return Ok ( v. as_deref ( ) ) ;
97+ return Ok ( v. as_ref ( ) ) ;
7198 }
7299 let cmdline = Cmdline :: from_proc ( ) ?;
73100 let Some ( kv) = cmdline. find_str ( COMPOSEFS_CMDLINE ) else {
74101 return Ok ( None ) ;
75102 } ;
76103 let Some ( v) = kv. value else { return Ok ( None ) } ;
77- let r = CACHED_DIGEST_VALUE . get_or_init ( || Some ( v. to_owned ( ) ) ) ;
78- Ok ( r. as_deref ( ) )
104+ let v = ComposefsCmdline :: new ( v) ;
105+ let r = CACHED_DIGEST_VALUE . get_or_init ( || Some ( v) ) ;
106+ Ok ( r. as_ref ( ) )
79107}
80108
81109/// Fixme lower serializability into ostree-ext
@@ -461,13 +489,9 @@ async fn boot_entry_from_composefs_deployment(
461489
462490#[ context( "Getting composefs deployment status" ) ]
463491pub ( crate ) async fn composefs_deployment_status ( ) -> Result < Host > {
464- let cmdline = Cmdline :: from_proc ( ) ?;
465- let composefs_arg = cmdline
466- . find_str ( COMPOSEFS_CMDLINE )
492+ let composefs_state = composefs_booted ( ) ?
467493 . ok_or_else ( || anyhow:: anyhow!( "Failed to find composefs parameter in kernel cmdline" ) ) ?;
468- let booted_image_verity = composefs_arg
469- . value
470- . ok_or_else ( || anyhow:: anyhow!( "Missing value for composefs" ) ) ?;
494+ let composefs_digest = & composefs_state. digest ;
471495
472496 let sysroot = cap_std:: fs:: Dir :: open_ambient_dir ( "/sysroot" , cap_std:: ambient_authority ( ) )
473497 . context ( "Opening sysroot" ) ?;
@@ -532,7 +556,7 @@ pub(crate) async fn composefs_deployment_status() -> Result<Host> {
532556 }
533557 } ;
534558
535- if depl. file_name ( ) == booted_image_verity {
559+ if depl. file_name ( ) == composefs_digest . as_ref ( ) {
536560 host. spec . image = boot_entry. image . as_ref ( ) . map ( |x| x. image . clone ( ) ) ;
537561 host. status . booted = Some ( boot_entry) ;
538562 continue ;
@@ -563,7 +587,7 @@ pub(crate) async fn composefs_deployment_status() -> Result<Host> {
563587 . options
564588 . as_ref ( )
565589 . ok_or ( anyhow:: anyhow!( "options key not found in bls config" ) ) ?
566- . contains ( composefs_arg . as_ref ( ) ) ;
590+ . contains ( composefs_digest . as_ref ( ) ) ;
567591 }
568592
569593 BootType :: Uki => {
@@ -574,7 +598,7 @@ pub(crate) async fn composefs_deployment_status() -> Result<Host> {
574598 . ok_or ( anyhow:: anyhow!( "First boot entry not found" ) ) ?
575599 . body
576600 . chainloader
577- . contains ( composefs_arg . as_ref ( ) )
601+ . contains ( composefs_digest . as_ref ( ) )
578602 }
579603 } ;
580604
@@ -1083,4 +1107,15 @@ mod tests {
10831107 assert ! ( w. contains( "Commit:" ) ) ;
10841108 assert ! ( w. contains( "Soft-reboot:" ) ) ;
10851109 }
1110+
1111+ #[ test]
1112+ fn test_composefs_parsing ( ) {
1113+ const DIGEST : & str = "8b7df143d91c716ecfa5fc1730022f6b421b05cedee8fd52b1fc65a96030ad52" ;
1114+ let v = ComposefsCmdline :: new ( DIGEST ) ;
1115+ assert ! ( !v. insecure) ;
1116+ assert_eq ! ( v. digest. as_ref( ) , DIGEST ) ;
1117+ let v = ComposefsCmdline :: new ( & format ! ( "?{}" , DIGEST ) ) ;
1118+ assert ! ( v. insecure) ;
1119+ assert_eq ! ( v. digest. as_ref( ) , DIGEST ) ;
1120+ }
10861121}
0 commit comments