Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

blog: add post on capability ptr #109

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

blog: add post on capability ptr #109

wants to merge 2 commits into from

Conversation

bradjc
Copy link
Contributor

@bradjc bradjc commented Jan 16, 2025

I'm probably not the best person to write the technical details in this post, but ideally this is at least technically correct and somewhat accessible to a broader audience.

holder of the pointer can actually use the pointer to access memory.

Traditionally, a pointer in `unsafe` Rust always has the capability to be
dereferenced. That is, the hardware will access the referenced memory.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Traditionally, a pointer in unsafe Rust always has the capability to be dereferenced.

As written, that statement isn't really true:

  1. The pointer may not point at a valid address (such an access would trap at the hardware level)
  2. The pointer may point at an address that the MPU/PMP/MMU/etc is blocking access to (hardware trap)
  3. The pointer may not have provenance that is valid for the dereference (the language's AM does not allow access through the pointer)

CapabilityPtr just adds one more element to that list (the pointer's data can contain permissions for that pointer).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "in Rust" is doing a lot of heavy lifting there, the memory access will be compiled into the program by the Rust compiler, and unconditionally executed at runtime. Now, whether or not the dereference succeeds in hardware, is (arguably) a different matter. Perhaps this depends a bit on the particular semantics of "dereference" the reader assumes.

I think I can add a qualifier to make this perhaps a bit more clear.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that's exactly true either. Given that trying to access a pointer might be UB (if it's not aligned / pointing to an allocated object / so on...) that Rust does not guarantee anything, including that hardware will access the referenced memory.

A compliant implementation of Rust (like MIRI, for instance) might make extra checks and do something like jump to a panic handler and this would be well within the bounds of "undefined behavior".


The primary driver for adding the `CapabilityPtr` type is the
[CHERI](https://www.cl.cam.ac.uk/research/security/ctsrd/cheri/) extension for
hardware architectures. With CHERI, hardware can track whether a pointer can be

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When someone talks about running "Rust on CHERI", they're usually referring to a pure-capability CHERI ABI. However, @LawrenceEsswood is porting the Tock kernel to a hybrid CHERI ABI, which has some different properties. One of those properties is that in hybrid CHERI, a language's default pointer types are not CHERI capabilities -- which is the reason why we need CapabilityPtr. In purecap CHERI, we don't need CapabilityPtr, as *mut T can do the same job.

We should probably clarify that CapabilityPtr is to support hybrid CHERI, otherwise this may be confusing for readers familiar with the upstream efforts to port Rust to CHERI.

(Lawrence, please correct me if I'm wrong about this).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can try to clarify this, but maybe this indicates this post is helpful as this difference is pretty opaque to me.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jonathan is correct. At the end of the day both *const T and CapabilityPtr are types in an abstract machine, and what hardware representation they have is always with respect to a given ABI.

"Legacy" CHERI ABI says that these should be lowered to an integer address
Hybrid CHERI ABIs say that *const T should be lowered to an address but CapabilityPtr to a CHERI capability.
Purecap CHERI ABIs say that both should be lowered to a CHERI capability.

Try to balance making a blog post which does not capture all complexity
while avoiding confusion from incorrect statements.
@bradjc
Copy link
Contributor Author

bradjc commented Jan 30, 2025

I added a bit more text, which maybe addresses the concerns. I do want this to remain a reasonably accessible blog post which does not need to capture all complexity, but shouldn't be overtly misleading or confusing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants