@@ -6296,20 +6296,34 @@ int btrfs_read_sys_array(struct btrfs_root *root)
6296
6296
6297
6297
while (cur_offset < array_size ) {
6298
6298
disk_key = (struct btrfs_disk_key * )array_ptr ;
6299
+ len = sizeof (* disk_key );
6300
+ if (cur_offset + len > array_size )
6301
+ goto out_short_read ;
6302
+
6299
6303
btrfs_disk_key_to_cpu (& key , disk_key );
6300
6304
6301
- len = sizeof (* disk_key );
6302
6305
array_ptr += len ;
6303
6306
sb_array_offset += len ;
6304
6307
cur_offset += len ;
6305
6308
6306
6309
if (key .type == BTRFS_CHUNK_ITEM_KEY ) {
6307
6310
chunk = (struct btrfs_chunk * )sb_array_offset ;
6311
+ /*
6312
+ * At least one btrfs_chunk with one stripe must be
6313
+ * present, exact stripe count check comes afterwards
6314
+ */
6315
+ len = btrfs_chunk_item_size (1 );
6316
+ if (cur_offset + len > array_size )
6317
+ goto out_short_read ;
6318
+
6319
+ num_stripes = btrfs_chunk_num_stripes (sb , chunk );
6320
+ len = btrfs_chunk_item_size (num_stripes );
6321
+ if (cur_offset + len > array_size )
6322
+ goto out_short_read ;
6323
+
6308
6324
ret = read_one_chunk (root , & key , sb , chunk );
6309
6325
if (ret )
6310
6326
break ;
6311
- num_stripes = btrfs_chunk_num_stripes (sb , chunk );
6312
- len = btrfs_chunk_item_size (num_stripes );
6313
6327
} else {
6314
6328
ret = - EIO ;
6315
6329
break ;
@@ -6320,6 +6334,12 @@ int btrfs_read_sys_array(struct btrfs_root *root)
6320
6334
}
6321
6335
free_extent_buffer (sb );
6322
6336
return ret ;
6337
+
6338
+ out_short_read :
6339
+ printk (KERN_ERR "BTRFS: sys_array too short to read %u bytes at offset %u\n" ,
6340
+ len , cur_offset );
6341
+ free_extent_buffer (sb );
6342
+ return - EIO ;
6323
6343
}
6324
6344
6325
6345
int btrfs_read_chunk_tree (struct btrfs_root * root )
0 commit comments