Skip to content

Commit 38f4d14

Browse files
davidcassanyfrelon
andauthored
[backport] Disable boot entry if efivars is read-only (#2059) (#2145)
* 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 <[email protected]> (cherry picked from commit 8baaef2) * Add test for auto disabled boot entry in Grub Signed-off-by: David Cassany <[email protected]> (cherry picked from commit 76caad5) --------- Co-authored-by: Fredrik Lönnegren <[email protected]>
1 parent 216ab93 commit 38f4d14

File tree

7 files changed

+45
-8
lines changed

7 files changed

+45
-8
lines changed

pkg/action/install.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,10 @@ func NewInstallAction(cfg *types.RunConfig, spec *types.InstallSpec, opts ...Ins
6161
}
6262

6363
if i.bootloader == nil {
64-
i.bootloader = bootloader.NewGrub(&cfg.Config, bootloader.WithGrubDisableBootEntry(i.spec.DisableBootEntry))
64+
i.bootloader = bootloader.NewGrub(&cfg.Config,
65+
bootloader.WithGrubDisableBootEntry(i.spec.DisableBootEntry),
66+
bootloader.WithGrubAutoDisableBootEntry(),
67+
)
6568
}
6669

6770
if i.snapshotter == nil {

pkg/action/reset.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,9 @@ func NewResetAction(cfg *types.RunConfig, spec *types.ResetSpec, opts ...ResetAc
8484

8585
if r.bootloader == nil {
8686
r.bootloader = bootloader.NewGrub(
87-
&cfg.Config, bootloader.WithGrubDisableBootEntry(r.spec.DisableBootEntry),
87+
&cfg.Config,
88+
bootloader.WithGrubDisableBootEntry(r.spec.DisableBootEntry),
89+
bootloader.WithGrubAutoDisableBootEntry(),
8890
bootloader.WithGrubClearBootEntry(false),
8991
)
9092
}

pkg/bootloader/grub.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"regexp"
2424

2525
"github.com/rancher/elemental-toolkit/v2/pkg/constants"
26+
"github.com/rancher/elemental-toolkit/v2/pkg/elemental"
2627
"github.com/rancher/elemental-toolkit/v2/pkg/types"
2728
"github.com/rancher/elemental-toolkit/v2/pkg/utils"
2829

@@ -121,6 +122,28 @@ func WithGrubDisableBootEntry(disableBootEntry bool) func(g *Grub) error {
121122
}
122123
}
123124

125+
func WithGrubAutoDisableBootEntry() func(g *Grub) error {
126+
return func(g *Grub) error {
127+
if g.disableBootEntry {
128+
// already disabled manually, doing nothing
129+
return nil
130+
}
131+
132+
rw, err := elemental.IsRWMountPoint(g.runner, constants.EfivarsMountPath)
133+
if err != nil {
134+
g.logger.Errorf("error finding efivar mounts: %s", err.Error())
135+
return err
136+
}
137+
138+
// If efivars is not RW, disable writing boot entries.
139+
if !rw {
140+
g.disableBootEntry = true
141+
}
142+
143+
return nil
144+
}
145+
}
146+
124147
func WithGrubClearBootEntry(clearBootEntry bool) func(g *Grub) error {
125148
return func(g *Grub) error {
126149
g.clearBootEntry = clearBootEntry

pkg/bootloader/grub_test.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,15 @@ var _ = Describe("Booloader", Label("bootloader", "grub"), func() {
105105
)
106106
})
107107

108-
It("installs without errors", func() {
109-
grub = bootloader.NewGrub(cfg, bootloader.WithGrubDisableBootEntry(true))
108+
It("installs without errors and auto detects there is no writable efivars", func() {
109+
runner.SideEffect = func(cmd string, args ...string) ([]byte, error) {
110+
if cmd == "findmnt" && len(args) > 0 && args[0] == "-fno" {
111+
return []byte("ro"), nil
112+
}
113+
return []byte{}, nil
114+
}
115+
116+
grub = bootloader.NewGrub(cfg, bootloader.WithGrubAutoDisableBootEntry())
110117
Expect(grub.Install(rootDir, efiDir)).To(Succeed())
111118

112119
// Check grub config in EFI directory

pkg/constants/constants.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ const (
6363
Tmpfs = "tmpfs"
6464
Autofs = "auto"
6565
Block = "block"
66+
EfivarsMountPath = "/sys/firmware/efi/efivars"
6667

6768
// Maxium number of nested symlinks to resolve
6869
MaxLinkDepth = 4

pkg/elemental/elemental.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ func IsMounted(c types.Config, part *types.Partition) (bool, error) {
177177
return !notMnt, nil
178178
}
179179

180-
func IsRWMountPoint(c types.Config, mountPoint string) (bool, error) {
181-
cmdOut, err := c.Runner.Run("findmnt", "-fno", "OPTIONS", mountPoint)
180+
func IsRWMountPoint(r types.Runner, mountPoint string) (bool, error) {
181+
cmdOut, err := r.Run("findmnt", "-fno", "OPTIONS", mountPoint)
182182
if err != nil {
183183
return false, err
184184
}
@@ -193,7 +193,7 @@ func IsRWMountPoint(c types.Config, mountPoint string) (bool, error) {
193193
// MountRWPartition mounts, or remounts if needed, a partition with RW permissions
194194
func MountRWPartition(c types.Config, part *types.Partition) (umount func() error, err error) {
195195
if mnt, _ := IsMounted(c, part); mnt {
196-
if ok, _ := IsRWMountPoint(c, part.MountPoint); ok {
196+
if ok, _ := IsRWMountPoint(c.Runner, part.MountPoint); ok {
197197
c.Logger.Debugf("Already RW mounted: %s at %s", part.Name, part.MountPoint)
198198
return func() error { return nil }, nil
199199
}

pkg/snapshotter/loopdevice.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"strings"
2727

2828
"github.com/hashicorp/go-multierror"
29+
2930
"github.com/rancher/elemental-toolkit/v2/pkg/constants"
3031
"github.com/rancher/elemental-toolkit/v2/pkg/elemental"
3132

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

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

0 commit comments

Comments
 (0)