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>
		
			
				
	
	
		
			109 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			109 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | |
| From: B Horn <b@horn.uk>
 | |
| Date: Tue, 11 Feb 2025 15:22:28 -0600
 | |
| Subject: [PATCH] disk/loopback: Reference tracking for the loopback
 | |
| 
 | |
| It was possible to delete a loopback while there were still references
 | |
| to it. This led to an exploitable use-after-free.
 | |
| 
 | |
| Fixed by implementing a reference counting in the grub_loopback struct.
 | |
| 
 | |
| 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/disk/loopback.c | 17 +++++++++++++++++
 | |
|  include/grub/err.h        |  3 ++-
 | |
|  include/grub/loopback.h   |  1 +
 | |
|  3 files changed, 20 insertions(+), 1 deletion(-)
 | |
| 
 | |
| diff --git a/grub-core/disk/loopback.c b/grub-core/disk/loopback.c
 | |
| index 11a5e0cbd..f39281323 100644
 | |
| --- a/grub-core/disk/loopback.c
 | |
| +++ b/grub-core/disk/loopback.c
 | |
| @@ -25,6 +25,7 @@
 | |
|  #include <grub/mm.h>
 | |
|  #include <grub/extcmd.h>
 | |
|  #include <grub/i18n.h>
 | |
| +#include <grub/safemath.h>
 | |
|  
 | |
|  GRUB_MOD_LICENSE ("GPLv3+");
 | |
|  
 | |
| @@ -57,6 +58,8 @@ delete_loopback (const char *name)
 | |
|    if (! dev)
 | |
|      return grub_error (GRUB_ERR_BAD_DEVICE, "device not found");
 | |
|  
 | |
| +  if (dev->refcnt > 0)
 | |
| +    return grub_error (GRUB_ERR_STILL_REFERENCED, "device still referenced");
 | |
|    /* Remove the device from the list.  */
 | |
|    *prev = dev->next;
 | |
|  
 | |
| @@ -113,6 +116,7 @@ grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args)
 | |
|  
 | |
|    newdev->file = file;
 | |
|    newdev->id = last_id++;
 | |
| +  newdev->refcnt = 0;
 | |
|  
 | |
|    /* Add the new entry to the list.  */
 | |
|    newdev->next = loopback_list;
 | |
| @@ -154,6 +158,9 @@ grub_loopback_open (const char *name, grub_disk_t disk)
 | |
|    if (! dev)
 | |
|      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
 | |
|  
 | |
| +  if (grub_add (dev->refcnt, 1, &dev->refcnt))
 | |
| +    grub_fatal ("Reference count overflow");
 | |
| +
 | |
|    /* Use the filesize for the disk size, round up to a complete sector.  */
 | |
|    if (dev->file->size != GRUB_FILE_SIZE_UNKNOWN)
 | |
|      disk->total_sectors = ((dev->file->size + GRUB_DISK_SECTOR_SIZE - 1)
 | |
| @@ -171,6 +178,15 @@ grub_loopback_open (const char *name, grub_disk_t disk)
 | |
|    return 0;
 | |
|  }
 | |
|  
 | |
| +static void
 | |
| +grub_loopback_close (grub_disk_t disk)
 | |
| +{
 | |
| +  struct grub_loopback *dev = disk->data;
 | |
| +
 | |
| +  if (grub_sub (dev->refcnt, 1, &dev->refcnt))
 | |
| +    grub_fatal ("Reference count underflow");
 | |
| +}
 | |
| +
 | |
|  static grub_err_t
 | |
|  grub_loopback_read (grub_disk_t disk, grub_disk_addr_t sector,
 | |
|  		    grub_size_t size, char *buf)
 | |
| @@ -213,6 +229,7 @@ static struct grub_disk_dev grub_loopback_dev =
 | |
|      .id = GRUB_DISK_DEVICE_LOOPBACK_ID,
 | |
|      .disk_iterate = grub_loopback_iterate,
 | |
|      .disk_open = grub_loopback_open,
 | |
| +    .disk_close = grub_loopback_close,
 | |
|      .disk_read = grub_loopback_read,
 | |
|      .disk_write = grub_loopback_write,
 | |
|      .next = 0
 | |
| diff --git a/include/grub/err.h b/include/grub/err.h
 | |
| index 3c587b9b8..29f1a73c5 100644
 | |
| --- a/include/grub/err.h
 | |
| +++ b/include/grub/err.h
 | |
| @@ -73,7 +73,8 @@ typedef enum
 | |
|      GRUB_ERR_NET_NO_DOMAIN,
 | |
|      GRUB_ERR_EOF,
 | |
|      GRUB_ERR_BAD_SIGNATURE,
 | |
| -    GRUB_ERR_BAD_FIRMWARE
 | |
| +    GRUB_ERR_BAD_FIRMWARE,
 | |
| +    GRUB_ERR_STILL_REFERENCED
 | |
|    }
 | |
|  grub_err_t;
 | |
|  
 | |
| diff --git a/include/grub/loopback.h b/include/grub/loopback.h
 | |
| index 3b9a9e32e..915ef65fc 100644
 | |
| --- a/include/grub/loopback.h
 | |
| +++ b/include/grub/loopback.h
 | |
| @@ -25,6 +25,7 @@ struct grub_loopback
 | |
|    grub_file_t file;
 | |
|    struct grub_loopback *next;
 | |
|    unsigned long id;
 | |
| +  grub_uint64_t refcnt;
 | |
|  };
 | |
|  
 | |
|  #endif /* ! GRUB_LOOPBACK_HEADER */
 |