Resolves: CVE-2024-45781 CVE-2024-45783 CVE-2024-45778 Resolves: CVE-2024-45775 CVE-2024-45780 CVE-2024-45774 Resolves: CVE-2025-0690 CVE-2025-1118 CVE-2024-45782 Resolves: CVE-2025-0624 CVE-2024-45779 CVE-2024-45776 Resolves: CVE-2025-0622 CVE-2025-0677 Resolves: #RHEL-80691 Resolves: #RHEL-80690 Resolves: #RHEL-80689 Resolves: #RHEL-80687 Resolves: #RHEL-80686 Signed-off-by: Leo Sandoval <lsandova@redhat.com> Signed-off-by: Nicolas Frayer <nfrayer@redhat.com>
		
			
				
	
	
		
			184 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			184 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| 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 dbda720e1..1c678f3d0 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,
 |