:: commit 0602546ad25b3de25e9deeb40aff7950223b2ee1

Mintsuki <mintsuki@protonmail.com> — 2026-01-04 15:05

parents: 5ab25d4dae

fs,lib: Check volume_read() and read_cluster_from_map() return values

diff --git a/common/fs/fat32.s2.c b/common/fs/fat32.s2.c
index ee6f26dc..626bb7e6 100644
--- a/common/fs/fat32.s2.c
+++ b/common/fs/fat32.s2.c
@@ -103,7 +103,9 @@ static int fat32_init_context(struct fat32_context* context, struct volume *part
     context->part = part;
 
     struct fat32_bpb bpb;
-    volume_read(context->part, &bpb, 0, sizeof(struct fat32_bpb));
+    if (!volume_read(context->part, &bpb, 0, sizeof(struct fat32_bpb))) {
+        return 1;
+    }
 
     // Sanity check of bpb
 
@@ -287,7 +289,9 @@ static int read_cluster_from_map(struct fat32_context *context, uint32_t cluster
                 return -1;
             }
 
-            volume_read(context->part, &tmp, fat_base + offset, sizeof(uint16_t));
+            if (!volume_read(context->part, &tmp, fat_base + offset, sizeof(uint16_t))) {
+                return -1;
+            }
             if (cluster % 2 == 0) {
                 *out = tmp & 0xfff;
             } else {
@@ -301,7 +305,9 @@ static int read_cluster_from_map(struct fat32_context *context, uint32_t cluster
             if (offset + sizeof(uint16_t) > fat_size) {
                 return -1;
             }
-            volume_read(context->part, out, fat_base + offset, sizeof(uint16_t));
+            if (!volume_read(context->part, out, fat_base + offset, sizeof(uint16_t))) {
+                return -1;
+            }
             break;
         }
         case 32: {
@@ -309,7 +315,9 @@ static int read_cluster_from_map(struct fat32_context *context, uint32_t cluster
             if (offset + sizeof(uint32_t) > fat_size) {
                 return -1;
             }
-            volume_read(context->part, out, fat_base + offset, sizeof(uint32_t));
+            if (!volume_read(context->part, out, fat_base + offset, sizeof(uint32_t))) {
+                return -1;
+            }
             *out &= 0x0fffffff;
             break;
         }
@@ -341,7 +349,9 @@ static uint32_t *cache_cluster_chain(struct fat32_context *context,
     uint32_t cluster = initial_cluster;
     size_t chain_length;
     for (chain_length = 1; chain_length <= max_clusters; chain_length++) {
-        read_cluster_from_map(context, cluster, &cluster);
+        if (read_cluster_from_map(context, cluster, &cluster) != 0) {
+            return NULL;
+        }
         if (cluster < 0x2 || cluster > cluster_limit)
             break;
     }
@@ -359,7 +369,10 @@ static uint32_t *cache_cluster_chain(struct fat32_context *context,
     cluster = initial_cluster;
     for (size_t i = 0; i < chain_length; i++) {
         cluster_chain[i] = cluster;
-        read_cluster_from_map(context, cluster, &cluster);
+        if (read_cluster_from_map(context, cluster, &cluster) != 0) {
+            pmm_free(cluster_chain, alloc_size);
+            return NULL;
+        }
     }
     *_chain_length = chain_length;
     return cluster_chain;
@@ -405,7 +418,9 @@ static bool read_cluster_chain(struct fat32_context *context,
         if (__builtin_mul_overflow(sector_offset, (uint64_t)context->bytes_per_sector, &base)) {
             return false;
         }
-        volume_read(context->part, buf + progress, base + offset, chunk);
+        if (!volume_read(context->part, buf + progress, base + offset, chunk)) {
+            return false;
+        }
 
         progress += chunk;
     }
@@ -510,7 +525,10 @@ static int fat32_open_in(struct fat32_context* context, struct fat32_directory_e
             pmm_free(directory_entries, alloc_size);
             return -1;
         }
-        volume_read(context->part, directory_entries, root_offset, context->root_entries * sizeof(struct fat32_directory_entry));
+        if (!volume_read(context->part, directory_entries, root_offset, context->root_entries * sizeof(struct fat32_directory_entry))) {
+            pmm_free(directory_entries, alloc_size);
+            return -1;
+        }
     }
 
     int ret;
diff --git a/common/fs/iso9660.s2.c b/common/fs/iso9660.s2.c
index 59b5cdb3..3e8f22c7 100644
--- a/common/fs/iso9660.s2.c
+++ b/common/fs/iso9660.s2.c
@@ -119,7 +119,9 @@ static void iso9660_find_PVD(struct iso9660_primary_volume *desc, struct volume
         if (__builtin_mul_overflow((uint64_t)lba, (uint64_t)ISO9660_SECTOR_SIZE, &offset)) {
             panic(false, "ISO9660: volume descriptor offset overflow");
         }
-        volume_read(vol, desc, offset, sizeof(struct iso9660_primary_volume));
+        if (!volume_read(vol, desc, offset, sizeof(struct iso9660_primary_volume))) {
+            panic(false, "ISO9660: failed to read volume descriptor");
+        }
 
         switch (desc->volume_descriptor.type) {
         case ISO9660_VDT_PRIMARY:
@@ -153,7 +155,9 @@ static void iso9660_cache_root(struct volume *vol,
     if (__builtin_mul_overflow((uint64_t)pv.root.extent.little, (uint64_t)ISO9660_SECTOR_SIZE, &offset)) {
         panic(false, "ISO9660: root extent offset overflow");
     }
-    volume_read(vol, *root, offset, *root_size);
+    if (!volume_read(vol, *root, offset, *root_size)) {
+        panic(false, "ISO9660: failed to read root directory");
+    }
 }
 
 static struct iso9660_context *iso9660_get_context(struct volume *vol) {
@@ -352,7 +356,9 @@ static void iso9660_close(struct file_handle *file);
 struct file_handle *iso9660_open(struct volume *vol, const char *path) {
     char buf[6];
     const uint64_t signature = ISO9660_FIRST_VOLUME_DESCRIPTOR * ISO9660_SECTOR_SIZE + 1;
-    volume_read(vol, buf, signature, 5);
+    if (!volume_read(vol, buf, signature, 5)) {
+        return NULL;
+    }
     buf[5] = '\0';
     if (strcmp(buf, "CD001") != 0) {
         return NULL;
@@ -488,7 +494,11 @@ struct file_handle *iso9660_open(struct volume *vol, const char *path) {
             pmm_free(ret, sizeof(struct iso9660_file_handle));
             return NULL;
         }
-        volume_read(vol, current, dir_offset, current_size);
+        if (!volume_read(vol, current, dir_offset, current_size)) {
+            pmm_free(current, current_size);
+            pmm_free(ret, sizeof(struct iso9660_file_handle));
+            return NULL;
+        }
     }
 
     // Free the last directory buffer if we allocated one (not the cached root)
@@ -542,7 +552,9 @@ static void iso9660_read(struct file_handle *file, void *buf, uint64_t loc, uint
                 panic(false, "iso9660: offset calculation overflow");
             }
 
-            volume_read(f->context->vol, buf, disk_offset, to_read);
+            if (!volume_read(f->context->vol, buf, disk_offset, to_read)) {
+                panic(false, "iso9660: failed to read file data");
+            }
 
             buf = (uint8_t *)buf + to_read;
             loc += to_read;
diff --git a/common/lib/part.s2.c b/common/lib/part.s2.c
index 3e746363..52dd07cc 100644
--- a/common/lib/part.s2.c
+++ b/common/lib/part.s2.c
@@ -156,7 +156,8 @@ bool gpt_get_guid(struct guid *guid, struct volume *volume) {
 
     for (size_t i = 0; i < SIZEOF_ARRAY(lb_guesses); i++) {
         // read header, located after the first block
-        volume_read(volume, &header, lb_guesses[i] * 1, sizeof(header));
+        if (!volume_read(volume, &header, lb_guesses[i] * 1, sizeof(header)))
+            continue;
 
         // check the header
         // 'EFI PART'
@@ -190,7 +191,8 @@ static int gpt_get_part(struct volume *ret, struct volume *volume, int partition
 
     for (size_t i = 0; i < SIZEOF_ARRAY(lb_guesses); i++) {
         // read header, located after the first block
-        volume_read(volume, &header, lb_guesses[i] * 1, sizeof(header));
+        if (!volume_read(volume, &header, lb_guesses[i] * 1, sizeof(header)))
+            continue;
 
         // check the header
         // 'EFI PART'
@@ -230,7 +232,9 @@ static int gpt_get_part(struct volume *ret, struct volume *volume, int partition
     }
 
     struct gpt_entry entry = {0};
-    volume_read(volume, &entry, entry_offset, sizeof(entry));
+    if (!volume_read(volume, &entry, entry_offset, sizeof(entry))) {
+        return END_OF_TABLE;
+    }
 
     struct guid empty_guid = {0};
     if (!memcmp(&entry.unique_partition_guid, &empty_guid, sizeof(struct guid)))
@@ -313,33 +317,42 @@ bool is_valid_mbr(struct volume *volume) {
     // Check if actually valid mbr
     uint16_t hint = 0;
 
-    volume_read(volume, &hint, 446, sizeof(uint8_t));
+    if (!volume_read(volume, &hint, 446, sizeof(uint8_t)))
+        return false;
     if ((uint8_t)hint != 0x00 && (uint8_t)hint != 0x80)
         return false;
-    volume_read(volume, &hint, 462, sizeof(uint8_t));
+    if (!volume_read(volume, &hint, 462, sizeof(uint8_t)))
+        return false;
     if ((uint8_t)hint != 0x00 && (uint8_t)hint != 0x80)
         return false;
-    volume_read(volume, &hint, 478, sizeof(uint8_t));
+    if (!volume_read(volume, &hint, 478, sizeof(uint8_t)))
+        return false;
     if ((uint8_t)hint != 0x00 && (uint8_t)hint != 0x80)
         return false;
-    volume_read(volume, &hint, 494, sizeof(uint8_t));
+    if (!volume_read(volume, &hint, 494, sizeof(uint8_t)))
+        return false;
     if ((uint8_t)hint != 0x00 && (uint8_t)hint != 0x80)
         return false;
 
     char hintc[64];
-    volume_read(volume, hintc, 3, 4);
+    if (!volume_read(volume, hintc, 3, 4))
+        return false;
     if (memcmp(hintc, "NTFS", 4) == 0)
         return false;
-    volume_read(volume, hintc, 54, 3);
+    if (!volume_read(volume, hintc, 54, 3))
+        return false;
     if (memcmp(hintc, "FAT", 3) == 0)
         return false;
-    volume_read(volume, hintc, 82, 3);
+    if (!volume_read(volume, hintc, 82, 3))
+        return false;
     if (memcmp(hintc, "FAT", 3) == 0)
         return false;
-    volume_read(volume, hintc, 3, 5);
+    if (!volume_read(volume, hintc, 3, 5))
+        return false;
     if (memcmp(hintc, "FAT32", 5) == 0)
         return false;
-    volume_read(volume, &hint, 1080, sizeof(uint16_t));
+    if (!volume_read(volume, &hint, 1080, sizeof(uint16_t)))
+        return false;
     if (hint == 0xef53)
         return false;
 
@@ -352,7 +365,9 @@ uint32_t mbr_get_id(struct volume *volume) {
     }
 
     uint32_t ret;
-    volume_read(volume, &ret, 0x1b8, sizeof(uint32_t));
+    if (!volume_read(volume, &ret, 0x1b8, sizeof(uint32_t))) {
+        return 0;
+    }
 
     return ret;
 }
@@ -375,7 +390,9 @@ static int mbr_get_logical_part(struct volume *ret, struct volume *extended_part
     for (int i = 0; i < partition; i++) {
         uint64_t entry_offset = ebr_sector * 512 + 0x1ce;
 
-        volume_read(extended_part, &entry, entry_offset, sizeof(struct mbr_entry));
+        if (!volume_read(extended_part, &entry, entry_offset, sizeof(struct mbr_entry))) {
+            return END_OF_TABLE;
+        }
 
         if (entry.type != 0x0f && entry.type != 0x05) {
             return END_OF_TABLE;
@@ -398,7 +415,9 @@ static int mbr_get_logical_part(struct volume *ret, struct volume *extended_part
 
     uint64_t entry_offset = ebr_sector * 512 + 0x1be;
 
-    volume_read(extended_part, &entry, entry_offset, sizeof(struct mbr_entry));
+    if (!volume_read(extended_part, &entry, entry_offset, sizeof(struct mbr_entry))) {
+        return END_OF_TABLE;
+    }
 
     if (entry.type == 0)
         return NO_PARTITION;
@@ -468,7 +487,9 @@ static int mbr_get_part(struct volume *ret, struct volume *volume, int partition
         for (int i = 0; i < 4; i++) {
             uint64_t entry_offset = 0x1be + sizeof(struct mbr_entry) * i;
 
-            volume_read(volume, &entry, entry_offset, sizeof(struct mbr_entry));
+            if (!volume_read(volume, &entry, entry_offset, sizeof(struct mbr_entry))) {
+                continue;
+            }
 
             if (entry.type != 0x0f && entry.type != 0x05)
                 continue;
@@ -503,7 +524,9 @@ static int mbr_get_part(struct volume *ret, struct volume *volume, int partition
 
     uint64_t entry_offset = 0x1be + sizeof(struct mbr_entry) * partition;
 
-    volume_read(volume, &entry, entry_offset, sizeof(struct mbr_entry));
+    if (!volume_read(volume, &entry, entry_offset, sizeof(struct mbr_entry))) {
+        return END_OF_TABLE;
+    }
 
     if (entry.type == 0)
         return NO_PARTITION;
diff --git a/common/protos/chainload.c b/common/protos/chainload.c
index 59941907..d02c8a1b 100644
--- a/common/protos/chainload.c
+++ b/common/protos/chainload.c
@@ -161,7 +161,9 @@ noreturn void chainload(char *config, char *cmdline) {
             }
 
             uint32_t mbr_id_1;
-            volume_read(p, &mbr_id_1, 0x1b8, sizeof(uint32_t));
+            if (!volume_read(p, &mbr_id_1, 0x1b8, sizeof(uint32_t))) {
+                continue;
+            }
 
             if (mbr_id_1 == mbr_id) {
                 p = volume_get_by_coord(false, p->index, part);
@@ -182,7 +184,9 @@ load:
 
     void *buf = ext_mem_alloc(512);
 
-    volume_read(p, buf, 0, 512);
+    if (!volume_read(p, buf, 0, 512)) {
+        panic(true, "bios: Failed to read boot sector");
+    }
 
     uint16_t *boot_sig = (uint16_t *)(buf + 0x1fe);
 
tab: 248 wrap: offon