Skip to content

Commit 451716a

Browse files
committed
uefi-raw: Add explicit padding field for MemoryDescriptor + add test
By convention, structs having a C representation should be explicit with their in-between padding fields. This allows users memory-safe trivial serialization and deserialization by accessing the underlying memory as byte slice. Without this fields being explicit, Miri complains about uninitialized memory accesses, which is UB. uefi-raw: add test for MemoryDescriptor to catch Miri problems The underlying issue is that if someone wants to cast a slice of descriptors to a byte slice, the uninitialized **implicit** padding bytes are UB. Miri complains about that.
1 parent a5b35f7 commit 451716a

File tree

5 files changed

+57
-2
lines changed

5 files changed

+57
-2
lines changed

uefi-raw/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# uefi-raw - [Unreleased]
22

3+
## Changed
4+
- `MemoryDescriptor` now has an explicit padding field, allowing trivial
5+
memory-safe serialization and deserialization
36

47
# uefi-raw - 0.8.0 (2024-09-09)
58

uefi-raw/src/table/boot.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,8 @@ bitflags! {
350350
pub struct MemoryDescriptor {
351351
/// Type of memory occupying this range.
352352
pub ty: MemoryType,
353-
// Implicit 32-bit padding.
353+
/// Padding field. Ignore.
354+
pub padding0: u32,
354355
/// Starting physical address.
355356
pub phys_start: PhysicalAddress,
356357
/// Starting virtual address.
@@ -370,6 +371,7 @@ impl Default for MemoryDescriptor {
370371
fn default() -> Self {
371372
Self {
372373
ty: MemoryType::RESERVED,
374+
padding0: 0,
373375
phys_start: 0,
374376
virt_start: 0,
375377
page_count: 0,
@@ -379,7 +381,7 @@ impl Default for MemoryDescriptor {
379381
}
380382

381383
newtype_enum! {
382-
/// The type of a memory range.
384+
/// The type of memory range.
383385
///
384386
/// UEFI allows firmwares and operating systems to introduce new memory types
385387
/// in the `0x7000_0000..=0xFFFF_FFFF` range. Therefore, we don't know the full set
@@ -484,3 +486,35 @@ pub enum Tpl: usize => {
484486
/// Note that this is not necessarily the processor's page size. The UEFI page
485487
/// size is always 4 KiB.
486488
pub const PAGE_SIZE: usize = 4096;
489+
490+
#[cfg(test)]
491+
mod tests {
492+
use core::{mem, slice};
493+
use super::*;
494+
495+
// This tests succeeds if Miri doesn't complain about uninitialized memory.
496+
#[test]
497+
fn memory_descriptor_trivial_serialization() {
498+
let descs = [
499+
MemoryDescriptor {
500+
ty: MemoryType::CONVENTIONAL,
501+
padding0: 0,
502+
phys_start: 0x1000,
503+
virt_start: 0x1000,
504+
page_count: 1,
505+
att: Default::default(),
506+
},
507+
];
508+
509+
510+
let raw_bytes: &[u8] = {
511+
let ptr = descs.as_ptr().cast::<u8>();
512+
let len = mem::size_of_val(&descs);
513+
unsafe { slice::from_raw_parts(ptr.cast(), len) }
514+
};
515+
516+
// Test succeeds if Miri doesn't complain about initialized memory
517+
// (implicit padding fields).
518+
dbg!(&raw_bytes);
519+
}
520+
}

uefi/src/mem/memory_map/impl_.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,20 +432,23 @@ mod tests {
432432
const BASE_MMAP_UNSORTED: [MemoryDescriptor; 3] = [
433433
MemoryDescriptor {
434434
ty: MemoryType::CONVENTIONAL,
435+
padding0: 0,
435436
phys_start: 0x3000,
436437
virt_start: 0x3000,
437438
page_count: 1,
438439
att: MemoryAttribute::WRITE_BACK,
439440
},
440441
MemoryDescriptor {
441442
ty: MemoryType::CONVENTIONAL,
443+
padding0: 0,
442444
phys_start: 0x2000,
443445
virt_start: 0x2000,
444446
page_count: 1,
445447
att: MemoryAttribute::WRITE_BACK,
446448
},
447449
MemoryDescriptor {
448450
ty: MemoryType::CONVENTIONAL,
451+
padding0: 0,
449452
phys_start: 0x1000,
450453
virt_start: 0x1000,
451454
page_count: 1,

uefi/src/mem/memory_map/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ mod tests_mmap_artificial {
131131

132132
const BASE: MemoryDescriptor = MemoryDescriptor {
133133
ty: TY,
134+
padding0: 0,
134135
phys_start: 0,
135136
virt_start: 0,
136137
page_count: 0,
@@ -169,6 +170,7 @@ mod tests_mmap_artificial {
169170

170171
const BASE: MemoryDescriptor = MemoryDescriptor {
171172
ty: TY,
173+
padding0: 0,
172174
phys_start: 0,
173175
virt_start: 0,
174176
page_count: 0,
@@ -278,6 +280,7 @@ mod tests_mmap_real {
278280
| MemoryAttribute::WRITE_COMBINE
279281
| MemoryAttribute::WRITE_THROUGH
280282
| MemoryAttribute::WRITE_BACK,
283+
..Default::default()
281284
},
282285
MemoryDescriptor {
283286
ty: MemoryType::CONVENTIONAL,
@@ -288,6 +291,7 @@ mod tests_mmap_real {
288291
| MemoryAttribute::WRITE_COMBINE
289292
| MemoryAttribute::WRITE_THROUGH
290293
| MemoryAttribute::WRITE_BACK,
294+
..Default::default()
291295
},
292296
MemoryDescriptor {
293297
ty: MemoryType::BOOT_SERVICES_DATA,
@@ -298,6 +302,7 @@ mod tests_mmap_real {
298302
| MemoryAttribute::WRITE_COMBINE
299303
| MemoryAttribute::WRITE_THROUGH
300304
| MemoryAttribute::WRITE_BACK,
305+
..Default::default()
301306
},
302307
MemoryDescriptor {
303308
ty: MemoryType::CONVENTIONAL,
@@ -308,6 +313,7 @@ mod tests_mmap_real {
308313
| MemoryAttribute::WRITE_COMBINE
309314
| MemoryAttribute::WRITE_THROUGH
310315
| MemoryAttribute::WRITE_BACK,
316+
..Default::default()
311317
},
312318
MemoryDescriptor {
313319
ty: MemoryType::CONVENTIONAL,
@@ -318,6 +324,7 @@ mod tests_mmap_real {
318324
| MemoryAttribute::WRITE_COMBINE
319325
| MemoryAttribute::WRITE_THROUGH
320326
| MemoryAttribute::WRITE_BACK,
327+
..Default::default()
321328
},
322329
MemoryDescriptor {
323330
ty: MemoryType::ACPI_NON_VOLATILE,
@@ -328,6 +335,7 @@ mod tests_mmap_real {
328335
| MemoryAttribute::WRITE_COMBINE
329336
| MemoryAttribute::WRITE_THROUGH
330337
| MemoryAttribute::WRITE_BACK,
338+
..Default::default()
331339
},
332340
MemoryDescriptor {
333341
ty: MemoryType::CONVENTIONAL,
@@ -338,6 +346,7 @@ mod tests_mmap_real {
338346
| MemoryAttribute::WRITE_COMBINE
339347
| MemoryAttribute::WRITE_THROUGH
340348
| MemoryAttribute::WRITE_BACK,
349+
..Default::default()
341350
},
342351
MemoryDescriptor {
343352
ty: MemoryType::ACPI_NON_VOLATILE,
@@ -348,6 +357,7 @@ mod tests_mmap_real {
348357
| MemoryAttribute::WRITE_COMBINE
349358
| MemoryAttribute::WRITE_THROUGH
350359
| MemoryAttribute::WRITE_BACK,
360+
..Default::default()
351361
},
352362
MemoryDescriptor {
353363
ty: MemoryType::CONVENTIONAL,
@@ -358,6 +368,7 @@ mod tests_mmap_real {
358368
| MemoryAttribute::WRITE_COMBINE
359369
| MemoryAttribute::WRITE_THROUGH
360370
| MemoryAttribute::WRITE_BACK,
371+
..Default::default()
361372
},
362373
MemoryDescriptor {
363374
ty: MemoryType::ACPI_NON_VOLATILE,
@@ -368,6 +379,7 @@ mod tests_mmap_real {
368379
| MemoryAttribute::WRITE_COMBINE
369380
| MemoryAttribute::WRITE_THROUGH
370381
| MemoryAttribute::WRITE_BACK,
382+
..Default::default()
371383
},
372384
];
373385
assert_eq!(entries.as_slice(), &expected);

uefi/tests/memory_map.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,23 @@ fn parse_boot_information_efi_mmap() {
1212
virt_start: 0x3000,
1313
page_count: 1,
1414
att: MemoryAttribute::WRITE_BACK,
15+
..Default::default()
1516
},
1617
MemoryDescriptor {
1718
ty: MemoryType::CONVENTIONAL,
1819
phys_start: 0x2000,
1920
virt_start: 0x2000,
2021
page_count: 1,
2122
att: MemoryAttribute::WRITE_BACK,
23+
..Default::default()
2224
},
2325
MemoryDescriptor {
2426
ty: MemoryType::CONVENTIONAL,
2527
phys_start: 0x1000,
2628
virt_start: 0x1000,
2729
page_count: 1,
2830
att: MemoryAttribute::WRITE_BACK,
31+
..Default::default()
2932
},
3033
];
3134
let map_size = mmap_source.len() * desc_size;

0 commit comments

Comments
 (0)