Skip to content

Commit

Permalink
boot,o/devicestate: extend HasFDESetupHook to consider unrelated kernels
Browse files Browse the repository at this point in the history
we need to check for hook presence also in kernels that are not the currently
installed kernel if any
  • Loading branch information
pedronis committed Oct 6, 2022
1 parent d7d965a commit f31235e
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 31 deletions.
2 changes: 1 addition & 1 deletion boot/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ func MockRebootArgsPath(argsPath string) (restore func()) {
return func() { rebootArgsPath = oldRebootArgsPath }
}

func MockHasFDESetupHook(f func() (bool, error)) (restore func()) {
func MockHasFDESetupHook(f func(*snap.Info) (bool, error)) (restore func()) {
oldHasFDESetupHook := HasFDESetupHook
HasFDESetupHook = f
return func() {
Expand Down
8 changes: 7 additions & 1 deletion boot/makebootable.go
Original file line number Diff line number Diff line change
Expand Up @@ -497,8 +497,14 @@ func makeRunnableSystem(model *asserts.Model, bootWith *BootableSet, sealer *Tru
}

if sealer != nil {
hasHook, err := HasFDESetupHook(bootWith.Kernel)
if err != nil {
return fmt.Errorf("cannot check for fde-setup hook: %v", err)
}

flags := sealKeyToModeenvFlags{
FactoryReset: makeOpts.AfterDataReset,
HasFDESetupHook: hasHook,
FactoryReset: makeOpts.AfterDataReset,
}
if makeOpts.Standalone {
flags.SnapsDir = snapBlobDir
Expand Down
10 changes: 10 additions & 0 deletions boot/makebootable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,14 @@ version: 5.0
})
defer restore()

hasFDESetupHoolCalled := false
restore = boot.MockHasFDESetupHook(func(kernel *snap.Info) (bool, error) {
c.Check(kernel, Equals, kernelInfo)
hasFDESetupHoolCalled = true
return false, nil
})
defer restore()

// set mock key sealing
sealKeysCalls := 0
restore = boot.MockSecbootSealKeys(func(keys []secboot.SealKeyRequest, params *secboot.SealKeysParams) error {
Expand Down Expand Up @@ -839,6 +847,8 @@ current_kernel_command_lines=["snapd_recovery_mode=run console=ttyS0 console=tty
c.Check(copiedRecoveryGrubBin, testutil.FileEquals, "recovery grub content")
c.Check(copiedRecoveryShimBin, testutil.FileEquals, "recovery shim content")

// we checked for fde-setup-hook
c.Check(hasFDESetupHoolCalled, Equals, true)
// make sure TPM was provisioned
c.Check(provisionCalls, Equals, 1)
// make sure SealKey was called for the run object and the fallback object
Expand Down
15 changes: 10 additions & 5 deletions boot/seal.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ var (
// disk encryption implementations. The state must be locked when these
// functions are called.
var (
HasFDESetupHook = func() (bool, error) {
// HasFDESetupHook purpose is to detect if the target kernel has a
// fde-setup-hook. If kernelInfo is nil the current kernel is checked
// assuming it is representive of the target one.
HasFDESetupHook = func(kernelInfo *snap.Info) (bool, error) {
return false, nil
}
RunFDESetupHook fde.RunSetupHookFunc = func(req *fde.SetupRequest) ([]byte, error) {
Expand Down Expand Up @@ -96,6 +99,8 @@ func recoveryBootChainsFileUnder(rootdir string) string {
}

type sealKeyToModeenvFlags struct {
// HasFDESetupHook is true if the kernel has a fde-setup hook to use
HasFDESetupHook bool
// FactoryReset indicates that the sealing is happening during factory
// reset.
FactoryReset bool
Expand All @@ -121,11 +126,11 @@ func sealKeyToModeenv(key, saveKey keys.EncryptionKey, model *asserts.Model, mod
}
}

hasHook, err := HasFDESetupHook()
/*hasHook, err := HasFDESetupHook()
if err != nil {
return fmt.Errorf("cannot check for fde-setup hook %v", err)
}
if hasHook {
}*/
if flags.HasFDESetupHook {
return sealKeyToModeenvUsingFDESetupHook(key, saveKey, model, modeenv, flags)
}

Expand Down Expand Up @@ -891,7 +896,7 @@ func postFactoryResetCleanupSecboot() error {
}

func postFactoryResetCleanup() error {
hasHook, err := HasFDESetupHook()
hasHook, err := HasFDESetupHook(nil)
if err != nil {
return fmt.Errorf("cannot check for fde-setup hook %v", err)
}
Expand Down
24 changes: 7 additions & 17 deletions boot/seal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1627,17 +1627,11 @@ func (s *sealSuite) TestSealToModeenvWithFdeHookHappy(c *C) {
rootdir := c.MkDir()
dirs.SetRootDir(rootdir)
defer dirs.SetRootDir("")

restore := boot.MockHasFDESetupHook(func() (bool, error) {
return true, nil
})
defer restore()

model := boottest.MakeMockUC20Model()

n := 0
var runFDESetupHookReqs []*fde.SetupRequest
restore = boot.MockRunFDESetupHook(func(req *fde.SetupRequest) ([]byte, error) {
restore := boot.MockRunFDESetupHook(func(req *fde.SetupRequest) ([]byte, error) {
n++
runFDESetupHookReqs = append(runFDESetupHookReqs, req)

Expand Down Expand Up @@ -1671,7 +1665,7 @@ func (s *sealSuite) TestSealToModeenvWithFdeHookHappy(c *C) {
key := keys.EncryptionKey{1, 2, 3, 4}
saveKey := keys.EncryptionKey{5, 6, 7, 8}

err := boot.SealKeyToModeenv(key, saveKey, model, modeenv, boot.SealKeyToModeenvFlags{})
err := boot.SealKeyToModeenv(key, saveKey, model, modeenv, boot.SealKeyToModeenvFlags{HasFDESetupHook: true})
c.Assert(err, IsNil)
// check that runFDESetupHook was called the expected way
c.Check(runFDESetupHookReqs, DeepEquals, []*fde.SetupRequest{
Expand Down Expand Up @@ -1699,12 +1693,7 @@ func (s *sealSuite) TestSealToModeenvWithFdeHookSad(c *C) {
dirs.SetRootDir(rootdir)
defer dirs.SetRootDir("")

restore := boot.MockHasFDESetupHook(func() (bool, error) {
return true, nil
})
defer restore()

restore = boot.MockSecbootSealKeysWithFDESetupHook(func(fde.RunSetupHookFunc, []secboot.SealKeyRequest, *secboot.SealKeysWithFDESetupHookParams) error {
restore := boot.MockSecbootSealKeysWithFDESetupHook(func(fde.RunSetupHookFunc, []secboot.SealKeyRequest, *secboot.SealKeysWithFDESetupHookParams) error {
return fmt.Errorf("hook failed")
})
defer restore()
Expand All @@ -1716,7 +1705,7 @@ func (s *sealSuite) TestSealToModeenvWithFdeHookSad(c *C) {
saveKey := keys.EncryptionKey{5, 6, 7, 8}

model := boottest.MakeMockUC20Model()
err := boot.SealKeyToModeenv(key, saveKey, model, modeenv, boot.SealKeyToModeenvFlags{})
err := boot.SealKeyToModeenv(key, saveKey, model, modeenv, boot.SealKeyToModeenvFlags{HasFDESetupHook: true})
c.Assert(err, ErrorMatches, "hook failed")
marker := filepath.Join(dirs.SnapFDEDirUnder(filepath.Join(dirs.GlobalRootDir, "/run/mnt/ubuntu-data/system-data")), "sealed-keys")
c.Check(marker, testutil.FileAbsent)
Expand All @@ -1737,7 +1726,7 @@ func (s *sealSuite) TestResealKeyToModeenvWithFdeHookCalled(c *C) {
// TODO: this simulates that the hook is not available yet
// because of e.g. seeding. Longer term there will be
// more, see TODO in resealKeyToModeenvUsingFDESetupHookImpl
restore = boot.MockHasFDESetupHook(func() (bool, error) {
restore = boot.MockHasFDESetupHook(func(kernel *snap.Info) (bool, error) {
return false, fmt.Errorf("hook not available yet because e.g. seeding")
})
defer restore()
Expand Down Expand Up @@ -2168,7 +2157,8 @@ func (s *sealSuite) TestMarkFactoryResetComplete(c *C) {
}
}

restore := boot.MockHasFDESetupHook(func() (bool, error) {
restore := boot.MockHasFDESetupHook(func(kernel *snap.Info) (bool, error) {
c.Check(kernel, IsNil)
return tc.hasFDEHook, nil
})
defer restore()
Expand Down
11 changes: 7 additions & 4 deletions overlord/devicestate/devicemgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -2222,7 +2222,7 @@ func (m *DeviceManager) ntpSyncedOrWaitedLongerThan(maxWait time.Duration) bool
return m.ntpSyncedOrTimedOut
}

func (m *DeviceManager) hasFDESetupHook() (bool, error) {
func (m *DeviceManager) hasFDESetupHook(kernelInfo *snap.Info) (bool, error) {
// state must be locked
st := m.state

Expand All @@ -2231,9 +2231,12 @@ func (m *DeviceManager) hasFDESetupHook() (bool, error) {
return false, fmt.Errorf("cannot get device context: %v", err)
}

kernelInfo, err := snapstate.KernelInfo(st, deviceCtx)
if err != nil {
return false, fmt.Errorf("cannot get kernel info: %v", err)
if kernelInfo == nil {
var err error
kernelInfo, err = snapstate.KernelInfo(st, deviceCtx)
if err != nil {
return false, fmt.Errorf("cannot get kernel info: %v", err)
}
}
return hasFDESetupHookInKernel(kernelInfo), nil
}
Expand Down
30 changes: 29 additions & 1 deletion overlord/devicestate/devicestate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1716,12 +1716,40 @@ func (s *deviceMgrSuite) TestHasFdeSetupHook(c *C) {
} {
makeInstalledMockKernelSnap(c, st, tc.kernelYaml)

hasHook, err := devicestate.DeviceManagerHasFDESetupHook(s.mgr)
hasHook, err := devicestate.DeviceManagerHasFDESetupHook(s.mgr, nil)
c.Assert(err, IsNil)
c.Check(hasHook, Equals, tc.hasFdeSetupHook)
}
}

func (s *deviceMgrSuite) TestHasFdeSetupHookOtherKernel(c *C) {
st := s.state
st.Lock()
defer st.Unlock()

s.makeModelAssertionInState(c, "canonical", "pc", map[string]interface{}{
"architecture": "amd64",
"kernel": "pc-kernel",
"gadget": "pc",
})
devicestatetest.SetDevice(s.state, &auth.DeviceState{
Brand: "canonical",
Model: "pc",
})

otherSI := &snap.SideInfo{RealName: "pc-kernel", Revision: snap.R(1), SnapID: "pc-kernel-id"}
_, otherInfo := snaptest.MakeTestSnapInfoWithFiles(c, kernelYamlWithFdeSetup, nil, otherSI)
makeInstalledMockKernelSnap(c, st, kernelYamlNoFdeSetup)

hasHook, err := devicestate.DeviceManagerHasFDESetupHook(s.mgr, nil)
c.Assert(err, IsNil)
c.Check(hasHook, Equals, false)

hasHook, err = devicestate.DeviceManagerHasFDESetupHook(s.mgr, otherInfo)
c.Assert(err, IsNil)
c.Check(hasHook, Equals, true)
}

func (s *deviceMgrSuite) TestRunFDESetupHookHappy(c *C) {
st := s.state

Expand Down
4 changes: 2 additions & 2 deletions overlord/devicestate/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,8 @@ func MockRestrictCloudInit(f func(sysconfig.CloudInitState, *sysconfig.CloudInit
}
}

func DeviceManagerHasFDESetupHook(mgr *DeviceManager) (bool, error) {
return mgr.hasFDESetupHook()
func DeviceManagerHasFDESetupHook(mgr *DeviceManager, kernelInfo *snap.Info) (bool, error) {
return mgr.hasFDESetupHook(kernelInfo)
}

func DeviceManagerRunFDESetupHook(mgr *DeviceManager, req *fde.SetupRequest) ([]byte, error) {
Expand Down

0 comments on commit f31235e

Please sign in to comment.