2121package fdestate_test
2222
2323import (
24+ "context"
2425 "fmt"
2526 "os"
2627
2728 . "gopkg.in/check.v1"
2829
2930 sb "github.com/snapcore/secboot"
3031 "github.com/snapcore/snapd/boot"
32+ "github.com/snapcore/snapd/bootloader"
33+ "github.com/snapcore/snapd/bootloader/bootloadertest"
3134 "github.com/snapcore/snapd/dirs"
3235 "github.com/snapcore/snapd/gadget/device"
3336 "github.com/snapcore/snapd/logger"
3437 "github.com/snapcore/snapd/overlord/fdestate"
3538 "github.com/snapcore/snapd/overlord/fdestate/backend"
3639 "github.com/snapcore/snapd/secboot"
40+ "github.com/snapcore/snapd/snap"
3741 "github.com/snapcore/snapd/testutil"
3842)
3943
@@ -54,6 +58,58 @@ func (s *autoRepairSuite) SetUpTest(c *C) {
5458 }))
5559}
5660
61+ func (s * autoRepairSuite ) mockPostInstallChecks (c * C ) {
62+ recoveryBl := bootloadertest .Mock ("recovery" , "" ).WithTrustedAssets ()
63+ recoveryBl .TrustedAssetsMap = map [string ]string {
64+ "EFI/ubuntu/shim.efi" : "ubuntu:shim" ,
65+ "EFI/ubuntu/grub.efi" : "ubuntu:grub" ,
66+ }
67+ recoveryBl .KernelBootFileBuilder = func (kernelPath string ) bootloader.BootFile {
68+ return bootloader .NewBootFile ("some-kernel" , "kernel.efi" , bootloader .RoleRunMode )
69+ }
70+ recoveryBl .BootChainList = []bootloader.BootFile {
71+ bootloader .NewBootFile ("" , "EFI/ubuntu/shim.efi" , bootloader .RoleRecovery ),
72+ bootloader .NewBootFile ("" , "EFI/ubuntu/grub.efi" , bootloader .RoleRecovery ),
73+ bootloader .NewBootFile ("" , "EFI/ubuntu/grub.efi" , bootloader .RoleRunMode ),
74+ }
75+
76+ runBl := bootloadertest .Mock ("run" , "" ).WithExtractedRunKernelImage ()
77+ runBl .SetEnabledKernel (& snap.Info {SuggestedName : "some-kernel" , InstanceKey : "x1" , SnapType : snap .TypeKernel })
78+
79+ s .AddCleanup (fdestate .MockBootloaderFind (func (rootdir string , opts * bootloader.Options ) (bootloader.Bootloader , error ) {
80+ if opts .Role == bootloader .RoleRecovery {
81+ return recoveryBl , nil
82+ } else if opts .Role == bootloader .RoleRunMode {
83+ return runBl , nil
84+ } else {
85+ c .Errorf ("unexpected" )
86+ return nil , fmt .Errorf ("unexpected" )
87+ }
88+ }))
89+
90+ s .AddCleanup (fdestate .MockBootReadModeenv (func (rootdir string ) (* boot.Modeenv , error ) {
91+ return & boot.Modeenv {
92+ CurrentTrustedBootAssets : map [string ][]string {
93+ "ubuntu:grub" : {
94+ "hash-grub-run" ,
95+ },
96+ },
97+ CurrentTrustedRecoveryBootAssets : map [string ][]string {
98+ "ubuntu:shim" : {
99+ "hash-shim-recovery" ,
100+ },
101+ "ubuntu:grub" : {
102+ "hash-grub-recovery" ,
103+ },
104+ },
105+ }, nil
106+ }))
107+
108+ s .AddCleanup (fdestate .MockSecbootPostinstallCheck (func (ctx context.Context , bootImagePaths []bootloader.BootFile ) (* secboot.PreinstallCheckContext , []secboot.PreinstallErrorDetails , error ) {
109+ return nil , nil , nil
110+ }))
111+ }
112+
57113func (s * autoRepairSuite ) TestAttemptAutoRepairNeeded (c * C ) {
58114 const onClassic = false
59115 s .startedManager (c , onClassic )
@@ -85,6 +141,8 @@ func (s *autoRepairSuite) TestAttemptAutoRepairNeeded(c *C) {
85141 return nil
86142 })()
87143
144+ s .mockPostInstallChecks (c )
145+
88146 err := fdestate .AttemptAutoRepairIfNeeded (s .st , nil )
89147 c .Assert (err , IsNil )
90148
@@ -174,6 +232,8 @@ func (s *autoRepairSuite) TestAttemptAutoRepairNeededBadReprovision(c *C) {
174232 return fmt .Errorf ("Unexpected call" )
175233 })()
176234
235+ s .mockPostInstallChecks (c )
236+
177237 err := fdestate .AttemptAutoRepairIfNeeded (s .st , nil )
178238 c .Assert (err , IsNil )
179239
@@ -251,6 +311,8 @@ func (s *autoRepairSuite) TestAttemptAutoRepairErrorNoActivateStateRecovery(c *C
251311 }, nil
252312 })()
253313
314+ s .mockPostInstallChecks (c )
315+
254316 logbuf , restore := logger .MockLogger ()
255317 defer restore ()
256318
@@ -355,6 +417,8 @@ func (s *autoRepairSuite) TestAttemptAutoRepairNeededBadReseal(c *C) {
355417 return fmt .Errorf ("some error" )
356418 })()
357419
420+ s .mockPostInstallChecks (c )
421+
358422 err := fdestate .AttemptAutoRepairIfNeeded (s .st , nil )
359423 c .Assert (err , IsNil )
360424
@@ -390,3 +454,106 @@ func (s *autoRepairSuite) TestIgnoreOldAutoRepairResult(c *C) {
390454 c .Assert (err , IsNil )
391455 c .Check (result .Result , Equals , fdestate .AutoRepairResult ("failed-platform-init" ))
392456}
457+
458+ func (s * autoRepairSuite ) TestAttemptAutoRepairFailedPostinstallChecks (c * C ) {
459+ const onClassic = false
460+ s .startedManager (c , onClassic )
461+
462+ s .st .Lock ()
463+ defer s .st .Unlock ()
464+
465+ c .Assert (device .StampSealedKeys (dirs .GlobalRootDir , device .SealingMethodTPM ), IsNil )
466+
467+ s .createUnlockedState (c , sb .ActivationSucceededWithPlatformKey )
468+
469+ defer fdestate .MockSecbootProvisionTPM (func (mode secboot.TPMProvisionMode , lockoutAuthFile string ) error {
470+ c .Errorf ("unexpected call" )
471+ return fmt .Errorf ("unexpected call" )
472+ })()
473+
474+ defer fdestate .MockSecbootShouldAttemptRepair (func (as * secboot.ActivateState ) bool {
475+ return true
476+ })()
477+
478+ s .mockBootAssetsStateForModeenv (c )
479+
480+ defer fdestate .MockBackendResealKeyForBootChains (func (manager backend.FDEStateManager , method device.SealingMethod , rootdir string , params * boot.ResealKeyForBootChainsParams ) error {
481+ c .Errorf ("unexpected call" )
482+ return fmt .Errorf ("unexpected call" )
483+ })()
484+
485+ s .mockPostInstallChecks (c )
486+ defer fdestate .MockSecbootPostinstallCheck (func (ctx context.Context , bootImagePaths []bootloader.BootFile ) (* secboot.PreinstallCheckContext , []secboot.PreinstallErrorDetails , error ) {
487+ return nil , nil , fmt .Errorf ("some error" )
488+ })()
489+
490+ logbuf , restore := logger .MockLogger ()
491+ defer restore ()
492+
493+ err := fdestate .AttemptAutoRepairIfNeeded (s .st , nil )
494+ c .Assert (err , IsNil )
495+
496+ result , err := fdestate .GetRepairAttemptResult (s .st )
497+ c .Assert (err , IsNil )
498+
499+ c .Check (result .Result , Equals , fdestate .AutoRepairResult ("failed-platform-init" ))
500+
501+ c .Check (logbuf .String (), testutil .Contains , `WARNING: could not auto repair keyslots due to failed platform initialization: some error` )
502+ }
503+
504+ func (s * autoRepairSuite ) TestAttemptAutoRepairFailedPostinstallChecksWithDetails (c * C ) {
505+ const onClassic = false
506+ s .startedManager (c , onClassic )
507+
508+ s .st .Lock ()
509+ defer s .st .Unlock ()
510+
511+ c .Assert (device .StampSealedKeys (dirs .GlobalRootDir , device .SealingMethodTPM ), IsNil )
512+
513+ s .createUnlockedState (c , sb .ActivationSucceededWithPlatformKey )
514+
515+ defer fdestate .MockSecbootProvisionTPM (func (mode secboot.TPMProvisionMode , lockoutAuthFile string ) error {
516+ c .Errorf ("unexpected call" )
517+ return fmt .Errorf ("unexpected call" )
518+ })()
519+
520+ defer fdestate .MockSecbootShouldAttemptRepair (func (as * secboot.ActivateState ) bool {
521+ return true
522+ })()
523+
524+ s .mockBootAssetsStateForModeenv (c )
525+
526+ defer fdestate .MockBackendResealKeyForBootChains (func (manager backend.FDEStateManager , method device.SealingMethod , rootdir string , params * boot.ResealKeyForBootChainsParams ) error {
527+ c .Errorf ("unexpected call" )
528+ return fmt .Errorf ("unexpected call" )
529+ })()
530+
531+ s .mockPostInstallChecks (c )
532+ defer fdestate .MockSecbootPostinstallCheck (func (ctx context.Context , bootImagePaths []bootloader.BootFile ) (* secboot.PreinstallCheckContext , []secboot.PreinstallErrorDetails , error ) {
533+ var details = []secboot.PreinstallErrorDetails {
534+ {
535+ Kind : "kind-1" ,
536+ Message : "error-1" ,
537+ },
538+ {
539+ Kind : "kind-2" ,
540+ Message : "error-2" ,
541+ },
542+ }
543+
544+ return nil , details , nil
545+ })()
546+
547+ logbuf , restore := logger .MockLogger ()
548+ defer restore ()
549+
550+ err := fdestate .AttemptAutoRepairIfNeeded (s .st , nil )
551+ c .Assert (err , IsNil )
552+
553+ result , err := fdestate .GetRepairAttemptResult (s .st )
554+ c .Assert (err , IsNil )
555+
556+ c .Check (result .Result , Equals , fdestate .AutoRepairResult ("failed-platform-init" ))
557+
558+ c .Check (logbuf .String (), testutil .Contains , "WARNING: could not auto repair keyslots due to failed platform initialization:\n - error-1\n - error-2\n " )
559+ }
0 commit comments