I think you should change the order of this patch and patch #3. On Mon, May 19, 2025 at 09:03:18PM -0500, Andrew Hamilton wrote: > Correct several memory access violations and hangs found during fuzzing. > The issues fixed here could occur if certain specific malformed NTFS > file systems were presented to GRUB. Currently, GRUB does not allow NTFS > file system access when lockdown mode is enforced, so these should be of > minimal impact. > > The changes made in this commit generally correct issues where pointers > into data buffers were being calculated using lengths read from the > NTFS file system without sufficient bounds / sanity checking; attempting > to iterate through a buffer using a length read from the NTFS file system > without confirming the length is larger than 0 (possible hang / infinite > loop); or attempting to access elements of a structure to free them, when > the structure pointer is null.
s/null/NULL/ Is it possible to group the changes logically and put them in separate patches? The leftovers can be put into one last patch. > Signed-off-by: Andrew Hamilton <adham...@gmail.com> > --- > grub-core/fs/ntfs.c | 95 ++++++++++++++++++++++++++++++++++++++------- > 1 file changed, 80 insertions(+), 15 deletions(-) > > diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c > index 0d087acd8..45fff2400 100644 > --- a/grub-core/fs/ntfs.c > +++ b/grub-core/fs/ntfs.c > @@ -246,6 +246,7 @@ fixup (grub_uint8_t *buf, grub_size_t len, const > grub_uint8_t *magic) > grub_uint16_t ss; > grub_uint8_t *pu; > grub_uint16_t us; > + grub_uint16_t pu_offset; > > COMPILE_TIME_ASSERT ((1 << GRUB_NTFS_BLK_SHR) == GRUB_DISK_SECTOR_SIZE); > > @@ -255,7 +256,10 @@ fixup (grub_uint8_t *buf, grub_size_t len, const > grub_uint8_t *magic) > ss = u16at (buf, 6) - 1; > if (ss != len) > return grub_error (GRUB_ERR_BAD_FS, "size not match"); > - pu = buf + u16at (buf, 4); > + pu_offset = u16at (buf, 4); > + if (pu_offset >= (len * GRUB_DISK_SECTOR_SIZE - (2 * ss))) > + return grub_error (GRUB_ERR_BAD_FS, "pu offset size incorrect"); > + pu = buf + pu_offset; > us = u16at (pu, 0); > buf -= 2; > while (ss > 0) > @@ -373,6 +377,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) > > new_pos = &at->emft_buf[first_attr_off (at->emft_buf)]; > end = &at->emft_buf[emft_buf_size]; > + at->end = end; > > while (new_pos && *new_pos != 0xFF) > { > @@ -395,7 +400,8 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) > } > at->attr_cur = at->attr_nxt; > mft_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR); > - while (at->attr_cur >= at->mft->buf && at->attr_cur < mft_end && > *at->attr_cur != 0xFF) > + while (at->attr_cur >= at->mft->buf && at->attr_cur < (mft_end - 4) > + && *at->attr_cur != 0xFF) > { > /* We can't use validate_attribute here because this logic > * seems to be used for both parsing through attributes > @@ -412,7 +418,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) > > if (*at->attr_cur == GRUB_NTFS_AT_ATTRIBUTE_LIST) > at->attr_end = at->attr_cur; > - if ((*at->attr_cur == attr) || (attr == 0)) > + if ((*at->attr_cur == attr) || (attr == 0) || (nsize == 0)) > return at->attr_cur; > at->attr_cur = at->attr_nxt; > } > @@ -442,13 +448,23 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) > return NULL; > } > at->attr_nxt = at->edat_buf; > - at->attr_end = at->edat_buf + u32at (pa, 0x30); > + grub_uint32_t edat_offset = u32at (pa, 0x30); > + if (edat_offset >= n) { > + grub_error (GRUB_ERR_BAD_FS, "edat offset is out of bounds"); > + return NULL; > + } > + at->attr_end = at->edat_buf + edat_offset; > pa_end = at->edat_buf + n; > } > else > { > at->attr_nxt = at->attr_end + res_attr_data_off (pa); > - at->attr_end = at->attr_end + u32at (pa, 4); > + grub_uint32_t edat_offset = u32at (pa, 4); > + if ((at->attr_end + edat_offset) >= (at->end)) { > + grub_error (GRUB_ERR_BAD_FS, "edat offset is out of bounds"); > + return NULL; > + } > + at->attr_end = at->attr_end + edat_offset; > pa_end = at->mft->buf + (at->mft->data->mft_size << > GRUB_NTFS_BLK_SHR); > } > at->flags |= GRUB_NTFS_AF_ALST; > @@ -470,7 +486,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) > at->attr_nxt = NULL; > } > > - if (at->attr_nxt >= at->attr_end || at->attr_nxt == NULL) > + if ((at->attr_nxt + GRUB_NTFS_ATTRIBUTE_HEADER_SIZE) >= at->attr_end > || at->attr_nxt == NULL) > return NULL; > > if ((at->flags & GRUB_NTFS_AF_MMFT) && (attr == GRUB_NTFS_AT_DATA)) > @@ -537,13 +553,16 @@ locate_attr (struct grub_ntfs_attr *at, struct > grub_ntfs_file *mft, > return NULL; > if ((at->flags & GRUB_NTFS_AF_ALST) == 0) > { > + /* Used to make sure we're not stuck in a loop. */ > + grub_uint8_t *last_pa = NULL; Missing empty line... > while (1) > { > pa = find_attr (at, attr); > - if (pa == NULL) > + if (pa == NULL || pa == last_pa) > break; > if (at->flags & GRUB_NTFS_AF_ALST) > return pa; > + last_pa = pa; > } > grub_errno = GRUB_ERR_NONE; > free_attr (at); > @@ -639,6 +658,7 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, > grub_uint8_t *dest, > grub_disk_read_hook_t read_hook, void *read_hook_data) > { > struct grub_ntfs_rlst cc, *ctx; > + grub_uint8_t *end_ptr = (pa + len); > > if (len == 0) > return 0; > @@ -671,7 +691,13 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, > grub_uint8_t *dest, > return 0; > } > > - ctx->cur_run = pa + u16at (pa, 0x20); > + grub_uint16_t run_offset = u16at (pa, 0x20); Please move variable definition to proper place... Daniel _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel