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

overlord/devicestate, overlord/snapstate: add task for updating kernel command lines from gadget #10148

Merged

Conversation

bboozzoo
Copy link
Collaborator

@bboozzoo bboozzoo commented Apr 14, 2021

Stacked on top of #10143. The relevant commits are in the overlord package and subpackages, start with 1351e70 and then subsequent ones.

…from gadget

Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
…kernel command line

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>
@bboozzoo bboozzoo added the Run nested The PR also runs tests inluded in nested suite label Apr 14, 2021
Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
…le secure boot. fix races, enable debugs

Also verify that boot chains exist

Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
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.

a couple nitpicks about the logging, but otherwise the main code and the spread test looks good to me. I didn't finish reviewing the unit tests yet however

var seeded bool
err := st.Get("seeded", &seeded)
if err != nil && err != state.ErrNoState {
fmt.Printf("not needed\n")
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
fmt.Printf("not needed\n")

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Hah, thanks for catching that.

return err
}
if !updated {
t.Logf("no kernel command line update from gadget")
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
t.Logf("no kernel command line update from gadget")
t.Debugf("no kernel command line update from gadget")

Copy link
Collaborator

Choose a reason for hiding this comment

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

+1

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I've updated the code here and at the place of the other comment to use logger.Debugf()

return err
}
if !updated {
t.Logf("no kernel command line update to undo")
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
t.Logf("no kernel command line update to undo")
t.Debugf("no kernel command line update to undo")

Copy link
Collaborator

Choose a reason for hiding this comment

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

+1

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

And there should be a return nil here right after the log too.

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.

thanks for this, I did a first pass, mostly minor comments but a question about reboots

// not using trusted boot assets, bootloader config is not
// managed and command line can be manipulated externally
return update, nil
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

so we understand, what's the situation here, grub is used but FDE is not enabled?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, the scenario is no FDE, in which case we do not track the trusted boot assets, but that unnecessarily gated the command line handling in bootstate.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added a test case for this.

// and system bootloader, indicating that the command line is
// not being tracked
return m, nil
}
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 these changes in boot needs new unit tests for the new scenarios, no?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added a test for this too. The scenario is basically a uc20 device which does not have the trusted assets bootloader, so kernel command lines will not be populated, and we do not expect a command line for it anyway.


func (m *DeviceManager) doUpdateGadgetCommandLine(t *state.Task, _ *tomb.Tomb) error {
if release.OnClassic {
return fmt.Errorf("cannot run update gadget kernel command line task on a classic system")
Copy link
Collaborator

Choose a reason for hiding this comment

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

this is an internal error

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Updated this and the other place


func (m *DeviceManager) undoUpdateGadgetCommandLine(t *state.Task, _ *tomb.Tomb) error {
if release.OnClassic {
return fmt.Errorf("cannot run update gadget kernel command line task on a classic system")
Copy link
Collaborator

Choose a reason for hiding this comment

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

same

return err
}
if !updated {
t.Logf("no kernel command line update from gadget")
Copy link
Collaborator

Choose a reason for hiding this comment

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

+1

size: 500M
`

func (s *mgrsSuite) testGadgetKernelCommandLine(c *C, snapPath string, si *snap.SideInfo, bl bootloader.Bootloader, currentFiles [][]string, currentModeenvCmdline string, commandLineAfterReboot string, update bool) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

s/snapPath/gadgetPath/ and s/si/gadgetSideInfo/ for a bit more clarity?

@@ -263,6 +263,12 @@ func doInstall(st *state.State, snapst *SnapState, snapsup *SnapSetup, flags int
addTask(gadgetUpdate)
prev = gadgetUpdate
}
if !release.OnClassic && snapsup.Type == snap.TypeGadget {
// XXX: kernel command line from gadget is for core systems only
Copy link
Collaborator

Choose a reason for hiding this comment

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

why the XXX?

@@ -160,6 +160,8 @@ func Manager(s *state.State, hookManager *hookstate.HookManager, runner *state.T
// config assets are assumed to be always backwards compatible.
runner.AddHandler("update-managed-boot-config", m.doUpdateManagedBootConfig, nil)

Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think we want this blank line, maybe just have a trivial comment if the issue with having nothing is the confusion with the previous comment

if !updated {
t.Logf("no kernel command line update to undo")
}
t.Logf("kernel command line update undone")
Copy link
Collaborator

Choose a reason for hiding this comment

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

"reverted kernel command line", to be more similar to the Do case?

t.SetStatus(state.DoneStatus)

// kernel command line was updated, request a reboot to make it effective
st.RequestRestart(state.RestartSystem)
Copy link
Collaborator

Choose a reason for hiding this comment

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

do we risk to reboot twice if there was an assets update from update-managed-boot-config as well? can we do something if that's the case?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, there is a change to require 2 reboots. One the one hand it is an inconvenience, on the other happens only when both the assets and the command line is changed in the new revision.

Copy link
Collaborator

@pedronis pedronis Apr 15, 2021

Choose a reason for hiding this comment

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

can you leave a TODO about thinking further about this? I have some ideas but probably not worth pursuing immediately

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure, I'll push it after the current spread run finishes

Thanks to @pedronis and @anonymouse64 for suggestions.

Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
…ne was not changed

Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
Add test cases for compatibility scenarios:
- a UC20 device with a bootloader that isn't the trusted assets one
- a UC20 device with trusted assets bootloader, but no assets are tracked (as
  happens when FDE isn't used)

Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
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.

thanks, small question/nitpick

}
t.Logf("kernel command line update undone")
t.Logf("Reverted kernel command line change")
Copy link
Collaborator

Choose a reason for hiding this comment

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

isn't this checked in tests like the do case?

Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
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.

lgtm, some super nitpicky comment suggestions

"snapd_recovery_mode=run panic=-1",
"snapd_recovery_mode=run candidate panic=-1",
})
// without encryption, the trusted assets are no tracked in the modeenv,
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// without encryption, the trusted assets are no tracked in the modeenv,
// without encryption, the trusted assets are not tracked in the modeenv,

}

func (s *deviceMgrGadgetSuite) TestUpdateGadgetCommandlineWithNewArgs(c *C) {
// no command line arguments prior to the gadget up
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// no command line arguments prior to the gadget up
// no command line arguments prior to the gadget update

}

func (s *deviceMgrGadgetSuite) TestUpdateGadgetCommandlineUnchanged(c *C) {
// no command line arguments prior to the gadget up
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// no command line arguments prior to the gadget up
// no command line arguments prior to the gadget update


t.SetStatus(state.DoneStatus)

// TODO: consider optimization to avoid double reboot when the gadget
Copy link
Member

Choose a reason for hiding this comment

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

thanks for this comment

Comment on lines +6244 to +6246
func (s *mgrsSuite) testGadgetKernelCommandLine(c *C, gadgetPath string, gadgetSideInfo *snap.SideInfo,
bl bootloader.Bootloader, currentFiles [][]string, currentModeenvCmdline string,
commandLineAfterReboot string, update bool) {
Copy link
Member

Choose a reason for hiding this comment

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

oh boy that's quite the signature :-)

{"meta/gadget.yaml", pcGadgetYaml},
{"cmdline.extra", "args from old gadget"},
}
// add new gadget snap kernel command line drop-in file
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// add new gadget snap kernel command line drop-in file
// add new gadget snap kernel command line without the file

Thanks to @anonymouse64 for suggestions

Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
Copy link
Contributor

@mvo5 mvo5 left a comment

Choose a reason for hiding this comment

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

Thanks, some nitpicks inside but looks good.

// pre UC20 system, do nothing
return false, nil
}
// but when undoing, we use the current gadget which should have
Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, this comment starts with // but ... - what does the "but" refers to? Should this maybe read just "when undoing, we use the current gadget which should have been restored"

Copy link
Contributor

Choose a reason for hiding this comment

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

Could this move into the "else" below? It seems we only need currentGadgetData inside this else condition?

logger.Debugf("no kernel command line update from gadget")
return nil
}
t.Logf("Updated kernel command line")
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for adding this

}

func (s *mgrsSuite) TestGadgetKernelCommandLineAddCmdline(c *C) {
mabloader := bootloadertest.Mock("mock", c.MkDir()).WithTrustedAssets()
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it make sense to have a "gadgetMgrsSuite" or something that does this bootloader setup in a single place? it seems like it's the same across the tests(?)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I can try to do that in a followup

@@ -5339,6 +5341,7 @@ func (s *snapmgrTestSuite) TestStopSnapServicesFirstSavesSnapSetupLastActiveDisa
},
Current: snap.R(11),
Active: true,
// gofmt
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe expand this a little bit? I assuem you add it to avoid indent?

# wait for previous change to finish before proceeding
nested_exec sudo snap watch "$REMOTE_CHG_ID"

# TODO: enable once full command line override is supported
Copy link
Contributor

Choose a reason for hiding this comment

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

This will be enabled once #10160 landed, yes?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes

Thanks to @mvo5 for suggestions

Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
@bboozzoo
Copy link
Collaborator Author

@mvo5 can you land this PR? the failure in google:ubuntu-18.04-64:tests/main/interfaces-content-default-provider is unrelated.

@mvo5 mvo5 merged commit 148e4d1 into snapcore:master Apr 16, 2021
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