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

Initial forward-edge CFI implementation #3693

Merged
merged 5 commits into from
Sep 8, 2022

Conversation

akirilov-arm
Copy link
Contributor

@akirilov-arm akirilov-arm commented Jan 14, 2022

This pull request is meant to illustrate the RFC proposal to improve control flow integrity for compiled WebAssembly code by using the Branch Target Identification (BTI) extension to the Arm instruction set architecture (bytecodealliance/rfcs#17), so it is not ready to be merged yet.

P.S. The RFC proposal has now been merged, and the changes in this PR have been updated the reflect the final version of the proposal, so they are now ready.

@github-actions github-actions bot added cranelift Issues related to the Cranelift code generator cranelift:area:machinst Issues related to instruction selection and the new MachInst backend. cranelift:area:aarch64 Issues related to AArch64 backend. cranelift:area:x64 Issues related to x64 codegen cranelift:meta Everything related to the meta-language. labels Jan 14, 2022
@github-actions github-actions bot added the wasmtime:api Related to the API of the `wasmtime` crate itself label Mar 7, 2022
@github-actions
Copy link

github-actions bot commented Mar 7, 2022

Subscribe to Label Action

cc @peterhuene

This issue or pull request has been labeled: "cranelift", "cranelift:area:aarch64", "cranelift:area:machinst", "cranelift:area:x64", "cranelift:meta", "wasmtime:api"

Thus the following users have been cc'd because of the following labels:

  • peterhuene: wasmtime:api

To subscribe or unsubscribe from this label, edit the .github/subscribe-to-label.json configuration file.

Learn more.

@akirilov-arm akirilov-arm changed the title [RFC] Initial forward-edge CFI implementation Initial forward-edge CFI implementation May 4, 2022
@github-actions github-actions bot added the fuzzing Issues related to our fuzzing infrastructure label May 4, 2022
@github-actions
Copy link

github-actions bot commented May 4, 2022

Subscribe to Label Action

cc @fitzgen

This issue or pull request has been labeled: "fuzzing"

Thus the following users have been cc'd because of the following labels:

  • fitzgen: fuzzing

To subscribe or unsubscribe from this label, edit the .github/subscribe-to-label.json configuration file.

Learn more.

@akirilov-arm
Copy link
Contributor Author

Note that the region crate lacks support for BTI (reported in darfink/region-rs#21), so I have used a work-around - a direct call to libc::mprotect().

@akirilov-arm akirilov-arm force-pushed the bti branch 2 times, most recently from f5f2375 to 43c50c2 Compare May 13, 2022 15:38
@akirilov-arm akirilov-arm force-pushed the bti branch 2 times, most recently from 0ae4b62 to b45cc6d Compare May 26, 2022 18:20
cranelift/jit/src/memory.rs Outdated Show resolved Hide resolved
cranelift/jit/src/memory.rs Outdated Show resolved Hide resolved
@akirilov-arm akirilov-arm force-pushed the bti branch 3 times, most recently from cfe59d0 to 0621025 Compare June 22, 2022 13:08
@akirilov-arm
Copy link
Contributor Author

@alexcrichton I added you as reviewer for the Wasmtime bits.

Copy link
Member

@alexcrichton alexcrichton left a comment

Choose a reason for hiding this comment

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

Seems reasonable enough to me! Sorry you've probably answered these questions before but I wanted to double-check something as well:

  • If a module is compiled with bti support and loaded into an engine that has bti support disabled, that's fine right? (since everything is a nop)
  • If a module is not compiled with bti support, but is loaded into an engine with bti support, that's bad right? (in that none of the branches are protected but the page permissions say that all branches need protection?)

Otherwise though I think this can cut down on the amount of is_branch_proetection_enabled calls and passing-of-the-bool by just making it a method on Engine to avoid some extra changes here.

crates/runtime/src/mmap.rs Outdated Show resolved Hide resolved
crates/runtime/src/mmap.rs Outdated Show resolved Hide resolved
crates/wasmtime/src/lib.rs Outdated Show resolved Hide resolved
crates/wasmtime/src/module.rs Outdated Show resolved Hide resolved
@akirilov-arm
Copy link
Contributor Author

@alexcrichton I wanted to finish with the pointer authentication PR before coming back to this one:

* If a module is compiled with bti support and loaded into an engine that has bti support disabled, that's fine right? (since everything is a nop)

Yes, that is correct; we just have to make sure that we do not request the PROT_BTI memory protection mode from the kernel, since the system call is going to fail.

* If a module is not compiled with bti support, but is loaded into an engine with bti support, that's bad right? (in that none of the branches are protected but the page permissions say that all branches need protection?)

Yes, assuming that the engine applies PROT_BTI unconditionally to all executable memory pages.

The current implementation supports the full flexibility the BTI extension enables, so we have to decouple the following:

  • whether the user passed --cranelift-enable use_bti on the Wasmtime command line
  • whether the environment (i.e. CPU and OS) supports BTI
  • whether the module that the engine is trying to load has been compiled to use BTI instructions; also, if I am not mistaken, the engine could be trying to load several modules, which might not necessarily have been compiled with the same settings

@afonso360
Copy link
Contributor

afonso360 commented Aug 16, 2022

We should add a target aarch64 use_bti to runtests/br_table.clif, we now use the cranelift-jit to run runtests so we can also test the cranelift-jit portion of this PR.

We don't yet support call's, but that's something I'm addressing in #4667, and can add some bti runtests there as well.

Copy link
Member

@alexcrichton alexcrichton left a comment

Choose a reason for hiding this comment

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

Just a few minor nits but otherwise the all the wasmtime bits look reasonable to me

crates/runtime/src/mmap.rs Outdated Show resolved Hide resolved
crates/wasmtime/src/engine.rs Outdated Show resolved Hide resolved
crates/wasmtime/src/module.rs Outdated Show resolved Hide resolved
crates/wasmtime/src/module.rs Outdated Show resolved Hide resolved
@alexcrichton
Copy link
Member

Ah sorry ok I see why this can't be an Engine-level thing. If that's the case though instead of ferrying a separate bool through the system could this get attached to CompiledModuleInfo somewhere internally?

Give the user the option to start all basic blocks that are targets
of indirect branches with the BTI instruction introduced by the
Branch Target Identification extension to the Arm instruction set
architecture.

Copyright (c) 2022, Arm Limited.
@akirilov-arm akirilov-arm force-pushed the bti branch 2 times, most recently from 2595dec to d7bfc26 Compare August 22, 2022 12:01
This involves "parsing" twice but this is parsing just the header of an
ELF file so it's not a very intensive operation and should be ok to do
twice.
@akirilov-arm
Copy link
Contributor Author

@cfallin I think that I have resolved all of @alexcrichton's comments that are related to Wasmtime, so do you have any feedback on the Cranelift side of things?

Copy link
Member

@cfallin cfallin left a comment

Choose a reason for hiding this comment

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

Thanks @akirilov-arm and sorry for the delay in giving the Cranelift parts a review!

Overall I think this is quite reasonable. I do have one suggestion for a simplification in the way that the locations of indirect-target blocks are determined (and I apologize for being extra-picky with this bit of code but the CFG lowering is a very critical and historically difficult-to-get-right piece of the backend!). With that modified, or at least with the suggestion explored, then LGTM.

cranelift/codegen/src/inst_predicates.rs Show resolved Hide resolved
cranelift/codegen/src/machinst/vcode.rs Outdated Show resolved Hide resolved
cranelift/jit/src/memory.rs Outdated Show resolved Hide resolved
Copyright (c) 2022, Arm Limited.
Copyright (c) 2022, Arm Limited.
Copy link
Member

@cfallin cfallin left a comment

Choose a reason for hiding this comment

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

LGTM for the Cranelift bits -- thanks a bunch for the patience!

cc @alexcrichton to double-check the Wasmtime-related changes?

@alexcrichton alexcrichton merged commit d8b2908 into bytecodealliance:main Sep 8, 2022
@akirilov-arm akirilov-arm deleted the bti branch September 8, 2022 14:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cranelift:area:aarch64 Issues related to AArch64 backend. cranelift:area:machinst Issues related to instruction selection and the new MachInst backend. cranelift:area:x64 Issues related to x64 codegen cranelift:meta Everything related to the meta-language. cranelift Issues related to the Cranelift code generator fuzzing Issues related to our fuzzing infrastructure wasmtime:api Related to the API of the `wasmtime` crate itself
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants