Skip to content

Commit 874c60e

Browse files
cmd/snap-bootstrap: make kernel-modules components available
on first boot, when installing from the initramfs.
1 parent 9879b79 commit 874c60e

File tree

2 files changed

+372
-54
lines changed

2 files changed

+372
-54
lines changed

cmd/snap-bootstrap/cmd_initramfs_mounts.go

Lines changed: 78 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import (
5454
"github.com/snapcore/snapd/secboot"
5555
"github.com/snapcore/snapd/seed"
5656
"github.com/snapcore/snapd/snap"
57+
"github.com/snapcore/snapd/snap/snapdir"
5758
"github.com/snapcore/snapd/snap/squashfs"
5859
"github.com/snapcore/snapd/sysconfig"
5960
"github.com/snapcore/snapd/timings"
@@ -262,6 +263,18 @@ func readSnapInfo(sysSnaps map[snap.Type]*seed.Snap, snapType snap.Type) (*snap.
262263

263264
}
264265

266+
func readComponentInfo(seedComp *seed.Component, mntPt string, snapInfo *snap.Info, csi *snap.ComponentSideInfo) (*snap.ComponentInfo, error) {
267+
container := snapdir.New(mntPt)
268+
ci, err := snap.ReadComponentInfoFromContainer(container, snapInfo, csi)
269+
if err != nil {
270+
return nil, err
271+
}
272+
if ci.Revision.Unset() {
273+
ci.Revision = snap.R(-1)
274+
}
275+
return ci, nil
276+
}
277+
265278
func runFDESetupHook(req *fde.SetupRequest) ([]byte, error) {
266279
// TODO: use systemd-run
267280
encoded, err := json.Marshal(req)
@@ -328,25 +341,54 @@ func doInstall(mst *initramfsMountsState, model *asserts.Model, sysSnaps map[sna
328341
return fmt.Errorf("cannot use gadget: %v", err)
329342
}
330343

331-
// TODO:COMPS take into account kernel-modules components, see
332-
// DeviceManager,doSetupRunSystem and other parts of
333-
// handlers_install.go.
344+
// Get kernel-modules information to have them ready early on first boot
334345

335-
bootDevice := ""
336-
kernelSnapInfo := &gadgetInstall.KernelSnapInfo{
337-
Name: kernelSnap.SnapName(),
338-
MountPoint: kernelMountDir,
339-
Revision: kernelSnap.Revision,
340-
// Should be true always anyway
341-
IsCore: !model.Classic(),
342-
}
343-
switch model.Base() {
344-
case "core20", "core22", "core22-desktop":
345-
kernelSnapInfo.NeedsDriversTree = false
346-
default:
347-
kernelSnapInfo.NeedsDriversTree = true
346+
kernCompsByName := make(map[string]*snap.Component)
347+
for _, c := range kernelSnap.Components {
348+
kernCompsByName[c.Name] = c
348349
}
349350

351+
kernelSeed := sysSnaps[snap.TypeKernel]
352+
kernCompsMntPts := make(map[string]string)
353+
compSeedInfos := []gadgetInstall.CompSeedInfo{}
354+
for _, sc := range kernelSeed.Components {
355+
seedComp := sc
356+
comp, ok := kernCompsByName[seedComp.CompSideInfo.Component.ComponentName]
357+
if !ok {
358+
return fmt.Errorf("component %s in seed but not defined by snap!",
359+
seedComp.CompSideInfo.Component.ComponentName)
360+
}
361+
if comp.Type != snap.KernelModulesComponent {
362+
continue
363+
}
364+
365+
// Mount ephemerally the kernel-modules components
366+
mntPt := filepath.Join(filepath.Join(boot.InitramfsRunMntDir, "snap-content",
367+
seedComp.CompSideInfo.Component.String()))
368+
if err := doSystemdMount(seedComp.Path, mntPt, &systemdMountOptions{
369+
ReadOnly: true,
370+
Private: true,
371+
Ephemeral: true}); err != nil {
372+
return err
373+
}
374+
kernCompsMntPts[seedComp.CompSideInfo.Component.String()] = mntPt
375+
376+
compInfo, err := readComponentInfo(&seedComp, mntPt, kernelSnap, &seedComp.CompSideInfo)
377+
if err != nil {
378+
return err
379+
}
380+
compSeedInfos = append(compSeedInfos, gadgetInstall.CompSeedInfo{
381+
CompInfo: compInfo,
382+
CompSeed: &seedComp,
383+
})
384+
}
385+
386+
isCore := !model.Classic()
387+
kernelSnapInfo, bootKMods := gadgetInstall.KernelBootInfo(
388+
kernelSnap, compSeedInfos, kernelMountDir, kernCompsMntPts,
389+
isCore, model.NeedsKernelSetup())
390+
391+
bootDevice := ""
350392
installedSystem, err := gadgetInstallRun(model, gadgetMountDir, kernelSnapInfo, bootDevice, options, installObserver, timings.New(nil))
351393
if err != nil {
352394
return err
@@ -379,6 +421,7 @@ func doInstall(mst *initramfsMountsState, model *asserts.Model, sysSnaps map[sna
379421
KernelPath: sysSnaps[snap.TypeKernel].Path,
380422
UnpackedGadgetDir: gadgetMountDir,
381423
RecoverySystemLabel: mst.recoverySystem,
424+
KernelMods: bootKMods,
382425
}
383426

384427
if err := bootMakeRunnableStandaloneSystem(model, bootWith, trustedInstallObserver); err != nil {
@@ -429,6 +472,25 @@ func generateMountsModeInstall(mst *initramfsMountsState) error {
429472
}
430473

431474
if installAndRun {
475+
kernSnap := snaps[snap.TypeKernel]
476+
// seed is cached at this point
477+
theSeed, err := mst.LoadSeed("")
478+
if err != nil {
479+
return fmt.Errorf("internal error: cannot load seed: %v", err)
480+
}
481+
// Filter by mode, this is relevant only to get the
482+
// kernel-modules components that are used in run mode and
483+
// therefore need to be considered when installing from the
484+
// initramfs to have the modules available early on first boot.
485+
// TODO when running normal install or recover/factory-reset,
486+
// we would need also this if we want the modules to be
487+
// available early.
488+
kernSnap, err = theSeed.ModeSnap(kernSnap.SnapName(), "run")
489+
if err != nil {
490+
return err
491+
}
492+
snaps[snap.TypeKernel] = kernSnap
493+
432494
if err := doInstall(mst, model, snaps); err != nil {
433495
return err
434496
}

0 commit comments

Comments
 (0)