Skip to content

Commit

Permalink
nydus-image: generate dm-verity data for block device
Browse files Browse the repository at this point in the history
Add `--verity` option to `nydus-image export --block` to generate
dm-verity data for block devices.

```
[root@iZ0jl3vazmhc81dur3xnm3Z image-service]# tar -cvf src.tar src
[root@iZ0jl3vazmhc81dur3xnm3Z image-service]# sha256sum src.tar
0e2dbe8b6e0f55f42c75034ed9dfc582ad0a94098cfc248c968522e7ef02e00a  src.tar
[root@iZ0jl3vazmhc81dur3xnm3Z image-service]# cp src.tar images/0e2dbe8b6e0f55f42c75034ed9dfc582ad0a94098cfc248c968522e7ef02e00a
[root@iZ0jl3vazmhc81dur3xnm3Z image-service]# target/debug/nydus-image create -t tar-tarfs -D images/ images/0e2dbe8b6e0f55f42c75034ed9dfc582ad0a94098cfc248c968522e7ef02e00a
[2023-03-27 16:32:00.068730 +08:00] INFO successfully built RAFS filesystem:
meta blob path: images/90f0e6e7e0ff822d4acddf30c36ac77fe06f549fe58f89a818fa824b19f70d47
data blob size: 0x3c000
data blobs: ["0e2dbe8b6e0f55f42c75034ed9dfc582ad0a94098cfc248c968522e7ef02e00a"]
[root@iZ0jl3vazmhc81dur3xnm3Z image-service]# target/debug/nydus-image export --block --verity -D images/ -B images/90f0e6e7e0ff822d4acddf30c36ac77fe06f549fe58f89a818fa824b19f70d47
[2023-03-27 23:49:14.450762 +08:00] INFO RAFS features: COMPRESSION_NONE | HASH_SHA256 | EXPLICIT_UID_GID | TARTFS_MODE
dm-verity options: --no-superblock --format=1 -s "" --hash=sha256 --data-block-size=4096 --hash-block-size=4096 --data-blocks 572 --hash-offset 2342912 ab7b417fc284c3b58a72044a996ec55e2c68a8b9dcf10bc469f4e640e5d98e6a
losetup -r /dev/loop1 images/90f0e6e7e0ff822d4acddf30c36ac77fe06f549fe58f89a818fa824b19f70d47.disk
[root@iZ0jl3vazmhc81dur3xnm3Z image-service]# veritysetup open -v --no-superblock --format=1 -s "" --hash=sha256 --data-block-size=4096 --hash-block-size=4096 --data-blocks 572 --hash-offset 2342912 /dev/loop1 verity /dev/loop1 ab7b417fc284c3b58a72044a996ec55e2c68a8b9dcf10bc469f4e640e5d98e6a
[root@iZ0jl3vazmhc81dur3xnm3Z image-service]# veritysetup status verity
/dev/mapper/verity is active.
  type:        VERITY
  status:      verified
  hash type:   1
  data block:  4096
  hash block:  4096
  hash name:   sha256
  salt:        -
  data device: /dev/loop1
  data loop:   /root/image-service/images/90f0e6e7e0ff822d4acddf30c36ac77fe06f549fe58f89a818fa824b19f70d47.disk
  size:        4576 sectors
  mode:        readonly
  hash device: /dev/loop1
  hash loop:   /root/image-service/images/90f0e6e7e0ff822d4acddf30c36ac77fe06f549fe58f89a818fa824b19f70d47.disk
  hash offset: 4576 sectors
  root hash:   ab7b417fc284c3b58a72044a996ec55e2c68a8b9dcf10bc469f4e640e5d98e6a
```

Signed-off-by: Jiang Liu <gerry@linux.alibaba.com>
  • Loading branch information
jiangliu committed Mar 28, 2023
1 parent c978f39 commit f96abb0
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 6 deletions.
76 changes: 71 additions & 5 deletions service/src/block_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use std::cmp::{max, min};
use std::fs::OpenOptions;
use std::io::Result;
use std::path::PathBuf;
use std::sync::Arc;
use std::sync::{Arc, Mutex};
use std::thread;
use std::thread::JoinHandle;

Expand All @@ -25,11 +25,15 @@ use nydus_rafs::metadata::layout::v6::{
EROFS_BLOCK_BITS_12, EROFS_BLOCK_BITS_9, EROFS_BLOCK_SIZE_4096, EROFS_BLOCK_SIZE_512,
};
use nydus_storage::utils::alloc_buf;
use nydus_utils::digest::RafsDigest;
use nydus_utils::verity::VerityGenerator;
use nydus_utils::{digest, div_round_up, round_up_usize};
use tokio_uring::buf::IoBufMut;

use crate::blob_cache::{generate_blob_key, BlobCacheMgr, BlobConfig, DataBlob, MetaBlob};

const BLOCK_DEVICE_EXPORT_BATCH_SIZE: usize = 0x80000;
const VERITY_PAGE_SIZE: usize = 4096;

enum BlockRange {
Hole,
Expand Down Expand Up @@ -287,6 +291,7 @@ impl BlockDevice {
output: Option<String>,
localfs_dir: Option<String>,
threads: u32,
verity: bool,
) -> Result<()> {
let cache_mgr = Arc::new(BlobCacheMgr::new());
cache_mgr.add_blob_entry(&blob_entry).map_err(|e| {
Expand Down Expand Up @@ -353,6 +358,31 @@ impl BlockDevice {
})?;
let output_file = Arc::new(tokio_uring::fs::File::from_std(output_file));

let mut verity_offset = 0;
let mut verity_pages = 0;
let generator = if verity {
let file = OpenOptions::new()
.read(true)
.write(true)
.open(&path)
.map_err(|e| {
eother!(format!(
"block_device: failed to create output file {}, {}",
path.display(),
e
))
})?;
let blocks = block_device.blocks();
let offset = block_device.blocks_to_size(blocks);
verity_pages = div_round_up(offset, VERITY_PAGE_SIZE as u64) as u32;
verity_offset = verity_pages as u64 * VERITY_PAGE_SIZE as u64;
let mut generator = VerityGenerator::new(file, offset, verity_pages)?;
generator.initialize()?;
Some(Arc::new(Mutex::new(generator)))
} else {
None
};

let blocks = block_device.blocks();
let batch_size = BLOCK_DEVICE_EXPORT_BATCH_SIZE as u32 / block_device.block_size() as u32;
assert_eq!(batch_size.count_ones(), 1);
Expand All @@ -363,8 +393,9 @@ impl BlockDevice {
}

if threads == 1 {
let generator = generator.clone();
tokio_uring::start(async move {
Self::do_export(block_device.clone(), output_file, 0, block_device.blocks()).await
Self::do_export(block_device, output_file, 0, blocks, generator).await
})?;
} else {
let mut thread_handlers: Vec<JoinHandle<Result<()>>> =
Expand All @@ -377,6 +408,7 @@ impl BlockDevice {
let mgr = cache_mgr.clone();
let id = blob_id.clone();
let path = path.to_path_buf();
let generator = generator.clone();

let handler = thread::spawn(move || {
let output_file = OpenOptions::new()
Expand All @@ -399,9 +431,9 @@ impl BlockDevice {
})?;
let device = Arc::new(block_device);

tokio_uring::start(
async move { Self::do_export(device, file, pos, count).await },
)?;
tokio_uring::start(async move {
Self::do_export(device, file, pos, count, generator).await
})?;
Ok(())
});
pos += count;
Expand All @@ -424,6 +456,21 @@ impl BlockDevice {
})?;
}
}

if let Some(generator) = generator.as_ref() {
let mut guard = generator.lock().unwrap();
let root_digest = guard.generate_all_digests()?;
let root_digest: String = root_digest
.data
.iter()
.map(|v| format!("{:02x}", v))
.collect();
println!(
"dm-verity options: --no-superblock --format=1 -s \"\" --hash=sha256 --data-block-size=4096 --hash-block-size=4096 --data-blocks {} --hash-offset {} {}",
verity_pages, verity_offset, root_digest
);
}

Ok(())
}

Expand All @@ -432,6 +479,7 @@ impl BlockDevice {
output_file: Arc<tokio_uring::fs::File>,
start: u32,
mut blocks: u32,
generator: Option<Arc<Mutex<VerityGenerator>>>,
) -> Result<()> {
let batch_size = BLOCK_DEVICE_EXPORT_BATCH_SIZE as u32 / block_device.block_size() as u32;
let mut pos = start;
Expand Down Expand Up @@ -462,6 +510,24 @@ impl BlockDevice {
}
buf = buf2;

// Generate Merkle tree leaf nodes.
if let Some(generator) = generator.as_ref() {
let mut page_idx =
(block_device.blocks_to_size(pos) / VERITY_PAGE_SIZE as u64) as u32;
let mut offset = 0;
let size = round_up_usize(buf.len(), VERITY_PAGE_SIZE);
while offset < size {
let digest = RafsDigest::from_buf(
&buf[offset..offset + VERITY_PAGE_SIZE],
digest::Algorithm::Sha256,
);
let mut guard = generator.lock().unwrap();
guard.set_digest(1, page_idx, &digest.data)?;
offset += VERITY_PAGE_SIZE;
page_idx += 1;
}
}

pos += count;
blocks -= count;
}
Expand Down
10 changes: 9 additions & 1 deletion src/bin/nydus-image/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,13 @@ fn prepare_cmd_args(bti_string: &'static str) -> App {
.help("File path for saving the exported content")
.required_unless_present("localfs-dir")
)
.arg(
Arg::new("verity")
.long("verity")
.help("Generate dm-verity data for block device")
.action(ArgAction::SetTrue)
.requires("block")
)
);

let app = app.subcommand(
Expand Down Expand Up @@ -1558,8 +1565,9 @@ impl Command {
.map(|n| n.parse().unwrap_or(1))
.unwrap_or(1);
let output = subargs.value_of("output").map(|v| v.to_string());
let verity = subargs.is_present("verity");

BlockDevice::export(entry, output, localfs_dir, threads)
BlockDevice::export(entry, output, localfs_dir, threads, verity)
.context("failed to export RAFS filesystem as raw block device image")
}
}
Expand Down

0 comments on commit f96abb0

Please sign in to comment.