Skip to content

Commit

Permalink
rafs: add special handling of invalid zero blob index
Browse files Browse the repository at this point in the history
The rafs v6 format reserves blob index 0 for meta blobs, so ensure
invalid zero blob index doesn't cause abnormal behavior.

Signed-off-by: Jiang Liu <gerry@linux.alibaba.com>
  • Loading branch information
jiangliu committed Jun 27, 2023
1 parent 65cf530 commit fc888c2
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 13 deletions.
28 changes: 18 additions & 10 deletions rafs/src/metadata/direct_v6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,16 @@ impl OndiskInodeWrapper {
is_tarfs_mode: bool,
is_tail: bool,
) -> Option<BlobIoDesc> {
let blob_index = chunk_addr.blob_index();
let blob_index = match chunk_addr.blob_index() {
Err(e) => {
warn!(
"failed to get blob index for chunk address {:?}, {}",
chunk_addr, e
);
return None;
}
Ok(v) => v,
};

match state.blob_table.get(blob_index) {
Err(e) => {
Expand All @@ -554,7 +563,7 @@ impl OndiskInodeWrapper {
} else {
self.chunk_size()
};
let chunk = TarfsChunkInfoV6::from_chunk_addr(chunk_addr, size);
let chunk = TarfsChunkInfoV6::from_chunk_addr(chunk_addr, size).ok()?;
let chunk = Arc::new(chunk) as Arc<dyn BlobChunkInfo>;
Some(BlobIoDesc::new(
blob,
Expand Down Expand Up @@ -1309,7 +1318,7 @@ impl RafsInodeExt for OndiskInodeWrapper {
let has_device = self.mapping.device.lock().unwrap().has_device();

if state.meta.has_inlined_chunk_digest() && has_device {
let blob_index = chunk_addr.blob_index();
let blob_index = chunk_addr.blob_index()?;
let chunk_index = chunk_addr.blob_ci_index();
let device = self.mapping.device.lock().unwrap();
device
Expand All @@ -1326,9 +1335,8 @@ impl RafsInodeExt for OndiskInodeWrapper {
} else {
self.chunk_size()
};
Ok(Arc::new(TarfsChunkInfoV6::from_chunk_addr(
chunk_addr, size,
)))
let chunk_info = TarfsChunkInfoV6::from_chunk_addr(chunk_addr, size)?;
Ok(Arc::new(chunk_info))
} else {
let mut chunk_map = self.mapping.info.chunk_map.lock().unwrap();
if chunk_map.is_none() {
Expand All @@ -1337,7 +1345,7 @@ impl RafsInodeExt for OndiskInodeWrapper {
match chunk_map.as_ref().unwrap().get(chunk_addr) {
None => Err(enoent!(format!(
"failed to get chunk info for chunk {}/{}/{}",
chunk_addr.blob_index(),
chunk_addr.blob_index().unwrap_or_default(),
chunk_addr.blob_ci_index(),
chunk_addr.block_addr()
))),
Expand Down Expand Up @@ -1468,11 +1476,11 @@ impl TarfsChunkInfoV6 {
}
}

fn from_chunk_addr(chunk_addr: &RafsV6InodeChunkAddr, size: u32) -> Self {
let blob_index = chunk_addr.blob_index();
fn from_chunk_addr(chunk_addr: &RafsV6InodeChunkAddr, size: u32) -> Result<Self> {
let blob_index = chunk_addr.blob_index()?;
let chunk_index = chunk_addr.blob_ci_index();
let offset = (chunk_addr.block_addr() as u64) << EROFS_BLOCK_BITS_9;
TarfsChunkInfoV6::new(blob_index, chunk_index, offset, size)
Ok(TarfsChunkInfoV6::new(blob_index, chunk_index, offset, size))
}
}

Expand Down
27 changes: 24 additions & 3 deletions rafs/src/metadata/layout/v6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1197,8 +1197,13 @@ impl RafsV6InodeChunkAddr {
/// The index in BlobInfo grows from 0, so when using this method to index the corresponding blob,
/// the index always needs to be minus 1
/// Get the blob index of the chunk.
pub fn blob_index(&self) -> u32 {
(u16::from_le(self.c_blob_addr_hi) & 0x00ff) as u32 - 1
pub fn blob_index(&self) -> Result<u32> {
let idx = (u16::from_le(self.c_blob_addr_hi) & 0x00ff) as u32;
if idx == 0 {
Err(einval!("invalid zero blob index from RafsV6InodeChunkAddr"))
} else {
Ok(idx - 1)
}
}

/// Set the blob index of the chunk.
Expand Down Expand Up @@ -2228,7 +2233,7 @@ mod tests {
writer.flush().unwrap();
let mut chunk2 = RafsV6InodeChunkAddr::new();
chunk2.load(&mut reader).unwrap();
assert_eq!(chunk2.blob_index(), 3);
assert_eq!(chunk2.blob_index().unwrap(), 3);
assert_eq!(chunk2.blob_ci_index(), 0x123456);
assert_eq!(chunk2.block_addr(), 0xa5a53412);
assert!(chunk2.validate(4));
Expand Down Expand Up @@ -2357,4 +2362,20 @@ mod tests {
assert!(entry2 == target1);
}
}

#[test]
fn test_invalid_blob_idx_from_chunk_addr() {
let mut addr = RafsV6InodeChunkAddr::new();
assert!(addr.blob_index().is_err());
addr.set_blob_index(8);
assert_eq!(addr.blob_index().unwrap(), 8);

assert_eq!(addr.blob_ci_index(), 0);
addr.set_blob_ci_index(131);
assert_eq!(addr.blob_ci_index(), 131);

assert_eq!(addr.block_addr(), 0);
addr.set_block_addr(179);
assert_eq!(addr.block_addr(), 179);
}
}

0 comments on commit fc888c2

Please sign in to comment.