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

JIT: Emit Intel CET instructions #287

Open
riptl opened this issue Mar 20, 2022 · 5 comments
Open

JIT: Emit Intel CET instructions #287

riptl opened this issue Mar 20, 2022 · 5 comments

Comments

@riptl
Copy link

riptl commented Mar 20, 2022

Description

Intel CET ("Control-flow Enforcement Technology") is a technology that aims to defend against exploitation techniques that rely on taking over control-flow like ROP.

It is a relatively recent extension that's only supported on recent Intel and AMD CPUs. Certain CET instructions map to the NOP opcode space to allow for backwards compatibility with older CPUs.

Since we are generating code at runtime, we can always conditionally enable new features based on CPUID. This would come at the expense of added complexity (=attack surface) however.

Introducing CET support to the SBF JIT compiler could improve the security of the Solana program sandbox.

Concepts

IBT (Indirect Branch Tracking)

endbr64 is a new instruction that encodes to f3 0f 1e fa, which is a NOP on older machines.
It marks valid indirect branch targets and return sites.

When enabled, the CPU will refuse to follow indirect branches or return addresses that do not have endbr64 as the next instruction.

Shadow Stack

Special stack that only stores return addresses to defend against stack smashing.

@riptl
Copy link
Author

riptl commented Mar 20, 2022

@Lichtso I would love to hear your thoughts on this. I'm interested in working on IBT support. It looks like a quick win.

@riptl
Copy link
Author

riptl commented Mar 20, 2022

At the very least, when Rust decides to do IBT by default the Solana JIT will brick. So we’ll have to do something about it, either disable CET, or add IBT support.

@Lichtso
Copy link

Lichtso commented Mar 21, 2022

For reference this is the tracking issue in Rust I think: rust-lang/rust#73820

The problem is that at the moment we do not know where possible indirect jump targets are, or in other words: Every BPF instruction (even e.g. inside loops) could be.

It is on the TODO list for SBFv2 here: solana-labs/solana#20323

Restrict the callx jump targets to only allow known symbols (e.g. registered functions in the ELF)

@riptl
Copy link
Author

riptl commented Mar 21, 2022

Thanks for taking a look. Another consideration is that crafted SBF code input can probably be used to create x86 R/C/J/whatever-OP gadgets. Coupled with the ability to introduce valid branch targets in lots of places (by defining SBFv2 symbols), this would make IBT much less useful.

@riptl
Copy link
Author

riptl commented Mar 21, 2022

@Lichtso I'll try this week to get a CET-enabled build of Solana rbpf-cli to pass various programs. I think we have a doable way to get there.

Even if SBFv2 can't track indirect targets yet, IBT also redefines the 0x3e instruction prefix for jumps as the "notrack" hint. It removes the endbr64 requirement at the end of the branch. I guess it's the Rust unsafe equivalent of x86 in a way, so it would be good to avoid widespread usage of notrack.

3e 67 ff 20             notrack jmp QWORD PTR [eax] 

In terms of testing approach, I would propose the following.

  1. Create a testbed for CET.
  2. Build Solana with IBT and make sure it passes in interpreter mode
  3. Enforce IBT for all "JIT statically generated" indirect branches.

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

No branches or pull requests

2 participants