From f7a83c2a5f643ae914fbb3e474894959d8a38e1e Mon Sep 17 00:00:00 2001 From: Theo de Raadt Date: Sun, 2 Jun 2024 15:40:44 +0000 Subject: add -fret-clean option (amd64 and i386 only at first), defaulting to off. 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 | 4 ++++ gnu/llvm/clang/lib/Driver/ToolChains/Clang.cpp | 10 ++++++++++ gnu/llvm/llvm/lib/Target/X86/X86.h | 4 ++++ gnu/llvm/llvm/lib/Target/X86/X86TargetMachine.cpp | 2 ++ 4 files changed, 20 insertions(+) (limited to 'gnu/llvm') diff --git a/gnu/llvm/clang/include/clang/Driver/Options.td b/gnu/llvm/clang/include/clang/Driver/Options.td index 7a299510905..a5df86eba14 100644 --- a/gnu/llvm/clang/include/clang/Driver/Options.td +++ b/gnu/llvm/clang/include/clang/Driver/Options.td @@ -2857,6 +2857,10 @@ def fno_fixup_gadgets : Flag<["-"], "fno-fixup-gadgets">, Group, Flags< HelpText<"Disable FixupGadgets pass (x86 only)">; def ffixup_gadgets : Flag<["-"], "ffixup-gadgets">, Group, Flags<[CoreOption]>, HelpText<"Replace ROP friendly instructions with safe alternatives (x86 only)">; +def fno_ret_clean : Flag<["-"], "fno-ret-clean">, Group, Flags<[CoreOption]>, + HelpText<"Disable ret-clean pass">; +def fret_clean : Flag<["-"], "fret-clean">, 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, Flags<[CC1Option, CoreOption]>, HelpText<"Stop initializing trivial automatic stack variables after the specified number of instances">, MarshallingInfoInt>; diff --git a/gnu/llvm/clang/lib/Driver/ToolChains/Clang.cpp b/gnu/llvm/clang/lib/Driver/ToolChains/Clang.cpp index 1d073428fe5..6eaa9918302 100644 --- a/gnu/llvm/clang/lib/Driver/ToolChains/Clang.cpp +++ b/gnu/llvm/clang/lib/Driver/ToolChains/Clang.cpp @@ -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); diff --git a/gnu/llvm/llvm/lib/Target/X86/X86.h b/gnu/llvm/llvm/lib/Target/X86/X86.h index 3d0eef8d8ac..bf4503dd65b 100644 --- a/gnu/llvm/llvm/lib/Target/X86/X86.h +++ b/gnu/llvm/llvm/lib/Target/X86/X86.h @@ -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(); diff --git a/gnu/llvm/llvm/lib/Target/X86/X86TargetMachine.cpp b/gnu/llvm/llvm/lib/Target/X86/X86TargetMachine.cpp index 306a53e94fd..5d4b1b9d010 100644 --- a/gnu/llvm/llvm/lib/Target/X86/X86TargetMachine.cpp +++ b/gnu/llvm/llvm/lib/Target/X86/X86TargetMachine.cpp @@ -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) -- cgit v1.2.3