diff options
21 files changed, 400 insertions, 8 deletions
diff --git a/distrib/amd64/ramdiskA/Makefile.inc b/distrib/amd64/ramdiskA/Makefile.inc index a2e02e30819..5248f4d1264 100644 --- a/distrib/amd64/ramdiskA/Makefile.inc +++ b/distrib/amd64/ramdiskA/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.6 2017/08/13 15:41:30 jasper Exp $ +# $OpenBSD: Makefile.inc,v 1.7 2018/06/06 00:14:29 mortimer Exp $ TOP= ${.CURDIR}/.. @@ -75,7 +75,7 @@ bsd.rd: mr.fs bsd rdsetroot bsd: cd ${.CURDIR}/../../../sys/arch/amd64/compile/${RAMDISK} && \ - su ${BUILDUSER} -c '${MAKE} config && ${MAKE} clean && env COPTS=-Oz ${MAKE}' + su ${BUILDUSER} -c '${MAKE} config && ${MAKE} clean && env COPTS="-Oz -fno-ret-protector" ${MAKE}' cp -p ${.CURDIR}/../../../sys/arch/amd64/compile/${RAMDISK}/obj/bsd bsd mr.fs: instbin diff --git a/gnu/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/gnu/llvm/include/llvm/CodeGen/MachineFrameInfo.h index f887517217e..ad18d16ee70 100644 --- a/gnu/llvm/include/llvm/CodeGen/MachineFrameInfo.h +++ b/gnu/llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -237,6 +237,11 @@ class MachineFrameInfo { /// The frame index for the stack protector. int StackProtectorIdx = -1; + /// The register to use for the return protector temp register + unsigned ReturnProtectorTempRegister = 0; + /// Set to true if using return protectors + bool ReturnProtector = false; + /// The frame index for the function context. Used for SjLj exceptions. int FunctionContextIdx = -1; @@ -314,6 +319,14 @@ public: void setStackProtectorIndex(int I) { StackProtectorIdx = I; } bool hasStackProtectorIndex() const { return StackProtectorIdx != -1; } + /// Return the temporary register for the return protector cookie calculation + int getReturnProtectorTempRegister() const { return ReturnProtectorTempRegister; } + void setReturnProtectorTempRegister(unsigned I) { ReturnProtectorTempRegister = I; } + bool hasReturnProtectorTempRegister() const { return ReturnProtectorTempRegister != 0; } + /// Return the return protector level + void setReturnProtector(bool I) { ReturnProtector = I; } + bool hasReturnProtector() const { return ReturnProtector; } + /// Return the index for the function context object. /// This object is used for SjLj exceptions. int getFunctionContextIndex() const { return FunctionContextIdx; } diff --git a/gnu/llvm/include/llvm/CodeGen/Passes.h b/gnu/llvm/include/llvm/CodeGen/Passes.h index 064526b1efa..d02eadd4e3c 100644 --- a/gnu/llvm/include/llvm/CodeGen/Passes.h +++ b/gnu/llvm/include/llvm/CodeGen/Passes.h @@ -307,6 +307,9 @@ namespace llvm { /// FunctionPass *createStackProtectorPass(); + // createReturnProtectorPass - This pass add return protectors to functions. + FunctionPass *createReturnProtectorPass(); + /// createMachineVerifierPass - This pass verifies cenerated machine code /// instructions for correctness. /// diff --git a/gnu/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/gnu/llvm/include/llvm/CodeGen/TargetFrameLowering.h index 61f1cf07bcf..e07aaddc076 100644 --- a/gnu/llvm/include/llvm/CodeGen/TargetFrameLowering.h +++ b/gnu/llvm/include/llvm/CodeGen/TargetFrameLowering.h @@ -165,6 +165,24 @@ public: virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const = 0; + /// determineReturnProtectorTempRegister - Find a register that can be used + /// during function prologue / epilogue to store the return protector cookie + virtual bool determineReturnProtectorTempRegister(MachineFunction &MF, + const SmallVector<MachineBasicBlock *, 4> &SaveBlocks, + const SmallVector<MachineBasicBlock *, 4> &RestoreBlocks) const { + return false; + } + + /// insertReturnProtectorPrologue/Epilogue - Insert ret-protector code + virtual void insertReturnProtectorPrologue(MachineFunction &MF, + MachineBasicBlock &MBB) const + {} + virtual bool insertReturnProtectorEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const + { + return false; + } + /// Replace a StackProbe stub (if any) with the actual probe code inline virtual void inlineStackProbe(MachineFunction &MF, MachineBasicBlock &PrologueMBB) const {} diff --git a/gnu/llvm/include/llvm/InitializePasses.h b/gnu/llvm/include/llvm/InitializePasses.h index 4c79333f5d2..8ec56344bad 100644 --- a/gnu/llvm/include/llvm/InitializePasses.h +++ b/gnu/llvm/include/llvm/InitializePasses.h @@ -321,6 +321,7 @@ void initializeRegionViewerPass(PassRegistry&); void initializeRegisterCoalescerPass(PassRegistry&); void initializeRenameIndependentSubregsPass(PassRegistry&); void initializeResetMachineFunctionPass(PassRegistry&); +void initializeReturnProtectorPass(PassRegistry&); void initializeReversePostOrderFunctionAttrsLegacyPassPass(PassRegistry&); void initializeRewriteStatepointsForGCLegacyPassPass(PassRegistry &); void initializeRewriteSymbolsLegacyPassPass(PassRegistry&); diff --git a/gnu/llvm/lib/CodeGen/CMakeLists.txt b/gnu/llvm/lib/CodeGen/CMakeLists.txt index 865de4f47af..42e91978782 100644 --- a/gnu/llvm/lib/CodeGen/CMakeLists.txt +++ b/gnu/llvm/lib/CodeGen/CMakeLists.txt @@ -120,6 +120,7 @@ add_llvm_library(LLVMCodeGen RegUsageInfoCollector.cpp RegUsageInfoPropagate.cpp ResetMachineFunctionPass.cpp + ReturnProtectorPass.cpp SafeStack.cpp SafeStackColoring.cpp SafeStackLayout.cpp diff --git a/gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp index a8d8ad8ac7d..529fa7406a5 100644 --- a/gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -175,6 +175,10 @@ bool PEI::runOnMachineFunction(MachineFunction &Fn) { const TargetRegisterInfo *TRI = Fn.getSubtarget().getRegisterInfo(); const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering(); + // Set Return Protector in the frame + if (F.hasFnAttribute("ret-protector")) + Fn.getFrameInfo().setReturnProtector(true); + RS = TRI->requiresRegisterScavenging(Fn) ? new RegScavenger() : nullptr; FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(Fn); FrameIndexEliminationScavenging = (RS && !FrameIndexVirtualScavenging) || @@ -209,6 +213,19 @@ bool PEI::runOnMachineFunction(MachineFunction &Fn) { if (!F.hasFnAttribute(Attribute::Naked)) insertPrologEpilogCode(Fn); + // Add Return Protectors if using them + if (Fn.getFrameInfo().hasReturnProtector()) { + std::vector<MachineBasicBlock *> ReturnBlocks; + bool insertedGuard = false; + for (auto &MBB: Fn) + if (MBB.isReturnBlock()) + ReturnBlocks.push_back(&MBB); + for (MachineBasicBlock *MBB: ReturnBlocks) + insertedGuard |= TFI->insertReturnProtectorEpilogue(Fn, *MBB); + if (insertedGuard) + TFI->insertReturnProtectorPrologue(Fn, Fn.front()); + } + // Replace all MO_FrameIndex operands with physical register references // and actual offsets. // @@ -293,7 +310,8 @@ void PEI::calculateCallFrameInfo(MachineFunction &Fn) { /// Compute the sets of entry and return blocks for saving and restoring /// callee-saved registers, and placing prolog and epilog code. void PEI::calculateSaveRestoreBlocks(MachineFunction &Fn) { - const MachineFrameInfo &MFI = Fn.getFrameInfo(); + MachineFrameInfo &MFI = Fn.getFrameInfo(); + const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering(); // Even when we do not change any CSR, we still want to insert the // prologue and epilogue of the function. @@ -309,7 +327,18 @@ void PEI::calculateSaveRestoreBlocks(MachineFunction &Fn) { // epilogue. if (!RestoreBlock->succ_empty() || RestoreBlock->isReturnBlock()) RestoreBlocks.push_back(RestoreBlock); - return; + + // If we are adding return protectors ensure we can find a free register + if (MFI.hasReturnProtector() && + !TFI->determineReturnProtectorTempRegister(Fn, SaveBlocks, RestoreBlocks)) { + // Shrinkwrapping will prevent finding a free register + SaveBlocks.clear(); + RestoreBlocks.clear(); + MFI.setSavePoint(nullptr); + MFI.setRestorePoint(nullptr); + } else { + return; + } } // Save refs to entry and return blocks. @@ -320,6 +349,9 @@ void PEI::calculateSaveRestoreBlocks(MachineFunction &Fn) { if (MBB.isReturnBlock()) RestoreBlocks.push_back(&MBB); } + + if (MFI.hasReturnProtector()) + TFI->determineReturnProtectorTempRegister(Fn, SaveBlocks, RestoreBlocks); } static void assignCalleeSavedSpillSlots(MachineFunction &F, @@ -341,6 +373,10 @@ static void assignCalleeSavedSpillSlots(MachineFunction &F, const TargetFrameLowering *TFI = F.getSubtarget().getFrameLowering(); MachineFrameInfo &MFI = F.getFrameInfo(); + + if (MFI.hasReturnProtectorTempRegister()) + CSI.push_back(CalleeSavedInfo(MFI.getReturnProtectorTempRegister())); + if (!TFI->assignCalleeSavedSpillSlots(F, RegInfo, CSI)) { // If target doesn't implement this, use generic code. diff --git a/gnu/llvm/lib/CodeGen/ReturnProtectorPass.cpp b/gnu/llvm/lib/CodeGen/ReturnProtectorPass.cpp new file mode 100644 index 00000000000..c4f8cb4f1b1 --- /dev/null +++ b/gnu/llvm/lib/CodeGen/ReturnProtectorPass.cpp @@ -0,0 +1,61 @@ +//===- ReturnProtectorPass.cpp - Set up rteurn protectors -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass sets up functions for return protectors. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/Passes.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/Pass.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +#define DEBUG_TYPE "return-protector" + +STATISTIC(NumSymbols, "Counts number of cookie symbols added"); + +namespace { + struct ReturnProtector : public FunctionPass { + static char ID; + ReturnProtector() : FunctionPass(ID) {} + + bool runOnFunction(Function &F) override { + if (F.hasFnAttribute("ret-protector")) { + // Create a symbol for the cookie + Module *M = F.getParent(); + std::hash<std::string> hasher; + std::string cookiename = "__retguard_" + std::to_string(hasher((M->getName() + F.getName()).str()) % 4000); + Type *cookietype = Type::getInt8PtrTy(M->getContext()); + GlobalVariable *cookie = dyn_cast_or_null<GlobalVariable>( + M->getOrInsertGlobal(cookiename, cookietype)); + cookie->setInitializer(Constant::getNullValue(cookietype)); + cookie->setLinkage(GlobalVariable::WeakAnyLinkage); + cookie->setVisibility(GlobalValue::HiddenVisibility); + cookie->setSection(".openbsd.randomdata"); + cookie->setExternallyInitialized(true); + F.addFnAttr("ret-protector-cookie", cookiename); + NumSymbols++; + } + return false; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesCFG(); + } + }; +} + +char ReturnProtector::ID = 0; +INITIALIZE_PASS(ReturnProtector, "return-protector", "Return Protector Pass", + false, false) +FunctionPass *llvm::createReturnProtectorPass() { return new ReturnProtector(); } + diff --git a/gnu/llvm/lib/CodeGen/TargetPassConfig.cpp b/gnu/llvm/lib/CodeGen/TargetPassConfig.cpp index 3e6ad3eeef0..04f60eca18b 100644 --- a/gnu/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/gnu/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -688,6 +688,8 @@ void TargetPassConfig::addISelPrepare() { if (requiresCodeGenSCCOrder()) addPass(new DummyCGSCCPass); + addPass(createReturnProtectorPass()); + // Add both the safe stack and the stack protection passes: each of them will // only protect functions that have corresponding attributes. addPass(createSafeStackPass()); diff --git a/gnu/llvm/lib/Target/X86/X86FrameLowering.cpp b/gnu/llvm/lib/Target/X86/X86FrameLowering.cpp index 11808f8995f..16acc7ea459 100644 --- a/gnu/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/gnu/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -3059,3 +3059,201 @@ void X86FrameLowering::processFunctionBeforeFrameFinalized( UnwindHelpFI) .addImm(-2); } + +static void markUsedRegsInSuccessors(MachineBasicBlock &MBB, + SmallSet<unsigned, 16> &Used, + SmallSet<int, 24> &Visited) { + int BBNum = MBB.getNumber(); + if (Visited.count(BBNum)) + return; + + // Mark all the registers used + for (auto &MBBI : MBB.instrs()) + for (auto &MBBIOp : MBBI.operands()) + if (MBBIOp.isReg()) + Used.insert(MBBIOp.getReg()); + // Mark this MBB as visited + Visited.insert(BBNum); + // Recurse over all successors + for (auto &SuccMBB : MBB.successors()) + markUsedRegsInSuccessors(*SuccMBB, Used, Visited); +} + +static inline bool opcodeIsRealReturn(unsigned opcode) { + switch (opcode) { + case X86::RET: + case X86::RETL: + case X86::RETQ: + case X86::RETW: + case X86::RETIL: + case X86::RETIQ: + case X86::RETIW: + case X86::LRETL: + case X86::LRETQ: + case X86::LRETW: + case X86::LRETIL: + case X86::LRETIQ: + case X86::LRETIW: + return true; + default: + return false; + } +} +static inline bool needsReturnProtector(MachineFunction &MF) { + for (auto &MBB : MF) + for (auto &T : MBB.terminators()) + if (opcodeIsRealReturn(T.getOpcode())) + return true; + return false; +} + +bool X86FrameLowering::determineReturnProtectorTempRegister(MachineFunction &MF, + const SmallVector<MachineBasicBlock *, 4> &SaveBlocks, + const SmallVector<MachineBasicBlock *, 4> &RestoreBlocks) const { + + MachineFrameInfo &MFI = MF.getFrameInfo(); + + if (!MFI.hasReturnProtector() || !needsReturnProtector(MF)) + return true; + + // CSR spills happen at the beginning of this block + std::vector<unsigned> TempRegs; + SmallSet<unsigned, 16> Used; + SmallSet<int, 24> Visited; + const Function &F = MF.getFunction(); + + TempRegs = {X86::R11, X86::R10}; + if (!F.isVarArg()) { + // We can use any of the caller saved unused arg registers + switch (F.arg_size()) { + case 0: TempRegs.push_back(X86::RDI); + case 1: TempRegs.push_back(X86::RSI); + case 2: // RDX is the 2nd return register + case 3: TempRegs.push_back(X86::RCX); + case 4: TempRegs.push_back(X86::R8); + case 5: TempRegs.push_back(X86::R9); + default: break; + } + } + + // so we can mark it as visited because anything past it is safe + for(auto &SB : SaveBlocks) + Visited.insert(SB->getNumber()); + + // CSR Restores happen at the end of restore blocks, before any terminators, + // so we need to search restores for MBB terminators, and any successor BBs. + for (auto &RB : RestoreBlocks) { + for (auto &RBI : RB->terminators()) + for (auto &RBIOp : RBI.operands()) + if (RBIOp.isReg()) + Used.insert(RBIOp.getReg()); + for (auto &SuccMBB : RB->successors()) + markUsedRegsInSuccessors(*SuccMBB, Used, Visited); + } + + // Now we iterate from the front to find code paths that + // bypass save blocks and land on return blocks + markUsedRegsInSuccessors(MF.front(), Used, Visited); + + // Now we have gathered all the regs used outside the frame save / restore, + // so we can see if we have a free reg to use for the retguard cookie. + for (unsigned Reg : TempRegs) { + bool canUse = true; + for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) { + if (Used.count(*AI)) { + // Reg is used somewhere, so we cannot use it + canUse = false; + break; + } + } + if (canUse) { + MFI.setReturnProtectorTempRegister(Reg); + break; + } + } + + // return whether or not we set a register + return MFI.hasReturnProtectorTempRegister(); +} + +void X86FrameLowering::insertReturnProtectorPrologue(MachineFunction &MF, + MachineBasicBlock &MBB) const +{ + + const MachineFrameInfo &MFI = MF.getFrameInfo(); + + if (!MFI.hasReturnProtector() || !MFI.hasReturnProtectorTempRegister()) + return; + + unsigned CFIIndex; + MachineBasicBlock::instr_iterator MBBI = MBB.instr_begin(); + DebugLoc MBBDL = MBB.findDebugLoc(MBBI); + const Function &Fn = MF.getFunction(); + const Module *M = Fn.getParent(); + GlobalVariable *cookie; + unsigned XORRM, MOVRM, SP, REG, IP; + + XORRM = X86::XOR64rm; + MOVRM = X86::MOV64rm; + SP = X86::RSP; + REG = MFI.getReturnProtectorTempRegister(); + IP = X86::RIP; + + cookie = dyn_cast_or_null<GlobalVariable>(M->getGlobalVariable( + Fn.getFnAttribute("ret-protector-cookie").getValueAsString(), + Type::getInt8PtrTy(M->getContext()))); + MBB.addLiveIn(REG); + BuildMI(MBB, MBBI, MBBDL, TII.get(MOVRM), REG) + .addReg(IP) + .addImm(0) + .addReg(0) + .addGlobalAddress(cookie) + .addReg(0); + addDirectMem(BuildMI(MBB, MBBI, MBBDL, TII.get(XORRM), REG).addReg(REG), SP); +} + +bool X86FrameLowering::insertReturnProtectorEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const +{ + const MachineFrameInfo &MFI = MF.getFrameInfo(); + + if (!MFI.hasReturnProtector() || !MFI.hasReturnProtectorTempRegister()) + return false; + + const Function &Fn = MF.getFunction(); + const Module *M = Fn.getParent(); + std::vector<MachineInstr *> returns; + GlobalVariable *cookie; + unsigned XORRM, CMPRM, SP, REG, IP; + + XORRM = X86::XOR64rm; + CMPRM = X86::CMP64rm; + SP = X86::RSP; + REG = MFI.getReturnProtectorTempRegister(); + IP = X86::RIP; + + for (auto &MI : MBB.terminators()) + if (opcodeIsRealReturn(MI.getOpcode())) + returns.push_back(&MI); + + if (returns.empty()) + return false; + + for (auto &MI : returns) { + const DebugLoc &DL = MI->getDebugLoc(); + cookie = dyn_cast_or_null<GlobalVariable>(M->getGlobalVariable( + Fn.getFnAttribute("ret-protector-cookie").getValueAsString(), + Type::getInt8PtrTy(M->getContext()))); + MBB.addLiveIn(REG); + addDirectMem(BuildMI(MBB, MI, DL, TII.get(XORRM), REG).addReg(REG), SP); + BuildMI(MBB, MI, DL, TII.get(CMPRM)) + .addReg(REG) + .addReg(IP) + .addImm(0) + .addReg(0) + .addGlobalAddress(cookie) + .addReg(0); + BuildMI(MBB, MI, DL, TII.get(X86::RETGUARD_JMP_TRAP)); + } + return true; +} diff --git a/gnu/llvm/lib/Target/X86/X86FrameLowering.h b/gnu/llvm/lib/Target/X86/X86FrameLowering.h index 909319fc18f..5938b36dbd7 100644 --- a/gnu/llvm/lib/Target/X86/X86FrameLowering.h +++ b/gnu/llvm/lib/Target/X86/X86FrameLowering.h @@ -68,6 +68,19 @@ public: void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + /// determineReturnProtectorTempRegister - find a free register for the + /// return protector cookie calculation. + virtual bool determineReturnProtectorTempRegister(MachineFunction &MF, + const SmallVector<MachineBasicBlock *, 4> &SaveBlocks, + const SmallVector<MachineBasicBlock *, 4> &RestoreBlocks) const override; + + + /// Insert Return Protector instrumentation prologue / epilogue + void insertReturnProtectorPrologue(MachineFunction &MF, + MachineBasicBlock &MBB) const override; + bool insertReturnProtectorEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const override; + void adjustForSegmentedStacks(MachineFunction &MF, MachineBasicBlock &PrologueMBB) const override; diff --git a/gnu/llvm/lib/Target/X86/X86InstrCompiler.td b/gnu/llvm/lib/Target/X86/X86InstrCompiler.td index d66d9258e96..34b20cba9aa 100644 --- a/gnu/llvm/lib/Target/X86/X86InstrCompiler.td +++ b/gnu/llvm/lib/Target/X86/X86InstrCompiler.td @@ -267,6 +267,21 @@ def MORESTACK_RET_RESTORE_R10 : I<0, Pseudo, (outs), (ins), } //===----------------------------------------------------------------------===// +// Pseudo instruction used by retguard + +// This is lowered to a JE 2; INT3; INT3. Prior to this pseudo should be a +// compare instruction to ensure the retguard cookie is correct. +// We use a pseudo here in order to avoid splitting the BB just before the return. +// Splitting the BB and inserting a JE_1 over a new INT3 BB occasionally +// resulted in incorrect code when a value from a byte register (CL) was +// used as a return value. When emitted as a split BB, the single byte +// register would sometimes be widened to 4 bytes, which would corrupt +// the return value (ie mov %ecx, %eax instead of mov %cl, %al). +let isCodeGenOnly = 1, Uses = [EFLAGS] in { +def RETGUARD_JMP_TRAP: I<0, Pseudo, (outs), (ins), "", []>; +} + +//===----------------------------------------------------------------------===// // Alias Instructions //===----------------------------------------------------------------------===// diff --git a/gnu/llvm/lib/Target/X86/X86MCInstLower.cpp b/gnu/llvm/lib/Target/X86/X86MCInstLower.cpp index 5f0ada2d6d1..8f1259cb6a9 100644 --- a/gnu/llvm/lib/Target/X86/X86MCInstLower.cpp +++ b/gnu/llvm/lib/Target/X86/X86MCInstLower.cpp @@ -1623,6 +1623,16 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) { .addReg(X86::RAX)); return; + case X86::RETGUARD_JMP_TRAP: { + MCSymbol *RGSuccSym = OutContext.createTempSymbol(); + const MCExpr *RGSuccExpr = MCSymbolRefExpr::create(RGSuccSym, OutContext); + EmitAndCountInstruction(MCInstBuilder(X86::JE_1).addExpr(RGSuccExpr)); + EmitAndCountInstruction(MCInstBuilder(X86::INT3)); + EmitAndCountInstruction(MCInstBuilder(X86::INT3)); + OutStreamer->EmitLabel(RGSuccSym); + return; + } + case X86::SEH_PushReg: case X86::SEH_SaveReg: case X86::SEH_SaveXMM: 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; diff --git a/gnu/usr.bin/clang/Makefile.inc b/gnu/usr.bin/clang/Makefile.inc index 27678e1d38b..f772277db45 100644 --- a/gnu/usr.bin/clang/Makefile.inc +++ b/gnu/usr.bin/clang/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.5 2017/04/17 15:53:21 kettenis Exp $ +# $OpenBSD: Makefile.inc,v 1.6 2018/06/06 00:14:29 mortimer Exp $ LLVM_SRCS?= ${.CURDIR}/../../../llvm @@ -20,6 +20,9 @@ CLANG_INCLUDES= -I${LLVM_SRCS}/tools/clang/include CPPFLAGS+= -I${LLVM_SRCS}/include -I${.CURDIR}/../include -I${.OBJDIR} \ -I${.OBJDIR}/../include CPPFLAGS+= -DNDEBUG +.if ${MACHINE} == "amd64" +CPPFLAGS+= -fno-ret-protector +.endif CPPFLAGS+= -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS \ -D__STDC_FORMAT_MACROS diff --git a/gnu/usr.bin/clang/libLLVMCodeGen/Makefile b/gnu/usr.bin/clang/libLLVMCodeGen/Makefile index ab2ed35d582..f66dfe270e8 100644 --- a/gnu/usr.bin/clang/libLLVMCodeGen/Makefile +++ b/gnu/usr.bin/clang/libLLVMCodeGen/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.6 2018/04/06 14:44:04 patrick Exp $ +# $OpenBSD: Makefile,v 1.7 2018/06/06 00:14:29 mortimer Exp $ LIB= LLVMCodeGen NOPIC= @@ -129,6 +129,7 @@ SRCS= AggressiveAntiDepBreaker.cpp \ RegisterUsageInfo.cpp \ RenameIndependentSubregs.cpp \ ResetMachineFunctionPass.cpp \ + ReturnProtectorPass.cpp \ SafeStack.cpp \ SafeStackColoring.cpp \ SafeStackLayout.cpp \ diff --git a/share/mk/bsd.lib.mk b/share/mk/bsd.lib.mk index 2a5e5906abf..aea8bfc468c 100644 --- a/share/mk/bsd.lib.mk +++ b/share/mk/bsd.lib.mk @@ -1,4 +1,4 @@ -# $OpenBSD: bsd.lib.mk,v 1.92 2017/11/14 10:02:56 kettenis Exp $ +# $OpenBSD: bsd.lib.mk,v 1.93 2018/06/06 00:14:29 mortimer Exp $ # $NetBSD: bsd.lib.mk,v 1.67 1996/01/17 20:39:26 mycroft Exp $ # @(#)bsd.lib.mk 5.26 (Berkeley) 5/2/91 @@ -34,7 +34,7 @@ CXXFLAGS+= ${NOPIE_FLAGS} AFLAGS+= ${NOPIE_FLAGS} .endif -DIST_CFLAGS+= -Oz +DIST_CFLAGS+= -Oz -fno-stack-protector .c.o: @echo "${COMPILE.c} ${.IMPSRC} -o ${.TARGET}" |
