Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

boot: reseal when changing kernel #9331

Merged
merged 9 commits into from Sep 15, 2020

Conversation

bboozzoo
Copy link
Collaborator

@bboozzoo bboozzoo commented Sep 11, 2020

stacked on #9337 now

@bboozzoo bboozzoo added the UC20 label Sep 11, 2020
@bboozzoo bboozzoo added the Run nested The PR also runs tests inluded in nested suite label Sep 11, 2020
@bboozzoo bboozzoo closed this Sep 11, 2020
@bboozzoo bboozzoo reopened this Sep 11, 2020
@pedronis pedronis force-pushed the bboozzoo/uc20-reseal-with-kernel branch from 401d31f to a31f6dd Compare September 12, 2020 07:46
bboozzoo and others added 4 commits September 12, 2020 20:12
Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
adjust tests

ATM we should never have sealed keys and not a TrustedAssetsBootloader
@pedronis pedronis force-pushed the bboozzoo/uc20-reseal-with-kernel branch from a31f6dd to 60ee9aa Compare September 12, 2020 18:17
@pedronis
Copy link
Collaborator

@mvo5 I rebased this now on #9337 and fixed/changed some things, unit tests should pass in boot

Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a bunch of comments, I have addressed some in here already, and some I'm addressing in #9340

@@ -93,6 +96,9 @@ type bootStateUpdate20 struct {

// tasks to run after the modeenv has been written
postModeenvTasks []bootCommitTask

// device
dev Device
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should store just the model atm (when we will have to support remodeling it will get more complex but let's do things one at a time), something like resealModel

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is done in #9340

@@ -103,6 +109,10 @@ func (u20 *bootStateUpdate20) postModeenv(task bootCommitTask) {
u20.postModeenvTasks = append(u20.postModeenvTasks, task)
}

func (u20 *bootStateUpdate20) setDevice(dev Device) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this then could have a meaningful name like resealForModel(model)

// in between, we are still able to boot properly
if u20.dev != nil {
model := u20.dev.Model()
if model.Grade() != asserts.ModelGradeUnset {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should always be true in our case

model := u20.dev.Model()
if model.Grade() != asserts.ModelGradeUnset {
// reseal if needed
if err := resealKeyToModeenv(model, u20.writeModeenv); err != nil {
Copy link
Collaborator

@pedronis pedronis Sep 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we'll have to think whether to use the fact we have written the modeenv in the if block before as hint to expect or not a reseal, maybe it's useful with unasserted kernel, anyway this can be a follow up

if model.Grade() != asserts.ModelGradeUnset {
// reseal if needed
if err := resealKeyToModeenv(model, u20.writeModeenv); err != nil {
return fmt.Errorf("cannot reseal encryption key: %v", err)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be just return err to avoid repetitive errors

return d.model
}

func (d *mockDevice) SetModel(model *asserts.Model) { d.model = model }
Copy link
Collaborator

@pedronis pedronis Sep 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we discussed this, but in hindsight it's confusing because then Kernel and Base return values get out of sync vs Model. I proposed #9339 instead

boot/seal.go Outdated
recoveryBootChains, err := recoveryBootChainsForSystems(modeenv.CurrentRecoverySystems, rbl, model, modeenv)
tbl, ok := rbl.(bootloader.TrustedAssetsBootloader)
if !ok {
// nothing to do
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made this an internal error now that we know whether we have sealed keys at all or not

boot/seal.go Outdated
@@ -59,8 +59,13 @@ func sealKeyToModeenv(key secboot.EncryptionKey, model *asserts.Model, modeenv *
if err != nil {
return fmt.Errorf("cannot find the recovery bootloader: %v", err)
}
tbl, ok := rbl.(bootloader.TrustedAssetsBootloader)
if !ok {
// nothing to do
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be an internal error I think...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done now

@@ -640,7 +664,9 @@ func genericInitramfsSelectSnap(bs bootState20, modeenv *Modeenv, expectedTrySta

// bootState20BootAssets implements the successfulBootState interface for trusted
// boot assets UC20.
type bootState20BootAssets struct{}
type bootState20BootAssets struct {
dev Device
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same about this being something like resealModel

tab.BootChainList = []bootloader.BootFile{
bootloader.NewBootFile("", "asset", bootloader.RoleRunMode),
// TODO:UC20: fix mocked trusted assets bootloader to actually
// geenerate kernel boot files
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this TODO is interesting, we'll have to think how to avoid having the mock code guess

@pedronis
Copy link
Collaborator

I noew addressed most of my own comments with the changes proposed via #9340

@pedronis pedronis marked this pull request as ready for review September 13, 2020 08:05
Copy link
Member

@anonymouse64 anonymouse64 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't get a chance to look at the tests, but the rest of the main code looks good to me

boot/seal.go Outdated
logger.Debugf("reseal not necessary")
return nil
}
pbcJSON, _ := json.Marshal(pbc)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as on other PR, but why no error checking here?

…eal-with-kernel

Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
@mvo5 mvo5 added this to the 2.47 milestone Sep 15, 2020
bboozzoo and others added 2 commits September 15, 2020 15:29
This test adds checks that resealing happens after the kernel
gets updated.
. "$TESTSLIB/nested.sh"

# Wait for snapd to be seeded
nested_exec sudo snap wait system seed.loaded
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

later we can drop this

Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm assuming we will land #9340 after

Copy link
Member

@anonymouse64 anonymouse64 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One question about the unit tests in boot, otherwise lgtm

"snap_kernel": s.kern2.Filename(),
"snap_try_kernel": boot.DefaultStatus,
}
c.Assert(tab.BootVars, DeepEquals, expected)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is fine for now, but in general I'd like to move away from accessing BootVars directly like this and instead use the GetBootVars method from the Bootloader interface as it makes it easier to make changes to the MockBootloader interface and such

m2, err := boot.ReadModeenv("")
c.Assert(err, IsNil)
c.Assert(m2.CurrentKernels, DeepEquals, []string{s.kern1.Filename(), s.kern2.Filename()})

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should check the kernel_status bl var as well here

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the run is green, I'll push that in a followup.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should get covered in #9340 I suppose

Comment on lines +1649 to +1653
tab.BootChainList = []bootloader.BootFile{
bootloader.NewBootFile("", "shim", bootloader.RoleRecovery),
bootloader.NewBootFile("", "asset", bootloader.RoleRecovery),
runKernelBf,
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this is the same as other tests, but it now occurs to me whether this is the right chain for run mode?

I thought with run mode our chain was something like:
recovery shim -> recovery grub -> run grub -> run kernel

or are these tests just being simplistic because it's easier than building the full chain? or perhaps I have again misunderstood how the chain is used when resealing?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as discussed on IRC with @pedronis, this is simplistic but it's fine for now, we have more realistic tests in seal_test.go so this is fine for now

@bboozzoo
Copy link
Collaborator Author

Spread run finished, the following failed on core20 nested:

2020-09-15T15:30:25.0076160Z 2020-09-15 15:30:25 Failed tasks: 2
2020-09-15T15:30:25.0076705Z     - google-nested:ubuntu-20.04-64:tests/nested/core20/basic
2020-09-15T15:30:25.0077412Z     - google-nested:ubuntu-20.04-64:tests/nested/manual/minimal-smoke

tests/nested/core20/basic which expected test-snapd-sh to be there but looking at the log, snap install command hit a timeout:

2020-09-15T14:42:59.9007179Z + nested_exec 'sudo snap install test-snapd-sh'
2020-09-15T14:42:59.9008238Z + sshpass -p ubuntu ssh -p 8022 -o ConnectTimeout=10 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no user1@localhost 'sudo snap install test-snapd-sh'
2020-09-15T14:42:59.9009297Z Warning: Permanently added '[localhost]:8022' (ECDSA) to the list of known hosts.
2020-09-15T14:42:59.9009958Z error: cannot communicate with server: timeout exceeded while waiting for response
2020-09-15T14:42:59.9010369Z + true
2020-09-15T14:42:59.9011254Z + echo 'Ensure '\''snap list'\'' works and test-snapd-sh snap is installed'

And the minimal got the a point where 3 out of 4 tests have already executed successfuly and it got killed (?):

2020-09-15T15:30:24.5270786Z 2020-09-15 15:24:47 Restoring external:ubuntu-core-20-64:tests/smoke/remove (external:ubuntu-core-20-64)...
2020-09-15T15:30:24.5271732Z 2020-09-15 15:24:56 Preparing external:ubuntu-core-20-64:tests/smoke/install (external:ubuntu-core-20-64)...
2020-09-15T15:30:24.5272686Z 2020-09-15 15:25:50 Executing external:ubuntu-core-20-64:tests/smoke/install (external:ubuntu-core-20-64) (3/4)...
2020-09-15T15:30:24.5273644Z 2020-09-15 15:28:28 Restoring external:ubuntu-core-20-64:tests/smoke/install (external:ubuntu-core-20-64)...
2020-09-15T15:30:24.5275718Z 2020-09-15 15:28:51 Preparing external:ubuntu-core-20-64:tests/smoke/find-info (external:ubuntu-core-20-64)...
2020-09-15T15:30:24.5276373Z -----

@bboozzoo bboozzoo requested a review from mvo5 September 15, 2020 16:06
@pedronis
Copy link
Collaborator

kernel-reseal itself passed, merging

@pedronis pedronis merged commit 556884a into snapcore:master Sep 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Run nested The PR also runs tests inluded in nested suite
Projects
None yet
4 participants