src/storage/blobfs/common.cc
// Validate the metadata for the superblock, given a maximum number of
// available blocks.
Validate the metadata for the superblock, given a maximum number of
available blocks.
Validate the metadata for the superblock given a maximum number of available blocks .
zx_status_t CheckSuperblock(const Superblock* info, uint64_t max) {
  if ((info->magic0 != kBlobfsMagic0) || (info->magic1 != kBlobfsMagic1)) {
    FS_TRACE_ERROR("blobfs: bad magic\n");
    return ZX_ERR_INVALID_ARGS;
  }
  if (info->version != kBlobfsVersion) {
    FS_TRACE_ERROR("blobfs: FS Version: %08x. Driver version: %08x\n", info->version,
                   kBlobfsVersion);
    DumpSuperblock(*info, stderr);
    return ZX_ERR_INVALID_ARGS;
  }
  if (info->block_size != kBlobfsBlockSize) {
    FS_TRACE_ERROR("blobfs: bsz %u unsupported\n", info->block_size);
    DumpSuperblock(*info, stderr);
    return ZX_ERR_INVALID_ARGS;
  }
  if (info->data_block_count < kMinimumDataBlocks) {
    FS_TRACE_ERROR("blobfs: Not enough space for minimum data partition\n");
    return ZX_ERR_NO_SPACE;
  }
#ifdef __Fuchsia__
  if ((info->flags & kBlobFlagClean) == 0) {
    FS_TRACE_ERROR("blobfs: filesystem in dirty state. Was not unmounted cleanly.\n");
  } else {
    FS_TRACE_INFO("blobfs: filesystem in clean state.\n");
  }
#endif
  uint64_t total_inode_size;
  if (mul_overflow(info->inode_count, sizeof(Inode), &total_inode_size)) {
    FS_TRACE_ERROR("Multiplication overflow");
    return ZX_ERR_OUT_OF_RANGE;
  }
  uint64_t node_map_size;
  if (mul_overflow(NodeMapBlocks(*info), kBlobfsBlockSize, &node_map_size)) {
    FS_TRACE_ERROR("Multiplication overflow");
    return ZX_ERR_OUT_OF_RANGE;
  }
  if (total_inode_size != node_map_size) {
    FS_TRACE_ERROR("blobfs: Inode table block must be entirely filled\n");
    return ZX_ERR_BAD_STATE;
  }
  if (info->journal_block_count < kMinimumJournalBlocks) {
    FS_TRACE_ERROR("blobfs: Not enough space for minimum journal partition\n");
    return ZX_ERR_NO_SPACE;
  }
  if ((info->flags & kBlobFlagFVM) == 0) {
    if (TotalBlocks(*info) > max) {
      FS_TRACE_ERROR("blobfs: too large for device\n");
      DumpSuperblock(*info, stderr);
      return ZX_ERR_INVALID_ARGS;
    }
  } else {
    const size_t blocks_per_slice = info->slice_size / info->block_size;
    size_t abm_blocks_needed = BlockMapBlocks(*info);
    size_t abm_blocks_allocated = info->abm_slices * blocks_per_slice;
    if (abm_blocks_needed > abm_blocks_allocated) {
      FS_TRACE_ERROR("blobfs: Not enough slices for block bitmap\n");
      DumpSuperblock(*info, stderr);
      return ZX_ERR_INVALID_ARGS;
    } else if (abm_blocks_allocated + BlockMapStartBlock(*info) >= NodeMapStartBlock(*info)) {
      FS_TRACE_ERROR("blobfs: Block bitmap collides into node map\n");
      DumpSuperblock(*info, stderr);
      return ZX_ERR_INVALID_ARGS;
    }
    size_t ino_blocks_needed = NodeMapBlocks(*info);
    size_t ino_blocks_allocated = info->ino_slices * blocks_per_slice;
    if (ino_blocks_needed > ino_blocks_allocated) {
      FS_TRACE_ERROR("blobfs: Not enough slices for node map\n");
      DumpSuperblock(*info, stderr);
      return ZX_ERR_INVALID_ARGS;
    } else if (ino_blocks_allocated + NodeMapStartBlock(*info) >= DataStartBlock(*info)) {
      FS_TRACE_ERROR("blobfs: Node bitmap collides into data blocks\n");
      DumpSuperblock(*info, stderr);
      return ZX_ERR_INVALID_ARGS;
    }
    size_t dat_blocks_needed = DataBlocks(*info);
    size_t dat_blocks_allocated = info->dat_slices * blocks_per_slice;
    if (dat_blocks_needed < kStartBlockMinimum) {
      FS_TRACE_ERROR("blobfs: Partition too small; no space left for data blocks\n");
      DumpSuperblock(*info, stderr);
      return ZX_ERR_INVALID_ARGS;
    } else if (dat_blocks_needed > dat_blocks_allocated) {
      FS_TRACE_ERROR("blobfs: Not enough slices for data blocks\n");
      DumpSuperblock(*info, stderr);
      return ZX_ERR_INVALID_ARGS;
    } else if (dat_blocks_allocated + DataStartBlock(*info) >
               std::numeric_limits<uint32_t>::max()) {
      FS_TRACE_ERROR("blobfs: Data blocks overflow uint32\n");
      DumpSuperblock(*info, stderr);
      return ZX_ERR_INVALID_ARGS;
    }
  }
  return ZX_OK;
}
zx_status_t CheckSuperblock ( const Superblock * info , uint64_t max ) { if ( ( info -> magic0 != kBlobfsMagic0 ) || ( info -> magic1 != kBlobfsMagic1 ) ) { FS_TRACE_ERROR ( " \n " ) ; return ZX_ERR_INVALID_ARGS ; } if ( info -> version != kBlobfsVersion ) { FS_TRACE_ERROR ( " \n " , info -> version , kBlobfsVersion ) ; DumpSuperblock ( * info , stderr ) ; return ZX_ERR_INVALID_ARGS ; } if ( info -> block_size != kBlobfsBlockSize ) { FS_TRACE_ERROR ( " \n " , info -> block_size ) ; DumpSuperblock ( * info , stderr ) ; return ZX_ERR_INVALID_ARGS ; } if ( info -> data_block_count < kMinimumDataBlocks ) { FS_TRACE_ERROR ( " \n " ) ; return ZX_ERR_NO_SPACE ; } #ifdef __Fuchsia__ if ( ( info -> flags & kBlobFlagClean ) == 0 ) { FS_TRACE_ERROR ( " \n " ) ; } else { FS_TRACE_INFO ( " \n " ) ; } #endif uint64_t total_inode_size ; if ( mul_overflow ( info -> inode_count , sizeof ( Inode ) , & total_inode_size ) ) { FS_TRACE_ERROR ( " " ) ; return ZX_ERR_OUT_OF_RANGE ; } uint64_t node_map_size ; if ( mul_overflow ( NodeMapBlocks ( * info ) , kBlobfsBlockSize , & node_map_size ) ) { FS_TRACE_ERROR ( " " ) ; return ZX_ERR_OUT_OF_RANGE ; } if ( total_inode_size != node_map_size ) { FS_TRACE_ERROR ( " \n " ) ; return ZX_ERR_BAD_STATE ; } if ( info -> journal_block_count < kMinimumJournalBlocks ) { FS_TRACE_ERROR ( " \n " ) ; return ZX_ERR_NO_SPACE ; } if ( ( info -> flags & kBlobFlagFVM ) == 0 ) { if ( TotalBlocks ( * info ) > max ) { FS_TRACE_ERROR ( " \n " ) ; DumpSuperblock ( * info , stderr ) ; return ZX_ERR_INVALID_ARGS ; } } else { const size_t blocks_per_slice = info -> slice_size / info -> block_size ; size_t abm_blocks_needed = BlockMapBlocks ( * info ) ; size_t abm_blocks_allocated = info -> abm_slices * blocks_per_slice ; if ( abm_blocks_needed > abm_blocks_allocated ) { FS_TRACE_ERROR ( " \n " ) ; DumpSuperblock ( * info , stderr ) ; return ZX_ERR_INVALID_ARGS ; } else if ( abm_blocks_allocated + BlockMapStartBlock ( * info ) >= NodeMapStartBlock ( * info ) ) { FS_TRACE_ERROR ( " \n " ) ; DumpSuperblock ( * info , stderr ) ; return ZX_ERR_INVALID_ARGS ; } size_t ino_blocks_needed = NodeMapBlocks ( * info ) ; size_t ino_blocks_allocated = info -> ino_slices * blocks_per_slice ; if ( ino_blocks_needed > ino_blocks_allocated ) { FS_TRACE_ERROR ( " \n " ) ; DumpSuperblock ( * info , stderr ) ; return ZX_ERR_INVALID_ARGS ; } else if ( ino_blocks_allocated + NodeMapStartBlock ( * info ) >= DataStartBlock ( * info ) ) { FS_TRACE_ERROR ( " \n " ) ; DumpSuperblock ( * info , stderr ) ; return ZX_ERR_INVALID_ARGS ; } size_t dat_blocks_needed = DataBlocks ( * info ) ; size_t dat_blocks_allocated = info -> dat_slices * blocks_per_slice ; if ( dat_blocks_needed < kStartBlockMinimum ) { FS_TRACE_ERROR ( " \n " ) ; DumpSuperblock ( * info , stderr ) ; return ZX_ERR_INVALID_ARGS ; } else if ( dat_blocks_needed > dat_blocks_allocated ) { FS_TRACE_ERROR ( " \n " ) ; DumpSuperblock ( * info , stderr ) ; return ZX_ERR_INVALID_ARGS ; } else if ( dat_blocks_allocated + DataStartBlock ( * info ) > std :: numeric_limits < uint32_t > :: max ( ) ) { FS_TRACE_ERROR ( " \n " ) ; DumpSuperblock ( * info , stderr ) ; return ZX_ERR_INVALID_ARGS ; } } return ZX_OK ; }
Validate the metadata for the superblock, given a maximum number of
available blocks.
Validate the metadata for the superblock given a maximum number of available blocks .
// Determine the number of blocks necessary for the block map and node map.