Skip to content

Commit

Permalink
support for read only /boot mount
Browse files Browse the repository at this point in the history
Support is added for greenboot to work with read-only /boot.
It uses PrivateMounts=yes to isolate the system and remounts
boot as rw followed by setting the grub parameters as per healthcheck.

The following services are affected:

greenboot-grub2-set-success.service
greenboot-grub2-set-counter.service
greenboot-rpm-ostree-check-fallback.service

The grub2-editenv command is decoupled from greenboot-grub2-set-success.service
and is part of a separate script.

Signed-off-by: saypaul <[email protected]>
  • Loading branch information
say-paul committed Aug 9, 2024
1 parent d64f4e9 commit 8f2ccff
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 5 deletions.
1 change: 1 addition & 0 deletions greenboot.spec
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ install -DpZm 0644 etc/greenboot/greenboot.conf %{buildroot}%{_sysconfdir}/%{nam
%{_prefix}/lib/bootupd/grub2-static/configs.d/*.cfg
%{_unitdir}/greenboot-status.service
%{_libexecdir}/%{name}/greenboot-grub2-set-counter
%{_libexecdir}/%{name}/greenboot-grub2-set-success
%{_unitdir}/greenboot-grub2-set-success.service
%{_unitdir}/greenboot-grub2-set-counter.service
%{_libexecdir}/%{name}/greenboot-rpm-ostree-grub2-check-fallback
Expand Down
1 change: 1 addition & 0 deletions usr/lib/systemd/system/greenboot-grub2-set-counter.service
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ RequiresMountsFor=/boot
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/libexec/greenboot/greenboot-grub2-set-counter
PrivateMounts=yes

[Install]
RequiredBy=ostree-finalize-staged.service
4 changes: 2 additions & 2 deletions usr/lib/systemd/system/greenboot-grub2-set-success.service
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ After=boot-complete.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/grub2-editenv - set boot_success=1
ExecStart=/usr/bin/grub2-editenv - unset boot_counter
ExecStart=/usr/libexec/greenboot/greenboot-grub2-set-success
PrivateMounts=yes

[Install]
WantedBy=multi-user.target
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Before=greenboot-grub2-set-success.service
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/libexec/greenboot/greenboot-rpm-ostree-grub2-check-fallback
PrivateMounts=yes

[Install]
RequiredBy=greenboot-healthcheck.service
29 changes: 27 additions & 2 deletions usr/libexec/greenboot/greenboot-grub2-set-counter
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
#!/bin/bash
set -eo pipefail

function remount_boot_ro {
if grep -q " /boot .* rw," /proc/mounts; then
mount -o remount,ro /boot || exit 5
fi
return
}

GREENBOOT_CONFIGURATION_FILE=/etc/greenboot/greenboot.conf
if test -f "$GREENBOOT_CONFIGURATION_FILE"; then
# shellcheck source=etc/greenboot/greenboot.conf
Expand All @@ -14,7 +21,25 @@ elif [ -n "$GREENBOOT_MAX_BOOT_ATTEMPTS" ]; then
else
max_boot_attempts=3 # default to 3 attempts
fi
grub2-editenv - set boot_counter="$max_boot_attempts"
grub2-editenv - set boot_success=0

# Remount /boot as read-only if it was mounted as read-write
if grep -q " /boot .* rw," /proc/mounts; then
mount -o remount,ro /boot || exit 5
fi

if ! /usr/bin/grub2-editenv - set boot_counter="$max_boot_attempts"; then
# If the first command fails, remount /boot as read-only and exit with failure
remount_boot_ro
exit 1
fi

if ! /usr/bin/grub2-editenv /boot/grub2/grubenv set boot_success=0; then
# If the first command fails, remount /boot as read-only and exit with failure
remount_boot_ro
exit 1
fi

# Revert /boot as read-only
remount_boot_ro

echo "<3>GRUB2 environment variables have been set for system upgrade. Max boot attempts is $max_boot_attempts"
34 changes: 34 additions & 0 deletions usr/libexec/greenboot/greenboot-grub2-set-success
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/bin/bash

set -eo pipefail

function remount_boot_ro {
if grep -q " /boot .* rw," /proc/mounts; then
mount -o remount,ro /boot || exit 5
fi
return
}

# Check if /boot is mounted as read-only, and remount as read-write if necessary
if grep -q " /boot .* ro," /proc/mounts; then
mount -o remount,rw /boot || exit 5
fi

# Run the grub2-editenv commands
if ! /usr/bin/grub2-editenv /boot/grub2/grubenv set boot_success=1; then
# If the first command fails, remount /boot as read-only and exit with failure
remount_boot_ro
exit 1
fi

if ! /usr/bin/grub2-editenv /boot/grubenv unset boot_counter; then
# If the second command fails, remount /boot as read-only and exit with failure
remount_boot_ro
exit 1
fi

# Remount /boot as read-only if it was mounted as read-write
remount_boot_ro

# If everything succeeded, exit with success
exit 0
23 changes: 22 additions & 1 deletion usr/libexec/greenboot/greenboot-rpm-ostree-grub2-check-fallback
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
#!/bin/bash
set -euo pipefail

function remount_boot_ro {
if grep -q " /boot .* rw," /proc/mounts; then
mount -o remount,ro /boot || exit 5
fi
return
}

# Determine if the current boot is a fallback boot
# If booted into fallback deployment, clean up bootloader entries (rollback)
if grub2-editenv list | grep -q "^boot_counter=-1$"; then
Expand All @@ -12,5 +19,19 @@ if grub2-editenv list | grep -q "^boot_counter=-1$"; then
echo "<3>Health check logs from previous boot:"
echo "<3>$prev_logs"
fi
grub2-editenv - unset boot_counter


# Check if /boot is mounted as read-only, and remount as read-write if necessary
if grep -q " /boot .* ro," /proc/mounts; then
mount -o remount,rw /boot || exit 5
fi

if ! /usr/bin/grub2-editenv - unset boot_counter; then
# If the above command fails, remount /boot as read-only and exit with failure
remount_boot_ro
exit 1
fi
fi

# Remount /boot as read-only if it was mounted as read-write
remount_boot_ro

0 comments on commit 8f2ccff

Please sign in to comment.