0021-kern-disk-Limit-recursion-depth.patch 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. From 195331a7a64c2a4ba754e2527ca8973012db68c9 Mon Sep 17 00:00:00 2001
  2. From: B Horn <b@horn.uk>
  3. Date: Sun, 12 May 2024 04:09:24 +0100
  4. Subject: [PATCH] kern/disk: Limit recursion depth
  5. The grub_disk_read() may trigger other disk reads, e.g. via loopbacks.
  6. This may lead to very deep recursion which can corrupt the heap. So, fix
  7. the issue by limiting reads depth.
  8. Reported-by: B Horn <b@horn.uk>
  9. Signed-off-by: B Horn <b@horn.uk>
  10. Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
  11. Upstream: 18212f0648b6de7d71d4c8f41eb4d8b78b3a299b
  12. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
  13. ---
  14. grub-core/kern/disk.c | 27 ++++++++++++++++++++-------
  15. include/grub/err.h | 3 ++-
  16. 2 files changed, 22 insertions(+), 8 deletions(-)
  17. diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c
  18. index 1eda58fe9..82e04fd00 100644
  19. --- a/grub-core/kern/disk.c
  20. +++ b/grub-core/kern/disk.c
  21. @@ -28,6 +28,10 @@
  22. #define GRUB_CACHE_TIMEOUT 2
  23. +/* Disk reads may trigger other disk reads. So, limit recursion depth. */
  24. +#define MAX_READ_RECURSION_DEPTH 16
  25. +static unsigned int read_recursion_depth = 0;
  26. +
  27. /* The last time the disk was used. */
  28. static grub_uint64_t grub_last_time = 0;
  29. @@ -417,6 +421,8 @@ grub_err_t
  30. grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
  31. grub_off_t offset, grub_size_t size, void *buf)
  32. {
  33. + grub_err_t err = GRUB_ERR_NONE;
  34. +
  35. /* First of all, check if the region is within the disk. */
  36. if (grub_disk_adjust_range (disk, &sector, &offset, size) != GRUB_ERR_NONE)
  37. {
  38. @@ -427,12 +433,17 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
  39. return grub_errno;
  40. }
  41. + if (++read_recursion_depth >= MAX_READ_RECURSION_DEPTH)
  42. + {
  43. + grub_error (GRUB_ERR_RECURSION_DEPTH, "grub_disk_read(): Maximum recursion depth exceeded");
  44. + goto error;
  45. + }
  46. +
  47. /* First read until first cache boundary. */
  48. if (offset || (sector & (GRUB_DISK_CACHE_SIZE - 1)))
  49. {
  50. grub_disk_addr_t start_sector;
  51. grub_size_t pos;
  52. - grub_err_t err;
  53. grub_size_t len;
  54. start_sector = sector & ~((grub_disk_addr_t) GRUB_DISK_CACHE_SIZE - 1);
  55. @@ -444,7 +455,7 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
  56. err = grub_disk_read_small (disk, start_sector,
  57. offset + pos, len, buf);
  58. if (err)
  59. - return err;
  60. + goto error;
  61. buf = (char *) buf + len;
  62. size -= len;
  63. offset += len;
  64. @@ -457,7 +468,6 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
  65. {
  66. char *data = NULL;
  67. grub_disk_addr_t agglomerate;
  68. - grub_err_t err;
  69. /* agglomerate read until we find a first cached entry. */
  70. for (agglomerate = 0; agglomerate
  71. @@ -493,7 +503,7 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
  72. - disk->log_sector_size),
  73. buf);
  74. if (err)
  75. - return err;
  76. + goto error;
  77. for (i = 0; i < agglomerate; i ++)
  78. grub_disk_cache_store (disk->dev->id, disk->id,
  79. @@ -527,13 +537,16 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
  80. /* And now read the last part. */
  81. if (size)
  82. {
  83. - grub_err_t err;
  84. err = grub_disk_read_small (disk, sector, 0, size, buf);
  85. if (err)
  86. - return err;
  87. + goto error;
  88. }
  89. - return grub_errno;
  90. + err = grub_errno;
  91. +
  92. + error:
  93. + read_recursion_depth--;
  94. + return err;
  95. }
  96. grub_uint64_t
  97. diff --git a/include/grub/err.h b/include/grub/err.h
  98. index b0e54e0a0..202fa8a7a 100644
  99. --- a/include/grub/err.h
  100. +++ b/include/grub/err.h
  101. @@ -74,7 +74,8 @@ typedef enum
  102. GRUB_ERR_EOF,
  103. GRUB_ERR_BAD_SIGNATURE,
  104. GRUB_ERR_BAD_FIRMWARE,
  105. - GRUB_ERR_STILL_REFERENCED
  106. + GRUB_ERR_STILL_REFERENCED,
  107. + GRUB_ERR_RECURSION_DEPTH
  108. }
  109. grub_err_t;
  110. --
  111. 2.50.1