mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
rust/(pv|pvimg): Add Secure Execution boot image metadata
Add metadata about the image to the Secure Execution image. This helps to identify where the Secure Execution header is located in the image and therefore it's less prone to errors to locate the header. This patch adds the support for it to 'pvimg' as well as to the 'pvsecret' and 'pvattest' tools. Reviewed-by: Steffen Eiden <seiden@linux.ibm.com> Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
committed by
Jan Höppner
parent
f4cf4ae6eb
commit
d2de7f2808
@@ -24,9 +24,9 @@ use pvimg::{
|
||||
};
|
||||
|
||||
use crate::se_img_comps::{
|
||||
create_ipib, ipib::Ipib, kernel::S390Kernel, render_stage3a, render_stage3b, sehdr::SeHdrComp,
|
||||
shortpsw::ShortPSWComp, stage3a_path, stage3b_path, CompTweakV1, Component, ComponentKind,
|
||||
STAGE3A_ENTRY, STAGE3A_INIT_ENTRY, STAGE3A_LOAD_ADDRESS,
|
||||
create_ipib, ipib::Ipib, kernel::S390Kernel, metadata::ImgMetaData, render_stage3a,
|
||||
render_stage3b, sehdr::SeHdrComp, shortpsw::ShortPSWComp, stage3a_path, stage3b_path,
|
||||
CompTweakV1, Component, ComponentKind, STAGE3A_ENTRY, STAGE3A_INIT_ENTRY, STAGE3A_LOAD_ADDRESS,
|
||||
};
|
||||
|
||||
pub struct SeHdrArgs<'a> {
|
||||
@@ -408,6 +408,10 @@ impl<W: Write + Seek> SeImgBuilder<W> {
|
||||
.ok_or(Error::UnexpectedOverflow)?,
|
||||
)?;
|
||||
|
||||
// Create and write Secure Execution boot image meta data right after the short PSW
|
||||
let _metadata_img_comp =
|
||||
self.add_metadata(ipib_img_comp.src.start, sehdr_img_comp.src.start)?;
|
||||
|
||||
Ok(self.comps)
|
||||
}
|
||||
|
||||
@@ -440,6 +444,18 @@ impl<W: Write + Seek> SeImgBuilder<W> {
|
||||
self.insert_nonsecure_component(&mut short_psw_comp, ShortPSWComp::OFFSET)
|
||||
}
|
||||
|
||||
/// Prepare Secure Execution image metadata and write it to the file
|
||||
fn add_metadata(&mut self, ipib_off: u64, hdr_off: u64) -> Result<Rc<ImgComponent>> {
|
||||
let mut metadata_comp = ImgMetaData::new(ipib_off, hdr_off)?;
|
||||
|
||||
let metadata_img_comp =
|
||||
self.insert_nonsecure_component(&mut metadata_comp, ImgMetaData::OFFSET)?;
|
||||
if metadata_img_comp.src.size() > ImgMetaData::MAX_SIZE {
|
||||
unreachable!("The metadata should never be larger than the BSS size of stage3a");
|
||||
}
|
||||
Ok(metadata_img_comp)
|
||||
}
|
||||
|
||||
/// Prepare stage3b and write it to file
|
||||
fn add_stage3b(&mut self, psw: PSW) -> Result<Rc<ImgComponent>> {
|
||||
// Prepare stage3b - for this we must prepare the arguments for it. Since we
|
||||
|
||||
@@ -14,8 +14,8 @@ use pv::request::random_array;
|
||||
use pvimg::{error::Result, secured_comp::ComponentTrait};
|
||||
|
||||
use self::{
|
||||
cmdline::Cmdline, kernel::S390Kernel, ramdisk::Ramdisk, sehdr::SeHdrComp,
|
||||
shortpsw::ShortPSWComp, stage3a::Stage3a, stage3b::Stage3b,
|
||||
cmdline::Cmdline, kernel::S390Kernel, metadata::ImgMetaData, ramdisk::Ramdisk,
|
||||
sehdr::SeHdrComp, shortpsw::ShortPSWComp, stage3a::Stage3a, stage3b::Stage3b,
|
||||
};
|
||||
pub use crate::se_img_comps::bootloader::{
|
||||
create_ipib, render_stage3a, render_stage3b, stage3a_path, stage3b_path, STAGE3A_ENTRY,
|
||||
@@ -28,6 +28,7 @@ mod bootloader;
|
||||
pub mod cmdline;
|
||||
pub mod ipib;
|
||||
pub mod kernel;
|
||||
pub mod metadata;
|
||||
pub mod ramdisk;
|
||||
pub mod sehdr;
|
||||
pub mod shortpsw;
|
||||
@@ -115,6 +116,7 @@ pub fn check_components(components: &mut [Component]) -> Result<(), anyhow::Erro
|
||||
#[enum_dispatch(ComponentCheckTrait)]
|
||||
pub enum Component {
|
||||
ShortPSW(ShortPSWComp),
|
||||
ImgMetaData(ImgMetaData),
|
||||
Stage3a(Stage3a),
|
||||
Kernel(S390Kernel),
|
||||
Ramdisk(Ramdisk),
|
||||
@@ -137,6 +139,7 @@ impl Seek for Component {
|
||||
Self::Stage3b(obj) => obj.seek(pos),
|
||||
Self::SeHdr(obj) => obj.seek(pos),
|
||||
Self::Ipib(obj) => obj.seek(pos),
|
||||
Self::ImgMetaData(obj) => obj.seek(pos),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -154,6 +157,7 @@ impl Read for Component {
|
||||
Self::Stage3b(obj) => obj.read(buf),
|
||||
Self::SeHdr(obj) => obj.read(buf),
|
||||
Self::Ipib(obj) => obj.read(buf),
|
||||
Self::ImgMetaData(obj) => obj.read(buf),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -171,6 +175,7 @@ impl ComponentTrait<ComponentKind> for Component {
|
||||
Self::Stage3b(obj) => obj.secure_mode(),
|
||||
Self::SeHdr(obj) => obj.secure_mode(),
|
||||
Self::Ipib(obj) => obj.secure_mode(),
|
||||
Self::ImgMetaData(obj) => obj.secure_mode(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,6 +189,7 @@ impl ComponentTrait<ComponentKind> for Component {
|
||||
Self::Stage3b(obj) => obj.kind(),
|
||||
Self::SeHdr(obj) => obj.kind(),
|
||||
Self::Ipib(obj) => obj.kind(),
|
||||
Self::ImgMetaData(obj) => obj.kind(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -221,6 +227,7 @@ impl Seek for CompReader {
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq)]
|
||||
pub enum ComponentKind {
|
||||
ShortPSW = 10,
|
||||
ImgMetaData = 20,
|
||||
Stage3a = 30,
|
||||
Kernel = 40,
|
||||
Ramdisk = 50,
|
||||
@@ -243,20 +250,17 @@ impl ComponentKind {
|
||||
|
||||
impl Display for ComponentKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
Display::fmt(
|
||||
&match self {
|
||||
Self::Kernel => "Linux kernel",
|
||||
Self::Ramdisk => "ramdisk",
|
||||
Self::Cmdline => "kernel cmdline",
|
||||
Self::Stage3a => "stage3a",
|
||||
Self::Stage3b => "stage3b",
|
||||
Self::SeHdr => "Secure Execution header",
|
||||
Self::Ipib => "IPIB",
|
||||
Self::ShortPSW => "short PSW",
|
||||
}
|
||||
.to_string(),
|
||||
f,
|
||||
)
|
||||
match self {
|
||||
Self::Kernel => write!(f, "Linux kernel"),
|
||||
Self::Ramdisk => write!(f, "ramdisk"),
|
||||
Self::Cmdline => write!(f, "kernel cmdline"),
|
||||
Self::Stage3a => write!(f, "stage3a"),
|
||||
Self::Stage3b => write!(f, "stage3b"),
|
||||
Self::SeHdr => write!(f, "Secure Execution header"),
|
||||
Self::Ipib => write!(f, "IPIB"),
|
||||
Self::ShortPSW => write!(f, "short PSW"),
|
||||
Self::ImgMetaData => write!(f, "Image metadata"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,6 +317,7 @@ mod tests {
|
||||
fn component_kind_strategy() -> impl Strategy<Value = ComponentKind> {
|
||||
prop_oneof![
|
||||
Just(ComponentKind::ShortPSW),
|
||||
Just(ComponentKind::ImgMetaData),
|
||||
Just(ComponentKind::Stage3a),
|
||||
Just(ComponentKind::Kernel),
|
||||
Just(ComponentKind::Ramdisk),
|
||||
|
||||
@@ -15,7 +15,9 @@ use pvimg::{
|
||||
secured_comp::Interval,
|
||||
};
|
||||
|
||||
pub use self::stage3a_defs::{STAGE3A_ENTRY, STAGE3A_INIT_ENTRY, STAGE3A_LOAD_ADDRESS};
|
||||
pub use self::stage3a_defs::{
|
||||
STAGE3A_BSS_ADDRESS, STAGE3A_BSS_SIZE, STAGE3A_ENTRY, STAGE3A_INIT_ENTRY, STAGE3A_LOAD_ADDRESS,
|
||||
};
|
||||
use self::{
|
||||
ipl::{
|
||||
ipl_parameter_block, ipl_pb0_pv, ipl_pb0_pv_comp, ipl_pbt_IPL_PBT_PV, ipl_pl_hdr,
|
||||
@@ -78,8 +80,8 @@ pub fn render_stage3a(
|
||||
let stage3a_size = stage3a.len();
|
||||
let stage3a_size_u64: u64 = stage3a_size.try_into()?;
|
||||
|
||||
if stage3a_size < 24 {
|
||||
unreachable!("Bug!");
|
||||
if stage3a_size <= 24 {
|
||||
return Err(Error::InvalidStage3a);
|
||||
}
|
||||
let stage3a_data_addr = stage3a_addr
|
||||
.checked_add(stage3a_size_u64)
|
||||
@@ -151,6 +153,7 @@ pub fn render_stage3b(
|
||||
| ComponentKind::Ipib
|
||||
| ComponentKind::SeHdr
|
||||
| ComponentKind::ShortPSW
|
||||
| ComponentKind::ImgMetaData
|
||||
| ComponentKind::Stage3b => unreachable!(),
|
||||
}
|
||||
Ok(())
|
||||
@@ -171,7 +174,9 @@ pub fn render_stage3b(
|
||||
let stage3b_args_bin_len = stage3b_args_bin.len();
|
||||
|
||||
// Insert the stage3b arguments
|
||||
assert!(stage3b_len > stage3b_args_bin_len);
|
||||
if stage3b_len <= stage3b_args_bin_len {
|
||||
return Err(Error::InvalidStage3b);
|
||||
}
|
||||
let stage3b_parms_off = stage3b_len - stage3b_args_bin_len;
|
||||
stage3b.splice(stage3b_parms_off.., stage3b_args_bin);
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright IBM Corp. 2024
|
||||
|
||||
use std::io::{Cursor, Read, Seek};
|
||||
|
||||
use pv::{request::SeImgMetaData, static_assert};
|
||||
use pvimg::error::Result;
|
||||
|
||||
use super::{
|
||||
bootloader::{STAGE3A_BSS_ADDRESS, STAGE3A_BSS_SIZE},
|
||||
CompReader, ComponentCheckCtx, ComponentCheckTrait, ComponentKind, ComponentTrait,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ImgMetaData(CompReader);
|
||||
static_assert!(ImgMetaData::OFFSET == SeImgMetaData::OFFSET);
|
||||
|
||||
impl ImgMetaData {
|
||||
pub const MAX_SIZE: u64 = STAGE3A_BSS_SIZE;
|
||||
pub const OFFSET: u64 = STAGE3A_BSS_ADDRESS;
|
||||
|
||||
pub fn new(ipib_off: u64, hdr_off: u64) -> Result<Self> {
|
||||
let data = SeImgMetaData::new_v1(hdr_off, ipib_off);
|
||||
|
||||
let reader = Box::new(Cursor::new(data.as_bytes().to_owned()));
|
||||
Ok(Self(CompReader { reader }))
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for ImgMetaData {
|
||||
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl Seek for ImgMetaData {
|
||||
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
|
||||
self.0.seek(pos)
|
||||
}
|
||||
}
|
||||
|
||||
impl ComponentCheckTrait for ImgMetaData {
|
||||
fn check(&mut self, _ctx: &ComponentCheckCtx) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn init_ctx(&mut self, _ctx: &mut ComponentCheckCtx) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ComponentTrait<ComponentKind> for ImgMetaData {
|
||||
fn kind(&self) -> ComponentKind {
|
||||
ComponentKind::ImgMetaData
|
||||
}
|
||||
|
||||
fn secure_mode(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user