// Copyright 2023 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. //! To test that CFG is working, build this executable on Windows and run it //! as: //! //! `out\Release\cdb\cdb.exe -G -g -o .\out\Release\test_control_flow_guard.exe` //! //! Which should print: //! ``` //! (a2d4.bcd8): Security check failure or stack buffer overrun - code c0000409 //! (!!! second chance !!!) //! Subcode: 0xa FAST_FAIL_GUARD_ICALL_CHECK_FAILURE //! ``` //! //! If cdb.exe is not present, first run `ninja -C out\Release cdb\cdb.exe`. use std::arch::asm; #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] const NOP_INSTRUCTION_SIZE: usize = 1; #[cfg(target_arch = "aarch64")] const NOP_INSTRUCTION_SIZE: usize = 4; #[inline(never)] fn nop_sled() { unsafe { asm!("nop", "nop", "ret",) } } #[inline(never)] fn indirect_call(func: fn()) { func(); } fn main() { let fptr = unsafe { std::mem::transmute::(nop_sled as usize + NOP_INSTRUCTION_SIZE) }; // Generates a FAST_FAIL_GUARD_ICALL_CHECK_FAILURE if CFG triggers. indirect_call(fptr); // Should only reach here if CFG is disabled. eprintln!("failed"); }