From b3ea4c3b5f65dc8e578772bffdc1c379c2dd478a Mon Sep 17 00:00:00 2001 From: Qiumiao Zhang Date: Wed, 6 Mar 2024 01:53:57 +0000 Subject: [PATCH] fix CVE-2024-1048 and backport some patches from upstream Signed-off-by: Qiumiao Zhang --- ...et-bootflag-Conservative-partial-fix.patch | 153 ++++++++++++++ ...ub-set-bootflag-Exit-calmly-when-not.patch | 40 ++++ ...-grub-set-bootflag-More-complete-fix.patch | 191 ++++++++++++++++++ ...x-calculation-of-ACPI-tables-address.patch | 84 ++++++++ ...mmands-acpi-Use-xsdt_addr-if-present.patch | 38 ++++ ...i-Skip-NULL-entries-in-RSDT-and-XSDT.patch | 64 ++++++ ...t-kern-acpi-Use-xsdt_addr-if-present.patch | 50 +++++ ...il-grub-mount-Check-file-path-sanity.patch | 34 ++++ grub.patches | 8 + grub2.spec | 13 +- 10 files changed, 674 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2024-1048-grub-set-bootflag-Conservative-partial-fix.patch create mode 100644 backport-CVE-2024-1048-grub-set-bootflag-Exit-calmly-when-not.patch create mode 100644 backport-CVE-2024-1048-grub-set-bootflag-More-complete-fix.patch create mode 100644 backport-commands-acpi-Fix-calculation-of-ACPI-tables-address.patch create mode 100644 backport-commands-acpi-Use-xsdt_addr-if-present.patch create mode 100644 backport-kern-acpi-Skip-NULL-entries-in-RSDT-and-XSDT.patch create mode 100644 backport-kern-acpi-Use-xsdt_addr-if-present.patch create mode 100644 backport-util-grub-mount-Check-file-path-sanity.patch diff --git a/backport-CVE-2024-1048-grub-set-bootflag-Conservative-partial-fix.patch b/backport-CVE-2024-1048-grub-set-bootflag-Conservative-partial-fix.patch new file mode 100644 index 0000000..5c851a6 --- /dev/null +++ b/backport-CVE-2024-1048-grub-set-bootflag-Conservative-partial-fix.patch @@ -0,0 +1,153 @@ +From 77f0ca016ae45fd5471cc89ac472868d94b8ed67 Mon Sep 17 00:00:00 2001 +From: Solar Designer +Date: Tue, 6 Feb 2024 21:39:41 +0100 +Subject: [PATCH] grub-set-bootflag: Conservative partial fix for CVE-2024-1048 + +Following up on CVE-2019-14865 and taking a fresh look at +grub2-set-bootflag now (through my work at CIQ on Rocky Linux), I saw some +other ways in which users could still abuse this little program: + +1. After CVE-2019-14865 fix, grub2-set-bootflag no longer rewrites the +grubenv file in-place, but writes into a temporary file and renames it +over the original, checking for error returns from each call first. +This prevents the original file truncation vulnerability, but it can +leave the temporary file around if the program is killed before it can +rename or remove the file. There are still many ways to get the program +killed, such as through RLIMIT_FSIZE triggering SIGXFSZ (tested, +reliable) or by careful timing (tricky) of signals sent by process group +leader, pty, pre-scheduled timers, SIGXCPU (probably not an exhaustive +list). Invoking the program multiple times fills up /boot (or if /boot +is not separate, then it can fill up the root filesystem). Since the +files are tiny, the filesystem is likely to run out of free inodes +before it'd run out of blocks, but the effect is similar - can't create +new files after this point (but still can add data to existing files, +such as logs). + +2. After CVE-2019-14865 fix, grub2-set-bootflag naively tries to protect +itself from signals by becoming full root. (This does protect it from +signals sent by the user directly to the PID, but e.g. "kill -9 -1" by +the user still works.) A side effect of such "protection" is that it's +possible to invoke more concurrent instances of grub2-set-bootflag than +the user's RLIMIT_NPROC would normally permit (as specified e.g. in +/etc/security/limits.conf, or say in Apache httpd's RLimitNPROC if +grub2-set-bootflag would be abused by a website script), thereby +exhausting system resources (e.g., bypassing RAM usage limit if +RLIMIT_AS was also set). + +3. umask is inherited. Again, due to how the CVE-2019-14865 fix creates +a new file, and due to how mkstemp() works, this affects grubenv's new +file permissions. Luckily, mkstemp() forces them to be no more relaxed +than 0600, but the user ends up being able to set them e.g. to 0. +Luckily, at least in my testing GRUB still works fine even when the file +has such (lack of) permissions. + +This commit deals with the abuses above as follows: + +1. RLIMIT_FSIZE is pre-checked, so this specific way to get the process +killed should no longer work. However, this isn't a complete fix +because there are other ways to get the process killed after it has +created the temporary file. + +The commit also fixes bug 1975892 ("RFE: grub2-set-bootflag should not +write the grubenv when the flag being written is already set") and +similar for "menu_show_once", which further reduces the abuse potential. + +2. RLIMIT_NPROC bypass should be avoided by not becoming full root (aka +dropping the partial "kill protection"). + +3. A safe umask is set. + +This is a partial fix (temporary files can still accumulate, but this is +harder to trigger). + +While at it, this commit also fixes potential 1- or 2-byte over-read of +env[] if its content is malformed - this was not a security issue since the +grubenv file is trusted input, and the fix is just for robustness. + +Reference:https://src.fedoraproject.org/rpms/grub2/c/de8520b84a00acd5152bfacb433cc577fe825bca?branch=rawhide +Conflict:NA + +Signed-off-by: Solar Designer +--- + util/grub-set-bootflag.c | 30 +++++++++++++++++------------- + 1 file changed, 17 insertions(+), 13 deletions(-) + +diff --git a/util/grub-set-bootflag.c b/util/grub-set-bootflag.c +index d1c5e28..6b2561c 100644 +--- a/util/grub-set-bootflag.c ++++ b/util/grub-set-bootflag.c +@@ -33,6 +33,8 @@ + #include + #include + #include ++#include ++#include + + #define GRUBENV "/" GRUB_BOOT_DIR_NAME "/" GRUB_DIR_NAME "/" GRUB_ENVBLK_DEFCFG + #define GRUBENV_SIZE 1024 +@@ -55,12 +57,17 @@ static void usage(void) + int main(int argc, char *argv[]) + { + /* NOTE buf must be at least the longest bootflag length + 4 bytes */ +- char env[GRUBENV_SIZE + 1], buf[64], *s; ++ char env[GRUBENV_SIZE + 1 + 2], buf[64], *s; + /* +1 for 0 termination, +6 for "XXXXXX" in tmp filename */ + char env_filename[PATH_MAX + 1], tmp_filename[PATH_MAX + 6 + 1]; + const char *bootflag; + int i, fd, len, ret; + FILE *f; ++ struct rlimit rlim; ++ ++ if (getrlimit(RLIMIT_FSIZE, &rlim) || rlim.rlim_cur < GRUBENV_SIZE || rlim.rlim_max < GRUBENV_SIZE) ++ return 1; ++ umask(077); + + if (argc != 2) + { +@@ -82,20 +89,11 @@ int main(int argc, char *argv[]) + len = strlen (bootflag); + + /* +- * Really become root. setuid avoids an user killing us, possibly leaking +- * the tmpfile. setgid avoids the new grubenv's gid being that of the user. ++ * setegid avoids the new grubenv's gid being that of the user. + */ +- ret = setuid(0); +- if (ret) +- { +- perror ("Error setuid(0) failed"); +- return 1; +- } +- +- ret = setgid(0); +- if (ret) ++ if (setegid(0)) + { +- perror ("Error setgid(0) failed"); ++ perror ("Error setegid(0) failed"); + return 1; + } + +@@ -124,6 +122,10 @@ int main(int argc, char *argv[]) + + /* 0 terminate env */ + env[GRUBENV_SIZE] = 0; ++ ++ /* not a valid flag value */ ++ env[GRUBENV_SIZE + 1] = 0; ++ env[GRUBENV_SIZE + 2] = 0; + + if (strncmp (env, GRUB_ENVBLK_SIGNATURE, strlen (GRUB_ENVBLK_SIGNATURE))) + { +@@ -159,6 +161,8 @@ int main(int argc, char *argv[]) + + /* The grubenv is not 0 terminated, so memcpy the name + '=' , '1', '\n' */ + snprintf(buf, sizeof(buf), "%s=1\n", bootflag); ++ if (!memcmp(s, buf, len + 3)) ++ return 0; /* nothing to do */ + memcpy(s, buf, len + 3); + + +-- +2.19.1 + diff --git a/backport-CVE-2024-1048-grub-set-bootflag-Exit-calmly-when-not.patch b/backport-CVE-2024-1048-grub-set-bootflag-Exit-calmly-when-not.patch new file mode 100644 index 0000000..1919312 --- /dev/null +++ b/backport-CVE-2024-1048-grub-set-bootflag-Exit-calmly-when-not.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Solar Designer +Date: Tue, 6 Feb 2024 22:05:45 +0100 +Subject: [PATCH] grub-set-bootflag: Exit calmly when not running as root + +Exit calmly when not installed SUID root and invoked by non-root. This +allows installing user/grub-boot-success.service unconditionally while +supporting non-SUID installation of the program for some limited usage. + +Reference:https://src.fedoraproject.org/rpms/grub2/c/de8520b84a00acd5152bfacb433cc577fe825bca?branch=rawhide +Conflict:NA + +Signed-off-by: Solar Designer +--- + util/grub-set-bootflag.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/util/grub-set-bootflag.c b/util/grub-set-bootflag.c +index 514c4f9091ac..31a868aeca8a 100644 +--- a/util/grub-set-bootflag.c ++++ b/util/grub-set-bootflag.c +@@ -98,6 +98,17 @@ int main(int argc, char *argv[]) + bootflag = bootflags[i]; + len = strlen (bootflag); + ++ /* ++ * Exit calmly when not installed SUID root and invoked by non-root. This ++ * allows installing user/grub-boot-success.service unconditionally while ++ * supporting non-SUID installation of the program for some limited usage. ++ */ ++ if (geteuid()) ++ { ++ printf ("grub-set-bootflag not running as root, no action taken\n"); ++ return 0; ++ } ++ + /* + * setegid avoids the new grubenv's gid being that of the user. + */ + diff --git a/backport-CVE-2024-1048-grub-set-bootflag-More-complete-fix.patch b/backport-CVE-2024-1048-grub-set-bootflag-More-complete-fix.patch new file mode 100644 index 0000000..ae92b97 --- /dev/null +++ b/backport-CVE-2024-1048-grub-set-bootflag-More-complete-fix.patch @@ -0,0 +1,191 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Solar Designer +Date: Tue, 6 Feb 2024 21:56:21 +0100 +Subject: [PATCH] grub-set-bootflag: More complete fix for CVE-2024-1048 + +Switch to per-user fixed temporary filenames along with a weird locking +mechanism, which is explained in source code comments. This is a more +complete fix than the previous commit (temporary files can't accumulate). +Unfortunately, it introduces new risks (by working on a temporary file +shared between the user's invocations), which are _hopefully_ avoided by +the patch's elaborate logic. I actually got it wrong at first, which +suggests that this logic is hard to reason about, and more errors or +omissions are possible. It also relies on the kernel's primitives' exact +semantics to a greater extent (nothing out of the ordinary, though). + +Remaining issues that I think cannot reasonably be fixed without a +redesign (e.g., having per-flag files with nothing else in them) and +without introducing new issues: + +A. A user can still revert a concurrent user's attempt of setting the +other flag - or of making other changes to grubenv by means other than +this program. + +B. One leftover temporary file per user is still possible. + +Reference:https://src.fedoraproject.org/rpms/grub2/c/de8520b84a00acd5152bfacb433cc577fe825bca?branch=rawhide +Conflict:NA + +Signed-off-by: Solar Designer +--- + util/grub-set-bootflag.c | 95 ++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 79 insertions(+), 16 deletions(-) + +diff --git a/util/grub-set-bootflag.c b/util/grub-set-bootflag.c +index 5bbbef804391..514c4f9091ac 100644 +--- a/util/grub-set-bootflag.c ++++ b/util/grub-set-bootflag.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -60,15 +61,12 @@ int main(int argc, char *argv[]) + { + /* NOTE buf must be at least the longest bootflag length + 4 bytes */ + char env[GRUBENV_SIZE + 1 + 2], buf[64], *s; +- /* +1 for 0 termination, +6 for "XXXXXX" in tmp filename */ +- char env_filename[PATH_MAX + 1], tmp_filename[PATH_MAX + 6 + 1]; ++ /* +1 for 0 termination, +11 for ".%u" in tmp filename */ ++ char env_filename[PATH_MAX + 1], tmp_filename[PATH_MAX + 11 + 1]; + const char *bootflag; + int i, fd, len, ret; + FILE *f; +- struct rlimit rlim; + +- if (getrlimit(RLIMIT_FSIZE, &rlim) || rlim.rlim_cur < GRUBENV_SIZE || rlim.rlim_max < GRUBENV_SIZE) +- return 1; + umask(077); + + if (argc != 2) +@@ -105,7 +103,7 @@ int main(int argc, char *argv[]) + */ + if (setegid(0)) + { +- perror ("Error setegid(0) failed"); ++ perror ("setegid(0) failed"); + return 1; + } + +@@ -176,19 +174,82 @@ int main(int argc, char *argv[]) + return 0; /* nothing to do */ + memcpy(s, buf, len + 3); + ++ struct rlimit rlim; ++ if (getrlimit(RLIMIT_FSIZE, &rlim) || rlim.rlim_cur < GRUBENV_SIZE || rlim.rlim_max < GRUBENV_SIZE) ++ { ++ fprintf (stderr, "Resource limits undetermined or too low\n"); ++ return 1; ++ } ++ ++ /* ++ * Here we work under the premise that we shouldn't write into the target ++ * file directly because we might not be able to have all of our changes ++ * written completely and atomically. That was CVE-2019-14865, known to ++ * have been triggerable via RLIMIT_FSIZE. While we've dealt with that ++ * specific attack via the check above, there may be other possibilities. ++ */ + + /* + * Create a tempfile for writing the new env. Use the canonicalized filename + * for the template so that the tmpfile is in the same dir / on same fs. ++ * ++ * We now use per-user fixed temporary filenames, so that a user cannot cause ++ * multiple files to accumulate. ++ * ++ * We don't use O_EXCL so that a stale temporary file doesn't prevent further ++ * usage of the program by the user. + */ +- snprintf(tmp_filename, sizeof(tmp_filename), "%sXXXXXX", env_filename); +- fd = mkstemp(tmp_filename); ++ snprintf(tmp_filename, sizeof(tmp_filename), "%s.%u", env_filename, getuid()); ++ fd = open(tmp_filename, O_CREAT | O_WRONLY, 0600); + if (fd == -1) + { + perror ("Creating tmpfile failed"); + return 1; + } + ++ /* ++ * The lock prevents the same user from reaching further steps ending in ++ * rename() concurrently, in which case the temporary file only partially ++ * written by one invocation could be renamed to the target file by another. ++ * ++ * The lock also guards the slow fsync() from concurrent calls. After the ++ * first time that and the rename() complete, further invocations for the ++ * same flag become no-ops. ++ * ++ * We lock the temporary file rather than the target file because locking the ++ * latter would allow any user having SIGSTOP'ed their process to make all ++ * other users' invocations fail (or lock up if we'd use blocking mode). ++ * ++ * We use non-blocking mode (LOCK_NB) because the lock having been taken by ++ * another process implies that the other process would normally have already ++ * renamed the file to target by the time it releases the lock (and we could ++ * acquire it), so we'd be working directly on the target if we proceeded, ++ * which is undesirable, and we'd kind of fail on the already-done rename. ++ */ ++ if (flock(fd, LOCK_EX | LOCK_NB)) ++ { ++ perror ("Locking tmpfile failed"); ++ return 1; ++ } ++ ++ /* ++ * Deal with the potential that another invocation proceeded all the way to ++ * rename() and process exit while we were between open() and flock(). ++ */ ++ { ++ struct stat st1, st2; ++ if (fstat(fd, &st1) || stat(tmp_filename, &st2)) ++ { ++ perror ("stat of tmpfile failed"); ++ return 1; ++ } ++ if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) ++ { ++ fprintf (stderr, "Another invocation won race\n"); ++ return 1; ++ } ++ } ++ + f = fdopen (fd, "w"); + if (!f) + { +@@ -213,6 +274,14 @@ int main(int argc, char *argv[]) + return 1; + } + ++ ret = ftruncate (fileno (f), GRUBENV_SIZE); ++ if (ret) ++ { ++ perror ("Error truncating tmpfile"); ++ unlink(tmp_filename); ++ return 1; ++ } ++ + ret = fsync (fileno (f)); + if (ret) + { +@@ -221,15 +290,9 @@ int main(int argc, char *argv[]) + return 1; + } + +- ret = fclose (f); +- if (ret) +- { +- perror ("Error closing tmpfile"); +- unlink(tmp_filename); +- return 1; +- } +- + /* ++ * We must not close the file before rename() as that would remove the lock. ++ * + * And finally rename the tmpfile with the new env over the old env, the + * linux kernel guarantees that this is atomic (from a syscall pov). + */ + diff --git a/backport-commands-acpi-Fix-calculation-of-ACPI-tables-address.patch b/backport-commands-acpi-Fix-calculation-of-ACPI-tables-address.patch new file mode 100644 index 0000000..cc2a805 --- /dev/null +++ b/backport-commands-acpi-Fix-calculation-of-ACPI-tables-address.patch @@ -0,0 +1,84 @@ +From 63fc253fc9f148c09d5bb38971edcb50dc090f9d Mon Sep 17 00:00:00 2001 +From: Qiumiao Zhang +Date: Mon, 11 Dec 2023 17:20:25 +0800 +Subject: commands/acpi: Fix calculation of ACPI tables addresses when + processing RSDT and XSDT + +According to the ACPI specification the XSDT Entry field contains an array +of 64-bit physical addresses which points to other DESCRIPTION_HEADERs. However, +the entry_ptr iterator is defined as a 32-bit pointer. It means each 64-bit +entry in the XSDT table is treated as two separate 32-bit entries then. Fix the +issue by using correct addresses sizes when processing RSDT and XSDT tables. + +Reference:https://git.savannah.gnu.org/cgit/grub.git/patch/?id=63fc253fc9f148c09d5bb38971edcb50dc090f9d +Conflict:NA + +Signed-off-by: Qiumiao Zhang +Reviewed-by: Daniel Kiper +--- + grub-core/commands/acpi.c | 33 ++++++++++++++++++++++----------- + 1 file changed, 22 insertions(+), 11 deletions(-) + +diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c +index 1c03446..77be99a 100644 +--- a/grub-core/commands/acpi.c ++++ b/grub-core/commands/acpi.c +@@ -490,12 +490,12 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) + + if (rsdp) + { +- grub_uint32_t *entry_ptr; ++ grub_uint8_t *entry_ptr; + char *exclude = 0; + char *load_only = 0; + char *ptr; +- /* RSDT consists of header and an array of 32-bit pointers. */ +- struct grub_acpi_table_header *rsdt; ++ grub_size_t tbl_addr_size; ++ struct grub_acpi_table_header *table_head; + + exclude = state[0].set ? grub_strdup (state[0].arg) : 0; + if (exclude) +@@ -515,20 +515,31 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) + rev1 = ! rsdp->revision; + rev2 = rsdp->revision; + if (rev2 && ((struct grub_acpi_table_header *) (grub_addr_t) ((struct grub_acpi_rsdp_v20 *) rsdp)->xsdt_addr) != NULL) +- rsdt = (struct grub_acpi_table_header *) (grub_addr_t) ((struct grub_acpi_rsdp_v20 *) rsdp)->xsdt_addr; ++ { ++ /* XSDT consists of header and an array of 64-bit pointers. */ ++ table_head = (struct grub_acpi_table_header *) (grub_addr_t) ((struct grub_acpi_rsdp_v20 *) rsdp)->xsdt_addr; ++ tbl_addr_size = sizeof (((struct grub_acpi_rsdp_v20 *) rsdp)->xsdt_addr); ++ } + else +- rsdt = (struct grub_acpi_table_header *) (grub_addr_t) rsdp->rsdt_addr; ++ { ++ /* RSDT consists of header and an array of 32-bit pointers. */ ++ table_head = (struct grub_acpi_table_header *) (grub_addr_t) rsdp->rsdt_addr; ++ tbl_addr_size = sizeof (rsdp->rsdt_addr); ++ } + + /* Load host tables. */ +- for (entry_ptr = (grub_uint32_t *) (rsdt + 1); +- entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt) +- + rsdt->length); +- entry_ptr++) ++ for (entry_ptr = (grub_uint8_t *) (table_head + 1); ++ entry_ptr < (grub_uint8_t *) (((grub_uint8_t *) table_head) + table_head->length); ++ entry_ptr += tbl_addr_size) + { + char signature[5]; + struct efiemu_acpi_table *table; +- struct grub_acpi_table_header *curtable +- = (struct grub_acpi_table_header *) (grub_addr_t) *entry_ptr; ++ struct grub_acpi_table_header *curtable; ++ if (tbl_addr_size == sizeof (rsdp->rsdt_addr)) ++ curtable = (struct grub_acpi_table_header *) (grub_addr_t) *((grub_uint32_t *) entry_ptr); ++ else ++ curtable = (struct grub_acpi_table_header *) (grub_addr_t) *((grub_uint64_t *) entry_ptr); ++ + signature[4] = 0; + for (i = 0; i < 4;i++) + signature[i] = grub_tolower (curtable->signature[i]); +-- +cgit v1.1 + diff --git a/backport-commands-acpi-Use-xsdt_addr-if-present.patch b/backport-commands-acpi-Use-xsdt_addr-if-present.patch new file mode 100644 index 0000000..c851e38 --- /dev/null +++ b/backport-commands-acpi-Use-xsdt_addr-if-present.patch @@ -0,0 +1,38 @@ +From b2b477e6b23a207321e2f9d7fde1a1624ef318dc Mon Sep 17 00:00:00 2001 +From: Qiumiao Zhang +Date: Tue, 13 Jun 2023 11:17:36 +0800 +Subject: [PATCH] commands/acpi: Use xsdt_addr if present + +According to the ACPI specification, in ACPI 2.0 or later, an +ACPI-compatible OS must use the XSDT if present. So, we should +use xsdt_addr instead of rsdt_addr if xsdt_addr is valid. + +Reference:https://git.savannah.gnu.org/cgit/grub.git/commit/?id=b2b477e6b23a207321e2f9d7fde1a1624ef318dc +Conflict:NA + +Signed-off-by: Qiumiao Zhang +Reviewed-by: Daniel Kiper +--- + grub-core/commands/acpi.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c +index deec4bb43..1c034463c 100644 +--- a/grub-core/commands/acpi.c ++++ b/grub-core/commands/acpi.c +@@ -514,7 +514,11 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) + /* Set revision variables to replicate the same version as host. */ + rev1 = ! rsdp->revision; + rev2 = rsdp->revision; +- rsdt = (struct grub_acpi_table_header *) (grub_addr_t) rsdp->rsdt_addr; ++ if (rev2 && ((struct grub_acpi_table_header *) (grub_addr_t) ((struct grub_acpi_rsdp_v20 *) rsdp)->xsdt_addr) != NULL) ++ rsdt = (struct grub_acpi_table_header *) (grub_addr_t) ((struct grub_acpi_rsdp_v20 *) rsdp)->xsdt_addr; ++ else ++ rsdt = (struct grub_acpi_table_header *) (grub_addr_t) rsdp->rsdt_addr; ++ + /* Load host tables. */ + for (entry_ptr = (grub_uint32_t *) (rsdt + 1); + entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt) +-- +2.27.0 + diff --git a/backport-kern-acpi-Skip-NULL-entries-in-RSDT-and-XSDT.patch b/backport-kern-acpi-Skip-NULL-entries-in-RSDT-and-XSDT.patch new file mode 100644 index 0000000..521ad90 --- /dev/null +++ b/backport-kern-acpi-Skip-NULL-entries-in-RSDT-and-XSDT.patch @@ -0,0 +1,64 @@ +From 48f569c78a496d3e11a4605b0999bc34fa5bc977 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Mon, 25 Sep 2023 13:58:18 +0800 +Subject: kern/acpi: Skip NULL entries in RSDT and XSDT + +During attempts to configure a serial console, a Page Fault Exception +and system reset were encountered, specifically on release 2.12~rc1. +This issue was not present in prior versions and seemed to affect only +a specific machine, potentially pointing to hardware or firmware flaw. + +After investigation, it was discovered that the invalid page access +occurred during the discovery of serial MMIO ports as specified by +ACPI's SPCR table [1]. The recent change uncovered an issue in GRUB's +ACPI driver. + +In certain cases, the XSDT/RSDT root table might contain a NULL entry as +a terminator, depending on how the tables are assembled. GRUB cannot +blindly trust the address in the root table to be valid and should +perform a sanity check for NULL entries. This patch introduces this +simple check. + +This fix is also inspired by a related Linux kernel fix [2]. + +[1] 7b192ec4c term/ns8250: Use ACPI SPCR table when available to configure serial +[2] 0f929fbf0 ACPICA: Tables: Add new mechanism to skip NULL entries in RSDT and XSDT. + +Reference:https://git.savannah.gnu.org/cgit/grub.git/commit/?id=48f569c78a496d3e11a4605b0999bc34fa5bc977 +Conflict:NA + +Signed-off-by: Michael Chang +Reviewed-by: Daniel Kiper +--- + grub-core/kern/acpi.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/grub-core/kern/acpi.c b/grub-core/kern/acpi.c +index c61115d..48ded4e 100644 +--- a/grub-core/kern/acpi.c ++++ b/grub-core/kern/acpi.c +@@ -51,6 +51,10 @@ grub_acpi_rsdt_find_table (struct grub_acpi_table_header *rsdt, const char *sig) + for (; s; s--, ptr++) + { + struct grub_acpi_table_header *tbl; ++ ++ /* Skip NULL entries in RSDT/XSDT. */ ++ if (!ptr->val) ++ continue; + tbl = (struct grub_acpi_table_header *) (grub_addr_t) ptr->val; + if (grub_memcmp (tbl->signature, sig, 4) == 0) + return tbl; +@@ -75,6 +79,10 @@ grub_acpi_xsdt_find_table (struct grub_acpi_table_header *xsdt, const char *sig) + for (; s; s--, ptr++) + { + struct grub_acpi_table_header *tbl; ++ ++ /* Skip NULL entries in RSDT/XSDT. */ ++ if (!ptr->val) ++ continue; + #if GRUB_CPU_SIZEOF_VOID_P != 8 + if (ptr->val >> 32) + continue; +-- +cgit v1.1 + diff --git a/backport-kern-acpi-Use-xsdt_addr-if-present.patch b/backport-kern-acpi-Use-xsdt_addr-if-present.patch new file mode 100644 index 0000000..fb236e6 --- /dev/null +++ b/backport-kern-acpi-Use-xsdt_addr-if-present.patch @@ -0,0 +1,50 @@ +From 4fb58cf0afe83d921e1072d58a4f899696d8fe7e Mon Sep 17 00:00:00 2001 +From: Qiumiao Zhang +Date: Tue, 13 Jun 2023 11:20:51 +0800 +Subject: [PATCH] kern/acpi: Use xsdt_addr if present + +According to the ACPI specification, in ACPI 2.0 or later, an +ACPI-compatible OS must use the XSDT if present. So, we should +use xsdt_addr instead of rsdt_addr if xsdt_addr is valid. + +Reference:https://git.savannah.gnu.org/cgit/grub.git/commit/?id=4fb58cf0afe83d921e1072d58a4f899696d8fe7e +Conflict:NA + +Signed-off-by: Qiumiao Zhang +Reviewed-by: Daniel Kiper +--- + grub-core/kern/acpi.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/grub-core/kern/acpi.c b/grub-core/kern/acpi.c +index 5746ac0..524c402 100644 +--- a/grub-core/kern/acpi.c ++++ b/grub-core/kern/acpi.c +@@ -99,12 +99,6 @@ grub_acpi_find_fadt (void) + if (fadt) + return fadt; + rsdpv2 = grub_machine_acpi_get_rsdpv2 (); +- if (rsdpv2) +- fadt = grub_acpi_rsdt_find_table ((struct grub_acpi_table_header *) +- (grub_addr_t) rsdpv2->rsdpv1.rsdt_addr, +- GRUB_ACPI_FADT_SIGNATURE); +- if (fadt) +- return fadt; + if (rsdpv2 + #if GRUB_CPU_SIZEOF_VOID_P != 8 + && !(rsdpv2->xsdt_addr >> 32) +@@ -115,5 +109,11 @@ grub_acpi_find_fadt (void) + GRUB_ACPI_FADT_SIGNATURE); + if (fadt) + return fadt; ++ if (rsdpv2) ++ fadt = grub_acpi_rsdt_find_table ((struct grub_acpi_table_header *) ++ (grub_addr_t) rsdpv2->rsdpv1.rsdt_addr, ++ GRUB_ACPI_FADT_SIGNATURE); ++ if (fadt) ++ return fadt; + return 0; + } +-- +2.27.0 + diff --git a/backport-util-grub-mount-Check-file-path-sanity.patch b/backport-util-grub-mount-Check-file-path-sanity.patch new file mode 100644 index 0000000..9da1c83 --- /dev/null +++ b/backport-util-grub-mount-Check-file-path-sanity.patch @@ -0,0 +1,34 @@ +From 3f79e3b158bc4aeef94220db676071cfe69e8a5f Mon Sep 17 00:00:00 2001 +From: Qiumiao Zhang +Date: Wed, 25 Oct 2023 11:54:57 +0800 +Subject: util/grub-mount: Check file path sanity + +The function argp_parser() in util/grub-mount.c lacks a check on the +sanity of the file path when parsing parameters. This results in +a segmentation fault if a partition is mounted to a non-existent path. + +Reference:https://git.savannah.gnu.org/cgit/grub.git/commit/?id=3f79e3b158bc4aeef94220db676071cfe69e8a5f +Conflict:NA + +Signed-off-by: Qiumiao Zhang +Reviewed-by: Daniel Kiper +--- + util/grub-mount.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/util/grub-mount.c b/util/grub-mount.c +index c69889d..bf4c8b8 100644 +--- a/util/grub-mount.c ++++ b/util/grub-mount.c +@@ -563,6 +563,8 @@ argp_parser (int key, char *arg, struct argp_state *state) + + images = xrealloc (images, (num_disks + 1) * sizeof (images[0])); + images[num_disks] = grub_canonicalize_file_name (arg); ++ if (images[num_disks] == NULL) ++ grub_util_error (_("cannot find `%s': %s"), arg, strerror (errno)); + num_disks++; + + return 0; +-- +cgit v1.1 + diff --git a/grub.patches b/grub.patches index 9c299ef..2a03b85 100644 --- a/grub.patches +++ b/grub.patches @@ -452,3 +452,11 @@ Patch0451: backport-fs-ntfs-Fix-an-OOB-read-when-parsing-directory-entri.patch Patch0452: backport-fs-ntfs-Fix-an-OOB-read-when-parsing-bitmaps-for-ind.patch Patch0453: backport-fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-label.patch Patch0454: backport-fs-ntfs-Make-code-more-readable.patch +Patch0455: backport-commands-acpi-Use-xsdt_addr-if-present.patch +Patch0456: backport-kern-acpi-Use-xsdt_addr-if-present.patch +Patch0457: backport-util-grub-mount-Check-file-path-sanity.patch +Patch0458: backport-kern-acpi-Skip-NULL-entries-in-RSDT-and-XSDT.patch +Patch0459: backport-commands-acpi-Fix-calculation-of-ACPI-tables-address.patch +Patch0460: backport-CVE-2024-1048-grub-set-bootflag-Conservative-partial-fix.patch +Patch0461: backport-CVE-2024-1048-grub-set-bootflag-More-complete-fix.patch +Patch0462: backport-CVE-2024-1048-grub-set-bootflag-Exit-calmly-when-not.patch diff --git a/grub2.spec b/grub2.spec index 7e46bd4..eb50a08 100644 --- a/grub2.spec +++ b/grub2.spec @@ -8,7 +8,7 @@ Name: grub2 Epoch: 1 Version: 2.04 -Release: 31 +Release: 32 Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -442,6 +442,17 @@ rm -r /boot/grub2.tmp/ || : %{_datadir}/man/man* %changelog +* Wed Mar 6 2024 zhangqiumiao - 1:2.04-32 +- Type:CVE +- CVE:CVE-2024-1048 +- SUG:NA +- DESC:grub-set-bootflag: Fix for CVE-2024-1048 + commands/acpi: Fix calculation of ACPI tables addresses when processing RSDT and XSDT + kern/acpi: Skip NULL entries in RSDT and XSDT + util/grub-mount: Check file path sanity + kern/acpi: Use xsdt_addr if present + commands/acpi: Use xsdt_addrifpresent + * Sun Oct 8 2023 zhangqiumiao - 1:2.04-31 - Type:CVE - CVE:CVE-2023-4692 CVE-2023-4693 -- Gitee