代码拉取完成,页面将自动刷新
From 959ff2fc63354be00b3e22ec268b36a96866055e Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 31 Mar 2023 15:19:58 +0800
Subject: [PATCH 157/272] prep_loadenv: Fix regex for Open Firmware device
specifier with encoded commas
The Open Firmware device specifier allows for comma-separated properties
of a component, but this conflicts with the way that grub separates
device and partition in its device specifier. To address this, grub
encodes commas in Open Firmware device strings with a leading backslash
as an established convention.
However, the regular expression used to extract the boot device
substring from the $cmdpath environment variable did not properly retain
commas with leading backslashes as part of the device. This could cause
the comma to be incorrectly interpreted as a partition delimiter and
result in a broken name for the boot disk.
To fix this issue, we have updated the regular expression to properly
handle the encoded comma in the Open Firmware device specifier, ensuring
that the correct boot device is identified and used.
v2:
Fix the issue of freeing an uninitialized pointer in early_prep_loadenv.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/commands/prep_loadenv.c | 112 ++++++++++++++++++++++--------
1 file changed, 82 insertions(+), 30 deletions(-)
diff --git a/grub-core/commands/prep_loadenv.c b/grub-core/commands/prep_loadenv.c
index eaef2c9d4..109b7ca5a 100644
--- a/grub-core/commands/prep_loadenv.c
+++ b/grub-core/commands/prep_loadenv.c
@@ -15,7 +15,7 @@
GRUB_MOD_LICENSE ("GPLv3+");
static char *
-match_substr (regmatch_t *match, const char *str)
+match_substr (const regmatch_t *match, const char *str)
{
if (match->rm_so != -1)
{
@@ -192,24 +192,18 @@ prep_partname (const char *devname, char **prep)
return err;
}
-static grub_err_t
-boot_disk_prep_partname (char **name)
+static regmatch_t *
+regex_match_str (const char *pattern, const char *str, grub_size_t *nmatch)
{
regex_t regex;
int ret;
grub_size_t s;
char *comperr;
- const char *cmdpath;
regmatch_t *matches = NULL;
grub_err_t err = GRUB_ERR_NONE;
- *name = NULL;
-
- cmdpath = grub_env_get ("cmdpath");
- if (!cmdpath)
- return GRUB_ERR_NONE;
-
- ret = regcomp (®ex, "\\(([^,]+)(,?.*)?\\)(.*)", REG_EXTENDED);
+ *nmatch = 0;
+ ret = regcomp (®ex, pattern, REG_EXTENDED);
if (ret)
goto fail;
@@ -217,22 +211,11 @@ boot_disk_prep_partname (char **name)
if (! matches)
goto fail;
- ret = regexec (®ex, cmdpath, regex.re_nsub + 1, matches, 0);
- if (!ret)
+ ret = regexec (®ex, str, regex.re_nsub + 1, matches, 0);
+ if (ret == 0)
{
- char *devname = devname = match_substr (matches + 1, cmdpath);
- if (!devname)
- {
- err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "%s contains no disk name", cmdpath);
- goto out;
- }
-
- err = prep_partname (devname, name);
- out:
- grub_free (devname);
- regfree (®ex);
- grub_free (matches);
- return err;
+ *nmatch = regex.re_nsub + 1;
+ return matches;
}
fail:
@@ -242,13 +225,60 @@ boot_disk_prep_partname (char **name)
if (!comperr)
{
regfree (®ex);
- return grub_errno;
+ return NULL;
}
regerror (ret, ®ex, comperr, s);
err = grub_error (GRUB_ERR_TEST_FAILURE, "%s", comperr);
regfree (®ex);
grub_free (comperr);
- return err;
+ return NULL;
+}
+
+static grub_err_t
+boot_disk_prep_partname (const char *varname, char **name)
+{
+ const char *cmdpath;
+ regmatch_t *matches;
+ grub_size_t nmatch;
+ char *devname = NULL;
+
+ *name = NULL;
+
+ if (varname)
+ cmdpath = grub_env_get (varname);
+ else
+ cmdpath = grub_env_get ("cmdpath");
+ if (!cmdpath)
+ return GRUB_ERR_NONE;
+
+ matches = regex_match_str("\\((.*)\\)(.*)", cmdpath, &nmatch);
+ if (matches && nmatch >= 2)
+ devname = match_substr (matches + 1, cmdpath);
+ if (devname == NULL)
+ goto quit;
+ grub_free (matches);
+
+ matches = regex_match_str ("(.*[^\\])(,.*)", devname, &nmatch);
+ if (matches && nmatch >= 2)
+ {
+ char *n = match_substr (matches + 1, devname);
+ grub_free (devname);
+ devname = n;
+ }
+ else
+ grub_errno = GRUB_ERR_NONE;
+ if (devname)
+ {
+ grub_printf ("search prep from disk `%s'\n", devname);
+ prep_partname (devname, name);
+ }
+
+ quit:
+ grub_free (devname);
+ grub_free (matches);
+ if (grub_errno)
+ grub_print_error ();
+ return GRUB_ERR_NONE;
}
static grub_err_t
@@ -281,13 +311,31 @@ grub_cmd_prep_loadenv (grub_command_t cmd __attribute__ ((unused)),
return GRUB_ERR_NONE;
}
+static grub_err_t
+grub_cmd_prep_partname (grub_command_t cmd __attribute__ ((unused)),
+ int argc,
+ char **argv)
+{
+ char *prep = NULL;
+ const char *varname = NULL;
+
+ if (argc > 0)
+ varname = argv[0];
+
+ boot_disk_prep_partname(varname, &prep);
+ if (prep)
+ grub_printf ("prep: %s\n", prep);
+
+ return GRUB_ERR_NONE;
+}
+
static void
early_prep_loadenv (void)
{
grub_err_t err;
- char *prep;
+ char *prep = NULL;
- err = boot_disk_prep_partname (&prep);
+ err = boot_disk_prep_partname (NULL, &prep);
if (err == GRUB_ERR_NONE && prep)
err = prep_read_envblk (prep);
if (err == GRUB_ERR_BAD_FILE_TYPE || err == GRUB_ERR_FILE_NOT_FOUND)
@@ -302,6 +350,10 @@ static grub_command_t cmd_prep_load;
GRUB_MOD_INIT(prep_loadenv)
{
early_env_hook = early_prep_loadenv;
+ cmd_prep_load =
+ grub_register_command("prep_partname", grub_cmd_prep_partname,
+ "VARNAME",
+ N_("Get partition name of PReP."));
cmd_prep_load =
grub_register_command("prep_load_env", grub_cmd_prep_loadenv,
"DEVICE",
--
2.41.0
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。