minirust/minirust

Support for CHERI

RalfJung opened this issue · 7 comments

Currently MiniRust defines how pointers are encoded and decoded pretty precisely. This might be too restrictive for CHERI so we might have to figure out a way to leave this more abstract.

I'm not so sure we should do this. Compilers are never going to be able to correctly compile to Cheri in reasonable ways anyway, and until we get some indication from T-lang that there's interest in supporting size_t != uintptr_t things feel fine as-is

Why do you think that?

Because ptr.wrapping_add(BIG).wrapping_sub(BIG) is not a nop on Cheri - if BIG is sufficiently large then the resulting pointer is invalid to dereference even if ptr isn't. I had heard something about this getting fixed at some point, but afaik it has not been.

Strict provenance provides an alternative to this - if programs do not cast directly between ptr and int, the size mismatch does not matter.

I don't really see how that's an alternative - either Rust guarantees that size_t == uintptr_t or it does not. If it does, then what we have right now seems fine. If it does not, then there are a lot of questions that need to be answered by T-lang before we can do anything in Minirust (what is usize? How do we fix the plethora of APIs that now no longer make sense?). The only thing that strict provenance does is provide a way to write code that is less likely to break if the language does allow size_t != uintptr_t

Because ptr.wrapping_add(BIG).wrapping_sub(BIG) is not a nop on Cheri - if BIG is sufficiently large then the resulting pointer is invalid to dereference even if ptr isn't. I had heard something about this getting fixed at some point, but afaik it has not been.

Ah yes. That is probably a compromise we have to make. It will lead to spurious errors where a program aborts with a permission error that should probably run. It is also unlikely in practice though.

I don't really see how that's an alternative - either Rust guarantees that size_t == uintptr_t or it does not. If it does, then what we have right now seems fine. If it does not, then there are a lot of questions that need to be answered by T-lang before we can do anything in Minirust (what is usize? How do we fix the plethora of APIs that now no longer make sense?). The only thing that strict provenance does is provide a way to write code that is less likely to break if the language does allow size_t != uintptr_t

My understanding was that usize remains the size of the address space (i.e., size_t, not uintptr_t), and if you avoid expose_addr/from_exposed_addr (and their as cast equivalents) then that takes case of the API issues. Are there other APIs you had in mind?

Ah yes. That is probably a compromise we have to make. It will lead to spurious errors where a program aborts with a permission error that should probably run. It is also unlikely in practice though.

Manual memcpy (ie looping over MaybeUninit<u8> copies) also doesn't work on Cheri though, and I have a feeling that one might be more common.

Are there other APIs you had in mind?

Ah, actually, Cheri specifically just might be feasible. APIs like ptr::offset_from don't work in general segmented architecture situations, but Cheri uses its extra bytes to store provenance only.

Manual memcpy (ie looping over MaybeUninit copies) also doesn't work on Cheri though, and I have a feeling that one might be more common.

Ah, right. That's "just" more cases of getting a permission error where none should be, though.

So yeah code might have to be ported to CHERI, but in principle I don't see why that would not be feasible.

So yeah code might have to be ported to CHERI, but in principle I don't see why that would not be feasible.

It definitely would be, but then users are already writing their code against some Rust/Minirust dialect that is not the one we're writing a spec for. Why can't the uintptr_t != size_t thing be a part of the changes associated with that dialect too?