From e36472a9a997d512b3737efa240d4790716b3c50 Mon Sep 17 00:00:00 2001 From: Leo Sandoval Date: Tue, 11 Mar 2025 10:40:56 -0600 Subject: [PATCH] Remove NTFS attribute verification patch The removed patch was part of the CVE patches ported recently into RHEL but is causing segfaults on dual boot (Windows & RHEL) systems when generating the grub configuration with the grub2-mkconfig tool. At some point the same patch will come back with the corresponding fix but for the time being, it is removed. Related: RHEL-83117 Signed-off-by: Nicolas Frayer Signed-off-by: Leo Sandoval --- ...tfs-Implement-attribute-verification.patch | 245 ------------------ grub.patches | 1 - grub2.spec | 6 +- 3 files changed, 5 insertions(+), 247 deletions(-) delete mode 100644 0372-fs-ntfs-Implement-attribute-verification.patch diff --git a/0372-fs-ntfs-Implement-attribute-verification.patch b/0372-fs-ntfs-Implement-attribute-verification.patch deleted file mode 100644 index 1498a56..0000000 --- a/0372-fs-ntfs-Implement-attribute-verification.patch +++ /dev/null @@ -1,245 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: B Horn -Date: Tue, 14 May 2024 12:39:56 +0100 -Subject: [PATCH] fs/ntfs: Implement attribute verification - -It was possible to read OOB when an attribute had a size that exceeded -the allocated buffer. This resolves that by making sure all attributes -that get read are fully in the allocated space by implementing -a function to validate them. - -Defining the offsets in include/grub/ntfs.h but they are only used in -the validation function and not across the rest of the NTFS code. - -Signed-off-by: B Horn -Reviewed-by: Daniel Kiper ---- - grub-core/fs/ntfs.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - include/grub/ntfs.h | 22 ++++++++ - 2 files changed, 175 insertions(+) - -diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c -index 9311ba9ef..8fdb8f2ff 100644 ---- a/grub-core/fs/ntfs.c -+++ b/grub-core/fs/ntfs.c -@@ -70,6 +70,149 @@ res_attr_data_len (void *res_attr_ptr) - return u32at (res_attr_ptr, 0x10); - } - -+/* -+ * Check if the attribute is valid and doesn't exceed the allocated region. -+ * This accounts for resident and non-resident data. -+ * -+ * This is based off the documentation from the linux-ntfs project: -+ * https://flatcap.github.io/linux-ntfs/ntfs/concepts/attribute_header.html -+ */ -+static bool -+validate_attribute (grub_uint8_t *attr, void *end) -+{ -+ grub_size_t attr_size = 0; -+ grub_size_t min_size = 0; -+ grub_size_t spare = (grub_uint8_t *) end - attr; -+ /* -+ * Just used as a temporary variable to try and deal with cases where someone -+ * tries to overlap fields. -+ */ -+ grub_size_t curr = 0; -+ -+ /* Need verify we can entirely read the attributes header. */ -+ if (attr + GRUB_NTFS_ATTRIBUTE_HEADER_SIZE >= (grub_uint8_t *) end) -+ goto fail; -+ -+ /* -+ * So, the rest of this code uses a 16bit int for the attribute length but -+ * from reading the all the documentation I could find it says this field is -+ * actually 32bit. But let's be consistent with the rest of the code. -+ * -+ * https://elixir.bootlin.com/linux/v6.10.7/source/fs/ntfs3/ntfs.h#L370 -+ */ -+ attr_size = u16at (attr, GRUB_NTFS_ATTRIBUTE_LENGTH); -+ -+ if (attr_size > spare) -+ goto fail; -+ -+ /* Not an error case, just reached the end of the attributes. */ -+ if (attr_size == 0) -+ return false; -+ -+ /* -+ * Extra validation by trying to calculate a minimum possible size for this -+ * attribute. +8 from the size of the resident data struct which is the -+ * minimum that can be added. -+ */ -+ min_size = GRUB_NTFS_ATTRIBUTE_HEADER_SIZE + 8; -+ -+ if (min_size > attr_size) -+ goto fail; -+ -+ /* Is the data is resident (0) or not (1). */ -+ if (attr[GRUB_NTFS_ATTRIBUTE_RESIDENT] == 0) -+ { -+ /* Read the offset and size of the attribute. */ -+ curr = u16at (attr, GRUB_NTFS_ATTRIBUTE_RES_OFFSET); -+ curr += u32at (attr, GRUB_NTFS_ATTRIBUTE_RES_LENGTH); -+ if (curr > min_size) -+ min_size = curr; -+ } -+ else -+ { -+ /* -+ * If the data is non-resident, the minimum size is 64 which is where -+ * the data runs start. We already have a minimum size of 24. So, just -+ * adding 40 to get to the real value. -+ */ -+ min_size += 40; -+ if (min_size > attr_size) -+ goto fail; -+ /* If the compression unit size is > 0, +8 bytes*/ -+ if (u16at (attr, GRUB_NTFS_ATTRIBUTE_COMPRESSION_UNIT_SIZE) > 0) -+ min_size += 8; -+ -+ /* -+ * Need to consider the data runs now. Each member of the run has byte -+ * that describes the size of the data length and offset. Each being -+ * 4 bits in the byte. -+ */ -+ curr = u16at (attr, GRUB_NTFS_ATTRIBUTE_DATA_RUNS); -+ -+ if (curr + 1 > min_size) -+ min_size = curr + 1; -+ -+ if (min_size > attr_size) -+ goto fail; -+ -+ /* -+ * Each attribute can store multiple data runs which are stored -+ * continuously in the attribute. They exist as one header byte -+ * with up to 14 bytes following it depending on the lengths. -+ * We stop when we hit a header that is just a NUL byte. -+ * -+ * https://flatcap.github.io/linux-ntfs/ntfs/concepts/data_runs.html -+ */ -+ while (attr[curr] != 0) -+ { -+ /* -+ * We stop when we hit a header that is just a NUL byte. The data -+ * run header is stored as a single byte where the top 4 bits refer -+ * to the number of bytes used to store the total length of the -+ * data run, and the number of bytes used to store the offset. -+ * These directly follow the header byte, so we use them to update -+ * the minimum size. -+ */ -+ min_size += (attr[curr] & 0x7) + ((attr[curr] >> 4) & 0x7); -+ curr += min_size; -+ min_size++; -+ if (min_size > attr_size) -+ goto fail; -+ } -+ } -+ -+ /* Name offset, doing this after data residence checks. */ -+ if (u16at (attr, GRUB_NTFS_ATTRIBUTE_NAME_OFFSET) != 0) -+ { -+ curr = u16at (attr, GRUB_NTFS_ATTRIBUTE_NAME_OFFSET); -+ /* -+ * Multiple the name length by 2 as its UTF-16. Can be zero if this in an -+ * unamed attribute. -+ */ -+ curr += attr[GRUB_NTFS_ATTRIBUTE_NAME_LENGTH] * 2; -+ if (curr > min_size) -+ min_size = curr; -+ } -+ -+ /* Padded to 8 bytes. */ -+ if (min_size % 8 != 0) -+ min_size += 8 - (min_size % 8); -+ -+ /* -+ * At this point min_size should be exactly attr_size but being flexible -+ * here to avoid any issues. -+ */ -+ if (min_size > attr_size) -+ goto fail; -+ -+ return true; -+ -+ fail: -+ grub_dprintf ("ntfs", "spare=%" PRIuGRUB_SIZE " min_size=%" PRIuGRUB_SIZE " attr_size=%" PRIuGRUB_SIZE "\n", -+ spare, min_size, attr_size); -+ return false; -+} -+ - /* Return the next attribute if it exists, otherwise return NULL. */ - static grub_uint8_t * - next_attribute (grub_uint8_t *curr_attribute, void *end) -@@ -84,6 +227,8 @@ next_attribute (grub_uint8_t *curr_attribute, void *end) - return NULL; - - next += u16at (curr_attribute, 4); -+ if (validate_attribute (next, end) == false) -+ return NULL; - - return next; - } -@@ -290,6 +435,9 @@ 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; - -+ if (validate_attribute (at->attr_nxt, pa_end) == false) -+ return NULL; -+ - while (at->attr_nxt) - { - if ((*at->attr_nxt == attr) || (attr == 0)) -@@ -319,6 +467,9 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) - + 1)); - pa = at->attr_nxt + u16at (pa, 4); - -+ if (validate_attribute (pa, pa_end) == true) -+ pa = NULL; -+ - while (pa) - { - if (*pa != attr) -@@ -572,6 +723,8 @@ 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); -+ if (validate_attribute (pa, at->attr_end) == false) -+ pa = NULL; - - while (pa) - { -diff --git a/include/grub/ntfs.h b/include/grub/ntfs.h -index 2c8078403..77b182acf 100644 ---- a/include/grub/ntfs.h -+++ b/include/grub/ntfs.h -@@ -91,6 +91,28 @@ enum - - #define GRUB_NTFS_ATTRIBUTE_HEADER_SIZE 16 - -+/* -+ * To make attribute validation clearer the offsets for each value in the -+ * attribute headers are defined as macros. -+ * -+ * These offsets are all from: -+ * https://flatcap.github.io/linux-ntfs/ntfs/concepts/attribute_header.html -+ */ -+ -+/* These offsets are part of the attribute header. */ -+#define GRUB_NTFS_ATTRIBUTE_LENGTH 4 -+#define GRUB_NTFS_ATTRIBUTE_RESIDENT 8 -+#define GRUB_NTFS_ATTRIBUTE_NAME_LENGTH 9 -+#define GRUB_NTFS_ATTRIBUTE_NAME_OFFSET 10 -+ -+/* Offsets for values needed for resident data. */ -+#define GRUB_NTFS_ATTRIBUTE_RES_LENGTH 16 -+#define GRUB_NTFS_ATTRIBUTE_RES_OFFSET 20 -+ -+/* Offsets for values needed for non-resident data. */ -+#define GRUB_NTFS_ATTRIBUTE_DATA_RUNS 32 -+#define GRUB_NTFS_ATTRIBUTE_COMPRESSION_UNIT_SIZE 34 -+ - enum - { - GRUB_NTFS_AF_ALST = 1, diff --git a/grub.patches b/grub.patches index 4720e55..9b8c8e7 100644 --- a/grub.patches +++ b/grub.patches @@ -369,7 +369,6 @@ Patch0368: 0368-fs-ext2-Fix-out-of-bounds-read-for-inline-extents.patch Patch0369: 0369-fs-ntfs-Fix-out-of-bounds-read.patch Patch0370: 0370-fs-ntfs-Track-the-end-of-the-MFT-attribute-buffer.patch Patch0371: 0371-fs-ntfs-Use-a-helper-function-to-access-attributes.patch -Patch0372: 0372-fs-ntfs-Implement-attribute-verification.patch Patch0373: 0373-fs-xfs-Fix-out-of-bounds-read.patch Patch0374: 0374-fs-xfs-Ensuring-failing-to-mount-sets-a-grub_errno.patch Patch0375: 0375-kern-file-Ensure-file-data-is-set.patch diff --git a/grub2.spec b/grub2.spec index e42bc87..3ca0d40 100644 --- a/grub2.spec +++ b/grub2.spec @@ -16,7 +16,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 97%{?dist} +Release: 98%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -547,6 +547,10 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Mon Mar 10 2025 Leo Sandoval 2.06-98 +- Remove 'fs/ntfs: Implement attribute verification' patch +- Related: RHEL-83117 + * Wed Feb 26 2025 Nicolas Frayer - 2.06-97 - fs/ext2: Rework out-of-bounds read for inline and external extents - Related: RHEL-79857