Skip to content
Snippets Groups Projects
Commit d5d567ea authored by Rocky Automation's avatar Rocky Automation :tv:
Browse files

import grub2-2.02-162.el8_10

parent 23427dc3
No related merge requests found
Showing
with 1246 additions and 6 deletions
810b3798d316394f94096ec2797909dbf23c858e48f7b3830826b8daa06b7b0f SOURCES/grub-2.02.tar.xz
224f7059328df355810fee105e79af2e9fc7e520504f9f545c08ca4e32e8c200 SOURCES/redhatsecureboot301.cer
3f564ef41227562f9ea45c3fd8f96bea9ab8205247ef72dd025fdcd728373a00 SOURCES/redhatsecureboot502.cer
8f435a96261e571ed557f9243e7fe7db5b93bc8f7eefcfc5b0c154d5d29292fb SOURCES/redhatsecureboot601.cer
c6d43c94bcbc73c81df3026bc201a88886b8ceebe98188cdb69bdd61bd6be287 SOURCES/redhatsecureboot701.cer
9996c73616ee42f13396c9abfb4b646b538c3c80940474b710afdbe53bf17d32 SOURCES/redhatsecurebootca3.cer
40175d4c7c5ab4bd753a493f47952f1d8dcf1c219b836968a693e48bd4766135 SOURCES/redhatsecurebootca5.cer
1fddd06b4854598a18ff3742c472c6a5c609929ce1ab74ec9901812aaf30be02 SOURCES/theme.tar.bz2
122b9c470f29b70223b0e07404a6dfa7f339fcfa6ae74c024f478945af7a9a63 SOURCES/unifont-5.1.20080820.pcf.gz
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Sat, 15 Jun 2024 02:33:08 +0100
Subject: [PATCH] misc: Implement grub_strlcpy()
grub_strlcpy() acts the same way as strlcpy() does on most *NIX,
returning the length of src and ensuring dest is always NUL
terminated except when size is 0.
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
include/grub/misc.h | 39 +++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/include/grub/misc.h b/include/grub/misc.h
index 1b722c818..88fc2a6b0 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -72,6 +72,45 @@ grub_stpcpy (char *dest, const char *src)
return d - 1;
}
+static inline grub_size_t
+grub_strlcpy (char *dest, const char *src, grub_size_t size)
+{
+ char *d = dest;
+ grub_size_t res = 0;
+ /*
+ * We do not subtract one from size here to avoid dealing with underflowing
+ * the value, which is why to_copy is always checked to be greater than one
+ * throughout this function.
+ */
+ grub_size_t to_copy = size;
+
+ /* Copy size - 1 bytes to dest. */
+ if (to_copy > 1)
+ while ((*d++ = *src++) != '\0' && ++res && --to_copy > 1)
+ ;
+
+ /*
+ * NUL terminate if size != 0. The previous step may have copied a NUL byte
+ * if it reached the end of the string, but we know dest[size - 1] must always
+ * be a NUL byte.
+ */
+ if (size != 0)
+ dest[size - 1] = '\0';
+
+ /* If there is still space in dest, but are here, we reached the end of src. */
+ if (to_copy > 1)
+ return res;
+
+ /*
+ * If we haven't reached the end of the string, iterate through to determine
+ * the strings total length.
+ */
+ while (*src++ != '\0' && ++res)
+ ;
+
+ return res;
+}
+
/* XXX: If grub_memmove is too slow, we must implement grub_memcpy. */
static inline void *
grub_memcpy (void *dest, const void *src, grub_size_t n)
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Sun, 12 May 2024 02:03:33 +0100
Subject: [PATCH] fs/ufs: Fix a heap OOB write
grub_strcpy() was used to copy a symlink name from the filesystem
image to a heap allocated buffer. This led to a OOB write to adjacent
heap allocations. Fix by using grub_strlcpy().
Fixes: CVE-2024-45781
Reported-by: B Horn <b@horn.uk>
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/ufs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c
index 293f027aa..0c2004fd7 100644
--- a/grub-core/fs/ufs.c
+++ b/grub-core/fs/ufs.c
@@ -463,7 +463,7 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino)
/* Check against zero is paylindromic, no need to swap. */
if (data->inode.nblocks == 0
&& INODE_SIZE (data) <= sizeof (data->inode.symlink))
- grub_strcpy (symlink, (char *) data->inode.symlink);
+ grub_strlcpy (symlink, (char *) data->inode.symlink, sz);
else
{
if (grub_ufs_read_file (data, 0, 0, 0, sz, symlink) < 0)
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Sun, 12 May 2024 02:48:33 +0100
Subject: [PATCH] fs/hfs: Fix stack OOB write with grub_strcpy()
Replaced with grub_strlcpy().
Fixes: CVE-2024-45782
Fixes: CVE-2024-56737
Fixes: https://savannah.gnu.org/bugs/?66599
Reported-by: B Horn <b@horn.uk>
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/hfs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c
index 49d1831c8..44859fe43 100644
--- a/grub-core/fs/hfs.c
+++ b/grub-core/fs/hfs.c
@@ -379,7 +379,7 @@ grub_hfs_mount (grub_disk_t disk)
volume name. */
key.parent_dir = grub_cpu_to_be32_compile_time (1);
key.strlen = data->sblock.volname[0];
- grub_strcpy ((char *) key.str, (char *) (data->sblock.volname + 1));
+ grub_strlcpy ((char *) key.str, (char *) (data->sblock.volname + 1), sizeof (key.str));
if (grub_hfs_find_node (data, (char *) &key, data->cat_root,
0, (char *) &dir, sizeof (dir)) == 0)
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Sun, 12 May 2024 02:47:54 +0100
Subject: [PATCH] fs/tar: Initialize name in grub_cpio_find_file()
It was possible to iterate through grub_cpio_find_file() without
allocating name and not setting mode to GRUB_ARCHELP_ATTR_END, which
would cause the uninitialized value for name to be used as an argument
for canonicalize() in grub_archelp_dir().
Reported-by: B Horn <b@horn.uk>
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/tar.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/grub-core/fs/tar.c b/grub-core/fs/tar.c
index 4864451e1..f1e6571c2 100644
--- a/grub-core/fs/tar.c
+++ b/grub-core/fs/tar.c
@@ -78,6 +78,7 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
int reread = 0, have_longname = 0, have_longlink = 0;
data->hofs = data->next_hofs;
+ *name = NULL;
for (reread = 0; reread < 3; reread++)
{
@@ -202,6 +203,10 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
}
return GRUB_ERR_NONE;
}
+
+ if (*name == NULL)
+ return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive");
+
return GRUB_ERR_NONE;
}
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lidong Chen <lidong.chen@oracle.com>
Date: Fri, 22 Nov 2024 06:27:58 +0000
Subject: [PATCH] fs/tar: Integer overflow leads to heap OOB write
Both namesize and linksize are derived from hd.size, a 12-digit octal
number parsed by read_number(). Later direct arithmetic calculation like
"namesize + 1" and "linksize + 1" may exceed the maximum value of
grub_size_t leading to heap OOB write. This patch fixes the issue by
using grub_add() and checking for an overflow.
Fixes: CVE-2024-45780
Reported-by: Nils Langius <nils@langius.de>
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Alec Brown <alec.r.brown@oracle.com>
---
grub-core/fs/tar.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/grub-core/fs/tar.c b/grub-core/fs/tar.c
index f1e6571c2..28baa5845 100644
--- a/grub-core/fs/tar.c
+++ b/grub-core/fs/tar.c
@@ -25,6 +25,7 @@
#include <grub/mm.h>
#include <grub/dl.h>
#include <grub/i18n.h>
+#include <grub/safemath.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -76,6 +77,7 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
{
struct head hd;
int reread = 0, have_longname = 0, have_longlink = 0;
+ grub_size_t sz;
data->hofs = data->next_hofs;
*name = NULL;
@@ -98,7 +100,11 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
{
grub_err_t err;
grub_size_t namesize = read_number (hd.size, sizeof (hd.size));
- *name = grub_malloc (namesize + 1);
+
+ if (grub_add (namesize, 1, &sz))
+ return grub_error (GRUB_ERR_BAD_FS, N_("name size overflow"));
+
+ *name = grub_malloc (sz);
if (*name == NULL)
return grub_errno;
err = grub_disk_read (data->disk, 0,
@@ -118,15 +124,19 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
{
grub_err_t err;
grub_size_t linksize = read_number (hd.size, sizeof (hd.size));
- if (data->linkname_alloc < linksize + 1)
+
+ if (grub_add (linksize, 1, &sz))
+ return grub_error (GRUB_ERR_BAD_FS, N_("link size overflow"));
+
+ if (data->linkname_alloc < sz)
{
char *n;
- n = grub_calloc (2, linksize + 1);
+ n = grub_calloc (2, sz);
if (!n)
return grub_errno;
grub_free (data->linkname);
data->linkname = n;
- data->linkname_alloc = 2 * (linksize + 1);
+ data->linkname_alloc = 2 * (sz);
}
err = grub_disk_read (data->disk, 0,
@@ -149,7 +159,10 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
while (extra_size < sizeof (hd.prefix)
&& hd.prefix[extra_size])
extra_size++;
- *name = grub_malloc (sizeof (hd.name) + extra_size + 2);
+
+ if (grub_add (sizeof (hd.name) + 2, extra_size, &sz))
+ return grub_error (GRUB_ERR_BAD_FS, N_("long name size overflow"));
+ *name = grub_malloc (sz);
if (*name == NULL)
return grub_errno;
if (hd.prefix[0])
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Sun, 12 May 2024 06:15:03 +0100
Subject: [PATCH] fs/f2fs: Set a grub_errno if mount fails
It was previously possible for grub_errno to not be set when
grub_f2fs_mount() failed if nat_bitmap_ptr() returned NULL.
This issue is solved by ensuring a grub_errno is set in the fail case.
Reported-by: B Horn <b@horn.uk>
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/f2fs.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c
index 07ea34196..706e595d3 100644
--- a/grub-core/fs/f2fs.c
+++ b/grub-core/fs/f2fs.c
@@ -871,6 +871,9 @@ grub_f2fs_mount (grub_disk_t disk)
return data;
fail:
+ if (grub_errno == GRUB_ERR_NONE)
+ grub_error (GRUB_ERR_BAD_FS, "not a F2FS filesystem");
+
grub_free (data);
return NULL;
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Sun, 12 May 2024 06:22:51 +0100
Subject: [PATCH] fs/hfsplus: Set a grub_errno if mount fails
It was possible for mount to fail but not set grub_errno. This led to
a possible double decrement of the module reference count if the NULL
page was mapped.
Fixing in general as a similar bug was fixed in commit 61b13c187
(fs/hfsplus: Set grub_errno to prevent NULL pointer access) and there
are likely more variants around.
Fixes: CVE-2024-45783
Reported-by: B Horn <b@horn.uk>
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/hfsplus.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
index 8c0c80473..2edb1649d 100644
--- a/grub-core/fs/hfsplus.c
+++ b/grub-core/fs/hfsplus.c
@@ -392,7 +392,7 @@ grub_hfsplus_mount (grub_disk_t disk)
fail:
- if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
+ if (grub_errno == GRUB_ERR_OUT_OF_RANGE || grub_errno == GRUB_ERR_NONE)
grub_error (GRUB_ERR_BAD_FS, "not a HFS+ filesystem");
grub_free (data);
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Sun, 12 May 2024 06:37:08 +0100
Subject: [PATCH] fs/iso9660: Set a grub_errno if mount fails
It was possible for a grub_errno to not be set if mount of an ISO 9660
filesystem failed when set_rockridge() returned 0.
This isn't known to be exploitable as the other filesystems due to
filesystem helper checking the requested file type. Though fixing
as a precaution.
Reported-by: B Horn <b@horn.uk>
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/iso9660.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c
index a4403e29d..736d56770 100644
--- a/grub-core/fs/iso9660.c
+++ b/grub-core/fs/iso9660.c
@@ -491,6 +491,9 @@ grub_iso9660_mount (grub_disk_t disk)
return data;
fail:
+ if (grub_errno == GRUB_ERR_NONE)
+ grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem");
+
grub_free (data);
return 0;
}
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 31 May 2024 15:14:42 +0800
Subject: [PATCH] fs/iso9660: Fix invalid free
The ctx->filename can point to either a string literal or a dynamically
allocated string. The ctx->filename_alloc field is used to indicate the
type of allocation.
An issue has been identified where ctx->filename is reassigned to
a string literal in susp_iterate_dir() but ctx->filename_alloc is not
correctly handled. This oversight causes a memory leak and an invalid
free operation later.
The fix involves checking ctx->filename_alloc, freeing the allocated
string if necessary and clearing ctx->filename_alloc for string literals.
Reported-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Michael Chang <mchang@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/iso9660.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c
index 736d56770..cf17702e2 100644
--- a/grub-core/fs/iso9660.c
+++ b/grub-core/fs/iso9660.c
@@ -568,9 +568,19 @@ susp_iterate_dir (struct grub_iso9660_susp_entry *entry,
filename type is stored. */
/* FIXME: Fix this slightly improper cast. */
if (entry->data[0] & GRUB_ISO9660_RR_DOT)
- ctx->filename = (char *) ".";
+ {
+ if (ctx->filename_alloc)
+ grub_free (ctx->filename);
+ ctx->filename_alloc = 0;
+ ctx->filename = (char *) ".";
+ }
else if (entry->data[0] & GRUB_ISO9660_RR_DOTDOT)
- ctx->filename = (char *) "..";
+ {
+ if (ctx->filename_alloc)
+ grub_free (ctx->filename);
+ ctx->filename_alloc = 0;
+ ctx->filename = (char *) "..";
+ }
else if (entry->len >= 5)
{
grub_size_t off = 0, csize = 1;
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lidong Chen <lidong.chen@oracle.com>
Date: Fri, 22 Nov 2024 06:27:59 +0000
Subject: [PATCH] fs/jfs: Fix OOB read in jfs_getent()
The JFS fuzzing revealed an OOB read in grub_jfs_getent(). The crash
was caused by an invalid leaf nodes count, diro->dirpage->header.count,
which was larger than the maximum number of leaf nodes allowed in an
inode. This fix is to ensure that the leaf nodes count is validated in
grub_jfs_opendir() before calling grub_jfs_getent().
On the occasion replace existing raw numbers with newly defined constant.
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Alec Brown <alec.r.brown@oracle.com>
---
grub-core/fs/jfs.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c
index 20d966abf..d4207eb64 100644
--- a/grub-core/fs/jfs.c
+++ b/grub-core/fs/jfs.c
@@ -41,6 +41,12 @@ GRUB_MOD_LICENSE ("GPLv3+");
#define GRUB_JFS_TREE_LEAF 2
+/*
+ * Define max entries stored in-line in an inode.
+ * https://jfs.sourceforge.net/project/pub/jfslayout.pdf
+ */
+#define GRUB_JFS_INODE_INLINE_ENTRIES 8
+
struct grub_jfs_sblock
{
/* The magic for JFS. It should contain the string "JFS1". */
@@ -203,9 +209,9 @@ struct grub_jfs_inode
grub_uint8_t freecnt;
grub_uint8_t freelist;
grub_uint32_t idotdot;
- grub_uint8_t sorted[8];
+ grub_uint8_t sorted[GRUB_JFS_INODE_INLINE_ENTRIES];
} header;
- struct grub_jfs_leaf_dirent dirents[8];
+ struct grub_jfs_leaf_dirent dirents[GRUB_JFS_INODE_INLINE_ENTRIES];
} GRUB_PACKED dir;
/* Fast symlink. */
struct
@@ -453,6 +459,13 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode)
/* Check if the entire tree is contained within the inode. */
if (inode->file.tree.flags & GRUB_JFS_TREE_LEAF)
{
+ if (inode->dir.header.count > GRUB_JFS_INODE_INLINE_ENTRIES)
+ {
+ grub_free (diro);
+ grub_error (GRUB_ERR_BAD_FS, N_("invalid JFS inode"));
+ return 0;
+ }
+
diro->leaf = inode->dir.dirents;
diro->next_leaf = (struct grub_jfs_leaf_next_dirent *) de;
diro->sorted = inode->dir.header.sorted;
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lidong Chen <lidong.chen@oracle.com>
Date: Fri, 22 Nov 2024 06:28:00 +0000
Subject: [PATCH] fs/jfs: Fix OOB read caused by invalid dir slot index
While fuzz testing JFS with ASAN enabled an OOB read was detected in
grub_jfs_opendir(). The issue occurred due to an invalid directory slot
index in the first entry of the sorted directory slot array in the inode
directory header. The fix ensures the slot index is validated before
accessing it. Given that an internal or a leaf node in a directory B+
tree is a 4 KiB in size and each directory slot is always 32 bytes, the
max number of slots in a node is 128. The validation ensures that the
slot index doesn't exceed this limit.
[1] https://jfs.sourceforge.net/project/pub/jfslayout.pdf
JFS will allocate 4K of disk space for an internal node of the B+ tree.
An internal node looks the same as a leaf node.
- page 10
Fixed number of Directory Slots depending on the size of the node. These are
the slots to be used for storing the directory slot array and the directory
entries or router entries. A directory slot is always 32 bytes.
...
A Directory Slot Array which is a sorted array of indices to the directory
slots that are currently in use.
...
An internal or a leaf node in the directory B+ tree is a 4K page.
- page 25
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Alec Brown <alec.r.brown@oracle.com>
---
grub-core/fs/jfs.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c
index d4207eb64..60dd62fe2 100644
--- a/grub-core/fs/jfs.c
+++ b/grub-core/fs/jfs.c
@@ -46,6 +46,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
* https://jfs.sourceforge.net/project/pub/jfslayout.pdf
*/
#define GRUB_JFS_INODE_INLINE_ENTRIES 8
+#define GRUB_JFS_DIR_MAX_SLOTS 128
struct grub_jfs_sblock
{
@@ -481,6 +482,14 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode)
return 0;
}
+ if (inode->dir.header.sorted[0] >= GRUB_JFS_DIR_MAX_SLOTS)
+ {
+ grub_error (GRUB_ERR_BAD_FS, N_("invalid directory slot index"));
+ grub_free (diro->dirpage);
+ grub_free (diro);
+ return 0;
+ }
+
blk = grub_le_to_cpu32 (de[inode->dir.header.sorted[0]].ex.blk2);
blk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS);
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lidong Chen <lidong.chen@oracle.com>
Date: Mon, 16 Dec 2024 20:22:39 +0000
Subject: [PATCH] fs/jfs: Use full 40 bits offset and address for a data extent
An extent's logical offset and address are represented as a 40-bit value
split into two parts: the most significant 8 bits and the least
significant 32 bits. Currently the JFS code uses only the least
significant 32 bits value for offsets and addresses assuming the data
size will never exceed the 32-bit range. This approach ignores the most
significant 8 bits potentially leading to incorrect offsets and
addresses for larger values. The patch fixes it by incorporating the
most significant 8 bits into the calculation to get the full 40-bits
value for offsets and addresses.
https://jfs.sourceforge.net/project/pub/jfslayout.pdf
"off1,off2 is a 40-bit field, containing the logical offset of the first
block in the extent.
...
addr1,addr2 is a 40-bit field, containing the address of the extent."
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
Reviewed-by: Alec Brown <alec.r.brown@oracle.com>
Reviewed-by: Ross Philipson <ross.philipson@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/jfs.c | 41 +++++++++++++++++++++++++++++------------
1 file changed, 29 insertions(+), 12 deletions(-)
diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c
index 60dd62fe2..8a908f00d 100644
--- a/grub-core/fs/jfs.c
+++ b/grub-core/fs/jfs.c
@@ -265,6 +265,20 @@ static grub_dl_t my_mod;
static grub_err_t grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino);
+/*
+ * An extent's offset, physical and logical, is represented as a 40-bit value.
+ * This 40-bit value is split into two parts:
+ * - offset1: the most signficant 8 bits of the offset,
+ * - offset2: the least significant 32 bits of the offset.
+ *
+ * This function calculates and returns the 64-bit offset of an extent.
+ */
+static grub_uint64_t
+get_ext_offset (grub_uint8_t offset1, grub_uint32_t offset2)
+{
+ return (((grub_uint64_t) offset1 << 32) | grub_le_to_cpu32 (offset2));
+}
+
static grub_int64_t
getblk (struct grub_jfs_treehead *treehead,
struct grub_jfs_tree_extent *extents,
@@ -274,22 +288,25 @@ getblk (struct grub_jfs_treehead *treehead,
{
int found = -1;
int i;
+ grub_uint64_t ext_offset, ext_blk;
for (i = 0; i < grub_le_to_cpu16 (treehead->count) - 2 &&
i < max_extents; i++)
{
+ ext_offset = get_ext_offset (extents[i].offset1, extents[i].offset2);
+ ext_blk = get_ext_offset (extents[i].extent.blk1, extents[i].extent.blk2);
+
if (treehead->flags & GRUB_JFS_TREE_LEAF)
{
/* Read the leafnode. */
- if (grub_le_to_cpu32 (extents[i].offset2) <= blk
+ if (ext_offset <= blk
&& ((grub_le_to_cpu16 (extents[i].extent.length))
+ (extents[i].extent.length2 << 16)
- + grub_le_to_cpu32 (extents[i].offset2)) > blk)
- return (blk - grub_le_to_cpu32 (extents[i].offset2)
- + grub_le_to_cpu32 (extents[i].extent.blk2));
+ + ext_offset) > blk)
+ return (blk - ext_offset + ext_blk);
}
else
- if (blk >= grub_le_to_cpu32 (extents[i].offset2))
+ if (blk >= ext_offset)
found = i;
}
@@ -307,10 +324,9 @@ getblk (struct grub_jfs_treehead *treehead,
return -1;
if (!grub_disk_read (data->disk,
- ((grub_disk_addr_t) grub_le_to_cpu32 (extents[found].extent.blk2))
- << (grub_le_to_cpu16 (data->sblock.log2_blksz)
- - GRUB_DISK_SECTOR_BITS), 0,
- sizeof (*tree), (char *) tree))
+ (grub_disk_addr_t) ext_blk
+ << (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS),
+ 0, sizeof (*tree), (char *) tree))
{
if (grub_memcmp (&tree->treehead, treehead, sizeof (struct grub_jfs_treehead)) ||
grub_memcmp (&tree->extents, extents, 254 * sizeof (struct grub_jfs_tree_extent)))
@@ -361,7 +377,7 @@ grub_jfs_read_inode (struct grub_jfs_data *data, grub_uint32_t ino,
sizeof (iag_inodes), &iag_inodes))
return grub_errno;
- inoblk = grub_le_to_cpu32 (iag_inodes[inoext].blk2);
+ inoblk = get_ext_offset (iag_inodes[inoext].blk1, iag_inodes[inoext].blk2);
inoblk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz)
- GRUB_DISK_SECTOR_BITS);
inoblk += inonum;
@@ -490,7 +506,8 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode)
return 0;
}
- blk = grub_le_to_cpu32 (de[inode->dir.header.sorted[0]].ex.blk2);
+ blk = get_ext_offset (de[inode->dir.header.sorted[0]].ex.blk1,
+ de[inode->dir.header.sorted[0]].ex.blk2);
blk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS);
/* Read in the nodes until we are on the leaf node level. */
@@ -508,7 +525,7 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode)
de = (struct grub_jfs_internal_dirent *) diro->dirpage->dirent;
index = diro->dirpage->sorted[diro->dirpage->header.sindex * 32];
- blk = (grub_le_to_cpu32 (de[index].ex.blk2)
+ blk = (get_ext_offset (de[index].ex.blk1, de[index].ex.blk2)
<< (grub_le_to_cpu16 (data->sblock.log2_blksz)
- GRUB_DISK_SECTOR_BITS));
} while (!(diro->dirpage->header.flags & GRUB_JFS_TREE_LEAF));
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lidong Chen <lidong.chen@oracle.com>
Date: Mon, 16 Dec 2024 20:22:40 +0000
Subject: [PATCH] fs/jfs: Inconsistent signed/unsigned types usage in return
values
The getblk() returns a value of type grub_int64_t which is assigned to
iagblk and inoblk, both of type grub_uint64_t, in grub_jfs_read_inode()
via grub_jfs_blkno(). This patch fixes the type mismatch in the
functions. Additionally, the getblk() will return 0 instead of -1 on
failure cases. This change is safe because grub_errno is always set in
getblk() to indicate errors and it is later checked in the callers.
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
Reviewed-by: Alec Brown <alec.r.brown@oracle.com>
Reviewed-by: Ross Philipson <ross.philipson@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/jfs.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c
index 8a908f00d..739b3c540 100644
--- a/grub-core/fs/jfs.c
+++ b/grub-core/fs/jfs.c
@@ -279,7 +279,7 @@ get_ext_offset (grub_uint8_t offset1, grub_uint32_t offset2)
return (((grub_uint64_t) offset1 << 32) | grub_le_to_cpu32 (offset2));
}
-static grub_int64_t
+static grub_uint64_t
getblk (struct grub_jfs_treehead *treehead,
struct grub_jfs_tree_extent *extents,
int max_extents,
@@ -290,6 +290,8 @@ getblk (struct grub_jfs_treehead *treehead,
int i;
grub_uint64_t ext_offset, ext_blk;
+ grub_errno = GRUB_ERR_NONE;
+
for (i = 0; i < grub_le_to_cpu16 (treehead->count) - 2 &&
i < max_extents; i++)
{
@@ -312,7 +314,7 @@ getblk (struct grub_jfs_treehead *treehead,
if (found != -1)
{
- grub_int64_t ret = -1;
+ grub_uint64_t ret = 0;
struct
{
struct grub_jfs_treehead treehead;
@@ -321,7 +323,7 @@ getblk (struct grub_jfs_treehead *treehead,
tree = grub_zalloc (sizeof (*tree));
if (!tree)
- return -1;
+ return 0;
if (!grub_disk_read (data->disk,
(grub_disk_addr_t) ext_blk
@@ -334,19 +336,20 @@ getblk (struct grub_jfs_treehead *treehead,
else
{
grub_error (GRUB_ERR_BAD_FS, "jfs: infinite recursion detected");
- ret = -1;
+ ret = 0;
}
}
grub_free (tree);
return ret;
}
- return -1;
+ grub_error (GRUB_ERR_READ_ERROR, "jfs: block %" PRIuGRUB_UINT64_T " not found", blk);
+ return 0;
}
/* Get the block number for the block BLK in the node INODE in the
mounted filesystem DATA. */
-static grub_int64_t
+static grub_uint64_t
grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode,
grub_uint64_t blk)
{
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 31 May 2024 15:14:23 +0800
Subject: [PATCH] fs/ext2: Fix out-of-bounds read for inline extents
When inline extents are used, i.e. the extent tree depth equals zero,
a maximum of four entries can fit into the inode's data block. If the
extent header states a number of entries greater than four the current
ext2 implementation causes an out-of-bounds read. Fix this issue by
capping the number of extents to four when reading inline extents.
Reported-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Michael Chang <mchang@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/ext2.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
index 3d59cf131..de5c268a9 100644
--- a/grub-core/fs/ext2.c
+++ b/grub-core/fs/ext2.c
@@ -473,6 +473,8 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
struct grub_ext4_extent *ext;
int i;
grub_disk_addr_t ret;
+ grub_uint16_t nent;
+ const grub_uint16_t max_inline_ext = sizeof (inode->blocks) / sizeof (*ext) - 1; /* Minus 1 extent header. */
leaf = grub_ext4_find_leaf (data, (struct grub_ext4_extent_header *) inode->blocks.dir_blocks, fileblock);
if (! leaf)
@@ -482,7 +484,13 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
}
ext = (struct grub_ext4_extent *) (leaf + 1);
- for (i = 0; i < grub_le_to_cpu16 (leaf->entries); i++)
+
+ nent = grub_le_to_cpu16 (leaf->entries);
+
+ if (leaf->depth == 0)
+ nent = grub_min (nent, max_inline_ext);
+
+ for (i = 0; i < nent; i++)
{
if (fileblock < grub_le_to_cpu32 (ext[i].block))
break;
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 3 Jun 2024 12:12:06 +0800
Subject: [PATCH] fs/ntfs: Fix out-of-bounds read
When parsing NTFS file records the presence of the 0xFF marker indicates
the end of the attribute list. This value signifies that there are no
more attributes to process.
However, when the end marker is missing due to corrupted metadata the
loop continues to read beyond the attribute list resulting in out-of-bounds
reads and potentially entering an infinite loop.
This patch adds a check to provide a stop condition for the loop ensuring
it stops at the end of the attribute list or at the end of the Master File
Table. This guards against out-of-bounds reads and prevents infinite loops.
Reported-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Michael Chang <mchang@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/ntfs.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
index d3fb5b48f..9c4d9be98 100644
--- a/grub-core/fs/ntfs.c
+++ b/grub-core/fs/ntfs.c
@@ -139,6 +139,8 @@ free_attr (struct grub_ntfs_attr *at)
static grub_uint8_t *
find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
{
+ grub_uint8_t *mft_end;
+
if (at->flags & GRUB_NTFS_AF_ALST)
{
retry:
@@ -191,7 +193,8 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
return NULL;
}
at->attr_cur = at->attr_nxt;
- while (*at->attr_cur != 0xFF)
+ mft_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
+ while (at->attr_cur < mft_end && *at->attr_cur != 0xFF)
{
at->attr_nxt += u16at (at->attr_cur, 4);
if (*at->attr_cur == GRUB_NTFS_AT_ATTRIBUTE_LIST)
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Tue, 7 Jan 2025 11:38:34 +0000
Subject: [PATCH] fs/ntfs: Track the end of the MFT attribute buffer
The end of the attribute buffer should be stored alongside the rest of
the attribute struct as right now it is not possible to implement bounds
checking when accessing attributes sequentially.
This is done via:
- updating init_attr() to set at->end and check is is not initially out of bounds,
- implementing checks as init_attr() had its type change in its callers,
- updating the value of at->end when needed.
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/ntfs.c | 34 ++++++++++++++++++++++++++++------
include/grub/ntfs.h | 1 +
2 files changed, 29 insertions(+), 6 deletions(-)
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
index 9c4d9be98..699cdb3c0 100644
--- a/grub-core/fs/ntfs.c
+++ b/grub-core/fs/ntfs.c
@@ -119,13 +119,20 @@ static grub_err_t read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa,
grub_disk_read_hook_t read_hook,
void *read_hook_data);
-static void
+static grub_err_t
init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft)
{
at->mft = mft;
at->flags = (mft == &mft->data->mmft) ? GRUB_NTFS_AF_MMFT : 0;
at->attr_nxt = mft->buf + first_attr_off (mft->buf);
+ at->end = mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR);
+
+ if (at->attr_nxt > at->end)
+ return grub_error (GRUB_ERR_BAD_FS, "attributes start outside the MFT");
+
at->attr_end = at->emft_buf = at->edat_buf = at->sbuf = NULL;
+
+ return GRUB_ERR_NONE;
}
static void
@@ -239,6 +246,10 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
pa_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
}
at->flags |= GRUB_NTFS_AF_ALST;
+
+ /* From this point on pa_end is the end of the buffer */
+ at->end = pa_end;
+
while (at->attr_nxt < at->attr_end)
{
if ((*at->attr_nxt == attr) || (attr == 0))
@@ -298,7 +309,9 @@ locate_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft,
{
grub_uint8_t *pa;
- init_attr (at, mft);
+ if (init_attr (at, mft) != GRUB_ERR_NONE)
+ return NULL;
+
pa = find_attr (at, attr);
if (pa == NULL)
return NULL;
@@ -314,7 +327,8 @@ locate_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft,
}
grub_errno = GRUB_ERR_NONE;
free_attr (at);
- init_attr (at, mft);
+ if (init_attr (at, mft) != GRUB_ERR_NONE)
+ return NULL;
pa = find_attr (at, attr);
}
return pa;
@@ -585,7 +599,7 @@ init_file (struct grub_ntfs_file *mft, grub_uint64_t mftno)
mft->attr.attr_end = 0; /* Don't jump to attribute list */
}
else
- init_attr (&mft->attr, mft);
+ return init_attr (&mft->attr, mft);
return 0;
}
@@ -807,7 +821,9 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
bmp = NULL;
at = &attr;
- init_attr (at, mft);
+ if (init_attr (at, mft) != GRUB_ERR_NONE)
+ return 0;
+
while (1)
{
cur_pos = find_attr (at, GRUB_NTFS_AT_INDEX_ROOT);
@@ -838,7 +854,9 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
bitmap = NULL;
bitmap_len = 0;
free_attr (at);
+ /* No need to check errors here, as it will already be fine */
init_attr (at, mft);
+
while ((cur_pos = find_attr (at, GRUB_NTFS_AT_BITMAP)) != NULL)
{
int ofs;
@@ -1203,6 +1221,7 @@ grub_ntfs_label (grub_device_t device, char **label)
struct grub_ntfs_data *data = 0;
struct grub_fshelp_node *mft = 0;
grub_uint8_t *pa;
+ grub_err_t err;
grub_dl_ref (my_mod);
@@ -1228,7 +1247,10 @@ grub_ntfs_label (grub_device_t device, char **label)
goto fail;
}
- init_attr (&mft->attr, mft);
+ err = init_attr (&mft->attr, mft);
+ if (err != GRUB_ERR_NONE)
+ return err;
+
pa = find_attr (&mft->attr, GRUB_NTFS_AT_VOLUME_NAME);
if (pa >= mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR))
diff --git a/include/grub/ntfs.h b/include/grub/ntfs.h
index d1a6af696..ec1c4db38 100644
--- a/include/grub/ntfs.h
+++ b/include/grub/ntfs.h
@@ -134,6 +134,7 @@ struct grub_ntfs_attr
grub_uint8_t *attr_cur, *attr_nxt, *attr_end;
grub_uint32_t save_pos;
grub_uint8_t *sbuf;
+ grub_uint8_t *end;
struct grub_ntfs_file *mft;
};
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Tue, 14 May 2024 12:39:56 +0100
Subject: [PATCH] fs/ntfs: Use a helper function to access attributes
Right now to access the next attribute the code reads the length of the
current attribute and adds that to the current pointer. This is error
prone as bounds checking needs to be performed all over the place. So,
implement a helper and ensure its used across find_attr() and read_attr().
This commit does *not* implement full bounds checking. It is just the
preparation work for this to be added into the helper.
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/ntfs.c | 69 +++++++++++++++++++++++++++++++++++++++++++----------
include/grub/ntfs.h | 2 ++
2 files changed, 58 insertions(+), 13 deletions(-)
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
index 699cdb3c0..5b3189ab2 100644
--- a/grub-core/fs/ntfs.c
+++ b/grub-core/fs/ntfs.c
@@ -70,6 +70,25 @@ res_attr_data_len (void *res_attr_ptr)
return u32at (res_attr_ptr, 0x10);
}
+/* Return the next attribute if it exists, otherwise return NULL. */
+static grub_uint8_t *
+next_attribute (grub_uint8_t *curr_attribute, void *end)
+{
+ grub_uint8_t *next = curr_attribute;
+
+ /*
+ * Need to verify we aren't exceeding the end of the buffer by reading the
+ * header for the current attribute
+ */
+ if (curr_attribute + GRUB_NTFS_ATTRIBUTE_HEADER_SIZE >= (grub_uint8_t *) end)
+ return NULL;
+
+ next += u16at (curr_attribute, 4);
+
+ return next;
+}
+
+
grub_ntfscomp_func_t grub_ntfscomp_func;
static grub_err_t
@@ -151,13 +170,13 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
if (at->flags & GRUB_NTFS_AF_ALST)
{
retry:
- while (at->attr_nxt < at->attr_end)
+ while (at->attr_nxt)
{
at->attr_cur = at->attr_nxt;
- at->attr_nxt += u16at (at->attr_cur, 4);
+ at->attr_nxt = next_attribute (at->attr_cur, at->attr_end);
if ((*at->attr_cur == attr) || (attr == 0))
{
- grub_uint8_t *new_pos;
+ grub_uint8_t *new_pos, *end;
if (at->flags & GRUB_NTFS_AF_MMFT)
{
@@ -181,15 +200,36 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
return NULL;
}
+ /*
+ * Only time emft_bufs is defined is in this function, with this
+ * size.
+ */
+ grub_size_t emft_buf_size =
+ at->mft->data->mft_size << GRUB_NTFS_BLK_SHR;
+
+ /*
+ * Needs to be enough space for the successful case to even
+ * bother.
+ */
+ if (first_attr_off (at->emft_buf) >= (emft_buf_size - 0x18 - 2))
+ {
+ grub_error (GRUB_ERR_BAD_FS,
+ "can\'t find 0x%X in attribute list",
+ (unsigned char) *at->attr_cur);
+ return NULL;
+ }
+
new_pos = &at->emft_buf[first_attr_off (at->emft_buf)];
- while (*new_pos != 0xFF)
+ end = &at->emft_buf[emft_buf_size];
+
+ while (new_pos && *new_pos != 0xFF)
{
if ((*new_pos == *at->attr_cur)
&& (u16at (new_pos, 0xE) == u16at (at->attr_cur, 0x18)))
{
return new_pos;
}
- new_pos += u16at (new_pos, 4);
+ new_pos = next_attribute (new_pos, end);
}
grub_error (GRUB_ERR_BAD_FS,
"can\'t find 0x%X in attribute list",
@@ -203,7 +243,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
mft_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
while (at->attr_cur < mft_end && *at->attr_cur != 0xFF)
{
- at->attr_nxt += u16at (at->attr_cur, 4);
+ at->attr_nxt = next_attribute (at->attr_cur, at->end);
if (*at->attr_cur == GRUB_NTFS_AT_ATTRIBUTE_LIST)
at->attr_end = at->attr_cur;
if ((*at->attr_cur == attr) || (attr == 0))
@@ -250,13 +290,14 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
/* From this point on pa_end is the end of the buffer */
at->end = pa_end;
- while (at->attr_nxt < at->attr_end)
+ while (at->attr_nxt)
{
if ((*at->attr_nxt == attr) || (attr == 0))
break;
- at->attr_nxt += u16at (at->attr_nxt, 4);
+ at->attr_nxt = next_attribute (at->attr_nxt, pa_end);
}
- if (at->attr_nxt >= at->attr_end)
+
+ if (at->attr_nxt >= at->attr_end || at->attr_nxt == NULL)
return NULL;
if ((at->flags & GRUB_NTFS_AF_MMFT) && (attr == GRUB_NTFS_AT_DATA))
@@ -277,7 +318,8 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
grub_cpu_to_le32 (at->mft->data->mft_start
+ 1));
pa = at->attr_nxt + u16at (pa, 4);
- while (pa < at->attr_end)
+
+ while (pa)
{
if (*pa != attr)
break;
@@ -293,7 +335,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
u32at (pa, 0x10) * (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR),
at->mft->data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0, 0))
return NULL;
- pa += u16at (pa, 4);
+ pa = next_attribute (pa, pa_end);
}
at->attr_nxt = at->attr_cur;
at->flags &= ~GRUB_NTFS_AF_GPOS;
@@ -530,14 +572,15 @@ read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest, grub_disk_addr_t ofs,
else
vcn = ofs >> (at->mft->data->log_spc + GRUB_NTFS_BLK_SHR);
pa = at->attr_nxt + u16at (at->attr_nxt, 4);
- while (pa < at->attr_end)
+
+ while (pa)
{
if (*pa != attr)
break;
if (u32at (pa, 8) > vcn)
break;
at->attr_nxt = pa;
- pa += u16at (pa, 4);
+ pa = next_attribute (pa, at->attr_end);
}
}
pp = find_attr (at, attr);
diff --git a/include/grub/ntfs.h b/include/grub/ntfs.h
index ec1c4db38..2c8078403 100644
--- a/include/grub/ntfs.h
+++ b/include/grub/ntfs.h
@@ -89,6 +89,8 @@ enum
#define GRUB_NTFS_COM_SEC (GRUB_NTFS_COM_LEN >> GRUB_NTFS_BLK_SHR)
#define GRUB_NTFS_LOG_COM_SEC (GRUB_NTFS_COM_LOG_LEN - GRUB_NTFS_BLK_SHR)
+#define GRUB_NTFS_ATTRIBUTE_HEADER_SIZE 16
+
enum
{
GRUB_NTFS_AF_ALST = 1,
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 31 May 2024 15:14:57 +0800
Subject: [PATCH] fs/xfs: Fix out-of-bounds read
The number of records in the root key array read from disk was not being
validated against the size of the root node. This could lead to an
out-of-bounds read.
This patch adds a check to ensure that the number of records in the root
key array does not exceed the expected size of a root node read from
disk. If this check detects an out-of-bounds condition the operation is
aborted to prevent random errors due to metadata corruption.
Reported-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Michael Chang <mchang@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/xfs.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
index 66e66dd58..f919bfd2a 100644
--- a/grub-core/fs/xfs.c
+++ b/grub-core/fs/xfs.c
@@ -540,6 +540,16 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
do
{
int i;
+ grub_addr_t keys_end, data_end;
+ if (grub_mul (sizeof (grub_uint64_t), nrec, &keys_end) ||
+ grub_add ((grub_addr_t) keys, keys_end, &keys_end) ||
+ grub_add ((grub_addr_t) node->data, node->data->data_size, &data_end) ||
+ keys_end > data_end)
+ {
+ grub_error (GRUB_ERR_BAD_FS, "invalid number of XFS root keys");
+ grub_free (leaf);
+ return 0;
+ }
for (i = 0; i < nrec; i++)
{
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Sun, 12 May 2024 06:03:58 +0100
Subject: [PATCH] fs/xfs: Ensuring failing to mount sets a grub_errno
It was previously possible for grub_xfs_mount() to return NULL without
setting grub_errno if the XFS version was invalid. This resulted in it
being possible for grub_dl_unref() to be called twice allowing the XFS
module to be unloaded while there were still references to it.
Fixing this problem in general by ensuring a grub_errno is set if the
fail label is reached.
Reported-by: B Horn <b@horn.uk>
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/xfs.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
index f919bfd2a..c9818a96a 100644
--- a/grub-core/fs/xfs.c
+++ b/grub-core/fs/xfs.c
@@ -297,6 +297,8 @@ static int grub_xfs_sb_valid(struct grub_xfs_data *data)
}
return 1;
}
+
+ grub_error (GRUB_ERR_BAD_FS, "unsupported XFS filesystem version");
return 0;
}
@@ -952,7 +954,7 @@ grub_xfs_mount (grub_disk_t disk)
return data;
fail:
- if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
+ if (grub_errno == GRUB_ERR_OUT_OF_RANGE || grub_errno == GRUB_ERR_NONE)
grub_error (GRUB_ERR_BAD_FS, "not an XFS filesystem");
grub_free (data);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment