}
static int
-valid_devblock(struct lafs_dev *db, sector_t addr)
+valid_devblock(struct lafs_dev *db, sector_t addr, sector_t size)
{
/* check that this devblock is valid, given that
* it was found at sector 'addr'
if (addr + (1<<db->statebits) > offset &&
addr < offset + segsize)
return 0;
+ if (addr + (1<<db->statebits) > (size << db->blockbits))
+ return 0;
}
- /* FIXME should range check segment_count, but need to know
- * size for that */
+ /* Check all segments fit within device */
+ if (le32_to_cpu(db->segment_offset) + segsize > (size << db->blockbits))
+ return 0;
+
if (le32_to_cpu(db->level) > 10)
return 0;
unsigned int n;
int i;
int have_dev = 0, have_state = 0;
+ sector_t devsize;
dv = &op->devlist[op->curr_dev];
BUG_ON(dv->devblock);
if (!pg)
return -ENOMEM;
+ devsize = i_size_read(bdev->bd_inode);
+
/* Now find a devblock, check the first two possible locations,
* and the last two. If two devblocks are found with different
* uuids, we are confused!
/* try to read block at 'sect' */
int ok = lafs_sync_page_io(bdev, sect, 0, n, pg, READ);
- if (ok && valid_devblock(page_address(pg), sect)) {
+ if (ok && valid_devblock(page_address(pg), sect, devsize)) {
if (!have_dev) {
have_dev = 1;
memcpy(dv->devblock, page_address(pg), n);
if (i != 1)
sect += (n>>9);
else {
- sect = bdev->bd_inode->i_size & ~(sector_t)(n-1);
+ sect = devsize & ~(sector_t)(n-1);
sect >>= 9;
sect -= (n>>9)*2;
}