View Issue Details

IDProjectCategoryView StatusLast Update
0018338CentOS-8grub2public2021-10-28 10:01
Reporterjcencek Assigned To 
PrioritynormalSeveritymajorReproducibilityalways
Status newResolutionopen 
Summary0018338: systemd "Type #1" boot loader specification is not compatible with actual grub2 behavior
DescriptionOn a small subset of systems, the kernel selected as default is not chosen by grub2 during boot. grub2 will chose a wrong kernel, seemingly at random.

The below explanations and steps to reproduce are fully supported by information documented here:
https://systemd.io/BOOT_LOADER_SPECIFICATION/

The issue in particular pertains to "Type #1 Boot Loader Specification Entries". The problem is that grub2, according to the source code, requires that loader entries do NOT start with a numerical character. If they do, they are parsed numerically as an index. Only should numerical parsing fail; are they parsed as one of the following:

1) the title of a kernel entry
2) a filename in /boot/loader/entries/

A problem arises because the Type #1 boot loader spec creates entries with the machine id as the prefix. This is precisely exemplified in the above article with the following case:
"$BOOT/loader/entries/6a9857a393724b7a981ebb5b8495b9ea-3.8.0-2.fc19.x86_64.conf"

The article seems unaware that such an entry is invalid, and is in fact interpreted by grub2 as "6", thus translating to the 7th item in the list. This is provable by examining the source code, which first attempts to obtain an index via strtoull, and falls back to a kernel title or entry name only if that fails:

--------------------------------------
/* Get the entry number from the variable NAME. */
static int
get_entry_number (grub_menu_t menu, const char *name)
{
  const char *val;
  int entry;

  val = grub_env_get (name);
  if (! val)
    return -1;

  grub_error_push ();

  entry = (int) grub_strtoul (val, 0, 0);

  if (grub_errno == GRUB_ERR_BAD_NUMBER)
    {
      /* See if the variable matches the title of a menu entry. */
      grub_menu_entry_t e = menu->entry_list;
      int i;

      grub_errno = GRUB_ERR_NONE;

      for (i = 0; e; i++)
    {
      if (menuentry_eq (e->title, val)
          || menuentry_eq (e->id, val))
        {
          entry = i;
          break;
        }
      e = e->next;
    }

      if (! e)
    entry = -1;
    }

  if (grub_errno != GRUB_ERR_NONE)
    {
      grub_errno = GRUB_ERR_NONE;
      entry = -1;
    }

  grub_error_pop ();

  return entry;
}
----------------------------
Steps To Reproduce* grub2 version: 2.02-99
* grubby package: grubby-8.40-41.el8.x86_64

* Set your machine-id (/etc/machine-id) to a 32-character hex string that translates to "1" under strtoull, e.g. anything that starts with 1c.
* Install at least two different kernels and configure the first kernel in the entry list to be the default.
* Ensure that your grub2 config has the following config clause
       set default="${saved_entry}"
and that grubenv contains a record for the first kernel which you have selected as default as the saved entry. The name should match the machine id, e.g.

head -n 2 grubenv
# GRUB Environment Block
saved_entry=1c152a16dc35a02c1a59933d47183a69-4.18.0-338.el8.x86_64

and assuming you followed the previous steps, it will begin with the characters 1c, based on the machine id.

Reboot the system, and when the menu list displays:

Expected result: grub has selected the first kernel as the default because that's what you configured
Actual result: grub has selected the second kernel as the default because it interprets the saved_entry to be the index 1 in the zero-indexed list
Additional InformationI apologize if this is not the correct place to file this bug. If so, please direct me to the appropriate place.
TagsNo tags attached.

Activities

jcencek

jcencek

2021-10-27 06:51

reporter   ~0038681

Note: the steps involving grubenv are only to verify that the bug will occur, and should not be done manually. The default kernel should be chosen normally using standard tools, e.g.:
/usr/sbin/grubby --set-default $vmlinuz --grub2;

and with the given software versions, this will populate the grubenv and grub configuration automatically in such a way as to reproduce this bug. grub2-mkconfig might also be required based on the setup.
jcencek

jcencek

2021-10-28 10:01

reporter   ~0038684

Note #2: it appears that GRUB_ENABLE_BLSCFG=true should be present in order to reproduce this. We want grub to load the entries from /boot/loader/entries and not have them be hardcoded into the config file

Issue History

Date Modified Username Field Change
2021-10-27 06:38 jcencek New Issue
2021-10-27 06:51 jcencek Note Added: 0038681
2021-10-28 10:01 jcencek Note Added: 0038684