summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/clang
diff options
context:
space:
mode:
authormortimer <mortimer@openbsd.org>2018-06-06 00:14:29 +0000
committermortimer <mortimer@openbsd.org>2018-06-06 00:14:29 +0000
commite688c2b0648a80551cf7353d9f455c7cbb98f13c (patch)
treebb3f8b6975fe82bca012e40729fe5e7d66f07427 /gnu/llvm/tools/clang
parentMove pluart(4) to dev/fdt. (diff)
downloadwireguard-openbsd-e688c2b0648a80551cf7353d9f455c7cbb98f13c.tar.xz
wireguard-openbsd-e688c2b0648a80551cf7353d9f455c7cbb98f13c.zip
Add RETGUARD to clang for amd64. This security mechanism uses per-function
random cookies to protect access to function return instructions, with the effect that the integrity of the return address is protected, and function return instructions are harder to use in ROP gadgets. On function entry the return address is combined with a per-function random cookie and stored in the stack frame. The integrity of this value is verified before function return, and if this check fails, the program aborts. In this way RETGUARD is an improved stack protector, since the cookies are per-function. The verification routine is constructed such that the binary space immediately before each ret instruction is padded with int03 instructions, which makes these return instructions difficult to use in ROP gadgets. In the kernel, this has the effect of removing approximately 50% of total ROP gadgets, and 15% of unique ROP gadgets compared to the 6.3 release kernel. Function epilogues are essentially gadget free, leaving only the polymorphic gadgets that result from jumping into the instruction stream partway through other instructions. Work to remove these gadgets will continue through other mechanisms. Remaining work includes adding this mechanism to assembly routines, which must be done by hand. Many thanks to all those who helped test and provide feedback, especially deaadt, tb, espie and naddy. ok deraadt@
Diffstat (limited to 'gnu/llvm/tools/clang')
-rw-r--r--gnu/llvm/tools/clang/include/clang/Driver/CC1Options.td2
-rw-r--r--gnu/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def3
-rw-r--r--gnu/llvm/tools/clang/lib/CodeGen/CGCall.cpp3
-rw-r--r--gnu/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp7
-rw-r--r--gnu/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp2
5 files changed, 17 insertions, 0 deletions
diff --git a/gnu/llvm/tools/clang/include/clang/Driver/CC1Options.td b/gnu/llvm/tools/clang/include/clang/Driver/CC1Options.td
index 7dea88b62cc..f19b2c3f277 100644
--- a/gnu/llvm/tools/clang/include/clang/Driver/CC1Options.td
+++ b/gnu/llvm/tools/clang/include/clang/Driver/CC1Options.td
@@ -665,6 +665,8 @@ def stack_protector : Separate<["-"], "stack-protector">,
HelpText<"Enable stack protectors">;
def stack_protector_buffer_size : Separate<["-"], "stack-protector-buffer-size">,
HelpText<"Lower bound for a buffer to be considered for stack protection">;
+def ret_protector : Flag<["-"], "ret-protector">,
+ HelpText<"Enable Return Protectors">;
def fvisibility : Separate<["-"], "fvisibility">,
HelpText<"Default type and symbol visibility">;
def ftype_visibility : Separate<["-"], "ftype-visibility">,
diff --git a/gnu/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def b/gnu/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def
index bb91cf5f742..5c4b4c3aa84 100644
--- a/gnu/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def
+++ b/gnu/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def
@@ -252,6 +252,9 @@ VALUE_CODEGENOPT(NumRegisterParameters, 32, 0)
/// The lower bound for a buffer to be considered for stack protection.
VALUE_CODEGENOPT(SSPBufferSize, 32, 0)
+/// Whether to use return protectors
+CODEGENOPT(ReturnProtector, 1, 0)
+
/// The kind of generated debug info.
ENUM_CODEGENOPT(DebugInfo, codegenoptions::DebugInfoKind, 3, codegenoptions::NoDebugInfo)
diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGCall.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGCall.cpp
index 38d7344572d..de67ee39c14 100644
--- a/gnu/llvm/tools/clang/lib/CodeGen/CGCall.cpp
+++ b/gnu/llvm/tools/clang/lib/CodeGen/CGCall.cpp
@@ -1878,6 +1878,9 @@ void CodeGenModule::ConstructAttributeList(
FuncAttrs.addAttribute("disable-tail-calls",
llvm::toStringRef(DisableTailCalls));
+ if (CodeGenOpts.ReturnProtector)
+ FuncAttrs.addAttribute("ret-protector");
+
// Add target-cpu and target-features attributes to functions. If
// we have a decl for the function and it has a target attribute then
// parse that and add it to the feature set.
diff --git a/gnu/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp b/gnu/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp
index f1137b2d928..91a656f4a48 100644
--- a/gnu/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/gnu/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp
@@ -3978,6 +3978,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
else if (A->getOption().matches(options::OPT_fret_protector))
RetProtector = 1;
}
+ if (RetProtector &&
+ (getToolChain().getArch() == llvm::Triple::x86_64) &&
+ !Args.hasArg(options::OPT_fno_stack_protector) &&
+ !Args.hasArg(options::OPT_pg)) {
+ CmdArgs.push_back(Args.MakeArgString("-D_RET_PROTECTOR"));
+ CmdArgs.push_back(Args.MakeArgString(Twine("-ret-protector")));
+ }
// Translate -mstackrealign
if (Args.hasFlag(options::OPT_mstackrealign, options::OPT_mno_stackrealign,
diff --git a/gnu/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp b/gnu/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
index 6ce719aac67..a637af723ab 100644
--- a/gnu/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/gnu/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
@@ -872,6 +872,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.StackAlignment = StackAlignment;
}
+ Opts.ReturnProtector = Args.hasArg(OPT_ret_protector);
+
if (Arg *A = Args.getLastArg(OPT_mstack_probe_size)) {
StringRef Val = A->getValue();
unsigned StackProbeSize = Opts.StackProbeSize;