On Thu, 22 Sep 2022, Martin Storsjö wrote:

On Thu, 22 Sep 2022, Alvin Wong via Mingw-w64-public wrote:

This adds support to enable building mingw-w64-crt and user code with
Control Flow Guard using Clang, with the option `--enable-cfguard`. With
this option enabled, the Clang 16 compiler option `-mguard=cf` will be
added to CFLAGS when building mingw-w64-crt.

Two new objects are also added to `libmingwex.a` to support CFGuard:

- `mingw_cfguard_support.c` contains the guard check and dispatch
 function pointers and their backward compatible no-op.
 * This object will be built regardless of the `--enable-cfguard`
   option, to allow linking CFGuard-enabled objects to a mingw-w64-crt
   built without CFGuard (the guard checks will effectively become
   no-ops.)
- `mingw_cfguard_loadcfg.S` contains the definition of a load config
 directory structure with the symbol name `_load_config_used`.
 * This object is only built when `--enable-cfguard` is enabled,
   because mingw-w64 doesn't use the load config directory for
   anything else yet. Checks have been added to LLD 16 such that, if
   CFGuard has been requested but the needed load config data is
   missing, it will emit a warning.

This change alone is not enough to fully enable CFGuard in user-built
binaries. All other libraries shipped with the toolchain will also need
to be built with `-mguard=cf` to include CFGuard checks. Same goes for
building user code. If the user builds and links an executable without
`-mguard=cf`, it will still run normally but without any of the CFGuard
checks being operational.

(An exception is the sanitizer libraries -- their API hooking mechanisms
may result in indirect calls that fails CFGuard checks.)

User code may use the function attribute `__declspec(guard(nocf))`
(supported by Clang 16) to stop CFGuard checks from being added to
indirect calls within one function.

===

CFGuard works by having the compiler insert a check before performing
any indirect calls (which terminates the process if the call target is
invalid). The compiler also has to keep track of all the address-taken
functions, which the linker will then use to assemble a
`GuardCFFunctionTable` to list all valid indirect call target addresses.

To maintain backward compatibile, the guard check function is referenced
via a function pointer which points to a no-op by default. On systems
supporting CFGuard, the image loader replaces the function pointer with
the address of the actual guard check function.

For this to work, the metadata is stored in the load config directory
struct. MSVC supplies this struct in vcruntime as a symbol with the name
`_load_config_used`, which the linker takes as the load config
directory. In addition, the linker generates synthetic symbols to be
included in the load config struct. This also works with LLD since it
has implemented this feature.

The load config directory can be inspected using `llvm-readobj
--coff-load-config file.exe` or `dumpbin.exe /loadconfig file.exe`
(dumpbin.exe is included in MSVC build tools.)

Further reading:
- Control Flow Guard: https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard - Load config structure: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-load-configuration-structure-image-only - Control Flow Guard metadata: https://docs.microsoft.com/en-us/windows/win32/secbp/pe-metadata - My personal notes on CFGuard: https://gist.github.com/alvinhochun/a65e4177e2b34d551d7ecb02b55a4b0a

Signed-off-by: Alvin Wong <al...@alvinhc.com>
---
Reworded the commit message to be a bit clearer on what's included when
the flag is not specified.

Great stuff! If the only thing changed is the commit message, then that does seem good to me. I can go ahead and push this after a day or two, to let others still chime in, if they would happen to have concerns.

I pushed this now - thanks for your contribution!

// Martin

_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to