aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CodeGenFunction.cpp
diff options
context:
space:
mode:
authorBill Wendling <morbo@google.com>2025-08-14 13:07:38 -0700
committerGitHub <noreply@github.com>2025-08-14 13:07:38 -0700
commitaa4805a09052c1b6298718eeb6d30c33dd0d695f (patch)
treeb9c2bf308e852f38c24b9f1f9eda317cb3997092 /clang/lib/CodeGen/CodeGenFunction.cpp
parent5479b7ed4200a85de3aa9335110883a86715811d (diff)
downloadllvm-aa4805a09052c1b6298718eeb6d30c33dd0d695f.zip
llvm-aa4805a09052c1b6298718eeb6d30c33dd0d695f.tar.gz
llvm-aa4805a09052c1b6298718eeb6d30c33dd0d695f.tar.bz2
[Clang][attr] Add 'cfi_salt' attribute (#141846)
The 'cfi_salt' attribute specifies a string literal that is used as a "salt" for Control-Flow Integrity (CFI) checks to distinguish between functions with the same type signature. This attribute can be applied to function declarations, function definitions, and function pointer typedefs. This attribute prevents function pointers from being replaced with pointers to functions that have a compatible type, which can be a CFI bypass vector. The attribute affects type compatibility during compilation and CFI hash generation during code generation. Attribute syntax: [[clang::cfi_salt("<salt_string>")]] GNU-style syntax: __attribute__((cfi_salt("<salt_string>"))) - The attribute takes a single string of non-NULL ASCII characters. - It only applies to function types; using it on a non-function type will generate an error. - All function declarations and the function definition must include the attribute and use identical salt values. Example usage: // Header file: #define __cfi_salt(S) __attribute__((cfi_salt(S))) // Convenient typedefs to avoid nested declarator syntax. typedef int (*fp_unsalted_t)(void); typedef int (*fp_salted_t)(void) __cfi_salt("pepper"); struct widget_ops { fp_unsalted_t init; // Regular CFI. fp_salted_t exec; // Salted CFI. fp_unsalted_t teardown; // Regular CFI. }; // bar.c file: static int bar_init(void) { ... } static int bar_salted_exec(void) __cfi_salt("pepper") { ... } static int bar_teardown(void) { ... } static struct widget_generator _generator = { .init = bar_init, .exec = bar_salted_exec, .teardown = bar_teardown, }; struct widget_generator *widget_gen = _generator; // 2nd .c file: int generate_a_widget(void) { int ret; // Called with non-salted CFI. ret = widget_gen.init(); if (ret) return ret; // Called with salted CFI. ret = widget_gen.exec(); if (ret) return ret; // Called with non-salted CFI. return widget_gen.teardown(); } Link: https://github.com/ClangBuiltLinux/linux/issues/1736 Link: https://github.com/KSPP/linux/issues/365 --------- Signed-off-by: Bill Wendling <morbo@google.com> Co-authored-by: Aaron Ballman <aaron@aaronballman.com>
Diffstat (limited to 'clang/lib/CodeGen/CodeGenFunction.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp14
1 files changed, 10 insertions, 4 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index d077ee5..652fe67 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -2903,10 +2903,16 @@ void CodeGenFunction::EmitSanitizerStatReport(llvm::SanitizerStatKind SSK) {
void CodeGenFunction::EmitKCFIOperandBundle(
const CGCallee &Callee, SmallVectorImpl<llvm::OperandBundleDef> &Bundles) {
- const FunctionProtoType *FP =
- Callee.getAbstractInfo().getCalleeFunctionProtoType();
- if (FP)
- Bundles.emplace_back("kcfi", CGM.CreateKCFITypeId(FP->desugar()));
+ const CGCalleeInfo &CI = Callee.getAbstractInfo();
+ const FunctionProtoType *FP = CI.getCalleeFunctionProtoType();
+ if (!FP)
+ return;
+
+ StringRef Salt;
+ if (const auto &Info = FP->getExtraAttributeInfo())
+ Salt = Info.CFISalt;
+
+ Bundles.emplace_back("kcfi", CGM.CreateKCFITypeId(FP->desugar(), Salt));
}
llvm::Value *