Skip to content

Tracking Issue for LLVM AllocToken and Heap Partitioning Support for Rust #159111

Open

Description

@rcvalle

View all comments

This is a tracking issue for the LLVM AllocToken and Heap Partitioning Support for Rust project (see the design document draft).

Steps

  • Add option to the Rust compiler driver and frontend (i.e., -Zsanitizer=alloc-token and related options).
  • Add support for emitting allocation token function attributes, module flags, and allocation token hint metadata to the Rust compiler code generation.
  • Implement the default pointer-split heap partitioning scheme in the rustc_sanitizers crate.
  • Define allocation token classifications and type name encodings for cross-language LLVM AllocToken and heap partitioning support.
  • Change the initial implementation to use the defined classifications and type name encodings for cross-language LLVM AllocToken and heap partitioning support.
  • Add typed allocation paths and allocation token hints to the Rust standard library.
  • Add token-enabled allocator interface support to the Rust standard library and to the Rust compiler allocator shim generation.
  • Add the alloc_token_infer intrinsic.
  • Create documentation and tests.

Unresolved Questions

None.

Implementation history

Activity

  1. added
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    on Jul 10, 2026
  2. self-assigned this
    on Jul 10, 2026
  3. bjorn3 commented on Jul 12, 2026

    @bjorn3
    Member

    Left a couple of review comments on rcvalle@41bf600

  4. bjorn3 commented on Jul 21, 2026

    @bjorn3
    Member

    I see you reacted to my comments, but github just doesn't show any commit comments at all anymore. The file sidebar shows comment counts, but nothing is shown inside the actual diff: rcvalle@41bf600

  5. rcvalle commented on Jul 22, 2026

    @rcvalle
    MemberAuthor

    Yes, it's happening to me as well. I had to expand all the files to be able to see your comments, but even doing so the third comment didn't show up--I wanted to reply I fixed it as well and I couldn't. Let me open a draft PR sometime later this week and we can continue the discussions and review there.

  6. nikic commented on Jul 23, 2026

    @nikic
    Contributor

    usize/isize should not be classified as pointer-containing types.

  7. rcvalle commented on Jul 31, 2026

    @rcvalle
    MemberAuthor

    usize/isize should not be classified as pointer-containing types.

    It's a bit complicated (see the Classification compatibility for the pointer-split heap partitioning scheme section in the design doc). The tl;dr is that the classification is conservative1 and consistent with how Clang classifies uintptr_t and intptr_t, which end up as usize and isize across the FFI boundary in "mixed binaries"--for cross-language LLVM AllocToken and heap partitioning support--and because pointers may be stored as usize (e.g., via ptr::expose_provenance and ptr::with_exposed_provenance, and AtomicUsize).

    Footnotes

    1. Misclassifying a type not containing pointers into the partition containing pointers only loses part of the separation benefit for that type, while misclassifying a type containing pointers into the partition not containing pointers breaks the guarantee of the partition not containing pointers. ↩

  8. RalfJung commented on Aug 8, 2026

    @RalfJung
    Member

    and because pointers may be stored as usize (e.g., via ptr::expose_provenance and ptr::with_exposed_provenance, and AtomicUsize).

    No, pointers can't be stored in usize. usize cannot hold provenance. The address part of a pointer can be stored in usize, but that's not a whole pointer. And almost all uses of usize are not for pointers.

    usize should be treated like size_t, not like uintptr_t.

  9. RalfJung commented on Aug 8, 2026

    @RalfJung
    Member

    Tracking issues are typically for already accepted proposals. Where was the prior discussion and which team has accepted this proposal using which process?

  10. rcvalle commented on Aug 8, 2026

    @rcvalle
    MemberAuthor

    and because pointers may be stored as usize (e.g., via ptr::expose_provenance and ptr::with_exposed_provenance, and AtomicUsize).

    No, pointers can't be stored in usize. usize cannot hold provenance. The address part of a pointer can be stored in usize, but that's not a whole pointer. And almost all uses of usize are not for pointers.

    usize should be treated like size_t, not like uintptr_t.

    Yes, an address is what an attacker would target in e.g., a heap-based out-of-bounds write, and that's what we want to hint the AllocTokenPass about the possibility of, and it doesn't change the language semantics or the program correctness in any way. Think of it as similar to a low-level optimization hint, and what a token-enabled memory allocator does with the token identifier derived from that (by the AllocTokenPass) is implementation specific.

  11. rcvalle commented on Aug 8, 2026

    @rcvalle
    MemberAuthor

    Tracking issues are typically for already accepted proposals. Where was the prior discussion and which team has accepted this proposal using which process?

    Sorry, almost all sanitizers support were done without an MCP or tracking issue (or a design document). I mostly use these tracking issues to track our Compiler team and PG exploit mitigations work (and for possibly future stabilization) and didn't know they were strictly for that so apologies. Happy to open an MCP or do as you suggested in the PR in this case if you think that would be helpful. Let me know.

  12. RalfJung commented on Aug 9, 2026

    @RalfJung
    Member

    Thanks for explaining. I haven't seen such tracking issues before so I was just a little surprised.

    The public lib API change will definitely need an ACP. As for the MCP, the change seemed big enough (with new flags and new attributes) for me to warrant one; I assume @bjorn3 would second it fairly quickly but it'd be a chance for the rest of the team to chime in with feedback.

    Yes, an address is what an attacker would target in e.g., a heap-based out-of-bounds write, and that's what we want to hint the AllocTokenPass about the possibility of, and it doesn't change the language semantics or the program correctness in any way. Think of it as similar to a low-level optimization hint, and what a token-enabled memory allocator does with the token identifier derived from that (by the AllocTokenPass) is implementation specific.

    I see. Still seems odd to me given that most usize are not pointers so mixing them with pointers could be bad, but you are the mitigation expert here. :)

  13. rcvalle commented on Aug 10, 2026

    @rcvalle
    MemberAuthor

    @RalfJung will do that as soon as I've some time. Thank you!

  14. nikic commented on Aug 21, 2026

    @nikic
    Contributor

    usize/isize should not be classified as pointer-containing types.

    It's a bit complicated (see the Classification compatibility for the pointer-split heap partitioning scheme section in the design doc). The tl;dr is that the classification is conservative1 and consistent with how Clang classifies uintptr_t and intptr_t, which end up as usize and isize across the FFI boundary in "mixed binaries"--for cross-language LLVM AllocToken and heap partitioning support--and because pointers may be stored as usize (e.g., via ptr::expose_provenance and ptr::with_exposed_provenance, and AtomicUsize).

    I don't think this makes sense. This goes beyond being conservative, into trying to handle some rare, very non-idiomatic code patterns like first-class citizens. For various reasons (including a focus on strict provenance) Rust generally has a lot less of these "storing pointers in integers" pattern than C does, and I don't think it's a good idea to assume that it's happening by default.

  15. rcvalle commented on Aug 25, 2026

    @rcvalle
    MemberAuthor

    I don't think this makes sense. This goes beyond being conservative, into trying to handle some rare, very non-idiomatic code patterns like first-class citizens. For various reasons (including a focus on strict provenance) Rust generally has a lot less of these "storing pointers in integers" pattern than C does, and I don't think it's a good idea to assume that it's happening by default.

    Storing pointers in usize and isize is very common in mixed binaries, which is also a very common use of Rust. What is the harm that you see in conservatively classifying them as may contain pointers? Does it outweigh the risk of classifying a type that may contain pointers into the partition not containing pointers and breaking the guarantee of the partition not containing pointers.

  16. RalfJung commented on Aug 25, 2026

    @RalfJung
    Member

    Storing pointers in usize and isize is very common in mixed binaries,

    Do we have actual data on that? Rust is quite clear that one shouldn't do this so I would hope people usually use proper types instead of letting bad C practices leak onto the Rust side.

  17. rcvalle commented on Aug 28, 2026

    @rcvalle
    MemberAuthor

    Storing pointers in usize and isize is very common in mixed binaries,

    Do we have actual data on that? Rust is quite clear that one shouldn't do this so I would hope people usually use proper types instead of letting bad C practices leak onto the Rust side.

    For example, pretty much all occurrences of uintptr_t in #[repr(C)] types and in FFI bindings/at the FFI boundary? I still want to know what is the harm that you see in conservatively classifying them as may contain pointers? Does it outweigh the risk of classifying a type that may contain pointers into the partition not containing pointers and breaking the guarantee of the partition not containing pointers?

  18. hanna-kruppe commented on Aug 28, 2026

    @hanna-kruppe
    Contributor

    The main risk I see is that it'll lead to classifying far more allocations as containing pointers than you would in C. In the limit, if you conservatively classify too many allocation as containing pointers when they don't, the mitigation becomes less effective, right?

    It's true that there are some C bindings that use usize for things that can contain pointers. The main offender I'm aware of are the signal handler/sigaction values, which are either SIG_DFL / SIG_IGN or function pointers (although these are very rarely, if ever, heap allocated). However, there are far less than you may expect from looking at uses of uintptr_t in C, since (as Ralf mentioned) it's generally incorrect to use integers for anything that needs pointer provenance. So I think it would be good to measure the actual difference between classifying usize/isize as pointers or as integers in Rust.

  19. rcvalle commented on Aug 28, 2026

    @rcvalle
    MemberAuthor

    Do you have any suggestions on how we could best measure the actual difference? My main concern is breaking the guarantee of the partition not containing pointers--this is what would meaningfully affect the mitigations effectiveness.

  20. hanna-kruppe commented on Aug 28, 2026

    @hanna-kruppe
    Contributor

    Once the sanitizer is implemented, one could compile a bunch of real world projects twice, once with usize/isize counting as pointers and once without, and look at:

    • Number of types classified has having pointers vs not, absolute and as fraction of all types, to get a feeling for if it leads to a lot more types being classified as having pointers
    • (Number and sizes of allocations of such types would be better, but that requires running the software, which requires much more investment per project.)
    • A sample of types that are only classified as having pointers if usize/isize is classified as pointer, to see if any jump out as plausibly containing pointers
  21. rcvalle commented on Aug 28, 2026

    @rcvalle
    MemberAuthor

    I can try to do that. I've a working implementation in the #160298 draft PR, and working examples in the rust-heap-partitioning-examples repository. Do you have any suggestions of real-world projects that would be close to being representative for doing that?

  22. RalfJung commented on Aug 28, 2026

    @RalfJung
    Member

    My main concern is breaking the guarantee of the partition not containing pointers--this is what would meaningfully affect the mitigations effectiveness.

    Can you talk a bit about the risks in the other direction here? What are potential problems associated with marking too many allocations as containing pointers? Why does the sanitizer not simply treat all allocations as potentially containing pointers?

  23. rcvalle commented on Aug 28, 2026

    @rcvalle
    MemberAuthor

    Can you talk a bit about the risks in the other direction here? What are potential problems associated with marking too many allocations as containing pointers? Why does the sanitizer not simply treat all allocations as potentially containing pointers?

    The main goal of the first-level pointer-split partitioning is isolating types that are susceptible to out-of-bounds reads and writes (e.g., char[] buffers, std::string, etc., or Box<[u8; N]>, Vec, etc., when unsafe operations are done on them) from types that contain pointers, so even if the attacker has such a primitive they can't read or write any pointers.

    That is why misclassifying a type not containing pointers into the partition containing pointers only loses part of the separation benefit for that type (i.e., only if that type is susceptible to out-of-bounds reads and writes and its use is actually vulnerable), while misclassifying a type containing pointers into the partition not containing pointers breaks the guarantee of the partition not containing pointers (i.e., any type that is susceptible to out-of-bounds reads and writes and their use are vulnerable becomes a way to read or write to the pointers that made in).

  24. added
    T-langRelevant to the language team
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    T-libsRelevant to the library team, which will review and decide on the PR/issue.
    on Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-sanitizersArea: Sanitizers for correctness and code qualityC-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCPG-exploit-mitigationsProject group: Exploit mitigationsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamT-libsRelevant to the library team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions