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

Add indirect branch tracking #15122

Merged

Conversation

ysbaddaden
Copy link
Contributor

Adds support for indirect branch tracking for X86[_64] (CET) and AArch64 targets through the following compile time flags (taken from gcc/clang/rust):

  • -Dcf-protection=branch (or =return or =full) for X86
  • -Dbranch-protection=bti for AArch64

These flags are automatically set for OpenBSD, that enforces IBT or BTI on all user land applications. The patch also removes the -Wl-znobtcfi linker option since we don't need to disable it anymore.

OpenBSD is the only OS I know to support and enforce IBT or BTI in user land. Linux for example only supports it for kernel code (for the time being). I manually tested IBT in an OpenBSD VM on x86_64 with a supported CPU (Intel Raptor Lake). I can compile & recompile crystal as well as run gmake std_spec without running into IBT issues 👍

Notes:

  • I expected to have to add the ASM instructions to the fiber context switch ASM... but messing with the stack pointer isn't considered as a conditional jump apparently 🤷
  • I'm using the genius idea from @straight-shoota that we can pass -Dkey=value then test for flag?("key=value") and it just worked 😲
  • I can't test BTI on AArch64: I have no hardware and there are no bindings for the aarch64-unknown-openbsd target; there are little reasons it wouldn't work though;
  • I added support for shadow stack (SHSTK) on X86 (-Dcf-protection=return). I'm not sure we really support it though, since fibers are messing with the stacks?

closes #13665
follow up to #15118 itself a followup of #15115

OpenBSD 7.4+ enforces Indirect Branch Tracking but we're not yet
compatible in Crystal, so we disable the feature for the time being.
This results in always reporting:

```
bin/crystal[204]: Brewfile: not found
```
This requires to pass the `-Dcf-protection=branch` flag for X86 or the
`-Dbranch-protection=bti` flag for AARCH64.
@ysbaddaden ysbaddaden force-pushed the feature/indirect-branch-tracking branch from ebdfc7a to db3a653 Compare October 24, 2024 09:35
@straight-shoota straight-shoota added this to the 1.15.0 milestone Oct 29, 2024
@straight-shoota straight-shoota changed the title Feature: indirect branch tracking Add indirect branch tracking Oct 30, 2024
@straight-shoota straight-shoota merged commit fd44c08 into crystal-lang:master Oct 30, 2024
69 checks passed
@GeopJr
Copy link
Contributor

GeopJr commented Oct 31, 2024

I guess #14026 can close too? IIRC the main blocker was indirect branch tracking and from what I can tell it's already on 1.13.2 (https://openbsd.app/?search=crystal)

@ysbaddaden ysbaddaden deleted the feature/indirect-branch-tracking branch November 5, 2024 08:44
CTC97 pushed a commit to CTC97/crystal that referenced this pull request Nov 9, 2024
Adds support for indirect branch tracking for X86[_64] (CET) and AArch64 targets through the following compile time flags (taken from gcc/clang/rust):

- `-Dcf-protection=branch` (or `=return` or `=full`) for X86
- `-Dbranch-protection=bti` for AArch64

These flags are automatically set for OpenBSD, that enforces IBT or BTI on all user land applications. The patch also removes the `-Wl-znobtcfi` linker option since we don't need to disable it anymore.

OpenBSD is the only OS I know to support _and_ enforce IBT or BTI in user land. Linux for example only supports it for kernel code (for the time being). I manually tested IBT in an OpenBSD VM on x86_64 with a supported CPU (Intel Raptor Lake). I can compile & recompile crystal as well as run `gmake std_spec` without running into IBT issues 👍 

Notes:
- I expected to have to add the ASM instructions to the fiber context switch ASM... but messing with the stack pointer isn't considered as a conditional jump apparently 🤷
- I'm using the genius idea from @straight-shoota that we can pass `-Dkey=value` then test for `flag?("key=value")` and it just worked 😲 
- I can't test BTI on AArch64: I have no hardware and there are no bindings for the `aarch64-unknown-openbsd` target; there are little reasons it wouldn't work though;
- I added support for shadow stack (SHSTK) on X86 (`-Dcf-protection=return`). I'm not sure we really support it though, since fibers are messing with the stacks?
straight-shoota added a commit to crystal-lang/crystal-book that referenced this pull request Nov 13, 2024
These flags were added in crystal-lang/crystal#15122

They are put in a new section *Codegen Features*. The existing *Compiler Features* section is renamed to *Language Features*.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Indirect branch tracking
3 participants