add -fret-clean option (amd64 and i386 only at first), defaulting to off.
authorderaadt <deraadt@openbsd.org>
Sun, 2 Jun 2024 15:40:38 +0000 (15:40 +0000)
committerderaadt <deraadt@openbsd.org>
Sun, 2 Jun 2024 15:40:38 +0000 (15:40 +0000)
This causes the caller to cleans the return address off the stack after
a callq completes.  The option is best used in low-level libraries (such as
libc), because libc contains low-level system call stubs.  The option
reduces hints (found on the stale parts of the stack) about libc.so's mapping
location, and together with random-relinking, relro got/pic, and xonly
makes some exploit methods more difficult.
ok mortimer, mlarkin, much discussion with kettenis, in snaps for 2 weeks.

gnu/llvm/clang/include/clang/Driver/Options.td
gnu/llvm/clang/lib/Driver/ToolChains/Clang.cpp
gnu/llvm/llvm/lib/Target/X86/X86.h
gnu/llvm/llvm/lib/Target/X86/X86TargetMachine.cpp
gnu/usr.bin/clang/libLLVMX86CodeGen/Makefile
share/man/man1/clang-local.1

index 7a29951..a5df86e 100644 (file)
@@ -2857,6 +2857,10 @@ def fno_fixup_gadgets : Flag<["-"], "fno-fixup-gadgets">, Group<f_Group>, Flags<
   HelpText<"Disable FixupGadgets pass (x86 only)">;
 def ffixup_gadgets : Flag<["-"], "ffixup-gadgets">, Group<f_Group>, Flags<[CoreOption]>,
   HelpText<"Replace ROP friendly instructions with safe alternatives (x86 only)">;
+def fno_ret_clean : Flag<["-"], "fno-ret-clean">, Group<f_Group>, Flags<[CoreOption]>,
+  HelpText<"Disable ret-clean pass">;
+def fret_clean : Flag<["-"], "fret-clean">, Group<f_Group>, Flags<[CoreOption]>,
+  HelpText<"Clean return address from stack after call">;
 def ftrivial_auto_var_init_stop_after : Joined<["-"], "ftrivial-auto-var-init-stop-after=">, Group<f_Group>,
   Flags<[CC1Option, CoreOption]>, HelpText<"Stop initializing trivial automatic stack variables after the specified number of instances">,
   MarshallingInfoInt<LangOpts<"TrivialAutoVarInitStopAfter">>;
index 1d07342..6eaa991 100644 (file)
@@ -6402,6 +6402,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
       CmdArgs.push_back(Args.MakeArgString(Twine("-x86-fixup-gadgets=true")));
   }
 
+  // -ret-clean
+  if (Arg *A = Args.getLastArg(options::OPT_fno_ret_clean,
+                               options::OPT_fret_clean)) {
+    CmdArgs.push_back(Args.MakeArgString(Twine("-mllvm")));
+    if (A->getOption().matches(options::OPT_fno_ret_clean))
+      CmdArgs.push_back(Args.MakeArgString(Twine("-x86-ret-clean=false")));
+    else if (A->getOption().matches(options::OPT_fret_clean))
+      CmdArgs.push_back(Args.MakeArgString(Twine("-x86-ret-clean=true")));
+  }
+
   RenderSCPOptions(TC, Args, CmdArgs);
   RenderTrivialAutoVarInitOptions(D, TC, Args, CmdArgs);
 
index 3d0eef8..bf4503d 100644 (file)
@@ -132,6 +132,10 @@ FunctionPass *createX86DomainReassignmentPass();
 /// ROP friendly instructions with alternatives.
 FunctionPass *createX86FixupGadgetsPass();
 
+/// Return a Machine Function pass that attempts to replace
+/// RET instructions with a cleaning sequence
+FunctionPass *createX86RetCleanPass();
+
 /// This pass replaces EVEX encoded of AVX-512 instructiosn by VEX
 /// encoding when possible in order to reduce code size.
 FunctionPass *createX86EvexToVexInsts();
index 306a53e..5d4b1b9 100644 (file)
@@ -596,6 +596,8 @@ void X86PassConfig::addPreEmitPass2() {
   addPass(createX86IndirectThunksPass());
   addPass(createX86ReturnThunksPass());
 
+  addPass(createX86RetCleanPass());
+
   // Insert extra int3 instructions after trailing call instructions to avoid
   // issues in the unwinder.
   if (TT.isOSWindows() && TT.getArch() == Triple::x86_64)
index 0dd32c5..143e37b 100644 (file)
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.18 2023/11/11 18:35:38 robert Exp $
+# $OpenBSD: Makefile,v 1.19 2024/06/02 15:40:42 deraadt Exp $
 
 LIB=   LLVMX86CodeGen
 NOPROFILE=
@@ -25,6 +25,7 @@ SRCS+=        X86AsmPrinter.cpp \
        X86FastISel.cpp \
        X86FixupBWInsts.cpp \
        X86FixupGadgets.cpp \
+       X86RetClean.cpp \
        X86FixupLEAs.cpp \
        X86AvoidStoreForwardingBlocks.cpp \
        X86DynAllocaExpander.cpp \
index 9e02e69..6cc7e0d 100644 (file)
@@ -1,4 +1,4 @@
-.\" $OpenBSD: clang-local.1,v 1.23 2022/02/18 00:39:18 jca Exp $
+.\" $OpenBSD: clang-local.1,v 1.24 2024/06/02 15:40:43 deraadt Exp $
 .\"
 .\" Copyright (c) 2016 Pascal Stumpf <pascal@stumpf.co>
 .\"
@@ -15,7 +15,7 @@
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
 .\"
-.Dd $Mdocdate: February 18 2022 $
+.Dd $Mdocdate: June 2 2024 $
 .Dt CLANG-LOCAL 1
 .Os
 .Sh NAME
@@ -119,6 +119,13 @@ This can be disabled with the
 option.
 .It
 .Nm clang
+includes a security pass that can clear the return address on the
+stack upon return from calling a function, on i386 and amd64.
+This can be enabled with the
+.Fl fret-clean
+option.
+.It
+.Nm clang
 includes the retguard security feature on amd64, arm64, mips64, powerpc
 and powerpc64.
 This feature can be disabled with the