1
1
mirror of https://github.com/rui314/mold.git synced 2024-10-04 00:31:41 +03:00
mold/test/arch-x86_64-z-rewrite-endbr.sh

28 lines
711 B
Bash
Raw Permalink Normal View History

Add an experimental `-z rewrite-endbr` option endbr64 is a relatively new x86 instruction to mark a location to which an indirect jump instruction can transfer control. If the control-flow integrity is turned on (i.e., endbr64 is effective), an indirect jump can only target an endbr64 or raise a runtime exception. This mechanism makes some types of control hijacking attacks, such as ROP or JOP, very hard because an attacker can no longer jump to an arbitrary location. If `-fcf-protection` is given, GCC emits an endbr64 at the beginning of each global function conservatively because the address of that function might be used by other translation units. In reality, most function addresses aren't taken, so the conservative assumption ends up emitting lots of unnecessary endbr64 instructions. This not only bloats the code but also weakens security because an attacker would have more locations to attack. The new linker option, `-z rewrite-endbr`, is designed to mitigate this situation. The linker is in a position to conduct whole-program analysis on the input files and determine functions whose addresses have never been taken. If `-z rewrite-endbr` is given, mold performs that analysis and rewrites the leading endbr64 with a nop if the function's address wasn't taken. For evaluation, I built the mold executable itself both with and without this option. Before using the `-z rewrite-endbr` option, the mold executable contained 25,994 endbr64 instructions. With the option, the number becomes 18,035, a 30% reduction. The new option is exprerimental; we may remove it in a future versions of the mold linker.
2023-10-02 11:30:21 +03:00
#!/bin/bash
. $(dirname $0)/common.inc
2023-10-02 14:03:24 +03:00
test_cflags -fcf-protection || skip
Add an experimental `-z rewrite-endbr` option endbr64 is a relatively new x86 instruction to mark a location to which an indirect jump instruction can transfer control. If the control-flow integrity is turned on (i.e., endbr64 is effective), an indirect jump can only target an endbr64 or raise a runtime exception. This mechanism makes some types of control hijacking attacks, such as ROP or JOP, very hard because an attacker can no longer jump to an arbitrary location. If `-fcf-protection` is given, GCC emits an endbr64 at the beginning of each global function conservatively because the address of that function might be used by other translation units. In reality, most function addresses aren't taken, so the conservative assumption ends up emitting lots of unnecessary endbr64 instructions. This not only bloats the code but also weakens security because an attacker would have more locations to attack. The new linker option, `-z rewrite-endbr`, is designed to mitigate this situation. The linker is in a position to conduct whole-program analysis on the input files and determine functions whose addresses have never been taken. If `-z rewrite-endbr` is given, mold performs that analysis and rewrites the leading endbr64 with a nop if the function's address wasn't taken. For evaluation, I built the mold executable itself both with and without this option. Before using the `-z rewrite-endbr` option, the mold executable contained 25,994 endbr64 instructions. With the option, the number becomes 18,035, a 30% reduction. The new option is exprerimental; we may remove it in a future versions of the mold linker.
2023-10-02 11:30:21 +03:00
cat <<EOF | $CC -o $t/a.o -c -xc - -ffunction-sections -O -fcf-protection
Add an experimental `-z rewrite-endbr` option endbr64 is a relatively new x86 instruction to mark a location to which an indirect jump instruction can transfer control. If the control-flow integrity is turned on (i.e., endbr64 is effective), an indirect jump can only target an endbr64 or raise a runtime exception. This mechanism makes some types of control hijacking attacks, such as ROP or JOP, very hard because an attacker can no longer jump to an arbitrary location. If `-fcf-protection` is given, GCC emits an endbr64 at the beginning of each global function conservatively because the address of that function might be used by other translation units. In reality, most function addresses aren't taken, so the conservative assumption ends up emitting lots of unnecessary endbr64 instructions. This not only bloats the code but also weakens security because an attacker would have more locations to attack. The new linker option, `-z rewrite-endbr`, is designed to mitigate this situation. The linker is in a position to conduct whole-program analysis on the input files and determine functions whose addresses have never been taken. If `-z rewrite-endbr` is given, mold performs that analysis and rewrites the leading endbr64 with a nop if the function's address wasn't taken. For evaluation, I built the mold executable itself both with and without this option. Before using the `-z rewrite-endbr` option, the mold executable contained 25,994 endbr64 instructions. With the option, the number becomes 18,035, a 30% reduction. The new option is exprerimental; we may remove it in a future versions of the mold linker.
2023-10-02 11:30:21 +03:00
int foo() { return 3; }
int bar() { return foo(); }
EOF
cat <<EOF | $CC -o $t/b.o -c -xc - -ffunction-sections -O -fcf-protection
Add an experimental `-z rewrite-endbr` option endbr64 is a relatively new x86 instruction to mark a location to which an indirect jump instruction can transfer control. If the control-flow integrity is turned on (i.e., endbr64 is effective), an indirect jump can only target an endbr64 or raise a runtime exception. This mechanism makes some types of control hijacking attacks, such as ROP or JOP, very hard because an attacker can no longer jump to an arbitrary location. If `-fcf-protection` is given, GCC emits an endbr64 at the beginning of each global function conservatively because the address of that function might be used by other translation units. In reality, most function addresses aren't taken, so the conservative assumption ends up emitting lots of unnecessary endbr64 instructions. This not only bloats the code but also weakens security because an attacker would have more locations to attack. The new linker option, `-z rewrite-endbr`, is designed to mitigate this situation. The linker is in a position to conduct whole-program analysis on the input files and determine functions whose addresses have never been taken. If `-z rewrite-endbr` is given, mold performs that analysis and rewrites the leading endbr64 with a nop if the function's address wasn't taken. For evaluation, I built the mold executable itself both with and without this option. Before using the `-z rewrite-endbr` option, the mold executable contained 25,994 endbr64 instructions. With the option, the number becomes 18,035, a 30% reduction. The new option is exprerimental; we may remove it in a future versions of the mold linker.
2023-10-02 11:30:21 +03:00
int main() {}
EOF
$CC -B. -o $t/exe1 $t/a.o $t/b.o
$OBJDUMP -dr $t/exe1 > $t/log1
grep -A1 '<foo>:' $t/log1 | grep -q endbr64
grep -A1 '<bar>:' $t/log1 | grep -q endbr64
grep -A1 '<main>:' $t/log1 | grep -q endbr64
$CC -B. -o $t/exe2 $t/a.o $t/b.o -Wl,-z,rewrite-endbr
Add an experimental `-z rewrite-endbr` option endbr64 is a relatively new x86 instruction to mark a location to which an indirect jump instruction can transfer control. If the control-flow integrity is turned on (i.e., endbr64 is effective), an indirect jump can only target an endbr64 or raise a runtime exception. This mechanism makes some types of control hijacking attacks, such as ROP or JOP, very hard because an attacker can no longer jump to an arbitrary location. If `-fcf-protection` is given, GCC emits an endbr64 at the beginning of each global function conservatively because the address of that function might be used by other translation units. In reality, most function addresses aren't taken, so the conservative assumption ends up emitting lots of unnecessary endbr64 instructions. This not only bloats the code but also weakens security because an attacker would have more locations to attack. The new linker option, `-z rewrite-endbr`, is designed to mitigate this situation. The linker is in a position to conduct whole-program analysis on the input files and determine functions whose addresses have never been taken. If `-z rewrite-endbr` is given, mold performs that analysis and rewrites the leading endbr64 with a nop if the function's address wasn't taken. For evaluation, I built the mold executable itself both with and without this option. Before using the `-z rewrite-endbr` option, the mold executable contained 25,994 endbr64 instructions. With the option, the number becomes 18,035, a 30% reduction. The new option is exprerimental; we may remove it in a future versions of the mold linker.
2023-10-02 11:30:21 +03:00
$OBJDUMP -dr $t/exe2 > $t/log2
grep -A1 '<foo>:' $t/log2 | grep -q nop
grep -A1 '<bar>:' $t/log2 | grep -q nop
grep -A1 '<main>:' $t/log2 | grep -q endbr64