diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b16bd94..0f5d692 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,3 +31,14 @@ All submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose. Consult [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more information on using pull requests. + +### Unsafe code policy + +* The use of `unsafe` code is generally disallowed. The Device Tree parser + must validate all input data, treating it as untrusted. This includes bounds + checking for all offsets and indices to prevent vulnerabilities. +* Should a compelling justification arise for the inclusion of `unsafe` code + (beyond performance optimization) it must be accompanied by + an `#[expect(unsafe_code)]` attribute, stating the rationale. +* All `unsafe` code must be tested. The CI suite includes Miri to detect any + undefined behavior. \ No newline at end of file diff --git a/src/fdt/mod.rs b/src/fdt/mod.rs index 20ff4e9..abe0add 100644 --- a/src/fdt/mod.rs +++ b/src/fdt/mod.rs @@ -216,6 +216,12 @@ impl<'a> Fdt<'a> { /// let ptr = dtb.as_ptr(); /// let fdt = unsafe { Fdt::from_raw(ptr).unwrap() }; /// ``` + #[expect( + unsafe_code, + reason = "Having a methods that reads a Device Tree from a raw pointer is useful for \ + embedded applications, where the binary only gets a pointer to DT from the firmware or \ + a bootloader. The user must ensure it trusts the data." + )] pub unsafe fn from_raw(data: *const u8) -> Result { // SAFETY: The caller guarantees that `data` is a valid pointer to a Flattened // Device Tree (FDT) blob. We are reading an `FdtHeader` from this diff --git a/src/lib.rs b/src/lib.rs index 9fcf740..aa3a585 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,6 +21,7 @@ #![no_std] #![warn(missing_docs, rustdoc::missing_crate_level_docs)] +#![deny(unsafe_code)] #![cfg_attr(docsrs, feature(doc_cfg))] #[cfg(feature = "write")] diff --git a/tests/fdt.rs b/tests/fdt.rs index 4059c6c..68ee5b3 100644 --- a/tests/fdt.rs +++ b/tests/fdt.rs @@ -7,6 +7,8 @@ // except according to those terms. use dtoolkit::fdt::Fdt; +#[cfg(feature = "write")] +use dtoolkit::model::DeviceTree; #[test] fn read_child_nodes() { @@ -183,11 +185,20 @@ fn pretty_print() { #[cfg(feature = "write")] fn round_trip() { for (dtb, _dts, name) in ALL_DT_FILES { - use dtoolkit::model::DeviceTree; - let fdt = Fdt::new(dtb).unwrap(); let ir = DeviceTree::from_fdt(&fdt).unwrap(); let new_dtb = ir.to_dtb(); assert_eq!(dtb.to_vec(), new_dtb, "Mismatch for {name}"); } } + +#[test] +#[cfg(feature = "write")] +fn round_trip_raw() { + for (dtb, _dts, name) in ALL_DT_FILES { + let fdt = unsafe { Fdt::from_raw(dtb.as_ptr()).unwrap() }; + let ir = DeviceTree::from_fdt(&fdt).unwrap(); + let new_dtb = ir.to_dtb(); + assert_eq!(dtb.to_vec(), new_dtb, "Mismatch for {name}"); + } +}