Skip to content

Commit 54296a3

Browse files
Implement a new kcfi_arity feature that encodes an indirect call target's arity (i.e., the number of live-in registers) in the function's __cfi header.
1 parent 5d6d982 commit 54296a3

File tree

12 files changed

+270
-1
lines changed

12 files changed

+270
-1
lines changed

clang/docs/ControlFlowIntegrity.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,15 @@ cross-DSO function address equality. These properties make KCFI easier to
336336
adopt in low-level software. KCFI is limited to checking only function
337337
pointers, and isn't compatible with executable-only memory.
338338

339+
``-fsanitize-kcfi-arity``
340+
-----------------------------
341+
342+
For supported targets, this feature extends kCFI by telling the compiler to
343+
record information about each indirect-callable function's arity (i.e., the
344+
number of arguments passed in registers) into the binary. Some kernel CFI
345+
techniques, such as FineIBT, may be able to use this information to provide
346+
enhanced security.
347+
339348
Member Function Pointer Call Checking
340349
=====================================
341350

clang/docs/UsersManual.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2220,6 +2220,12 @@ are listed below.
22202220

22212221
This option is currently experimental.
22222222

2223+
.. option:: -fsanitize-kcfi-arity
2224+
2225+
Extends kernel indirect call forward-edge control flow integrity with
2226+
additional function arity information (for supported targets). See
2227+
:doc:`ControlFlowIntegrity` for more details.
2228+
22232229
.. option:: -fstrict-vtable-pointers
22242230

22252231
Enable optimizations based on the strict rules for overwriting polymorphic

clang/include/clang/Basic/CodeGenOptions.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ CODEGENOPT(SanitizeCfiICallNormalizeIntegers, 1, 0) ///< Normalize integer types
277277
///< CFI icall function signatures
278278
CODEGENOPT(SanitizeCfiCanonicalJumpTables, 1, 0) ///< Make jump table symbols canonical
279279
///< instead of creating a local jump table.
280+
CODEGENOPT(SanitizeKcfiArity, 1, 0) ///< Embed arity in KCFI patchable function prefix
280281
CODEGENOPT(SanitizeCoverageType, 2, 0) ///< Type of sanitizer coverage
281282
///< instrumentation.
282283
CODEGENOPT(SanitizeCoverageIndirectCalls, 1, 0) ///< Enable sanitizer coverage

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ def err_drv_cannot_open_randomize_layout_seed_file : Error<
209209
"cannot read randomize layout seed file '%0'">;
210210
def err_drv_invalid_version_number : Error<
211211
"invalid version number in '%0'">;
212+
def err_drv_kcfi_arity_unsupported_target : Error<
213+
"target '%0' is unsupported by -fsanitize-kcfi-arity">;
212214
def err_drv_no_linker_llvm_support : Error<
213215
"'%0': unable to pass LLVM bit-code files to linker">;
214216
def err_drv_no_ast_support : Error<

clang/include/clang/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ FEATURE(is_trivially_constructible, LangOpts.CPlusPlus)
254254
FEATURE(is_trivially_copyable, LangOpts.CPlusPlus)
255255
FEATURE(is_union, LangOpts.CPlusPlus)
256256
FEATURE(kcfi, LangOpts.Sanitize.has(SanitizerKind::KCFI))
257+
FEATURE(kcfi_arity, LangOpts.Sanitize.has(SanitizerKind::KCFI))
257258
FEATURE(modules, LangOpts.Modules)
258259
FEATURE(safe_stack, LangOpts.Sanitize.has(SanitizerKind::SafeStack))
259260
FEATURE(shadow_call_stack,

clang/include/clang/Driver/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2619,6 +2619,10 @@ defm sanitize_cfi_canonical_jump_tables : BoolOption<"f", "sanitize-cfi-canonica
26192619
"Do not make">,
26202620
BothFlags<[], [ClangOption], " the jump table addresses canonical in the symbol table">>,
26212621
Group<f_clang_Group>;
2622+
def fsanitize_kcfi_arity : Flag<["-"], "fsanitize-kcfi-arity">,
2623+
Group<f_clang_Group>,
2624+
HelpText<"Embed function arity information into the KCFI patchable function prefix">,
2625+
MarshallingInfoFlag<CodeGenOpts<"SanitizeKcfiArity">>;
26222626
defm sanitize_stats : BoolOption<"f", "sanitize-stats",
26232627
CodeGenOpts<"SanitizeStats">, DefaultFalse,
26242628
PosFlag<SetTrue, [], [ClangOption], "Enable">,

clang/include/clang/Driver/SanitizerArgs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class SanitizerArgs {
4343
bool CfiICallGeneralizePointers = false;
4444
bool CfiICallNormalizeIntegers = false;
4545
bool CfiCanonicalJumpTables = false;
46+
bool KcfiArity = false;
4647
int AsanFieldPadding = 0;
4748
bool SharedRuntime = false;
4849
bool StableABI = false;

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,8 @@ void CodeGenModule::Release() {
11491149
if (CodeGenOpts.PatchableFunctionEntryOffset)
11501150
getModule().addModuleFlag(llvm::Module::Override, "kcfi-offset",
11511151
CodeGenOpts.PatchableFunctionEntryOffset);
1152+
if (CodeGenOpts.SanitizeKcfiArity)
1153+
getModule().addModuleFlag(llvm::Module::Override, "kcfi-arity", 1);
11521154
}
11531155

11541156
if (CodeGenOpts.CFProtectionReturn &&

clang/lib/Driver/SanitizerArgs.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
829829
CfiICallNormalizeIntegers =
830830
Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
831831

832+
KcfiArity = Args.hasArg(options::OPT_fsanitize_kcfi_arity);
833+
832834
if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)
833835
D.Diag(diag::err_drv_argument_not_allowed_with)
834836
<< "-fsanitize=kcfi"
@@ -1383,6 +1385,14 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
13831385
if (CfiICallNormalizeIntegers)
13841386
CmdArgs.push_back("-fsanitize-cfi-icall-experimental-normalize-integers");
13851387

1388+
if (KcfiArity) {
1389+
if (!TC.getTriple().isOSLinux() || !TC.getTriple().isArch64Bit()) {
1390+
TC.getDriver().Diag(clang::diag::err_drv_kcfi_arity_unsupported_target)
1391+
<< TC.getTriple().str();
1392+
}
1393+
CmdArgs.push_back("-fsanitize-kcfi-arity");
1394+
}
1395+
13861396
if (CfiCanonicalJumpTables)
13871397
CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables");
13881398

clang/test/CodeGen/kcfi-arity.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=kcfi -fsanitize-kcfi-arity -o - %s | FileCheck %s
2+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=kcfi -fsanitize-kcfi-arity -x c++ -o - %s | FileCheck %s
3+
#if !__has_feature(kcfi_arity)
4+
#error Missing kcfi_arity?
5+
#endif
6+
7+
// CHECK: ![[#]] = !{i32 4, !"kcfi-arity", i32 1}

0 commit comments

Comments
 (0)