oreboot
oreboot copied to clipboard
Serialize and deserialize structs safely
There are a few places where we unnecessarily use unsafe
blocks to serialize and deserialize structs:
In particular see https://github.com/oreboot/oreboot/blob/main/src/lib/uefi/src/lib.rs. For example:
let fveh: efi::EFI_FIRMWARE_VOLUME_EXT_HEADER =
unsafe { core::ptr::read(fveh_bytes.as_ptr() as *const _) };
Instead, we should be using some Rust macros to achieve this safely. There are a number of crates built for this task:
- https://serde.rs/ is obviously the most popular. Some of its flexibility gets in the way. We just need to be able to serialize/deserialize a struct in the same format as a packed C struct.
- https://github.com/xoac/endian_codec
- https://crates.io/crates/packed_struct
- ... (I have no strong opinions for a particular crate at the moment)
I saw a blog post recently about this: https://adventures.michaelfbryan.com/posts/deserializing-binary-data-files/
About the crates that can be used:
ssmarshal
is surprisingly good for that (I'd give it 10 of 10 points)--but technically one would be using the crate for something it was not designed for (it's designed as a message format for a microkernel). It does work very well for general C struct serialization--and it's very easy to think about serialization that way (it's just using serde and serde derive).
zerocopy
is the right way to do it; but boy is it annoying. I'm using zerocopy
quite a lot nowadays regardless.
But really, if you don't care about endianness and the architectures are the same anyway, then just using repr(C)
and no crates is fine.
packed_struct
is also OK.
With the core
library alone, is there a non-unsafe
way to convert a &[u8]
to a repr(C)
struct?
The safe way I know how to do it is parse field-by-field like nom
(supports no_std
). You can also structure it to parse lazily with accessors (a la capnproto
) if you want to avoid having original and deserialized versions in memory. These are not nearly as easy as transmutation.
TIL that there's a safe transmute working group.