runtime-rs: Fix initdata length field missing when create block

The init data could not be read properly within kata-agent because the
data length field was omitted, a consequence of a mismatch in the data
write format.

Fixes #11556

Signed-off-by: alex.lyn <alex.lyn@antgroup.com>
This commit is contained in:
alex.lyn 2025-07-11 20:16:32 +08:00 committed by Fupan Li
parent b76efa2a25
commit 56c0c172fa

View File

@ -6,7 +6,7 @@
use flate2::{Compression, GzBuilder}; use flate2::{Compression, GzBuilder};
use std::{ use std::{
fmt, fs, fmt, fs,
io::{self, BufWriter, Seek, Write}, io::{self, BufWriter, Write},
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
use tempfile::NamedTempFile; use tempfile::NamedTempFile;
@ -159,7 +159,7 @@ fn create_compressed_block(
writer.write_all(MAGIC_HEADER)?; writer.write_all(MAGIC_HEADER)?;
info!(sl!(), "Magic header written: {:?}", MAGIC_HEADER); info!(sl!(), "Magic header written: {:?}", MAGIC_HEADER);
// 7. Configure compression level and initialize GZ writer // 7. First compress data to get the actual compressed size
let compression = let compression =
compression_level.map_or(Compression::best(), |lvl| Compression::new(lvl.min(9))); compression_level.map_or(Compression::best(), |lvl| Compression::new(lvl.min(9)));
@ -169,22 +169,24 @@ fn create_compressed_block(
compression.level() compression.level()
); );
let mut gz = GzBuilder::new() // Compress data to a temporary buffer first to get the compressed size
.filename("initdata.toml") // Embed original filename metadata let mut compressed_data = Vec::new();
.comment("Generated by Confidential Containers") {
.write(writer, compression); let mut gz = GzBuilder::new()
.filename("initdata.toml") // Embed original filename metadata
.comment("Generated by Confidential Containers")
.write(&mut compressed_data, compression);
// 8. Write data in chunks to avoid large memory allocation // Write data in chunks to avoid large memory allocation
let mut bytes_written = 0; for chunk in initdata.as_bytes().chunks(buffer_size) {
for chunk in initdata.as_bytes().chunks(buffer_size) { gz.write_all(chunk)?;
bytes_written += gz.write(chunk)?; }
// Finalize compression
gz.finish()?;
} }
info!(sl!(), "written {} bytes", bytes_written);
// 9. Finalize compression and retrieve writer
let mut writer = gz.finish()?;
let compressed_size = writer.stream_position()?;
let compressed_size = compressed_data.len() as u64;
info!( info!(
sl!(), sl!(),
"Data compressed: {} -> {} bytes (ratio: {:.2}%)", "Data compressed: {} -> {} bytes (ratio: {:.2}%)",
@ -193,8 +195,19 @@ fn create_compressed_block(
(compressed_size as f64 / initdata_size as f64) * 100.0 (compressed_size as f64 / initdata_size as f64) * 100.0
); );
// 8. Write compressed data length (8 bytes, little-endian)
writer.write_all(&compressed_size.to_le_bytes())?;
info!(
sl!(),
"Compressed data length written: {} bytes", compressed_size
);
// 9. Write compressed data
writer.write_all(&compressed_data)?;
info!(sl!(), "Compressed data written");
// 10. Calculate padding for sector alignment // 10. Calculate padding for sector alignment
let current_pos = compressed_size; let current_pos = MAGIC_HEADER.len() as u64 + 8 + compressed_size; // magic + length + data
let padding = (SECTOR_SIZE - (current_pos % SECTOR_SIZE)) % SECTOR_SIZE; let padding = (SECTOR_SIZE - (current_pos % SECTOR_SIZE)) % SECTOR_SIZE;
// 11. Zero-byte padding using small blocks // 11. Zero-byte padding using small blocks