-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #723 from ReFirmLabs/btrfs_support
Btrfs support
- Loading branch information
Showing
7 changed files
with
133 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
use crate::signatures::common::{SignatureError, SignatureResult, CONFIDENCE_MEDIUM}; | ||
use crate::structures::btrfs::parse_btrfs_header; | ||
|
||
/// Human readable description | ||
pub const DESCRIPTION: &str = "BTRFS file system"; | ||
|
||
/// BTRFS magic bytes | ||
pub fn btrfs_magic() -> Vec<Vec<u8>> { | ||
vec![b"_BHRfS_M".to_vec()] | ||
} | ||
|
||
/// Validates the BTRFS header | ||
pub fn btrfs_parser(file_data: &[u8], offset: usize) -> Result<SignatureResult, SignatureError> { | ||
// Offset of the superblock magic bytes in a BTRFS image | ||
const MAGIC_OFFSET: usize = 0x10040; | ||
|
||
// Successful return value | ||
let mut result = SignatureResult { | ||
description: DESCRIPTION.to_string(), | ||
confidence: CONFIDENCE_MEDIUM, | ||
..Default::default() | ||
}; | ||
|
||
// Sanity check the reported offset | ||
if offset >= MAGIC_OFFSET { | ||
// Actual offset is the location of the magic bytes minus the magic byte offset | ||
result.offset = offset - MAGIC_OFFSET; | ||
|
||
// Parse the superblock header; this also validates the superblock CRC | ||
if let Ok(btrfs_header) = parse_btrfs_header(&file_data[result.offset..]) { | ||
result.size = btrfs_header.total_size; | ||
result.description = format!( | ||
"{}, node size: {}, sector size: {}, leaf size: {}, stripe size: {}, bytes used: {}, total size: {} bytes", | ||
result.description, btrfs_header.node_size, btrfs_header.sector_size, btrfs_header.leaf_size, btrfs_header.stripe_size, btrfs_header.bytes_used, result.size | ||
); | ||
return Ok(result); | ||
} | ||
} | ||
|
||
Err(SignatureError) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
use crate::structures::common::{self, StructureError}; | ||
use crc32c::crc32c; | ||
|
||
/// Struct to store BTRFS super block info | ||
#[derive(Debug, Default, Clone)] | ||
pub struct BTRFSHeader { | ||
pub bytes_used: usize, | ||
pub total_size: usize, | ||
pub leaf_size: usize, | ||
pub node_size: usize, | ||
pub stripe_size: usize, | ||
pub sector_size: usize, | ||
} | ||
|
||
/// Parse and validate a BTRFS super block | ||
pub fn parse_btrfs_header(btrfs_data: &[u8]) -> Result<BTRFSHeader, StructureError> { | ||
const SUPERBLOCK_OFFSET: usize = 0x10000; | ||
const SUPERBLOCK_END: usize = SUPERBLOCK_OFFSET + 0x1000; | ||
const CRC_START: usize = 0x20; | ||
|
||
// Partial BTRFS superblock structure for obtaining image size and CRC validation | ||
// https://archive.kernel.org/oldwiki/btrfs.wiki.kernel.org/index.php/On-disk_Format.html#Superblock | ||
let btrfs_structure = vec![ | ||
("header_checksum", "u32"), | ||
("unused1", "u32"), | ||
("unused2", "u64"), | ||
("unused3", "u64"), | ||
("unused4", "u64"), | ||
("uuid_p1", "u64"), | ||
("uuid_p2", "u64"), | ||
("block_phys_addr", "u64"), | ||
("flags", "u64"), | ||
("magic", "u64"), | ||
("generation", "u64"), | ||
("root_tree_address", "u64"), | ||
("chunk_tree_address", "u64"), | ||
("log_tree_address", "u64"), | ||
("log_root_transid", "u64"), | ||
("total_bytes", "u64"), | ||
("bytes_used", "u64"), | ||
("root_dir_objid", "u64"), | ||
("num_devices", "u64"), | ||
("sector_size", "u32"), | ||
("node_size", "u32"), | ||
("leaf_size", "u32"), | ||
("stripe_size", "u32"), | ||
]; | ||
|
||
// Parse the header | ||
if let Some(btrfs_header_data) = btrfs_data.get(SUPERBLOCK_OFFSET..SUPERBLOCK_END) { | ||
if let Ok(btrfs_header) = common::parse(btrfs_header_data, &btrfs_structure, "little") { | ||
// Validate the superblock CRC | ||
if btrfs_header["header_checksum"] == (crc32c(&btrfs_header_data[CRC_START..]) as usize) | ||
{ | ||
return Ok(BTRFSHeader { | ||
sector_size: btrfs_header["sector_size"], | ||
node_size: btrfs_header["node_size"], | ||
leaf_size: btrfs_header["leaf_size"], | ||
stripe_size: btrfs_header["stripe_size"], | ||
bytes_used: btrfs_header["bytes_used"], | ||
total_size: btrfs_header["total_bytes"], | ||
}); | ||
} | ||
} | ||
} | ||
|
||
Err(StructureError) | ||
} |