Skip to content

Commit

Permalink
Merge pull request canonical#9401 from bboozzoo/bboozzoo/uc20-preserv…
Browse files Browse the repository at this point in the history
…e-through-observer

 gadget: allow content observer to have opinions about a change
  • Loading branch information
mvo5 authored Sep 28, 2020
2 parents abac2b9 + 95aecd8 commit ff17d06
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 124 deletions.
64 changes: 32 additions & 32 deletions boot/assets.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,36 +227,36 @@ type TrustedAssetsInstallObserver struct {
// of the secure boot.
//
// Implements gadget.ContentObserver.
func (o *TrustedAssetsInstallObserver) Observe(op gadget.ContentOperation, affectedStruct *gadget.LaidOutStructure, root, relativeTarget string, data *gadget.ContentChange) (bool, error) {
func (o *TrustedAssetsInstallObserver) Observe(op gadget.ContentOperation, affectedStruct *gadget.LaidOutStructure, root, relativeTarget string, data *gadget.ContentChange) (gadget.ContentChangeAction, error) {
if affectedStruct.Role != gadget.SystemBoot {
// only care about system-boot
return true, nil
return gadget.ChangeApply, nil
}

if o.blName == "" {
// we have no information about the bootloader yet
bl, err := bootloader.ForGadget(o.gadgetDir, root, &bootloader.Options{Role: bootloader.RoleRunMode, NoSlashBoot: true})
if err != nil {
return false, fmt.Errorf("cannot find bootloader: %v", err)
return gadget.ChangeAbort, fmt.Errorf("cannot find bootloader: %v", err)
}
o.blName = bl.Name()
tbl, ok := bl.(bootloader.TrustedAssetsBootloader)
if !ok {
return true, nil
return gadget.ChangeApply, nil
}
trustedAssets, err := tbl.TrustedAssets()
if err != nil {
return false, fmt.Errorf("cannot list %q bootloader trusted assets: %v", bl.Name(), err)
return gadget.ChangeAbort, fmt.Errorf("cannot list %q bootloader trusted assets: %v", bl.Name(), err)
}
o.trustedAssets = trustedAssets
}
if len(o.trustedAssets) == 0 || !strutil.ListContains(o.trustedAssets, relativeTarget) {
// not one of the trusted assets
return true, nil
return gadget.ChangeApply, nil
}
ta, err := o.cache.Add(data.After, o.blName, filepath.Base(relativeTarget))
if err != nil {
return false, err
return gadget.ChangeAbort, err
}
// during installation, modeenv is written out later, at this point we
// only care that the same file may appear multiple times in gadget
Expand All @@ -266,11 +266,11 @@ func (o *TrustedAssetsInstallObserver) Observe(op gadget.ContentOperation, affec
o.trackedAssets = bootAssetsMap{}
}
if len(o.trackedAssets[ta.name]) > 0 {
return false, fmt.Errorf("cannot reuse asset name %q", ta.name)
return gadget.ChangeAbort, fmt.Errorf("cannot reuse asset name %q", ta.name)
}
o.trackedAssets[ta.name] = append(o.trackedAssets[ta.name], ta.hash)
}
return true, nil
return gadget.ChangeApply, nil
}

// ObserveExistingTrustedRecoveryAssets observes existing trusted assets of a
Expand Down Expand Up @@ -380,7 +380,7 @@ func findMaybeTrustedAssetsBootloader(root string, opts *bootloader.Options) (fo
// the bootloader binary which is measured as part of the secure boot.
//
// Implements gadget.ContentUpdateObserver.
func (o *TrustedAssetsUpdateObserver) Observe(op gadget.ContentOperation, affectedStruct *gadget.LaidOutStructure, root, relativeTarget string, data *gadget.ContentChange) (bool, error) {
func (o *TrustedAssetsUpdateObserver) Observe(op gadget.ContentOperation, affectedStruct *gadget.LaidOutStructure, root, relativeTarget string, data *gadget.ContentChange) (gadget.ContentChangeAction, error) {
var whichBootloader bootloader.Bootloader
var whichAssets []string
var err error
Expand All @@ -394,7 +394,7 @@ func (o *TrustedAssetsUpdateObserver) Observe(op gadget.ContentOperation, affect
NoSlashBoot: true,
})
if err != nil {
return false, err
return gadget.ChangeAbort, err
}
}
whichBootloader = o.bootBootloader
Expand All @@ -405,25 +405,25 @@ func (o *TrustedAssetsUpdateObserver) Observe(op gadget.ContentOperation, affect
Role: bootloader.RoleRecovery,
})
if err != nil {
return false, err
return gadget.ChangeAbort, err
}
}
whichBootloader = o.seedBootloader
whichAssets = o.seedTrustedAssets
isRecovery = true
default:
// only system-seed and system-boot are of interest
return true, nil
return gadget.ChangeApply, nil
}
if len(whichAssets) == 0 || !strutil.ListContains(whichAssets, relativeTarget) {
// not one of the trusted assets
return true, nil
return gadget.ChangeApply, nil
}
if o.modeenv == nil {
// we've hit a trusted asset, so a modeenv is needed now too
o.modeenv, err = ReadModeenv("")
if err != nil {
return false, fmt.Errorf("cannot load modeenv: %v", err)
return gadget.ChangeAbort, fmt.Errorf("cannot load modeenv: %v", err)
}
}
switch op {
Expand All @@ -433,14 +433,14 @@ func (o *TrustedAssetsUpdateObserver) Observe(op gadget.ContentOperation, affect
return o.observeRollback(whichBootloader, isRecovery, root, relativeTarget, data)
default:
// we only care about update and rollback actions
return false, nil
return gadget.ChangeApply, nil
}
}

func (o *TrustedAssetsUpdateObserver) observeUpdate(bl bootloader.Bootloader, recovery bool, root, relativeTarget string, change *gadget.ContentChange) (bool, error) {
func (o *TrustedAssetsUpdateObserver) observeUpdate(bl bootloader.Bootloader, recovery bool, root, relativeTarget string, change *gadget.ContentChange) (gadget.ContentChangeAction, error) {
modeenvBefore, err := o.modeenv.Copy()
if err != nil {
return false, fmt.Errorf("cannot copy modeenv: %v", err)
return gadget.ChangeAbort, fmt.Errorf("cannot copy modeenv: %v", err)
}

// we may be running after a mid-update reboot, where a successful boot
Expand All @@ -453,13 +453,13 @@ func (o *TrustedAssetsUpdateObserver) observeUpdate(bl bootloader.Bootloader, re
// it existed
taBefore, err = o.cache.Add(change.Before, bl.Name(), filepath.Base(relativeTarget))
if err != nil {
return false, err
return gadget.ChangeAbort, err
}
}

ta, err := o.cache.Add(change.After, bl.Name(), filepath.Base(relativeTarget))
if err != nil {
return false, err
return gadget.ChangeAbort, err
}

trustedAssets := &o.modeenv.CurrentTrustedBootAssets
Expand Down Expand Up @@ -490,21 +490,21 @@ func (o *TrustedAssetsUpdateObserver) observeUpdate(bl bootloader.Bootloader, re
// during an update; more entries indicates that the
// same asset name is used multiple times with different
// content
return false, fmt.Errorf("cannot reuse asset name %q", ta.name)
return gadget.ChangeAbort, fmt.Errorf("cannot reuse asset name %q", ta.name)
}
(*trustedAssets)[ta.name] = append((*trustedAssets)[ta.name], ta.hash)
}

if o.modeenv.deepEqual(modeenvBefore) {
return true, nil
return gadget.ChangeApply, nil
}
if err := o.modeenv.Write(); err != nil {
return false, fmt.Errorf("cannot write modeeenv: %v", err)
return gadget.ChangeAbort, fmt.Errorf("cannot write modeeenv: %v", err)
}
return true, nil
return gadget.ChangeApply, nil
}

func (o *TrustedAssetsUpdateObserver) observeRollback(bl bootloader.Bootloader, recovery bool, root, relativeTarget string, data *gadget.ContentChange) (bool, error) {
func (o *TrustedAssetsUpdateObserver) observeRollback(bl bootloader.Bootloader, recovery bool, root, relativeTarget string, data *gadget.ContentChange) (gadget.ContentChangeAction, error) {
trustedAssets := &o.modeenv.CurrentTrustedBootAssets
otherTrustedAssets := o.modeenv.CurrentTrustedRecoveryBootAssets
if recovery {
Expand All @@ -516,7 +516,7 @@ func (o *TrustedAssetsUpdateObserver) observeRollback(bl bootloader.Bootloader,
hashList, ok := (*trustedAssets)[assetName]
if !ok || len(hashList) == 0 {
// asset not tracked in modeenv
return true, nil
return gadget.ChangeApply, nil
}

// new assets are appended to the list
Expand All @@ -527,20 +527,20 @@ func (o *TrustedAssetsUpdateObserver) observeRollback(bl bootloader.Bootloader,
if err != nil {
// file may not exist if it was added by the update, that's ok
if !os.IsNotExist(err) {
return false, fmt.Errorf("cannot calculate the digest of current asset: %v", err)
return gadget.ChangeAbort, fmt.Errorf("cannot calculate the digest of current asset: %v", err)
}
newlyAdded = true
if len(hashList) > 1 {
// we have more than 1 hash of the asset, so we expected
// a previous revision to be restored, but got nothing
// instead
return false, fmt.Errorf("tracked asset %q is unexpectedly missing from disk",
return gadget.ChangeAbort, fmt.Errorf("tracked asset %q is unexpectedly missing from disk",
assetName)
}
} else {
if ondiskHash != expectedOldHash {
// this is unexpected, a different file exists on disk?
return false, fmt.Errorf("unexpected content of existing asset %q", relativeTarget)
return gadget.ChangeAbort, fmt.Errorf("unexpected content of existing asset %q", relativeTarget)
}
}

Expand All @@ -556,7 +556,7 @@ func (o *TrustedAssetsUpdateObserver) observeRollback(bl bootloader.Bootloader,
// asset revision is not used used elsewhere, we can remove it from the cache
if err := o.cache.Remove(bl.Name(), assetName, newHash); err != nil {
// XXX: should this be a log instead?
return false, fmt.Errorf("cannot remove unused boot asset %v:%v: %v", assetName, newHash, err)
return gadget.ChangeAbort, fmt.Errorf("cannot remove unused boot asset %v:%v: %v", assetName, newHash, err)
}
}

Expand All @@ -568,10 +568,10 @@ func (o *TrustedAssetsUpdateObserver) observeRollback(bl bootloader.Bootloader,
}

if err := o.modeenv.Write(); err != nil {
return false, fmt.Errorf("cannot write modeeenv: %v", err)
return gadget.ChangeAbort, fmt.Errorf("cannot write modeeenv: %v", err)
}

return false, nil
return gadget.ChangeApply, nil
}

// BeforeWrite is called when the update process has been staged for execution.
Expand Down
Loading

0 comments on commit ff17d06

Please sign in to comment.