Skip to content

Commit 7aaeaef

Browse files
committed
[clang][RISCV] Introduce command line options for Zicfilp-backed forward-edge CFI
This patch enables the following command line flags for RISC-V targets: + `-fcf-protection=branch` turns on forward-edge control-flow integrity conditioning on RISC-V targets with Zicfilp extension + `-mcf-branch-label-scheme=unlabeled|func-sig` selects the label scheme used in the forward-edge CFI conditioning
1 parent ea902d1 commit 7aaeaef

File tree

14 files changed

+257
-0
lines changed

14 files changed

+257
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//===-- CFProtectionOptions.def - cf-protection options ---------*- C++ -*-===//
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+
10+
#ifdef CF_BRANCH_LABEL_SCHEME
11+
CF_BRANCH_LABEL_SCHEME(Unlabeled, unlabeled)
12+
CF_BRANCH_LABEL_SCHEME(FuncSig, func-sig)
13+
14+
#undef CF_BRANCH_LABEL_SCHEME
15+
#endif // #ifdef CF_BRANCH_LABEL_SCHEME
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//===--- CFProtectionOptions.h ----------------------------------*- C++ -*-===//
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 file defines constants for -fcf-protection and other related flags.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_CLANG_BASIC_CFPROTECTIONOPTIONS_H
14+
#define LLVM_CLANG_BASIC_CFPROTECTIONOPTIONS_H
15+
16+
#include "llvm/Support/ErrorHandling.h"
17+
18+
namespace clang {
19+
20+
enum class CFBranchLabelSchemeKind {
21+
Default,
22+
#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal) Kind,
23+
#include "clang/Basic/CFProtectionOptions.def"
24+
};
25+
26+
static inline const char *
27+
getCFBranchLabelSchemeFlagVal(const CFBranchLabelSchemeKind Scheme) {
28+
#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal) \
29+
if (Scheme == CFBranchLabelSchemeKind::Kind) \
30+
return #FlagVal;
31+
#include "clang/Basic/CFProtectionOptions.def"
32+
33+
llvm::report_fatal_error("invalid scheme");
34+
}
35+
36+
} // namespace clang
37+
38+
#endif // #ifndef LLVM_CLANG_BASIC_CFPROTECTIONOPTIONS_H

clang/include/clang/Basic/CodeGenOptions.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ CODEGENOPT(CFProtectionReturn , 1, 0) ///< if -fcf-protection is
110110
///< set to full or return.
111111
CODEGENOPT(CFProtectionBranch , 1, 0) ///< if -fcf-protection is
112112
///< set to full or branch.
113+
ENUM_CODEGENOPT(CFBranchLabelScheme, CFBranchLabelSchemeKind, 2,
114+
CFBranchLabelSchemeKind::Default) ///< if -mcf-branch-label-scheme is set.
113115
CODEGENOPT(FunctionReturnThunks, 1, 0) ///< -mfunction-return={keep|thunk-extern}
114116
CODEGENOPT(IndirectBranchCSPrefix, 1, 0) ///< if -mindirect-branch-cs-prefix
115117
///< is set.

clang/include/clang/Basic/CodeGenOptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef LLVM_CLANG_BASIC_CODEGENOPTIONS_H
1414
#define LLVM_CLANG_BASIC_CODEGENOPTIONS_H
1515

16+
#include "clang/Basic/CFProtectionOptions.h"
1617
#include "clang/Basic/PointerAuthOptions.h"
1718
#include "clang/Basic/Sanitizers.h"
1819
#include "clang/Basic/XRayInstr.h"

clang/include/clang/Basic/LangOptions.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,8 @@ BENIGN_LANGOPT(CompatibilityQualifiedIdBlockParamTypeChecking, 1, 0,
364364
LANGOPT(ObjCDisableDirectMethodsForTesting, 1, 0,
365365
"Disable recognition of objc_direct methods")
366366
LANGOPT(CFProtectionBranch , 1, 0, "Control-Flow Branch Protection enabled")
367+
ENUM_LANGOPT(CFBranchLabelScheme, CFBranchLabelSchemeKind, 2, CFBranchLabelSchemeKind::Default,
368+
"Control-Flow Branch Protection Label Scheme")
367369
LANGOPT(FakeAddressSpaceMap , 1, 0, "OpenCL fake address space map")
368370
ENUM_LANGOPT(AddressSpaceMapMangling , AddrSpaceMapMangling, 2, ASMM_Target, "OpenCL address space map mangling mode")
369371
LANGOPT(IncludeDefaultHeader, 1, 0, "Include default header file for OpenCL")

clang/include/clang/Basic/LangOptions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#ifndef LLVM_CLANG_BASIC_LANGOPTIONS_H
1515
#define LLVM_CLANG_BASIC_LANGOPTIONS_H
1616

17+
#include "clang/Basic/CFProtectionOptions.h"
1718
#include "clang/Basic/CommentOptions.h"
1819
#include "clang/Basic/LLVM.h"
1920
#include "clang/Basic/LangStandard.h"
@@ -73,6 +74,7 @@ class LangOptionsBase {
7374
public:
7475
using Visibility = clang::Visibility;
7576
using RoundingMode = llvm::RoundingMode;
77+
using CFBranchLabelSchemeKind = clang::CFBranchLabelSchemeKind;
7678

7779
enum GCMode { NonGC, GCOnly, HybridGC };
7880
enum StackProtectorMode { SSPOff, SSPOn, SSPStrong, SSPReq };

clang/include/clang/Basic/TargetInfo.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "clang/Basic/AddressSpaces.h"
1818
#include "clang/Basic/BitmaskEnum.h"
19+
#include "clang/Basic/CFProtectionOptions.h"
1920
#include "clang/Basic/CodeGenOptions.h"
2021
#include "clang/Basic/LLVM.h"
2122
#include "clang/Basic/LangOptions.h"
@@ -1727,6 +1728,13 @@ class TargetInfo : public TransferrableTargetInfo,
17271728
virtual bool
17281729
checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const;
17291730

1731+
/// Get the target default CFBranchLabelScheme scheme
1732+
virtual CFBranchLabelSchemeKind getDefaultCFBranchLabelScheme() const;
1733+
1734+
virtual bool
1735+
checkCFBranchLabelSchemeSupported(const CFBranchLabelSchemeKind Scheme,
1736+
DiagnosticsEngine &Diags) const;
1737+
17301738
/// Check if the target supports CFProtection return.
17311739
virtual bool
17321740
checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const;

clang/include/clang/Driver/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2841,6 +2841,10 @@ def fcf_protection : Flag<["-"], "fcf-protection">, Group<f_Group>,
28412841
Visibility<[ClangOption, CLOption, CC1Option]>,
28422842
Alias<fcf_protection_EQ>, AliasArgs<["full"]>,
28432843
HelpText<"Enable cf-protection in 'full' mode">;
2844+
def mcf_branch_label_scheme_EQ : Joined<["-"], "mcf-branch-label-scheme=">,
2845+
Visibility<[ClangOption, CC1Option]>, Group<m_Group>,
2846+
HelpText<"Select label scheme for branch control-flow architecture protection">,
2847+
Values<"unlabeled,func-sig">;
28442848
def mfunction_return_EQ : Joined<["-"], "mfunction-return=">,
28452849
Group<m_Group>, Visibility<[ClangOption, CLOption, CC1Option]>,
28462850
HelpText<"Replace returns with jumps to ``__x86_return_thunk`` (x86 only, error otherwise)">,

clang/lib/Basic/TargetInfo.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,21 @@ TargetInfo::checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const {
198198
return false;
199199
}
200200

201+
CFBranchLabelSchemeKind TargetInfo::getDefaultCFBranchLabelScheme() const {
202+
// if this hook is called, the target should override it to return a
203+
// non-default scheme
204+
llvm::report_fatal_error("not implemented");
205+
}
206+
207+
bool TargetInfo::checkCFBranchLabelSchemeSupported(
208+
const CFBranchLabelSchemeKind Scheme, DiagnosticsEngine &Diags) const {
209+
Diags.Report(diag::err_opt_not_valid_on_target)
210+
<< (Twine("mcf-branch-label-scheme=") +
211+
getCFBranchLabelSchemeFlagVal(Scheme))
212+
.str();
213+
return false;
214+
}
215+
201216
bool
202217
TargetInfo::checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const {
203218
Diags.Report(diag::err_opt_not_valid_on_target) << "cf-protection=return";

clang/lib/Basic/Targets/RISCV.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,28 @@ class RISCVTargetInfo : public TargetInfo {
134134

135135
bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,
136136
bool &HasSizeMismatch) const override;
137+
138+
bool checkCFProtectionBranchSupported(DiagnosticsEngine &) const override {
139+
// Always generate Zicfilp lpad insns
140+
// Non-zicfilp CPUs would read them as NOP
141+
return true;
142+
}
143+
144+
CFBranchLabelSchemeKind getDefaultCFBranchLabelScheme() const override {
145+
return CFBranchLabelSchemeKind::FuncSig;
146+
}
147+
148+
bool
149+
checkCFBranchLabelSchemeSupported(const CFBranchLabelSchemeKind Scheme,
150+
DiagnosticsEngine &Diags) const override {
151+
switch (Scheme) {
152+
case CFBranchLabelSchemeKind::Default:
153+
case CFBranchLabelSchemeKind::Unlabeled:
154+
case CFBranchLabelSchemeKind::FuncSig:
155+
return true;
156+
}
157+
return TargetInfo::checkCFBranchLabelSchemeSupported(Scheme, Diags);
158+
}
137159
};
138160
class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo {
139161
public:

0 commit comments

Comments
 (0)