Skip to content

Commit

Permalink
[backport] Disable boot entry if efivars is read-only (#2059) (#2145)
Browse files Browse the repository at this point in the history
* Disable boot entry if efivars is read-only (#2059)

On some systems the efivars is mounted read-only if the firmware does
not support writing (such as RPI).

This commit turns off writing boot entries to efivars if the efivars
filesystem is mounted read-only.

Signed-off-by: Fredrik Lönnegren <fredrik.lonnegren@suse.com>
(cherry picked from commit 8baaef2)

* Add test for auto disabled boot entry in Grub

Signed-off-by: David Cassany <dcassany@suse.com>
(cherry picked from commit 76caad5)

---------

Co-authored-by: Fredrik Lönnegren <fredrik.lonnegren@suse.com>
  • Loading branch information
davidcassany and frelon authored Jul 29, 2024
1 parent 216ab93 commit 38f4d14
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 8 deletions.
5 changes: 4 additions & 1 deletion pkg/action/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ func NewInstallAction(cfg *types.RunConfig, spec *types.InstallSpec, opts ...Ins
}

if i.bootloader == nil {
i.bootloader = bootloader.NewGrub(&cfg.Config, bootloader.WithGrubDisableBootEntry(i.spec.DisableBootEntry))
i.bootloader = bootloader.NewGrub(&cfg.Config,
bootloader.WithGrubDisableBootEntry(i.spec.DisableBootEntry),
bootloader.WithGrubAutoDisableBootEntry(),
)
}

if i.snapshotter == nil {
Expand Down
4 changes: 3 additions & 1 deletion pkg/action/reset.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ func NewResetAction(cfg *types.RunConfig, spec *types.ResetSpec, opts ...ResetAc

if r.bootloader == nil {
r.bootloader = bootloader.NewGrub(
&cfg.Config, bootloader.WithGrubDisableBootEntry(r.spec.DisableBootEntry),
&cfg.Config,
bootloader.WithGrubDisableBootEntry(r.spec.DisableBootEntry),
bootloader.WithGrubAutoDisableBootEntry(),
bootloader.WithGrubClearBootEntry(false),
)
}
Expand Down
23 changes: 23 additions & 0 deletions pkg/bootloader/grub.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"regexp"

"github.com/rancher/elemental-toolkit/v2/pkg/constants"
"github.com/rancher/elemental-toolkit/v2/pkg/elemental"
"github.com/rancher/elemental-toolkit/v2/pkg/types"
"github.com/rancher/elemental-toolkit/v2/pkg/utils"

Expand Down Expand Up @@ -121,6 +122,28 @@ func WithGrubDisableBootEntry(disableBootEntry bool) func(g *Grub) error {
}
}

func WithGrubAutoDisableBootEntry() func(g *Grub) error {
return func(g *Grub) error {
if g.disableBootEntry {
// already disabled manually, doing nothing
return nil
}

rw, err := elemental.IsRWMountPoint(g.runner, constants.EfivarsMountPath)
if err != nil {
g.logger.Errorf("error finding efivar mounts: %s", err.Error())
return err
}

// If efivars is not RW, disable writing boot entries.
if !rw {
g.disableBootEntry = true
}

return nil
}
}

func WithGrubClearBootEntry(clearBootEntry bool) func(g *Grub) error {
return func(g *Grub) error {
g.clearBootEntry = clearBootEntry
Expand Down
11 changes: 9 additions & 2 deletions pkg/bootloader/grub_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,15 @@ var _ = Describe("Booloader", Label("bootloader", "grub"), func() {
)
})

It("installs without errors", func() {
grub = bootloader.NewGrub(cfg, bootloader.WithGrubDisableBootEntry(true))
It("installs without errors and auto detects there is no writable efivars", func() {
runner.SideEffect = func(cmd string, args ...string) ([]byte, error) {
if cmd == "findmnt" && len(args) > 0 && args[0] == "-fno" {
return []byte("ro"), nil
}
return []byte{}, nil
}

grub = bootloader.NewGrub(cfg, bootloader.WithGrubAutoDisableBootEntry())
Expect(grub.Install(rootDir, efiDir)).To(Succeed())

// Check grub config in EFI directory
Expand Down
1 change: 1 addition & 0 deletions pkg/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const (
Tmpfs = "tmpfs"
Autofs = "auto"
Block = "block"
EfivarsMountPath = "/sys/firmware/efi/efivars"

// Maxium number of nested symlinks to resolve
MaxLinkDepth = 4
Expand Down
6 changes: 3 additions & 3 deletions pkg/elemental/elemental.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,8 @@ func IsMounted(c types.Config, part *types.Partition) (bool, error) {
return !notMnt, nil
}

func IsRWMountPoint(c types.Config, mountPoint string) (bool, error) {
cmdOut, err := c.Runner.Run("findmnt", "-fno", "OPTIONS", mountPoint)
func IsRWMountPoint(r types.Runner, mountPoint string) (bool, error) {
cmdOut, err := r.Run("findmnt", "-fno", "OPTIONS", mountPoint)
if err != nil {
return false, err
}
Expand All @@ -193,7 +193,7 @@ func IsRWMountPoint(c types.Config, mountPoint string) (bool, error) {
// MountRWPartition mounts, or remounts if needed, a partition with RW permissions
func MountRWPartition(c types.Config, part *types.Partition) (umount func() error, err error) {
if mnt, _ := IsMounted(c, part); mnt {
if ok, _ := IsRWMountPoint(c, part.MountPoint); ok {
if ok, _ := IsRWMountPoint(c.Runner, part.MountPoint); ok {
c.Logger.Debugf("Already RW mounted: %s at %s", part.Name, part.MountPoint)
return func() error { return nil }, nil
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/snapshotter/loopdevice.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"strings"

"github.com/hashicorp/go-multierror"

"github.com/rancher/elemental-toolkit/v2/pkg/constants"
"github.com/rancher/elemental-toolkit/v2/pkg/elemental"

Expand Down Expand Up @@ -91,7 +92,7 @@ func (l *LoopDevice) InitSnapshotter(state *types.Partition, efiDir string) erro
l.legacyClean = true

// Legacy deployments might not include RW mounts for state partitions
if ok, _ := elemental.IsRWMountPoint(l.cfg, l.rootDir); !ok {
if ok, _ := elemental.IsRWMountPoint(l.cfg.Runner, l.rootDir); !ok {
err = l.cfg.Mounter.Mount("", l.rootDir, "auto", []string{"remount", "rw"})
if err != nil {
l.cfg.Logger.Errorf("Failed remounting root as RW: %v", err)
Expand Down

0 comments on commit 38f4d14

Please sign in to comment.