fix!: introduce access api and VolatileBuf to safely interact with volatile ParamMemref buffers#278
fix!: introduce access api and VolatileBuf to safely interact with volatile ParamMemref buffers#278TheButlah wants to merge 16 commits intoapache:mainfrom
Conversation
b20304a to
8c8555e
Compare
8c8555e to
1bba296
Compare
|
Thanks for your commit!
Thanks! |
|
OK I've addressed the feedback so far, let me know what you think 👍 |
|
Thanks for the changes! Since this is a core part of the API design, it's worth taking the extra time to consider it carefully. I really appreciate your patience and collaboration on this! Some new suggestions: In the example: Let me know what you think, thanks! |
|
Edit: Hmm on second thought, maybe we should just always ensure capacity and set updated size when doing copy_from? |
|
I believe the Rust SDK should provide primitives that are as safe as possible. In our context, checking capacity, copying data, and updating the size should be treated as a single atomic operation to maintain consistency. Decoupling them only creates more opportunities for logic bugs (like forgetting to update the size) and leads to redundant error handling.
I cannot think of a valid use case for skipping the update... If the capacity is insufficient, why not updating the capacity to inform the client?
It also makes sense to me. To keep the API explicit, we may need a more descriptive name than just copy_from to indicate it handles the full lifecycle (check, copy, and size update). Also requesting feedback from @ivila for this API design (once he is available). Since we are heading into the Chinese New Year holiday, our responses would be slower than usual. Thanks for your patience! |
Fixes #273
Summarizing that issue, the current api to access a
ParamMemref's buffer is unsound when having to account for malicious CAs (and probably benign ones too). The main issue is that since this memory is not synchronized, Linux can change its contents at any time, and therefore it is essentially volatile memory. Constructing a reference to volatile memory is always unsound.Additionally, OP-TEE only allows reads when the memref is an
[in]or[inout]param, and writes when its an[out]or[inout]param. The original API doesn't check theParamTypeat all, which means that the end user can easily write to a buffer they can only read from, or read from a buffer they can only write to.This PR fixes the issue by introducing two concepts:
access.rs. This api has traits and zero sized types that allow us to encode the access permissions into the type system via a typestate pattern. This sort of approach is a zero cost abstraction and allows us to check the param_type only once, as opposed to every interaction with the memref. It also helps ensure that only the appropriate functions (such as .read() or .write()) are expose for a given access type. The typestate approach is also extremely common in the bare-metal rust ecosystem (see embedded-hal crates), so I figured it isn't overly unfamiliar for this domain of work.VolatileBufinvolatile.rs, which is a type that ensures that all access to its memory is done throughcore::ptr::read_volatileorcore::ptr::write_volatile, and leverages the access api to expose only the appropriate read/write functionality.A few things reviewers should be aware of:
bytemuck::Pod. This was done because I wanted to support arbitrary buffers ofTrather than justu8. This was done in an attempt to allow faster accessing of data without needing to repeatedly call deserialization code, as if it were only u8 some sort of deserialization (or subsequent bytemuck cast) would be required. The downside is the additional dependency, but bytemuck is a 1.0 crate and well known and commonly used, and itself has no dependencies. I didn't want to introduce a first-party Pod trait of our own, because it would have less compatibility with the broader ecosystem and would require us to then implement bytemuck-style derive macros for user-defined types.I am definitely open to workshopping this submission, please let me know your thoughts and I will adjust the PR accordingly. Thanks for your time 👍