Skip to content

Commit 4ba21a2

Browse files
uki: add support for reading .cmdline section
We're going to want to use this soon in order to verify the correctness of the composefs= cmdline parameter when installing images. Signed-off-by: Allison Karlitskaya <[email protected]>
1 parent 94025b1 commit 4ba21a2

File tree

1 file changed

+25
-13
lines changed

1 file changed

+25
-13
lines changed

src/uki.rs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,15 @@ struct SectionHeader {
5353
number_of_line_numbers: U16,
5454
characteristics: U32,
5555
}
56-
const OSREL_SECTION: [u8; 8] = *b".osrel\0\0";
5756

5857
#[derive(Debug, Error, PartialEq)]
5958
pub enum UkiError {
6059
#[error("UKI is not valid EFI executable")]
6160
PortableExecutableError,
62-
#[error("UKI doesn't contain a '.osrel' section")]
63-
MissingOsrelSection,
64-
#[error(".osrel section is not UTF-8")]
65-
UnicodeError,
61+
#[error("UKI doesn't contain a '{0}' section")]
62+
MissingSection(&'static str),
63+
#[error("UKI section '{0}' is not UTF-8")]
64+
UnicodeError(&'static str),
6665
#[error("No name information found in .osrel section")]
6766
NoName,
6867
}
@@ -72,7 +71,15 @@ pub enum UkiError {
7271
// - the error types returned from FromBytes can't be used with `?` because they try to return a
7372
// reference to the data, which causes problems with lifetime rules
7473
// - it saves us from having to type Err(UkiError::PortableExecutableError) everywhere
75-
fn get_osrel_section(image: &[u8]) -> Option<Result<&str, UkiError>> {
74+
fn get_text_section<'a>(
75+
image: &'a [u8],
76+
section_name: &'static str,
77+
) -> Option<Result<&'a str, UkiError>> {
78+
// Turn the section_name ".osrel" into a section_key b".osrel\0\0".
79+
// This will panic if section_name.len() > 8, which is what we want.
80+
let mut section_key = [0u8; 8];
81+
section_key[..section_name.len()].copy_from_slice(section_name.as_bytes());
82+
7683
// Skip the DOS stub
7784
let (dos_stub, ..) = DosStub::ref_from_prefix(image).ok()?;
7885
let rest = image.get(dos_stub.pe_offset.get() as usize..)?;
@@ -91,15 +98,15 @@ fn get_osrel_section(image: &[u8]) -> Option<Result<&str, UkiError>> {
9198
let (sections, ..) = <[SectionHeader]>::ref_from_prefix_with_elems(rest, n_sections).ok()?;
9299

93100
for section in sections {
94-
if section.name == OSREL_SECTION {
101+
if section.name == section_key {
95102
let bytes = image
96103
.get(section.pointer_to_raw_data.get() as usize..)?
97104
.get(..section.virtual_size.get() as usize)?;
98-
return Some(std::str::from_utf8(bytes).or(Err(UkiError::UnicodeError)));
105+
return Some(std::str::from_utf8(bytes).or(Err(UkiError::UnicodeError(section_name))));
99106
}
100107
}
101108

102-
Some(Err(UkiError::MissingOsrelSection))
109+
Some(Err(UkiError::MissingSection(section_name)))
103110
}
104111

105112
/// Gets an appropriate label for display in the boot menu for the given UKI image, according to
@@ -124,12 +131,17 @@ fn get_osrel_section(image: &[u8]) -> Option<Result<&str, UkiError>> {
124131
/// If we couldn't parse the PE file or couldn't find an ".osrel" section then an error will be
125132
/// returned.
126133
pub fn get_boot_label(image: &[u8]) -> Result<String, UkiError> {
127-
let osrel = get_osrel_section(image).ok_or(UkiError::PortableExecutableError)??;
134+
let osrel = get_text_section(image, ".osrel").ok_or(UkiError::PortableExecutableError)??;
128135
OsReleaseInfo::parse(osrel)
129136
.get_boot_label()
130137
.ok_or(UkiError::NoName)
131138
}
132139

140+
/// Gets the contents of the .cmdline section of a UKI.
141+
pub fn get_cmdline(image: &[u8]) -> Result<&str, UkiError> {
142+
get_text_section(image, ".cmdline").ok_or(UkiError::PortableExecutableError)?
143+
}
144+
133145
#[cfg(test)]
134146
mod test {
135147
use core::mem::size_of;
@@ -180,7 +192,7 @@ mod test {
180192
peify(
181193
b"",
182194
&[SectionHeader {
183-
name: OSREL_SECTION,
195+
name: *b".osrel\0\0",
184196
virtual_size: U32::new(osrel.len() as u32),
185197
pointer_to_raw_data: U32::new(osrel_offset as u32),
186198
..Default::default()
@@ -212,7 +224,7 @@ ID=pretty-os
212224
assert_eq!(get_boot_label(img), Err(UkiError::PortableExecutableError));
213225
}
214226
fn no_sec(img: &[u8]) {
215-
assert_eq!(get_boot_label(img), Err(UkiError::MissingOsrelSection));
227+
assert_eq!(get_boot_label(img), Err(UkiError::MissingSection(".osrel")));
216228
}
217229

218230
pe_err(b"");
@@ -248,7 +260,7 @@ ID=pretty-os
248260
pe_err(&peify(
249261
b"",
250262
&[SectionHeader {
251-
name: OSREL_SECTION,
263+
name: *b".osrel\0\0",
252264
pointer_to_raw_data: U32::new(1234567),
253265
..Default::default()
254266
}],

0 commit comments

Comments
 (0)