@@ -116,8 +116,7 @@ use crate::{
116116} ;
117117use crate :: {
118118 composefs_consts:: {
119- BOOT_LOADER_ENTRIES , ORIGIN_KEY_BOOT , ORIGIN_KEY_BOOT_DIGEST , STAGED_BOOT_LOADER_ENTRIES ,
120- STATE_DIR_ABS , USER_CFG , USER_CFG_STAGED ,
119+ BOOT_LOADER_ENTRIES , STAGED_BOOT_LOADER_ENTRIES , USER_CFG , USER_CFG_STAGED ,
121120 } ,
122121 spec:: { Bootloader , Host } ,
123122} ;
@@ -328,6 +327,27 @@ fn compute_boot_digest(
328327 Ok ( hex:: encode ( digest) )
329328}
330329
330+ #[ context( "Computing boot digest for Type1 entries" ) ]
331+ fn compute_boot_digest_type1 ( dir : & Dir ) -> Result < String > {
332+ let mut vmlinuz = dir
333+ . open ( VMLINUZ )
334+ . with_context ( || format ! ( "Opening {VMLINUZ}" ) ) ?;
335+
336+ let mut initrd = dir
337+ . open ( INITRD )
338+ . with_context ( || format ! ( "Opening {INITRD}" ) ) ?;
339+
340+ let mut hasher = openssl:: hash:: Hasher :: new ( openssl:: hash:: MessageDigest :: sha256 ( ) )
341+ . context ( "Creating hasher" ) ?;
342+
343+ std:: io:: copy ( & mut vmlinuz, & mut hasher) ?;
344+ std:: io:: copy ( & mut initrd, & mut hasher) ?;
345+
346+ let digest: & [ u8 ] = & hasher. finish ( ) . context ( "Finishing digest" ) ?;
347+
348+ Ok ( hex:: encode ( digest) )
349+ }
350+
331351/// Compute SHA256Sum of .linux + .initrd section of the UKI
332352///
333353/// # Arguments
@@ -355,52 +375,35 @@ pub(crate) fn compute_boot_digest_uki(uki: &[u8]) -> Result<String> {
355375/// Given the SHA256 sum of current VMlinuz + Initrd combo, find boot entry with the same SHA256Sum
356376///
357377/// # Returns
358- /// Returns the verity of all deployments that have a boot digest same as the one passed in
378+ /// Returns the directory name that has the same sha256 digest for vmlinuz + initrd as the one
379+ /// that's passed in
359380#[ context( "Checking boot entry duplicates" ) ]
360- pub ( crate ) fn find_vmlinuz_initrd_duplicates ( digest : & str ) -> Result < Option < Vec < String > > > {
361- let deployments = Dir :: open_ambient_dir ( STATE_DIR_ABS , ambient_authority ( ) ) ;
362-
363- let deployments = match deployments {
364- Ok ( d) => d,
365- // The first ever deployment
366- Err ( e) if e. kind ( ) == std:: io:: ErrorKind :: NotFound => return Ok ( None ) ,
367- Err ( e) => anyhow:: bail!( e) ,
368- } ;
369-
370- let mut symlink_to: Option < Vec < String > > = None ;
371-
372- for depl in deployments. entries ( ) ? {
373- let depl = depl?;
374-
375- let depl_file_name = depl. file_name ( ) ;
376- let depl_file_name = depl_file_name. as_str ( ) ?;
377-
378- let config = depl
379- . open_dir ( )
380- . with_context ( || format ! ( "Opening {depl_file_name}" ) ) ?
381- . read_to_string ( format ! ( "{depl_file_name}.origin" ) )
382- . context ( "Reading origin file" ) ?;
381+ pub ( crate ) fn find_vmlinuz_initrd_duplicate (
382+ storage : & Storage ,
383+ digest : & str ,
384+ ) -> Result < Option < String > > {
385+ let boot_dir = storage. bls_boot_binaries_dir ( ) ?;
386+
387+ for entry in boot_dir. entries_utf8 ( ) ? {
388+ let entry = entry?;
389+ let dir_name = entry. file_name ( ) ?;
390+
391+ if !entry. file_type ( ) ?. is_dir ( ) {
392+ continue ;
393+ }
383394
384- let ini = tini:: Ini :: from_string ( & config)
385- . with_context ( || format ! ( "Failed to parse file {depl_file_name}.origin as ini" ) ) ?;
395+ let Some ( ..) = dir_name. strip_prefix ( TYPE1_BOOT_DIR_PREFIX ) else {
396+ continue ;
397+ } ;
386398
387- match ini. get :: < String > ( ORIGIN_KEY_BOOT , ORIGIN_KEY_BOOT_DIGEST ) {
388- Some ( hash) => {
389- if hash == digest {
390- match symlink_to {
391- Some ( ref mut prev) => prev. push ( depl_file_name. to_string ( ) ) ,
392- None => symlink_to = Some ( vec ! [ depl_file_name. to_string( ) ] ) ,
393- }
394- }
395- }
399+ let entry_digest = compute_boot_digest_type1 ( & boot_dir. open_dir ( & dir_name) ?) ?;
396400
397- // No SHASum recorded in origin file
398- // `symlink_to` is already none, but being explicit here
399- None => symlink_to = None ,
400- } ;
401+ if entry_digest == digest {
402+ return Ok ( Some ( dir_name) ) ;
403+ }
401404 }
402405
403- Ok ( symlink_to )
406+ Ok ( None )
404407}
405408
406409#[ context( "Writing BLS entries to disk" ) ]
@@ -687,45 +690,20 @@ pub(crate) fn setup_composefs_bls_boot(
687690 options : Some ( cmdline_refs) ,
688691 } ) ;
689692
690- match find_vmlinuz_initrd_duplicates ( & boot_digest) ? {
691- Some ( shared_entries) => {
693+ let shared_entry = match setup_type {
694+ BootSetupType :: Setup ( _) => None ,
695+ BootSetupType :: Upgrade ( ( storage, ..) ) => {
696+ find_vmlinuz_initrd_duplicate ( storage, & boot_digest) ?
697+ }
698+ } ;
699+
700+ match shared_entry {
701+ Some ( shared_entry) => {
692702 // Multiple deployments could be using the same kernel + initrd, but there
693703 // would be only one available
694704 //
695705 // Symlinking directories themselves would be better, but vfat does not support
696706 // symlinks
697-
698- let mut shared_entry: Option < String > = None ;
699-
700- let entries =
701- Dir :: open_ambient_dir ( entry_paths. entries_path , ambient_authority ( ) )
702- . context ( "Opening entries path" ) ?
703- . entries_utf8 ( )
704- . context ( "Getting dir entries" ) ?;
705-
706- for ent in entries {
707- let ent = ent?;
708- // We shouldn't error here as all our file names are UTF-8 compatible
709- let ent_name = ent. file_name ( ) ?;
710-
711- let Some ( entry_verity_part) = ent_name. strip_prefix ( TYPE1_BOOT_DIR_PREFIX )
712- else {
713- // Not our directory
714- continue ;
715- } ;
716-
717- if shared_entries
718- . iter ( )
719- . any ( |shared_ent| shared_ent == entry_verity_part)
720- {
721- shared_entry = Some ( ent_name) ;
722- break ;
723- }
724- }
725-
726- let shared_entry = shared_entry
727- . ok_or_else ( || anyhow:: anyhow!( "Shared boot binaries not found" ) ) ?;
728-
729707 match bls_config. cfg_type {
730708 BLSConfigType :: NonEFI {
731709 ref mut linux,
0 commit comments