@@ -191,7 +191,8 @@ Shadow byte legend (one shadow byte represents 8 application bytes):
191191
192192The LLVM Control Flow Integrity (CFI) support in the Rust compiler initially
193193provides forward-edge control flow protection for Rust-compiled code only by
194- aggregating function pointers in groups identified by their number of arguments.
194+ aggregating function pointers in groups identified by their return and parameter
195+ types.
195196
196197Forward-edge control flow protection for C or C++ and Rust -compiled code " mixed
197198binaries" (i.e., for when C or C++ and Rust -compiled code share the same
@@ -243,7 +244,7 @@ fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
243244fn main () {
244245 let answer = do_twice(add_one, 5);
245246
246- println! (" The answer is: {answer} " );
247+ println! (" The answer is: {} " , answer );
247248
248249 println! (" With CFI enabled, you should not see the next answer" );
249250 let f: fn(i32) -> i32 = unsafe {
@@ -253,30 +254,30 @@ fn main() {
253254 };
254255 let next_answer = do_twice(f, 5);
255256
256- println! (" The next answer is: {next_answer} " );
257+ println! (" The next answer is: {} " , next_answer );
257258}
258259` ` `
259260Fig. 1. Modified example from the [Advanced Functions and
260261Closures][rust-book-ch19-05] chapter of the [The Rust Programming
261262Language][rust-book] book.
262263
263- [//]: # (FIXME: Replace with output from cargo using nightly when #89652 is merged)
264-
265264` ` ` shell
266- $ rustc rust_cfi.rs -o rust_cfi
267- $ ./rust_cfi
265+ $ cargo run --release
266+ Compiling rust-cfi-1 v0.1.0 (/home/rcvalle/rust-cfi-1)
267+ Finished release [optimized] target(s) in 0.76s
268+ Running ` target/release/rust-cfi-1`
268269The answer is: 12
269270With CFI enabled, you should not see the next answer
270271The next answer is: 14
271272$
272273` ` `
273274Fig. 2. Build and execution of the modified example with LLVM CFI disabled.
274275
275- [//]: # (FIXME: Replace with output from cargo using nightly when #89652 is merged)
276-
277276` ` ` shell
278- $ rustc -Clto -Zsanitizer=cfi rust_cfi.rs -o rust_cfi
279- $ ./rust_cfi
277+ $ RUSTFLAGS=" -Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release
278+ Compiling rust-cfi-1 v0.1.0 (/home/rcvalle/rust-cfi-1)
279+ Finished release [optimized] target(s) in 3.39s
280+ Running ` target/release/rust-cfi-1`
280281The answer is: 12
281282With CFI enabled, you should not see the next answer
282283Illegal instruction
@@ -306,37 +307,37 @@ fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
306307fn main () {
307308 let answer = do_twice(add_one, 5);
308309
309- println! (" The answer is: {answer} " );
310+ println! (" The answer is: {} " , answer );
310311
311312 println! (" With CFI enabled, you should not see the next answer" );
312313 let f: fn(i32) -> i32 =
313314 unsafe { mem::transmute::< * const u8, fn(i32) -> i32> (add_two as * const u8) };
314315 let next_answer = do_twice(f, 5);
315316
316- println! (" The next answer is: {next_answer} " );
317+ println! (" The next answer is: {} " , next_answer );
317318}
318319` ` `
319320Fig. 4. Another modified example from the [Advanced Functions and
320321Closures][rust-book-ch19-05] chapter of the [The Rust Programming
321322Language][rust-book] book.
322323
323- [//]: # (FIXME: Replace with output from cargo using nightly when #89652 is merged)
324-
325324` ` ` shell
326- $ rustc rust_cfi.rs -o rust_cfi
327- $ ./rust_cfi
325+ $ cargo run --release
326+ Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2)
327+ Finished release [optimized] target(s) in 0.76s
328+ Running ` target/release/rust-cfi-2`
328329The answer is: 12
329330With CFI enabled, you should not see the next answer
330331The next answer is: 14
331332$
332333` ` `
333334Fig. 5. Build and execution of the modified example with LLVM CFI disabled.
334335
335- [//]: # (FIXME: Replace with output from cargo using nightly when #89652 is merged)
336-
337336` ` ` shell
338- $ rustc -Clto -Zsanitizer=cfi rust_cfi.rs -o rust_cfi
339- $ ./rust_cfi
337+ $ RUSTFLAGS=" -Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release
338+ Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2)
339+ Finished release [optimized] target(s) in 3.38s
340+ Running ` target/release/rust-cfi-2`
340341The answer is: 12
341342With CFI enabled, you should not see the next answer
342343Illegal instruction
@@ -346,14 +347,69 @@ Fig. 6. Build and execution of the modified example with LLVM CFI enabled.
346347
347348When LLVM CFI is enabled, if there are any attempts to change/hijack control
348349flow using an indirect branch/call to a function with different number of
349- arguments than intended/passed in the call/branch site, the execution is also
350- terminated (see Fig. 6).
351-
352- Forward-edge control flow protection not only by aggregating function pointers
353- in groups identified by their number of arguments, but also their argument
354- types, will also be provided in later work by defining and using compatible type
355- identifiers (see Type metadata in the design document in the tracking
356- issue [# 89653](https://github.com/rust-lang/rust/issues/89653)).
350+ parameters than arguments intended/passed in the call/branch site, the
351+ execution is also terminated (see Fig. 6).
352+
353+ ` ` ` rust
354+ use std::mem;
355+
356+ fn add_one(x: i32) -> i32 {
357+ x + 1
358+ }
359+
360+ fn add_two(x: i64) -> i64 {
361+ x + 2
362+ }
363+
364+ fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
365+ f(arg) + f(arg)
366+ }
367+
368+ fn main () {
369+ let answer = do_twice(add_one, 5);
370+
371+ println! (" The answer is: {}" , answer);
372+
373+ println! (" With CFI enabled, you should not see the next answer" );
374+ let f: fn(i32) -> i32 =
375+ unsafe { mem::transmute::< * const u8, fn(i32) -> i32> (add_two as * const u8) };
376+ let next_answer = do_twice(f, 5);
377+
378+ println! (" The next answer is: {}" , next_answer);
379+ }
380+ ` ` `
381+ Fig. 7. Another modified example from the [Advanced Functions and
382+ Closures][rust-book-ch19-05] chapter of the [The Rust Programming
383+ Language][rust-book] book.
384+
385+ ` ` ` shell
386+ cargo run --release
387+ Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3)
388+ Finished release [optimized] target(s) in 0.74s
389+ Running ` target/release/rust-cfi-3`
390+ The answer is: 12
391+ With CFI enabled, you should not see the next answer
392+ The next answer is: 14
393+ $
394+ ` ` `
395+ Fig. 8. Build and execution of the modified example with LLVM CFI disabled.
396+
397+ ` ` ` shell
398+ $ RUSTFLAGS=" -Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release
399+ Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3)
400+ Finished release [optimized] target(s) in 3.40s
401+ Running ` target/release/rust-cfi-3`
402+ The answer is: 12
403+ With CFI enabled, you should not see the next answer
404+ Illegal instruction
405+ $
406+ ` ` `
407+ Fig. 9. Build and execution of the modified example with LLVM CFI enabled.
408+
409+ When LLVM CFI is enabled, if there are any attempts to change/hijack control
410+ flow using an indirect branch/call to a function with different return and
411+ parameter types than the return type expected and arguments intended/passed in
412+ the call/branch site, the execution is also terminated (see Fig. 9).
357413
358414[rust-book-ch19-05]: https://doc.rust-lang.org/book/ch19-05-advanced-functions-and-closures.html
359415[rust-book]: https://doc.rust-lang.org/book/title-page.html
0 commit comments