fix CVE-2024-1048 and backport some patches from upstream
Signed-off-by: Qiumiao Zhang <zhangqiumiao1@huawei.com> (cherry picked from commit e62f9657ab28a168cd5badeccf75370414ad34f5)
This commit is contained in:
parent
35b4aa0aac
commit
90f546b2c1
@ -0,0 +1,153 @@
|
|||||||
|
From 77f0ca016ae45fd5471cc89ac472868d94b8ed67 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Solar Designer <solar@openwall.com>
|
||||||
|
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 <solar@openwall.com>
|
||||||
|
---
|
||||||
|
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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
+#include <sys/stat.h>
|
||||||
|
+#include <sys/resource.h>
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Solar Designer <solar@openwall.com>
|
||||||
|
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 <solar@openwall.com>
|
||||||
|
---
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
191
backport-CVE-2024-1048-grub-set-bootflag-More-complete-fix.patch
Normal file
191
backport-CVE-2024-1048-grub-set-bootflag-More-complete-fix.patch
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Solar Designer <solar@openwall.com>
|
||||||
|
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 <solar@openwall.com>
|
||||||
|
---
|
||||||
|
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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
+#include <sys/file.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
|
||||||
|
@@ -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).
|
||||||
|
*/
|
||||||
|
|
||||||
@ -0,0 +1,84 @@
|
|||||||
|
From 63fc253fc9f148c09d5bb38971edcb50dc090f9d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Qiumiao Zhang <zhangqiumiao1@huawei.com>
|
||||||
|
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 <zhangqiumiao1@huawei.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
64
backport-kern-acpi-Skip-NULL-entries-in-RSDT-and-XSDT.patch
Normal file
64
backport-kern-acpi-Skip-NULL-entries-in-RSDT-and-XSDT.patch
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
From 48f569c78a496d3e11a4605b0999bc34fa5bc977 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Chang <mchang@suse.com>
|
||||||
|
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 <mchang@suse.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
34
backport-util-grub-mount-Check-file-path-sanity.patch
Normal file
34
backport-util-grub-mount-Check-file-path-sanity.patch
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
From 3f79e3b158bc4aeef94220db676071cfe69e8a5f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Qiumiao Zhang <zhangqiumiao1@huawei.com>
|
||||||
|
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 <zhangqiumiao1@huawei.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
@ -343,3 +343,9 @@ Patch0343: backport-fs-ntfs-Make-code-more-readable.patch
|
|||||||
Patch0344: add-TPCM-support-with-ipmi-channel.patch
|
Patch0344: add-TPCM-support-with-ipmi-channel.patch
|
||||||
Patch0345: skip-verification-when-not-loading-grub.cfg.patch
|
Patch0345: skip-verification-when-not-loading-grub.cfg.patch
|
||||||
Patch0346: 1008-loongarch-Disable-relaxation-relocations.patch
|
Patch0346: 1008-loongarch-Disable-relaxation-relocations.patch
|
||||||
|
Patch0347: backport-util-grub-mount-Check-file-path-sanity.patch
|
||||||
|
Patch0348: backport-kern-acpi-Skip-NULL-entries-in-RSDT-and-XSDT.patch
|
||||||
|
Patch0349: backport-commands-acpi-Fix-calculation-of-ACPI-tables-address.patch
|
||||||
|
Patch0350: backport-CVE-2024-1048-grub-set-bootflag-Conservative-partial-fix.patch
|
||||||
|
Patch0351: backport-CVE-2024-1048-grub-set-bootflag-More-complete-fix.patch
|
||||||
|
Patch0352: backport-CVE-2024-1048-grub-set-bootflag-Exit-calmly-when-not.patch
|
||||||
|
|||||||
11
grub2.spec
11
grub2.spec
@ -14,7 +14,7 @@
|
|||||||
Name: grub2
|
Name: grub2
|
||||||
Epoch: 1
|
Epoch: 1
|
||||||
Version: 2.06
|
Version: 2.06
|
||||||
Release: 43
|
Release: 44
|
||||||
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/
|
||||||
@ -448,6 +448,15 @@ fi
|
|||||||
%{_datadir}/man/man*
|
%{_datadir}/man/man*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Sat Mar 2 2024 zhangqiumiao <zhangqiumiao1@huawei.com> - 1:2.06-44
|
||||||
|
- 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
|
||||||
|
|
||||||
* Mon Dec 25 2023 mengyingkun <mengyingkun@loongson.cn> - 1:2.06-43
|
* Mon Dec 25 2023 mengyingkun <mengyingkun@loongson.cn> - 1:2.06-43
|
||||||
- Type:requirement
|
- Type:requirement
|
||||||
- CVE:NA
|
- CVE:NA
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user