Skip to content

Commit fb04b7b

Browse files
committed
[clang][CodeGen] Software Bill of Mitigations Metadata
The goal of this stack is to create a high fidelity mapping of mitigations to their possible insertion points and their actual insertion points. This would let us track where we do and don't have mitigations rather than the current approach of tracking where we have the flag. There are some challenges posed by this like: - Some mitigations are not emitted by the compiler, but the preprocessor - Some mitigations are lowered later during IR -> MIR (stack cookies)
1 parent 15edf87 commit fb04b7b

File tree

12 files changed

+190
-0
lines changed

12 files changed

+190
-0
lines changed

clang/include/clang/Basic/CodeGenOptions.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ CODEGENOPT(NoTypeCheck , 1, 0) ///< Set when -Wa,--no-type-check is enable
191191
CODEGENOPT(MisExpect , 1, 0) ///< Set when -Wmisexpect is enabled
192192
CODEGENOPT(EnableSegmentedStacks , 1, 0) ///< Set when -fsplit-stack is enabled.
193193
CODEGENOPT(StackClashProtector, 1, 0) ///< Set when -fstack-clash-protection is enabled.
194+
CODEGENOPT(MitigationAnalysis, 1, 0) ///< Set when -fmitigation-analysis is enabled.
194195
CODEGENOPT(NoImplicitFloat , 1, 0) ///< Set when -mno-implicit-float is enabled.
195196
CODEGENOPT(NullPointerIsValid , 1, 0) ///< Assume Null pointer deference is defined.
196197
CODEGENOPT(OpenCLCorrectlyRoundedDivSqrt, 1, 0) ///< -cl-fp32-correctly-rounded-divide-sqrt

clang/include/clang/Driver/Options.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3891,6 +3891,12 @@ defm split_stack : BoolFOption<"split-stack",
38913891
CodeGenOpts<"EnableSegmentedStacks">, DefaultFalse,
38923892
NegFlag<SetFalse, [], [ClangOption], "Wouldn't use segmented stack">,
38933893
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Use segmented stack">>;
3894+
defm mitigation_analysis : BoolFOption<"mitigation-analysis",
3895+
CodeGenOpts<"MitigationAnalysis">, DefaultFalse,
3896+
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Enable">,
3897+
NegFlag<SetFalse, [], [ClangOption], "Disable">,
3898+
BothFlags<[], [ClangOption], " mitigation analysis">>,
3899+
DocBrief<"Instrument mitigations (CFI, Stack Protectors, Auto-Var-Init, StackClashProtection) to analyze their coverage">;
38943900
def fstack_protector_all : Flag<["-"], "fstack-protector-all">, Group<f_Group>,
38953901
HelpText<"Enable stack protectors for all functions">;
38963902
defm stack_clash_protection : BoolFOption<"stack-clash-protection",

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "CodeGenFunction.h"
2222
#include "CodeGenModule.h"
2323
#include "ConstantEmitter.h"
24+
#include "MitigationTagging.h"
2425
#include "PatternInit.h"
2526
#include "TargetInfo.h"
2627
#include "clang/AST/ASTContext.h"
@@ -83,6 +84,8 @@ static void initializeAlloca(CodeGenFunction &CGF, AllocaInst *AI, Value *Size,
8384
switch (CGF.getLangOpts().getTrivialAutoVarInit()) {
8485
case LangOptions::TrivialAutoVarInitKind::Uninitialized:
8586
// Nothing to initialize.
87+
AttachMitigationMetadataToFunction(CGF, MitigationKey::AUTO_VAR_INIT,
88+
false);
8689
return;
8790
case LangOptions::TrivialAutoVarInitKind::Zero:
8891
Byte = CGF.Builder.getInt8(0x00);
@@ -94,6 +97,7 @@ static void initializeAlloca(CodeGenFunction &CGF, AllocaInst *AI, Value *Size,
9497
break;
9598
}
9699
}
100+
AttachMitigationMetadataToFunction(CGF, MitigationKey::AUTO_VAR_INIT, true);
97101
if (CGF.CGM.stopAutoInit())
98102
return;
99103
auto *I = CGF.Builder.CreateMemSet(AI, Byte, Size, AlignmentInBytes);
@@ -4642,6 +4646,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
46424646
AI->setAlignment(SuitableAlignmentInBytes);
46434647
if (BuiltinID != Builtin::BI__builtin_alloca_uninitialized)
46444648
initializeAlloca(*this, AI, Size, SuitableAlignmentInBytes);
4649+
else
4650+
AttachMitigationMetadataToFunction(*this, MitigationKey::AUTO_VAR_INIT,
4651+
false);
46454652
LangAS AAS = getASTAllocaAddressSpace();
46464653
LangAS EAS = E->getType()->getPointeeType().getAddressSpace();
46474654
if (AAS != EAS) {
@@ -4664,6 +4671,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
46644671
AI->setAlignment(AlignmentInBytes);
46654672
if (BuiltinID != Builtin::BI__builtin_alloca_with_align_uninitialized)
46664673
initializeAlloca(*this, AI, Size, AlignmentInBytes);
4674+
else
4675+
AttachMitigationMetadataToFunction(*this, MitigationKey::AUTO_VAR_INIT,
4676+
false);
46674677
LangAS AAS = getASTAllocaAddressSpace();
46684678
LangAS EAS = E->getType()->getPointeeType().getAddressSpace();
46694679
if (AAS != EAS) {

clang/lib/CodeGen/CGClass.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "CGDebugInfo.h"
1717
#include "CGRecordLayout.h"
1818
#include "CodeGenFunction.h"
19+
#include "MitigationTagging.h"
1920
#include "TargetInfo.h"
2021
#include "clang/AST/Attr.h"
2122
#include "clang/AST/CXXInheritance.h"
@@ -2847,6 +2848,8 @@ void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
28472848
Builder.CreateCall(CGM.getIntrinsic(IID), {VTable, TypeId});
28482849
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::assume), TypeTest);
28492850
}
2851+
2852+
AttachMitigationMetadataToFunction(*this, MitigationKey::CFI_VCALL, false);
28502853
}
28512854

28522855
void CodeGenFunction::EmitVTablePtrCheckForCall(const CXXRecordDecl *RD,

clang/lib/CodeGen/CGDecl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "CodeGenModule.h"
2121
#include "ConstantEmitter.h"
2222
#include "EHScopeStack.h"
23+
#include "MitigationTagging.h"
2324
#include "PatternInit.h"
2425
#include "TargetInfo.h"
2526
#include "clang/AST/ASTContext.h"
@@ -1974,6 +1975,9 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
19741975
? LangOptions::TrivialAutoVarInitKind::Uninitialized
19751976
: getContext().getLangOpts().getTrivialAutoVarInit());
19761977

1978+
AttachMitigationMetadataToFunction(
1979+
*this, MitigationKey::AUTO_VAR_INIT,
1980+
trivialAutoVarInit != LangOptions::TrivialAutoVarInitKind::Uninitialized);
19771981
auto initializeWhatIsTechnicallyUninitialized = [&](Address Loc) {
19781982
if (trivialAutoVarInit ==
19791983
LangOptions::TrivialAutoVarInitKind::Uninitialized)

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "CodeGenFunction.h"
2323
#include "CodeGenModule.h"
2424
#include "ConstantEmitter.h"
25+
#include "MitigationTagging.h"
2526
#include "TargetInfo.h"
2627
#include "clang/AST/ASTContext.h"
2728
#include "clang/AST/ASTLambda.h"
@@ -6091,6 +6092,10 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType,
60916092
// function pointer is a member of the bit set for the function type.
60926093
if (SanOpts.has(SanitizerKind::CFIICall) &&
60936094
(!TargetDecl || !isa<FunctionDecl>(TargetDecl))) {
6095+
AttachMitigationMetadataToFunction(
6096+
*this, MitigationKey::CFI_ICALL,
6097+
SanOpts.has(clang::SanitizerKind::CFIICall));
6098+
60946099
SanitizerScope SanScope(this);
60956100
EmitSanitizerStatReport(llvm::SanStat_CFI_ICall);
60966101

clang/lib/CodeGen/CGExprCXX.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "CGObjCRuntime.h"
1717
#include "CodeGenFunction.h"
1818
#include "ConstantEmitter.h"
19+
#include "MitigationTagging.h"
1920
#include "TargetInfo.h"
2021
#include "clang/Basic/CodeGenOptions.h"
2122
#include "clang/CodeGen/CGFunctionInfo.h"
@@ -416,6 +417,11 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
416417
std::tie(VTable, RD) = CGM.getCXXABI().LoadVTablePtr(
417418
*this, This.getAddress(), CalleeDecl->getParent());
418419
EmitVTablePtrCheckForCall(RD, VTable, CFITCK_NVCall, CE->getBeginLoc());
420+
AttachMitigationMetadataToFunction(*this, MitigationKey::CFI_NVCALL,
421+
true);
422+
} else if (MD->getParent()->isDynamicClass()) {
423+
AttachMitigationMetadataToFunction(*this, MitigationKey::CFI_NVCALL,
424+
false);
419425
}
420426

421427
if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier)

clang/lib/CodeGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ add_clang_library(clangCodeGen
110110
LinkInModulesPass.cpp
111111
MacroPPCallbacks.cpp
112112
MicrosoftCXXABI.cpp
113+
MitigationTagging.cpp
113114
ModuleBuilder.cpp
114115
ObjectFilePCHContainerWriter.cpp
115116
PatternInit.cpp

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "CodeGenPGO.h"
2727
#include "ConstantEmitter.h"
2828
#include "CoverageMappingGen.h"
29+
#include "MitigationTagging.h"
2930
#include "TargetInfo.h"
3031
#include "clang/AST/ASTContext.h"
3132
#include "clang/AST/ASTLambda.h"
@@ -2490,6 +2491,8 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
24902491
if ((!D || !D->hasAttr<NoUwtableAttr>()) && CodeGenOpts.UnwindTables)
24912492
B.addUWTableAttr(llvm::UWTableKind(CodeGenOpts.UnwindTables));
24922493

2494+
AttachMitigationMetadataToFunction(*F, MitigationKey::STACK_CLASH_PROTECTION,
2495+
CodeGenOpts.StackClashProtector);
24932496
if (CodeGenOpts.StackClashProtector)
24942497
B.addAttribute("probe-stack", "inline-asm");
24952498

@@ -2512,6 +2515,25 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
25122515
else if (isStackProtectorOn(LangOpts, getTriple(), LangOptions::SSPReq))
25132516
B.addAttribute(llvm::Attribute::StackProtectReq);
25142517

2518+
bool noStackProtectionAttr = D && D->hasAttr<NoStackProtectorAttr>();
2519+
AttachMitigationMetadataToFunction(
2520+
*F, MitigationKey::STACK_PROTECTOR,
2521+
!noStackProtectionAttr &&
2522+
(isStackProtectorOn(LangOpts, getTriple(), LangOptions::SSPOn) ||
2523+
isStackProtectorOn(LangOpts, getTriple(), LangOptions::SSPStrong) ||
2524+
isStackProtectorOn(LangOpts, getTriple(), LangOptions::SSPReq)));
2525+
2526+
AttachMitigationMetadataToFunction(
2527+
*F, MitigationKey::STACK_PROTECTOR_STRONG,
2528+
!noStackProtectionAttr &&
2529+
(isStackProtectorOn(LangOpts, getTriple(), LangOptions::SSPStrong) ||
2530+
isStackProtectorOn(LangOpts, getTriple(), LangOptions::SSPReq)));
2531+
2532+
AttachMitigationMetadataToFunction(
2533+
*F, MitigationKey::STACK_PROTECTOR_ALL,
2534+
!noStackProtectionAttr &&
2535+
isStackProtectorOn(LangOpts, getTriple(), LangOptions::SSPReq));
2536+
25152537
if (!D) {
25162538
// Non-entry HLSL functions must always be inlined.
25172539
if (getLangOpts().HLSL && !F->hasFnAttribute(llvm::Attribute::NoInline))
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//===--- MitigationTagging.cpp - Emit LLVM Code from ASTs for a Module ----===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This enables tagging functions with metadata to indicate mitigations are
10+
// applied to them.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#include "MitigationTagging.h"
15+
#include "llvm/IR/Constants.h"
16+
#include "llvm/IR/LLVMContext.h"
17+
#include "llvm/IR/Metadata.h"
18+
19+
#include <string>
20+
#include <vector>
21+
22+
namespace clang {
23+
namespace CodeGen {
24+
25+
inline static std::string
26+
MitigationKeyToString(enum MitigationKey key) noexcept {
27+
switch (key) {
28+
case MitigationKey::AUTO_VAR_INIT:
29+
return "auto-var-init";
30+
case MitigationKey::STACK_CLASH_PROTECTION:
31+
return "stack-clash-protection";
32+
case MitigationKey::STACK_PROTECTOR:
33+
return "stack-protector";
34+
case MitigationKey::STACK_PROTECTOR_STRONG:
35+
return "stack-protector-strong";
36+
case MitigationKey::STACK_PROTECTOR_ALL:
37+
return "stack-protector-all";
38+
case MitigationKey::CFI_VCALL:
39+
return "cfi-vcall";
40+
case MitigationKey::CFI_ICALL:
41+
return "cfi-icall";
42+
case MitigationKey::CFI_NVCALL:
43+
return "cfi-nvcall";
44+
}
45+
}
46+
47+
void AttachMitigationMetadataToFunction(llvm::Function &F,
48+
enum MitigationKey key, bool enabled) {
49+
llvm::LLVMContext &Context = F.getContext();
50+
51+
unsigned kindID = Context.getMDKindID("security_mitigations");
52+
53+
llvm::Metadata *ValueMD = llvm::ConstantAsMetadata::get(
54+
llvm::ConstantInt::get(llvm::Type::getInt1Ty(Context), enabled));
55+
llvm::MDString *KeyMD =
56+
llvm::MDString::get(Context, MitigationKeyToString(key));
57+
58+
llvm::MDNode *NewMD = llvm::MDNode::get(Context, {KeyMD, ValueMD});
59+
llvm::MDNode *ExistingMD = F.getMetadata(kindID);
60+
61+
if (ExistingMD) {
62+
std::vector<llvm::Metadata *> MDs;
63+
for (unsigned i = 0, e = ExistingMD->getNumOperands(); i != e; ++i) {
64+
MDs.push_back(ExistingMD->getOperand(i));
65+
}
66+
MDs.push_back(NewMD);
67+
68+
llvm::MDNode *CombinedMD = llvm::MDNode::get(Context, MDs);
69+
F.setMetadata(kindID, CombinedMD);
70+
} else {
71+
F.setMetadata(kindID, NewMD);
72+
}
73+
}
74+
75+
void AttachMitigationMetadataToFunction(CodeGenFunction &CGF,
76+
enum MitigationKey key, bool enabled) {
77+
if (!CGF.CGM.getCodeGenOpts().MitigationAnalysis) {
78+
return;
79+
}
80+
AttachMitigationMetadataToFunction(*(CGF.CurFn), key, enabled);
81+
}
82+
83+
} // namespace CodeGen
84+
} // namespace clang

0 commit comments

Comments
 (0)