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);
