Rust-GCC / Rust-GCC/gccrs

Investigate proper Rust CFI implementation

Open
#4,876 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

codegen rust-for-linux
Dominant language
C++
Stars
2.9k
Forks
231
Avg merge
19h 55m
Merged PRs (30d)
67

Description

This will be needed in order to properly support Control Flow Integrity. I reached out to @darksonn to discuss CFI use in the Rust parts of the Linux kernel especially, and she gave me some really useful information for CFI implementation details that I'm pasting here verbatim (with her approval):

A few implementation tips:

In some scenarios you will need to create a "trampoline" to give a
function a different signature than its "native" signature. For
example, given:

trait Foo {
    fn foo(&self);
}

impl Foo for String {
    fn foo(&self) { println!("{}", self); }
}

Then String::foo will give you an fn(&String), and the hash stored for
this function pointer needs to be the hash for that signature. This
means that it cannot be the same function pointer as the one stored in
the Foo vtable for String, as that function pointer is invoked with
dynamic dispatch by callers that expect a signature of "pointer to
Foo" rather than "pointer to String".

Similarly, a Rust vtable also contains a function pointer to the
destructor, and the same problem applies here. But this one has one
difference as the same destructor can be in many vtables for different
traits.

Rust approached this by letting the "native" signature of
String::foo() be a pointer to "Foo", and if you create an fn(&String)
to the same function, then rustc generates a trammpoline function that
has the other signature and calls the original function. This ensures
that trampolines are not needed for the common case (the fp in the
vtable). The trampoline is just a function that will immediately jump
to the true implementation.

For destructors the reverse convention is chosen. This means that
trait vtables contain a trampoline to the destructor.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the CFI implementation details and Rust vtable/trampoline examples quoted in the issue. Determine the required approach for supporting CFI in the Rust parts of the Linux kernel and define what proper support entails; the issue names no files or tests, so completion criteria must first be established.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.