Store cmdline in BLS snippets instead of using a grubenv variable

The kernel cmdline was stored as a kernelopts variable in the grubenv file
and the BLS snippets used that. But this turned out to be fragile since the
grubenv file could be removed or get corrupted easily.

To prevent the entries to not have a cmdline if the grubenv can't be read,
a fallback variable was set in the GRUB config file. But this still caused
issues since the config needs to be re-generated to change the parameters.

Instead, let's store the cmdline in the BLS snippets. This will make the
configuration more robust, since it will work even without the grubenv
file and the BLS entries will contain all the information needed to boot.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
This commit is contained in:
Javier Martinez Canillas 2020-05-06 19:13:01 +02:00
parent 107dc9a693
commit 4a742183a3
No known key found for this signature in database
GPG key ID: C751E590D63F3D69
4 changed files with 188 additions and 16 deletions

View file

@ -0,0 +1,160 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Wed, 13 May 2020 19:40:10 +0200
Subject: [PATCH] 10_linux.in: Store cmdline in BLS snippets instead of using a
variable
The kernel cmdline was stored as a kernelopts variable in the grubenv file
and the BLS snippets used that. But this turned out to be fragile since the
grubenv file could be removed or get corrupted easily.
To prevent the entries to not have a cmdline if the grubenv can't be read,
a fallback variable was set in the GRUB config file. But this still caused
issues since the config needs to be re-generated to change the parameters.
Instead, let's store the cmdline in the BLS snippets. This will make the
configuration more robust, since it will work even without the grubenv
file and the BLS entries will contain all the information needed to boot.
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---
util/grub-switch-to-blscfg.in | 30 ++++++++++--------------------
util/grub.d/10_linux.in | 41 +++++++++++++++++++++++++++++++----------
2 files changed, 41 insertions(+), 30 deletions(-)
diff --git a/util/grub-switch-to-blscfg.in b/util/grub-switch-to-blscfg.in
index 3333a620c28..cb229126128 100644
--- a/util/grub-switch-to-blscfg.in
+++ b/util/grub-switch-to-blscfg.in
@@ -190,7 +190,7 @@ fi
mkbls() {
local kernelver=$1 && shift
local datetime=$1 && shift
- local bootprefix=$1 && shift
+ local kernelopts=$1 && shift
local debugname=""
local debugid=""
@@ -209,10 +209,9 @@ mkbls() {
cat <<EOF
title ${NAME} (${kernelver}) ${VERSION}${debugname}
version ${kernelver}${debugid}
-linux ${bootprefix}/vmlinuz-${kernelver}
-initrd ${bootprefix}/initramfs-${kernelver}.img
-options \$kernelopts
-id ${ID}-${datetime}-${kernelver}
+linux /vmlinuz-${kernelver}
+initrd /initramfs-${kernelver}.img
+options ${kernelopts}
grub_users \$grub_users
grub_arg --unrestricted
grub_class kernel${flavor}
@@ -236,28 +235,19 @@ copy_bls() {
linux_relpath="$("${grub_mkrelpath}" "${linux_path}")"
bootprefix="${linux_relpath%%"${linux}"}"
+ cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
- if [ -f "${kernel_dir}/bls.conf" ] ; then
- cp -af "${kernel_dir}/bls.conf" "${bls_target}"
- if [ -n "${bootprefix}" ]; then
- sed -i -e "s,^\(linux[^ \t]*[ \t]\+\).*,\1${bootprefix}${linux},g" "${bls_target}"
- sed -i -e "/^initrd/ s,\([ \t]\+\)\([^ \t]\+\),\1${bootprefix}\2,g" "${bls_target}"
- fi
- else
- mkbls "${kernelver}" \
- "$(date -u +%Y%m%d%H%M%S -d "$(stat -c '%y' "${kernel_dir}")")" \
- "${bootprefix}" \
- >"${bls_target}"
- fi
+ mkbls "${kernelver}" \
+ "$(date -u +%Y%m%d%H%M%S -d "$(stat -c '%y' "${kernel_dir}")")" \
+ "${bootprefix}" "${cmdline}" >"${bls_target}"
if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then
bls_debug="$(echo ${bls_target} | sed -e "s/${kernelver}/${kernelver}~debug/")"
cp -aT "${bls_target}" "${bls_debug}"
title="$(grep '^title[ \t]' "${bls_debug}" | sed -e 's/^title[ \t]*//')"
- blsid="$(grep '^id[ \t]' "${bls_debug}" | sed -e "s/\.${ARCH}/-debug.${arch}/")"
+ options="$(echo "${cmdline} ${GRUB_CMDLINE_LINUX_DEBUG}" | sed -e 's/\//\\\//g')"
sed -i -e "s/^title.*/title ${title}${GRUB_LINUX_DEBUG_TITLE_POSTFIX}/" "${bls_debug}"
- sed -i -e "s/^id.*/${blsid}/" "${bls_debug}"
- sed -i -e "s/^options.*/options \$kernelopts ${GRUB_CMDLINE_LINUX_DEBUG}/" "${bls_debug}"
+ sed -i -e "s/^options.*/options ${options}/" "${bls_debug}"
fi
done
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 09adfce80fd..80299ecaf00 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -134,23 +134,43 @@ read_config()
done < ${config_file}
}
-populate_menu()
+blsdir="/boot/loader/entries"
+
+get_sorted_bls()
{
- blsdir="/boot/loader/entries"
- local -a files
local IFS=$'\n'
- gettext_printf "Generating boot entries from BLS files...\n" >&2
- files=($(for bls in ${blsdir}/*.conf ; do
- if ! [[ -e "${bls}" ]] ; then
- continue
- fi
+ files=($(for bls in ${blsdir}/*.conf; do
bls="${bls%.conf}"
bls="${bls##*/}"
echo "${bls}"
done | ${kernel_sort} | tac)) || :
- for bls in "${files[@]}" ; do
+ echo "${files[@]}"
+}
+
+update_bls_cmdline()
+{
+ local cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+ local -a files=($(get_sorted_bls))
+
+ for bls in "${files[@]}"; do
+ local options="${cmdline}"
+ if [ -z "${bls##*debug*}" ]; then
+ options="${options} ${GRUB_CMDLINE_LINUX_DEBUG}"
+ fi
+ options="$(echo "${options}" | sed -e 's/\//\\\//g')"
+ sed -i -e "s/^options.*/options ${options}/" "${blsdir}/${bls}.conf"
+ done
+}
+
+populate_menu()
+{
+ local -a files=($(get_sorted_bls))
+
+ gettext_printf "Generating boot entries from BLS files...\n" >&2
+
+ for bls in "${files[@]}"; do
read_config "${blsdir}/${bls}.conf"
menu="${menu}menuentry '${title}' ${grub_arg} --id=${bls} {\n"
@@ -224,6 +244,8 @@ if [ -z "\${kernelopts}" ]; then
fi
EOF
+ update_bls_cmdline
+
if [ "x${BLS_POPULATE_MENU}" = "xtrue" ]; then
populate_menu
else
@@ -244,7 +266,6 @@ EOF
fi
fi
- ${grub_editenv} - set kernelopts="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
if [ -n "${GRUB_EARLY_INITRD_LINUX_CUSTOM}" ]; then
${grub_editenv} - set early_initrd="${GRUB_EARLY_INITRD_LINUX_CUSTOM}"
fi

View file

@ -24,6 +24,7 @@ BLS_DIR="/boot/loader/entries"
mkbls() { mkbls() {
local kernelver=$1 && shift local kernelver=$1 && shift
local datetime=$1 && shift local datetime=$1 && shift
local kernelopts=$1 && shift
local debugname="" local debugname=""
local debugid="" local debugid=""
@ -42,7 +43,7 @@ title ${NAME} (${kernelver}) ${VERSION}${debugname}
version ${kernelver}${debugid} version ${kernelver}${debugid}
linux /vmlinuz-${kernelver} linux /vmlinuz-${kernelver}
initrd /initramfs-${kernelver}.img initrd /initramfs-${kernelver}.img
options \$kernelopts options ${kernelopts}
grub_users \$grub_users grub_users \$grub_users
grub_arg --unrestricted grub_arg --unrestricted
grub_class kernel${flavor} grub_class kernel${flavor}
@ -77,19 +78,29 @@ case "$COMMAND" in
fi fi
if [[ "x${GRUB_ENABLE_BLSCFG}" = "xtrue" ]] || [[ ! -f /sbin/new-kernel-pkg ]]; then if [[ "x${GRUB_ENABLE_BLSCFG}" = "xtrue" ]] || [[ ! -f /sbin/new-kernel-pkg ]]; then
if [[ -f /etc/kernel/cmdline ]]; then
read -r -d '' -a BOOT_OPTIONS < /etc/kernel/cmdline
elif [[ -f /usr/lib/kernel/cmdline ]]; then
read -r -d '' -a BOOT_OPTIONS < /usr/lib/kernel/cmdline
else
declare -a BOOT_OPTIONS
read -r -d '' -a line < /proc/cmdline
for i in "${line[@]}"; do
[[ "${i#initrd=*}" != "$i" ]] && continue
[[ "${i#BOOT_IMAGE=*}" != "$i" ]] && continue
BOOT_OPTIONS+=("$i")
done
fi
eval "$(grub2-get-kernel-settings)" || true eval "$(grub2-get-kernel-settings)" || true
[[ -d "$BLS_DIR" ]] || mkdir -m 0700 -p "$BLS_DIR" [[ -d "$BLS_DIR" ]] || mkdir -m 0700 -p "$BLS_DIR"
BLS_ID="${MACHINE_ID}-${KERNEL_VERSION}" BLS_ID="${MACHINE_ID}-${KERNEL_VERSION}"
BLS_TARGET="${BLS_DIR}/${BLS_ID}.conf" BLS_TARGET="${BLS_DIR}/${BLS_ID}.conf"
if [[ -f "${KERNEL_DIR}/bls.conf" ]]; then mkbls "${KERNEL_VERSION}" \
cp -aT "${KERNEL_DIR}/bls.conf" "${BLS_TARGET}" || exit $? "$(date -u +%Y%m%d%H%M%S -d "$(stat -c '%y' "${KERNEL_DIR}")")" \
else "${BOOT_OPTIONS[*]}" >"${BLS_TARGET}"
mkbls "${KERNEL_VERSION}" \ command -v restorecon &>/dev/null && restorecon -R "${BLS_TARGET}"
"$(date -u +%Y%m%d%H%M%S -d "$(stat -c '%y' "${KERNEL_DIR}")")" \
>"${BLS_TARGET}"
fi
command -v restorecon &>/dev/null && \
restorecon -R "${BLS_TARGET}"
LINUX="$(grep '^linux[ \t]' "${BLS_TARGET}" | sed -e 's,^linux[ \t]*,,')" LINUX="$(grep '^linux[ \t]' "${BLS_TARGET}" | sed -e 's,^linux[ \t]*,,')"
INITRD="$(grep '^initrd[ \t]' "${BLS_TARGET}" | sed -e 's,^initrd[ \t]*,,')" INITRD="$(grep '^initrd[ \t]' "${BLS_TARGET}" | sed -e 's,^initrd[ \t]*,,')"
@ -111,14 +122,12 @@ case "$COMMAND" in
fi fi
if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then
ARCH="$(uname -m)"
BLS_DEBUG_ID="$(echo ${BLS_ID} | sed -e "s/${KERNEL_VERSION}/${KERNEL_VERSION}~debug/")"
BLS_DEBUG="$(echo ${BLS_TARGET} | sed -e "s/${KERNEL_VERSION}/${KERNEL_VERSION}~debug/")" BLS_DEBUG="$(echo ${BLS_TARGET} | sed -e "s/${KERNEL_VERSION}/${KERNEL_VERSION}~debug/")"
cp -aT "${BLS_TARGET}" "${BLS_DEBUG}" cp -aT "${BLS_TARGET}" "${BLS_DEBUG}"
TITLE="$(grep '^title[ \t]' "${BLS_DEBUG}" | sed -e 's/^title[ \t]*//')" TITLE="$(grep '^title[ \t]' "${BLS_DEBUG}" | sed -e 's/^title[ \t]*//')"
OPTIONS="$(echo "${BOOT_OPTIONS[*]} ${GRUB_CMDLINE_LINUX_DEBUG}" | sed -e 's/\//\\\//g')"
sed -i -e "s/^title.*/title ${TITLE}${GRUB_LINUX_DEBUG_TITLE_POSTFIX}/" "${BLS_DEBUG}" sed -i -e "s/^title.*/title ${TITLE}${GRUB_LINUX_DEBUG_TITLE_POSTFIX}/" "${BLS_DEBUG}"
sed -i -e "s/^id.*/id ${BLS_DEBUG_ID}/" "${BLS_DEBUG}" sed -i -e "s/^options.*/options ${OPTIONS}/" "${BLS_DEBUG}"
sed -i -e "s/^options.*/options \$kernelopts ${GRUB_CMDLINE_LINUX_DEBUG}/" "${BLS_DEBUG}"
if [ -n "$NEWDEFAULT" -a "x$GRUB_DEFAULT_TO_DEBUG" = "xtrue" ]; then if [ -n "$NEWDEFAULT" -a "x$GRUB_DEFAULT_TO_DEBUG" = "xtrue" ]; then
NEWDEFAULT="${BLS_DEBUG_ID}" NEWDEFAULT="${BLS_DEBUG_ID}"
fi fi
@ -145,7 +154,6 @@ case "$COMMAND" in
remove) remove)
if [[ "x${GRUB_ENABLE_BLSCFG}" = "xtrue" ]] || [[ ! -f /sbin/new-kernel-pkg ]]; then if [[ "x${GRUB_ENABLE_BLSCFG}" = "xtrue" ]] || [[ ! -f /sbin/new-kernel-pkg ]]; then
ARCH="$(uname -m)"
BLS_TARGET="${BLS_DIR}/${MACHINE_ID}-${KERNEL_VERSION}.conf" BLS_TARGET="${BLS_DIR}/${MACHINE_ID}-${KERNEL_VERSION}.conf"
BLS_DEBUG="$(echo ${BLS_TARGET} | sed -e "s/${KERNEL_VERSION}/${KERNEL_VERSION}~debug/")" BLS_DEBUG="$(echo ${BLS_TARGET} | sed -e "s/${KERNEL_VERSION}/${KERNEL_VERSION}~debug/")"
rm -f "${BLS_TARGET}" "${BLS_DEBUG}" rm -f "${BLS_TARGET}" "${BLS_DEBUG}"

View file

@ -211,3 +211,4 @@ Patch0210: 0210-efi-Set-image-base-address-before-jumping-to-the-PE-.patch
Patch0211: 0211-blscfg-Lookup-default_kernelopts-variable-as-fallbac.patch Patch0211: 0211-blscfg-Lookup-default_kernelopts-variable-as-fallbac.patch
Patch0212: 0212-10_linux.in-fix-early-exit-due-error-when-reading-pe.patch Patch0212: 0212-10_linux.in-fix-early-exit-due-error-when-reading-pe.patch
Patch0213: 0213-envblk-Fix-buffer-overrun-when-attempting-to-shrink-.patch Patch0213: 0213-envblk-Fix-buffer-overrun-when-attempting-to-shrink-.patch
Patch0214: 0214-10_linux.in-Store-cmdline-in-BLS-snippets-instead-of.patch

View file

@ -9,7 +9,7 @@
Name: grub2 Name: grub2
Epoch: 1 Epoch: 1
Version: 2.04 Version: 2.04
Release: 16%{?dist} Release: 17%{?dist}
Summary: Bootloader with support for Linux, Multiboot and more Summary: Bootloader with support for Linux, Multiboot and more
License: GPLv3+ License: GPLv3+
URL: http://www.gnu.org/software/grub/ URL: http://www.gnu.org/software/grub/
@ -504,6 +504,9 @@ rm -r /boot/grub2.tmp/ || :
%endif %endif
%changelog %changelog
* Wed May 13 2020 Javier Martinez Canillas <javierm@redhat.com> - 2.04-17
- Store cmdline in BLS snippets instead of using a grubenv variable
* Tue May 12 2020 Javier Martinez Canillas <javierm@redhat.com> - 2.04-16 * Tue May 12 2020 Javier Martinez Canillas <javierm@redhat.com> - 2.04-16
- Fix a segfault in grub2-editenv when attempting to shrink a variable - Fix a segfault in grub2-editenv when attempting to shrink a variable