Skip to content

Commit 6fd1bba

Browse files
authored
overlord/devicestate, secboot: install setup encryption check must use cached context (canonical#16577)
* overlord/devicestate, secboot: install setup encryption check must use cache from context * fixup! overlord/devicestate, secboot: install setup encryption check must use cache from context * fixup! overlord/devicestate, secboot: install setup encryption check must use cache from context
1 parent 2be93ef commit 6fd1bba

File tree

7 files changed

+53
-20
lines changed

7 files changed

+53
-20
lines changed

overlord/devicestate/devicestate_install_api_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -864,7 +864,7 @@ func (s *deviceMgrInstallAPISuite) testInstallSetupStorageEncryption(c *C, isSup
864864
gadgetSnapPath, kernelSnapPath, _, ginfo, mountCmd, _ := s.mockSystemSeedWithLabel(
865865
c, label, seedCopyFn, seedOpts)
866866

867-
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, isSupportedHybrid, hasTPM)
867+
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, isSupportedHybrid, hasTPM, label)
868868

869869
// Mock encryption of partitions
870870
encrytpPartCalls := 0
@@ -934,7 +934,7 @@ func (s *deviceMgrInstallAPISuite) testInstallSetupStorageEncryption(c *C, isSup
934934

935935
// ensure the expected encryption availability check was used
936936
if isSupportedHybrid {
937-
c.Assert(callCnt, DeepEquals, &callCounter{checkCnt: 1, checkActionCnt: 0, sealingSupportedCnt: 0})
937+
c.Assert(callCnt, DeepEquals, &callCounter{checkCnt: 0, checkActionCnt: 1, sealingSupportedCnt: 0})
938938
} else {
939939
c.Assert(callCnt, DeepEquals, &callCounter{checkCnt: 0, checkActionCnt: 0, sealingSupportedCnt: 1})
940940
}
@@ -1170,7 +1170,7 @@ func (s *deviceMgrInstallAPISuite) testInstallSetupStorageEncryptionPassphraseAu
11701170
s.state.Lock()
11711171
defer s.state.Unlock()
11721172

1173-
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, true, true)
1173+
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, true, true, "")
11741174

11751175
restore := devicestate.MockInstallEncryptPartitions(func(
11761176
onVolumes map[string]*gadget.Volume,

overlord/devicestate/devicestate_install_mode_test.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ func (s *deviceMgrInstallModeSuite) SetUpTest(c *C) {
360360
})
361361
s.AddCleanup(restore)
362362

363-
mockHelperForEncryptionAvailabilityCheck(s, c, false, false)
363+
mockHelperForEncryptionAvailabilityCheck(s, c, false, false, "")
364364

365365
s.state.Lock()
366366
defer s.state.Unlock()
@@ -648,7 +648,7 @@ func (s *deviceMgrInstallModeSuite) doRunChangeTestWithEncryption(c *C, grade st
648648
})
649649
defer restore()
650650

651-
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, tc.tpm)
651+
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, tc.tpm, "")
652652

653653
if tc.trustedBootloader {
654654
tab := bootloadertest.Mock("trusted", bootloaderRootdir).WithTrustedAssets()
@@ -1781,7 +1781,7 @@ func (s *deviceMgrInstallModeSuite) TestInstallBootloaderVarSetFails(c *C) {
17811781
})
17821782
defer restore()
17831783

1784-
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, false)
1784+
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, false, "")
17851785

17861786
err := os.WriteFile(filepath.Join(dirs.GlobalRootDir, "/var/lib/snapd/modeenv"),
17871787
[]byte("mode=install\nrecovery_system=1234"), 0644)
@@ -1823,7 +1823,7 @@ func (s *deviceMgrInstallModeSuite) testInstallEncryptionValidityChecks(c *C, er
18231823
restore := release.MockOnClassic(false)
18241824
defer restore()
18251825

1826-
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, true)
1826+
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, true, "")
18271827

18281828
err := os.WriteFile(filepath.Join(dirs.GlobalRootDir, "/var/lib/snapd/modeenv"),
18291829
[]byte("mode=install\n"), 0644)
@@ -2010,7 +2010,7 @@ func (s *deviceMgrInstallModeSuite) TestInstallWithEncryptionValidatesGadgetErr(
20102010
defer restore()
20112011

20122012
// pretend we have a TPM
2013-
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, true)
2013+
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, true, "")
20142014

20152015
// must be a model that requires encryption to error
20162016
s.testInstallGadgetNoSave(c, "secured")
@@ -2041,7 +2041,7 @@ func (s *deviceMgrInstallModeSuite) TestInstallWithEncryptionValidatesGadgetWarn
20412041
defer restore()
20422042

20432043
// pretend we have a TPM
2044-
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, true)
2044+
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, true, "")
20452045

20462046
s.testInstallGadgetNoSave(c, "dangerous")
20472047

@@ -2067,7 +2067,7 @@ func (s *deviceMgrInstallModeSuite) TestInstallWithoutEncryptionValidatesGadgetW
20672067
defer restore()
20682068

20692069
// pretend we have a TPM
2070-
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, true)
2070+
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, true, "")
20712071

20722072
s.testInstallGadgetNoSave(c, "dangerous")
20732073

@@ -2146,7 +2146,7 @@ func (s *deviceMgrInstallModeSuite) TestInstallCheckEncrypted(c *C) {
21462146
makeInstalledMockKernelSnap(c, st, kernelYamlNoFdeSetup)
21472147
}
21482148

2149-
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, tc.hasTPM)
2149+
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, tc.hasTPM, "")
21502150

21512151
encryptionType, err := devicestate.DeviceManagerCheckEncryption(s.mgr, st, deviceCtx, secboot.TPMProvisionFull)
21522152
c.Assert(callCnt.checkCnt, Equals, 0)
@@ -2314,7 +2314,7 @@ func (s *deviceMgrInstallModeSuite) doRunFactoryResetChange(c *C, model *asserts
23142314
})
23152315
defer restore()
23162316

2317-
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, tc.tpm)
2317+
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, tc.tpm, "")
23182318

23192319
if tc.trustedBootloader {
23202320
tab := bootloadertest.Mock("trusted", bootloaderRootdir).WithTrustedAssets()
@@ -3135,7 +3135,7 @@ func (s *deviceMgrInstallModeSuite) TestFactoryResetExpectedTasks(c *C) {
31353135
restore := release.MockOnClassic(false)
31363136
defer restore()
31373137

3138-
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, false)
3138+
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, false, "")
31393139

31403140
restore = devicestate.MockInstallFactoryReset(func(mod gadget.Model, gadgetRoot string, kernelSnapInfo *install.KernelSnapInfo, device string, options install.Options, obs gadget.ContentObserver, pertTimings timings.Measurer) (*install.InstalledSystemSideData, error) {
31413141
c.Assert(os.MkdirAll(dirs.SnapDeviceDirUnder(filepath.Join(dirs.GlobalRootDir, "/run/mnt/ubuntu-data/system-data")), 0755), IsNil)
@@ -3207,7 +3207,7 @@ func (s *deviceMgrInstallModeSuite) TestFactoryResetInstallDeviceHook(c *C) {
32073207
restore := release.MockOnClassic(false)
32083208
defer restore()
32093209

3210-
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, false)
3210+
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, false, "")
32113211

32123212
hooksCalled := []*hookstate.Context{}
32133213
restore = hookstate.MockRunHook(func(ctx *hookstate.Context, tomb *tomb.Tomb) ([]byte, error) {

overlord/devicestate/devicestate_systems_test.go

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2983,6 +2983,7 @@ var preinstallAction = &secboot.PreinstallAction{
29832983

29842984
type suiteWithAddCleanup interface {
29852985
AddCleanup(func())
2986+
DeviceManager() *devicestate.DeviceManager
29862987
}
29872988

29882989
type callCounter struct {
@@ -2998,7 +2999,8 @@ type callCounter struct {
29982999
//
29993000
// isSupportedUbuntuHybrid: modify system release information and place current boot images to simulate supported Ubuntu hybrid install
30003001
// hasTPM: indicates if we should simulate having a TPM (no error detected) or no TPM (some representative error)
3001-
func mockHelperForEncryptionAvailabilityCheck(s suiteWithAddCleanup, c *C, isSupportedUbuntuHybrid, hasTPM bool) *callCounter {
3002+
// cacheLabel: system label to use to cache check context where "" means do not cache check context
3003+
func mockHelperForEncryptionAvailabilityCheck(s suiteWithAddCleanup, c *C, isSupportedUbuntuHybrid, hasTPM bool, cacheLabel string) *callCounter {
30023004
callCnt := &callCounter{}
30033005

30043006
releaseInfo := &release.OS{
@@ -3035,6 +3037,15 @@ func mockHelperForEncryptionAvailabilityCheck(s suiteWithAddCleanup, c *C, isSup
30353037
}
30363038
}
30373039

3040+
if isSupportedUbuntuHybrid && cacheLabel != "" {
3041+
// populate the cache with encryption support information that
3042+
// includes a check context similar to having performed an
3043+
// initial preinstall check
3044+
encInfo := &install.EncryptionSupportInfo{}
3045+
encInfo.SetAvailabilityCheckContext(&secboot.PreinstallCheckContext{})
3046+
s.DeviceManager().SetEncryptionSupportInfoInCacheUnlocked(cacheLabel, encInfo)
3047+
}
3048+
30383049
restore := install.MockSecbootPreinstallCheck(func(ctx context.Context, bootImagePaths []string) (*secboot.PreinstallCheckContext, []secboot.PreinstallErrorDetails, error) {
30393050
callCnt.checkCnt++
30403051
c.Assert(bootImagePaths, HasLen, 3)
@@ -3051,7 +3062,11 @@ func mockHelperForEncryptionAvailabilityCheck(s suiteWithAddCleanup, c *C, isSup
30513062
callCnt.checkActionCnt++
30523063
c.Assert(pcc, NotNil)
30533064
c.Assert(ctx, NotNil)
3054-
c.Assert(action, DeepEquals, preinstallAction)
3065+
if cacheLabel != "" {
3066+
c.Assert(action, DeepEquals, &secboot.PreinstallAction{Action: secboot.ActionNone})
3067+
} else {
3068+
c.Assert(action, DeepEquals, preinstallAction)
3069+
}
30553070
c.Assert(isSupportedUbuntuHybrid, Equals, true)
30563071

30573072
if hasTPM {
@@ -3160,7 +3175,7 @@ func (s *modelAndGadgetInfoSuite) TestSystemAndGadgetAndEncryptionInfoNotSupport
31603175
UnavailableWarning: "not encrypting device storage as checking TPM gave: cannot connect to TPM device",
31613176
}
31623177

3163-
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, isSupportedHybrid, false)
3178+
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, isSupportedHybrid, false, "")
31643179

31653180
// basic availability check - fill empty info cache
31663181
encInfoFromCache := false
@@ -3211,7 +3226,7 @@ func (s *modelAndGadgetInfoSuite) TestSystemAndGadgetAndEncryptionInfoSupportedH
32113226
}
32123227
expectedEncInfo.SetAvailabilityCheckContext(preinstallCheckContext)
32133228

3214-
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, isSupportedHybrid, false)
3229+
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, isSupportedHybrid, false, "")
32153230

32163231
// comprehensive preinstall check - fill empty info cache
32173232
encInfoFromCache := false
@@ -3298,7 +3313,7 @@ func (s *modelAndGadgetInfoSuite) testSystemAndGadgetAndEncryptionInfoPassphrase
32983313
PassphraseAuthAvailable: hasPassphraseSupport,
32993314
}
33003315

3301-
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, true)
3316+
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, false, true, "")
33023317

33033318
// refresh empty cache
33043319
encInfoFromCache := false
@@ -3431,7 +3446,7 @@ func (s *modelAndGadgetInfoSuite) TestSystemAndGadgetInfoBadClassicGadget(c *C)
34313446
isClassic := true
34323447
s.makeMockUC20SeedWithGadgetYaml(c, "some-label", mockGadgetUCYamlNoBootRole, isClassic, nil)
34333448

3434-
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, true, true)
3449+
callCnt := mockHelperForEncryptionAvailabilityCheck(s, c, true, true, "")
34353450

34363451
_, _, _, err := s.mgr.SystemAndGadgetAndEncryptionInfo("some-label", false)
34373452
c.Assert(callCnt, DeepEquals, &callCounter{checkCnt: 1, checkActionCnt: 0, sealingSupportedCnt: 0})

overlord/devicestate/devicestate_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,10 @@ func (s *deviceMgrBaseSuite) addKeyToManagerInState(c *C) {
510510
c.Assert(err, IsNil)
511511
}
512512

513+
func (s *deviceMgrBaseSuite) DeviceManager() *devicestate.DeviceManager {
514+
return s.mgr
515+
}
516+
513517
func (s *deviceMgrSuite) SetUpTest(c *C) {
514518
classic := false
515519
s.setupBaseTest(c, classic)

overlord/devicestate/handlers_install.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,12 +1370,22 @@ func (m *DeviceManager) doInstallSetupStorageEncryption(t *state.Task, _ *tomb.T
13701370
return fmt.Errorf("reading gadget information: %v", err)
13711371
}
13721372

1373+
var checkAction *secboot.PreinstallAction
1374+
if m.readCacheEncryptionSupportInfoLocked(systemLabel) != nil {
1375+
// If a cached context is available, the preinstall check was previously run
1376+
// and must be repeated. Set an action to signal reuse of the preinstall check
1377+
// context. Use the inert "ActionNone" to repeat the check without requesting
1378+
// any modifications.
1379+
checkAction = &secboot.PreinstallAction{Action: secboot.ActionNone}
1380+
}
1381+
13731382
constraints := installLogic.EncryptionConstraints{
13741383
Model: systemAndSeeds.Model,
13751384
Kernel: systemAndSeeds.InfosByType[snap.TypeKernel],
13761385
Gadget: gadgetInfo,
13771386
TPMMode: secboot.TPMProvisionFull,
13781387
SnapdVersions: systemAndSeeds.SystemSnapdVersions,
1388+
CheckAction: checkAction,
13791389
}
13801390

13811391
// do not use cached encryption information; perform a fresh encryption

secboot/preinstall_nosb.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import (
2727
type PreinstallCheckContext struct{}
2828
type PreinstallCheckResult struct{}
2929

30+
const ActionNone = ""
31+
3032
func PreinstallCheck(ctx context.Context, bootImagePaths []string) (*PreinstallCheckContext, []PreinstallErrorDetails, error) {
3133
return nil, nil, errBuildWithoutSecboot
3234
}

secboot/preinstall_sb.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ var (
6161
sbPreinstallRunChecks = (*sb_preinstall.RunChecksContext).Run
6262
)
6363

64+
const ActionNone = string(sb_preinstall.ActionNone)
65+
6466
// PreinstallCheck runs preinstall checks using default check configuration and
6567
// TCG-compliant PCR profile generation options to evaluate whether the host
6668
// environment is an EFI system suitable for TPM-based Full Disk Encryption. The

0 commit comments

Comments
 (0)