Skip to content

Commit 8a793cd

Browse files
committed
fix: preserve boot mount state
greenboot forces /boot to ro after every check, this now prerves the previous boot state instead of forcing ro.It also ensure the /boot mount is preserved even if the grub command fails. Signed-off-by: saypaul <saypaul@redhat.com>
1 parent ecc575e commit 8a793cd

2 files changed

Lines changed: 42 additions & 10 deletions

File tree

src/lib/grub.rs

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::path::Path;
33
use std::process::Command;
44
use std::str;
55

6-
use crate::mount::{remount_boot_ro, remount_boot_rw};
6+
use crate::mount::{is_boot_rw, remount_boot_ro, remount_boot_rw};
77

88
/// fetches boot_counter value, none if not set
99
pub fn get_boot_counter(grub_path: &str) -> Result<Option<i32>> {
@@ -65,27 +65,57 @@ pub fn unset_boot_counter(grub_path: &str, mount_info_path: &str) -> Result<()>
6565
}
6666

6767
fn unset_grub_var(key: &str, grub_path: &str, mount_info_path: &str) -> Result<()> {
68-
remount_boot_rw(Path::new(mount_info_path)).context("Failed to remount /boot as rw")?;
69-
Command::new("grub2-editenv")
68+
let was_rw = is_boot_rw(Path::new(mount_info_path))
69+
.map_err(|e| anyhow::anyhow!("Failed to check boot mount state: {}", e))?;
70+
71+
if !was_rw {
72+
remount_boot_rw(Path::new(mount_info_path)).context("Failed to remount /boot as rw")?;
73+
}
74+
75+
// Execute GRUB command and capture result
76+
let grub_result = Command::new("grub2-editenv")
7077
.arg(grub_path)
7178
.arg("unset")
7279
.arg(key)
7380
.status()
74-
.context("Unable to clear boot_counter")?;
81+
.context("Unable to clear boot_counter");
82+
83+
// Always attempt to restore mount state, regardless of GRUB command result
84+
if !was_rw {
85+
remount_boot_ro(Path::new(mount_info_path)).context("Failed to remount /boot as ro")?;
86+
}
87+
88+
// Now check the GRUB command result
89+
grub_result?;
7590
log::info!("Clear grubenv: {key}");
76-
remount_boot_ro(Path::new(mount_info_path)).context("Failed to remount /boot as read-only")
91+
Ok(())
7792
}
7893

7994
fn set_grub_var(key: &str, val: u16, grub_path: &str, mount_info_path: &str) -> Result<()> {
80-
remount_boot_rw(Path::new(mount_info_path)).context("Failed to remount /boot as rw")?;
81-
Command::new("grub2-editenv")
95+
let was_rw = is_boot_rw(Path::new(mount_info_path))
96+
.map_err(|e| anyhow::anyhow!("Failed to check boot mount state: {}", e))?;
97+
98+
if !was_rw {
99+
remount_boot_rw(Path::new(mount_info_path)).context("Failed to remount /boot as rw")?;
100+
}
101+
102+
// Execute GRUB command and capture result
103+
let grub_result = Command::new("grub2-editenv")
82104
.arg(grub_path)
83105
.arg("set")
84106
.arg(format!("{key}={val}"))
85107
.status()
86-
.context("Unable to set grubenv")?;
108+
.context("Unable to set grubenv");
109+
110+
// Always attempt to restore mount state, regardless of GRUB command result
111+
if !was_rw {
112+
remount_boot_ro(Path::new(mount_info_path))
113+
.context("Failed to remount /boot as read-only")?;
114+
}
115+
116+
grub_result?;
87117
log::info!("Set grubenv: {key}={val}");
88-
remount_boot_ro(Path::new(mount_info_path)).context("Failed to remount /boot as read-only")
118+
Ok(())
89119
}
90120

91121
#[cfg(test)]

src/lib/mount.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
#[cfg(not(feature = "test-remount"))]
12
use log::{info, warn};
23
use std::fs;
34
use std::path::Path;
5+
#[cfg(not(feature = "test-remount"))]
46
use std::process::{Command, Stdio};
57
use thiserror::Error;
68

@@ -12,7 +14,7 @@ pub enum MountError {
1214
MountInfoError,
1315
}
1416

15-
fn is_boot_rw(mounts_path: &Path) -> Result<bool, MountError> {
17+
pub fn is_boot_rw(mounts_path: &Path) -> Result<bool, MountError> {
1618
let mounts = fs::read_to_string(mounts_path).map_err(|_| MountError::MountInfoError)?;
1719
for line in mounts.lines() {
1820
let parts: Vec<&str> = line.split_whitespace().collect();

0 commit comments

Comments
 (0)