[clang] [llvm] [RISCV] Add Zicfiss support to the shadow call stack implementation. (PR #68075)

2024-01-16 Thread Sami Tolvanen via cfe-commits


@@ -57,11 +57,16 @@ compiled application or the operating system. Integrating 
the runtime into
 the operating system should be preferred since otherwise all thread creation
 and destruction would need to be intercepted by the application.
 
-The instrumentation makes use of the platform register ``x18`` on AArch64 and
-``x3`` (``gp``) on RISC-V. For simplicity we will refer to this as the
-``SCSReg``. On some platforms, ``SCSReg`` is reserved, and on others, it is
-designated as a scratch register.  This generally means that any code that may
-run on the same thread as code compiled with ShadowCallStack must either target
+The instrumentation makes use of the platform register ``x18`` on AArch64,
+``x3`` (``gp``) on RISC-V with software shadow stack and ``ssp`` on RISC-V with
+hardware shadow stack, which needs `Zicfiss`_ and 
``-mno-forced-sw-shadow-stack``

samitolvanen wrote:

> Should Android default to shadow stack?
> 
> My concern is that if a user passes an -mcpu that supports Zicfiss, but the 
> OS doesn't, the compiler will emit shadow stack instructions that silently 
> fall back to NOPs due to the missing OS support. This leaves your binary in a 
> state where it gets no protection.

I agree, changing `-fsanitize=shadow-call-stack` behavior based on `-mcpu` is 
problematic, especially when it can result in the program silently falling back 
to unprotected state. This might be a problem for other platforms too, not only 
Android.

https://github.com/llvm/llvm-project/pull/68075
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 1aad641 - [Clang][Sema] Add -Wcast-function-type-strict

2022-10-26 Thread Sami Tolvanen via cfe-commits

Author: Sami Tolvanen
Date: 2022-10-26T20:38:37Z
New Revision: 1aad641c793090b4d036c03e737df2ebe2c32c57

URL: 
https://github.com/llvm/llvm-project/commit/1aad641c793090b4d036c03e737df2ebe2c32c57
DIFF: 
https://github.com/llvm/llvm-project/commit/1aad641c793090b4d036c03e737df2ebe2c32c57.diff

LOG: [Clang][Sema] Add -Wcast-function-type-strict

Clang supports indirect call Control-Flow Integrity (CFI) sanitizers
(e.g. -fsanitize=cfi-icall), which enforce an exact type match between
a function pointer and the target function. Unfortunately, Clang
doesn't provide diagnostics that would help developers avoid function
type casts that lead to runtime CFI failures. -Wcast-function-type,
while helpful, only warns about ABI incompatibility, which isn't
sufficient with CFI.

Add -Wcast-function-type-strict, which checks for a strict type
compatibility in function type casts and helps warn about casts that
can potentially lead to CFI failures.

Reviewed By: nickdesaulniers, aaron.ballman

Differential Revision: https://reviews.llvm.org/D134831

Added: 
clang/test/Sema/warn-cast-function-type-strict.c
clang/test/SemaCXX/warn-cast-function-type-strict.cpp

Modified: 
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticGroups.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaCast.cpp
clang/test/Sema/warn-cast-function-type.c
clang/test/SemaCXX/warn-cast-function-type.cpp

Removed: 




diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5beaf8e532c91..e4ae29da4848f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -328,6 +328,11 @@ Improvements to Clang's diagnostics
 - Clang now correctly points to the problematic parameter for the ``-Wnonnull``
   warning. This fixes
   `Issue 58273 `_.
+- Introduced ``-Wcast-function-type-strict`` to warn about function type 
mismatches
+  in casts that may result in runtime indirect call `Control-Flow Integrity 
(CFI)
+  `_ failures. This 
diagnostic
+  is grouped under ``-Wcast-function-type`` as it identifies a more strict set 
of
+  potentially problematic function type casts.
 
 Non-comprehensive list of changes in this release
 -

diff  --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index cddb127cae58f..2e22f89266a4a 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -538,7 +538,8 @@ def PrivateExtern : DiagGroup<"private-extern">;
 def SelTypeCast : DiagGroup<"cast-of-sel-type">;
 def FunctionDefInObjCContainer : DiagGroup<"function-def-in-objc-container">;
 def BadFunctionCast : DiagGroup<"bad-function-cast">;
-def CastFunctionType : DiagGroup<"cast-function-type">;
+def CastFunctionTypeStrict : DiagGroup<"cast-function-type-strict">;
+def CastFunctionType : DiagGroup<"cast-function-type", 
[CastFunctionTypeStrict]>;
 def ObjCPropertyImpl : DiagGroup<"objc-property-implementation">;
 def ObjCPropertyNoAttribute : DiagGroup<"objc-property-no-attribute">;
 def ObjCPropertyAssignOnObjectType : 
DiagGroup<"objc-property-assign-on-object-type">;

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 8cf73784d97b6..d3299f6314570 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8694,6 +8694,8 @@ def warn_bad_function_cast : Warning<
 def warn_cast_function_type : Warning<
   "cast %
diff {from $ to $ |}0,1converts to incompatible function type">,
   InGroup, DefaultIgnore;
+def warn_cast_function_type_strict : Warning,
+  InGroup, DefaultIgnore;
 def err_cast_pointer_to_non_pointer_int : Error<
   "pointer cannot be cast to type %0">;
 def err_nullptr_cast : Error<

diff  --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index d21c5b7d10270..bfdf06fc47c6f 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -1059,11 +1059,19 @@ static bool argTypeIsABIEquivalent(QualType SrcType, 
QualType DestType,
   return Context.hasSameUnqualifiedType(SrcType, DestType);
 }
 
-static bool checkCastFunctionType(Sema &Self, const ExprResult &SrcExpr,
-  QualType DestType) {
-  if (Self.Diags.isIgnored(diag::warn_cast_function_type,
-   SrcExpr.get()->getExprLoc()))
-return true;
+static unsigned int checkCastFunctionType(Sema &Self, const ExprResult 
&SrcExpr,
+  QualType DestType) {
+  unsigned int DiagID = 0;
+  const unsigned int DiagList[] = {diag::warn_cast_function_type_strict,
+   diag::warn_cast_function_type};
+  

[clang] 41ce74e - [Clang][Sema] Add -Wincompatible-function-pointer-types-strict

2022-11-07 Thread Sami Tolvanen via cfe-commits

Author: Sami Tolvanen
Date: 2022-11-07T23:05:28Z
New Revision: 41ce74e6e983f523d44d3a80be5ae778c35df85a

URL: 
https://github.com/llvm/llvm-project/commit/41ce74e6e983f523d44d3a80be5ae778c35df85a
DIFF: 
https://github.com/llvm/llvm-project/commit/41ce74e6e983f523d44d3a80be5ae778c35df85a.diff

LOG: [Clang][Sema] Add -Wincompatible-function-pointer-types-strict

Clang supports indirect call Control-Flow Integrity (CFI) sanitizers
(e.g. -fsanitize=cfi-icall), which enforce an exact type match
between a function pointer and the target function. Unfortunately,
Clang doesn't provide diagnostics that help developers avoid
function pointer assignments that can lead to runtime CFI
failures. -Wincompatible-function-pointer-types doesn't warn about
enum to integer mismatches if the types are otherwise compatible, for
example, which isn't sufficient with CFI.

Add -Wincompatible-function-pointer-types-strict, which checks for a
stricter function type compatibility in assignments and helps warn about
assignments that can potentially lead to CFI failures.

Reviewed By: aaron.ballman, nickdesaulniers

Differential Revision: https://reviews.llvm.org/D136790

Added: 
clang/test/Sema/incompatible-function-pointer-types-strict.c

Modified: 
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaExpr.cpp

Removed: 




diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 72b9a52c7cd0d..2ce5fd48ca13a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -366,11 +366,14 @@ Improvements to Clang's diagnostics
 - Clang now correctly points to the problematic parameter for the ``-Wnonnull``
   warning. This fixes
   `Issue 58273 `_.
-- Introduced ``-Wcast-function-type-strict`` to warn about function type 
mismatches
-  in casts that may result in runtime indirect call `Control-Flow Integrity 
(CFI)
-  `_ failures. This 
diagnostic
-  is grouped under ``-Wcast-function-type`` as it identifies a more strict set 
of
-  potentially problematic function type casts.
+- Introduced ``-Wcast-function-type-strict`` and
+  ``-Wincompatible-function-pointer-types-strict`` to warn about function type
+  mismatches in casts and assignments that may result in runtime indirect call
+  `Control-Flow Integrity (CFI)
+  `_ failures. The
+  ``-Wcast-function-type-strict`` diagnostic is grouped under
+  ``-Wcast-function-type`` as it identifies a more strict set of potentially
+  problematic function type casts.
 - Clang will now disambiguate NTTP types when printing diagnostic that contain 
NTTP types.
   Fixes `Issue 57562 `_.
 - Better error recovery for pack expansion of expressions.

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1b1db765fa7a9..eea38a4cab8a3 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8214,6 +8214,9 @@ def err_typecheck_convert_incompatible_function_pointer : 
Error<
 def ext_typecheck_convert_incompatible_function_pointer : ExtWarn<
   err_typecheck_convert_incompatible_function_pointer.Text>,
   InGroup, DefaultError;
+def warn_typecheck_convert_incompatible_function_pointer_strict : Warning<
+  err_typecheck_convert_incompatible_function_pointer.Text>,
+  InGroup>, 
DefaultIgnore;
 def ext_typecheck_convert_discards_qualifiers : ExtWarn<
   "%select{%
diff {assigning to $ from $|assigning to 
diff erent types}0,1"
   "|%
diff {passing $ to parameter of type $|"

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index e8c9cb966bae7..25d9d2e0c3baa 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -12228,6 +12228,12 @@ class Sema final {
 /// extension.
 IncompatibleFunctionPointer,
 
+/// IncompatibleFunctionPointerStrict - The assignment is between two
+/// function pointer types that are not identical, but are compatible,
+/// unless compiled with -fsanitize=cfi, in which case the type mismatch
+/// may trip an indirect call runtime check.
+IncompatibleFunctionPointerStrict,
+
 /// IncompatiblePointerSign - The assignment is between two pointers types
 /// which point to integers which have a 
diff erent sign, but are otherwise
 /// identical. This is a subset of the above, but broken out because it's 
by

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index c40bcb083907b..1ba88ad6cc2a6 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -9240,7 +9240,8 @@ static bool IsInvalidCmseNSCallConver

[clang] eb2a57e - Add generic KCFI operand bundle lowering

2022-11-17 Thread Sami Tolvanen via cfe-commits

Author: Sami Tolvanen
Date: 2022-11-17T21:55:00Z
New Revision: eb2a57ebc7aaad551af30462097a9e06c96db925

URL: 
https://github.com/llvm/llvm-project/commit/eb2a57ebc7aaad551af30462097a9e06c96db925
DIFF: 
https://github.com/llvm/llvm-project/commit/eb2a57ebc7aaad551af30462097a9e06c96db925.diff

LOG: Add generic KCFI operand bundle lowering

The KCFI sanitizer emits "kcfi" operand bundles to indirect
call instructions, which the LLVM back-end lowers into an
architecture-specific type check with a known machine instruction
sequence. Currently, KCFI operand bundle lowering is supported only
on 64-bit X86 and AArch64 architectures.

As a lightweight forward-edge CFI implementation that doesn't
require LTO is also useful for non-Linux low-level targets on
other machine architectures, add a generic KCFI operand bundle
lowering pass that's only used when back-end lowering support is not
available and allows -fsanitize=kcfi to be enabled in Clang on all
architectures.

Reviewed By: nickdesaulniers, MaskRay

Differential Revision: https://reviews.llvm.org/D135411

Added: 
llvm/include/llvm/Transforms/Instrumentation/KCFI.h
llvm/lib/Transforms/Instrumentation/KCFI.cpp
llvm/test/Transforms/KCFI/kcfi-patchable-function-prefix.ll
llvm/test/Transforms/KCFI/kcfi-supported.ll
llvm/test/Transforms/KCFI/kcfi.ll

Modified: 
clang/lib/CodeGen/BackendUtil.cpp
clang/lib/Driver/ToolChain.cpp
llvm/include/llvm/InitializePasses.h
llvm/lib/Passes/PassBuilder.cpp
llvm/lib/Passes/PassRegistry.def
llvm/lib/Transforms/Instrumentation/CMakeLists.txt
llvm/utils/gn/secondary/llvm/lib/Transforms/Instrumentation/BUILD.gn

Removed: 




diff  --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index 8498ca2e63388..7082fb74ab591 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -72,6 +72,7 @@
 #include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
 #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
 #include "llvm/Transforms/Instrumentation/InstrProfiling.h"
+#include "llvm/Transforms/Instrumentation/KCFI.h"
 #include "llvm/Transforms/Instrumentation/MemProfiler.h"
 #include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
 #include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
@@ -644,6 +645,31 @@ static OptimizationLevel mapToLevel(const CodeGenOptions 
&Opts) {
   }
 }
 
+static void addKCFIPass(TargetMachine *TM, const Triple &TargetTriple,
+const LangOptions &LangOpts, PassBuilder &PB) {
+  // If the back-end supports KCFI operand bundle lowering, skip KCFIPass.
+  if (TargetTriple.getArch() == llvm::Triple::x86_64 ||
+  TargetTriple.isAArch64(64))
+return;
+
+  // Ensure we lower KCFI operand bundles with -O0.
+  PB.registerOptimizerLastEPCallback(
+  [&, TM](ModulePassManager &MPM, OptimizationLevel Level) {
+if (Level == OptimizationLevel::O0 &&
+LangOpts.Sanitize.has(SanitizerKind::KCFI))
+  MPM.addPass(createModuleToFunctionPassAdaptor(KCFIPass(TM)));
+  });
+
+  // When optimizations are requested, run KCIFPass after InstCombine to
+  // avoid unnecessary checks.
+  PB.registerPeepholeEPCallback(
+  [&, TM](FunctionPassManager &FPM, OptimizationLevel Level) {
+if (Level != OptimizationLevel::O0 &&
+LangOpts.Sanitize.has(SanitizerKind::KCFI))
+  FPM.addPass(KCFIPass(TM));
+  });
+}
+
 static void addSanitizers(const Triple &TargetTriple,
   const CodeGenOptions &CodeGenOpts,
   const LangOptions &LangOpts, PassBuilder &PB) {
@@ -946,8 +972,10 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
 
 // Don't add sanitizers if we are here from ThinLTO PostLink. That already
 // done on PreLink stage.
-if (!IsThinLTOPostLink)
+if (!IsThinLTOPostLink) {
   addSanitizers(TargetTriple, CodeGenOpts, LangOpts, PB);
+  addKCFIPass(TM.get(), TargetTriple, LangOpts, PB);
+}
 
 if (Optional Options = getGCOVOptions(CodeGenOpts, LangOpts))
   PB.registerPipelineStartEPCallback(

diff  --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 695741f73dcc9..1cb95065ade24 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -1089,7 +1089,7 @@ SanitizerMask ToolChain::getSupportedSanitizers() const {
~SanitizerKind::Function) |
   (SanitizerKind::CFI & ~SanitizerKind::CFIICall) |
   SanitizerKind::CFICastStrict | SanitizerKind::FloatDivideByZero |
-  SanitizerKind::UnsignedIntegerOverflow |
+  SanitizerKind::KCFI | SanitizerKind::UnsignedIntegerOverflow |
   SanitizerKind::UnsignedShiftBase | SanitizerKind::ImplicitConversion |
   SanitizerKind::Nullability | SanitizerKind::LocalBounds;
   if (getTriple().getArch() == llvm::Triple::x86 ||
@@ -1097,9 +1097,6

[clang] b1e9ab7 - Add CFI integer types normalization

2023-02-01 Thread Sami Tolvanen via cfe-commits

Author: Ramon de C Valle
Date: 2023-02-01T17:48:03Z
New Revision: b1e9ab7438a098a18fecda88fc87ef4ccadfcf1e

URL: 
https://github.com/llvm/llvm-project/commit/b1e9ab7438a098a18fecda88fc87ef4ccadfcf1e
DIFF: 
https://github.com/llvm/llvm-project/commit/b1e9ab7438a098a18fecda88fc87ef4ccadfcf1e.diff

LOG: Add CFI integer types normalization

This commit adds a new option (i.e.,
`-fsanitize-cfi-icall-normalize-integers`) for normalizing integer types
as vendor extended types for cross-language LLVM CFI/KCFI support with
other languages that can't represent and encode C/C++ integer types.

Specifically, integer types are encoded as their defined representations
(e.g., 8-bit signed integer, 16-bit signed integer, 32-bit signed
integer, ...) for compatibility with languages that define
explicitly-sized integer types (e.g., i8, i16, i32, ..., in Rust).

``-fsanitize-cfi-icall-normalize-integers`` is compatible with
``-fsanitize-cfi-icall-generalize-pointers``.

This helps with providing cross-language CFI support with the Rust
compiler and is an alternative solution for the issue described and
alternatives proposed in the RFC
https://github.com/rust-lang/rfcs/pull/3296.

For more information about LLVM CFI/KCFI and cross-language LLVM
CFI/KCFI support for the Rust compiler, see the design document in the
tracking issue https://github.com/rust-lang/rust/issues/89653.

Reviewed By: pcc, samitolvanen

Differential Revision: https://reviews.llvm.org/D139395

Added: 
clang/test/CodeGen/cfi-icall-normalize.c
clang/test/CodeGen/cfi-icall-normalize2.c
clang/test/CodeGen/kcfi-normalize.c

Modified: 
clang/docs/ControlFlowIntegrity.rst
clang/docs/UsersManual.rst
clang/include/clang/AST/Mangle.h
clang/include/clang/Basic/CodeGenOptions.def
clang/include/clang/Driver/Options.td
clang/include/clang/Driver/SanitizerArgs.h
clang/lib/AST/ItaniumMangle.cpp
clang/lib/AST/MicrosoftMangle.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/Driver/SanitizerArgs.cpp

Removed: 




diff  --git a/clang/docs/ControlFlowIntegrity.rst 
b/clang/docs/ControlFlowIntegrity.rst
index ef47b1c5b4b2b..f375199f40617 100644
--- a/clang/docs/ControlFlowIntegrity.rst
+++ b/clang/docs/ControlFlowIntegrity.rst
@@ -236,6 +236,25 @@ long as the qualifiers for the type they point to match. 
For example, ``char*``,
 ``-fsanitize-cfi-icall-generalize-pointers`` is not compatible with
 ``-fsanitize-cfi-cross-dso``.
 
+.. _cfi-icall-experimental-normalize-integers:
+
+``-fsanitize-cfi-icall-experimental-normalize-integers``
+
+
+This option enables normalizing integer types as vendor extended types for
+cross-language LLVM CFI/KCFI support with other languages that can't represent
+and encode C/C++ integer types.
+
+Specifically, integer types are encoded as their defined representations (e.g.,
+8-bit signed integer, 16-bit signed integer, 32-bit signed integer, ...) for
+compatibility with languages that define explicitly-sized integer types (e.g.,
+i8, i16, i32, ..., in Rust).
+
+``-fsanitize-cfi-icall-experimental-normalize-integers`` is compatible with
+``-fsanitize-cfi-icall-generalize-pointers``.
+
+This option is currently experimental.
+
 .. _cfi-canonical-jump-tables:
 
 ``-fsanitize-cfi-canonical-jump-tables``

diff  --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index 7dd8ecb5fcc4d..dfb062ee034cf 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -1992,6 +1992,14 @@ are listed below.
checked by Control Flow Integrity indirect call checking. See
:doc:`ControlFlowIntegrity` for more details.
 
+.. option:: -fsanitize-cfi-icall-experimental-normalize-integers
+
+   Normalize integers in return and argument types in function type signatures
+   checked by Control Flow Integrity indirect call checking. See
+   :doc:`ControlFlowIntegrity` for more details.
+
+   This option is currently experimental.
+
 .. option:: -fstrict-vtable-pointers
 
Enable optimizations based on the strict rules for overwriting polymorphic

diff  --git a/clang/include/clang/AST/Mangle.h 
b/clang/include/clang/AST/Mangle.h
index 9662a33c61cb7..c04bcc7f01cb4 100644
--- a/clang/include/clang/AST/Mangle.h
+++ b/clang/include/clang/AST/Mangle.h
@@ -140,7 +140,8 @@ class MangleContext {
 unsigned ManglingNumber,
 raw_ostream &) = 0;
   virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0;
-  virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0;
+  virtual void mangleCXXRTTIName(QualType T, raw_ostream &,
+ bool NormalizeIntegers = false) = 0;
   virtual void mangleStringLiteral(const StringLiteral *SL, raw_ostream &) = 0;
   virtual void mangleMSGuidDecl(const MSGuidDecl *GD, raw_ostream&);
 
@@ -177,7 +178,8 @@ class Mangle

[clang] fd5e262 - [ModuleUtils][KCFI] Set patchable-function-prefix for synthesized functions

2023-01-11 Thread Sami Tolvanen via cfe-commits

Author: Sami Tolvanen
Date: 2023-01-11T23:45:49Z
New Revision: fd5e2627066075f3d15ef774ef368e08735a9ac9

URL: 
https://github.com/llvm/llvm-project/commit/fd5e2627066075f3d15ef774ef368e08735a9ac9
DIFF: 
https://github.com/llvm/llvm-project/commit/fd5e2627066075f3d15ef774ef368e08735a9ac9.diff

LOG: [ModuleUtils][KCFI] Set patchable-function-prefix for synthesized functions

When -fpatchable-function-entry is used to emit prefix nops
before functions, KCFI assumes all indirectly called functions
have the same number of prefix nops, because the nops are emitted
between the KCFI type hash and the function entry. However, as
patchable-function-prefix is a function attribute set by Clang,
functions later synthesized by LLVM don't inherit this attribute
and end up not having prefix nops. One of these functions
is asan.module_ctor, which the Linux kernel ends up calling
indirectly when KASAN is enabled.

In order to avoid tripping KCFI, save the expected prefix offset
to a module flag, and use it when we're setting KCFI type for the
relevant synthesized functions.

Link: https://github.com/ClangBuiltLinux/linux/issues/1742

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D141172

Added: 
llvm/test/Instrumentation/AddressSanitizer/kcfi-offset.ll

Modified: 
clang/lib/CodeGen/CodeGenModule.cpp
clang/test/CodeGen/kcfi.c
llvm/lib/Transforms/Utils/ModuleUtils.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index c8e27b2f975ca..b85d8926941a5 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -758,8 +758,14 @@ void CodeGenModule::Release() {
   CodeGenOpts.SanitizeCfiCanonicalJumpTables);
   }
 
-  if (LangOpts.Sanitize.has(SanitizerKind::KCFI))
+  if (LangOpts.Sanitize.has(SanitizerKind::KCFI)) {
 getModule().addModuleFlag(llvm::Module::Override, "kcfi", 1);
+// KCFI assumes patchable-function-prefix is the same for all indirectly
+// called functions. Store the expected offset for code generation.
+if (CodeGenOpts.PatchableFunctionEntryOffset)
+  getModule().addModuleFlag(llvm::Module::Override, "kcfi-offset",
+CodeGenOpts.PatchableFunctionEntryOffset);
+  }
 
   if (CodeGenOpts.CFProtectionReturn &&
   Target.checkCFProtectionReturnSupported(getDiags())) {

diff  --git a/clang/test/CodeGen/kcfi.c b/clang/test/CodeGen/kcfi.c
index b0368d59fc744..1adf6df92a654 100644
--- a/clang/test/CodeGen/kcfi.c
+++ b/clang/test/CodeGen/kcfi.c
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=kcfi 
-o - %s | FileCheck %s
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=kcfi 
-x c++ -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=kcfi 
-fpatchable-function-entry-offset=3 -o - %s | FileCheck %s 
--check-prefixes=CHECK,OFFSET
 #if !__has_feature(kcfi)
 #error Missing kcfi?
 #endif
@@ -54,5 +55,6 @@ int test(void) {
 }
 
 // CHECK-DAG: ![[#]] = !{i32 4, !"kcfi", i32 1}
+// OFFSET-DAG: ![[#]] = !{i32 4, !"kcfi-offset", i32 3}
 // CHECK-DAG: ![[#TYPE]] = !{i32 [[#HASH]]}
 // CHECK-DAG: ![[#TYPE2]] = !{i32 [[#%d,HASH2:]]}

diff  --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp 
b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
index ee5e65fbaa505..2c2e8db34f278 100644
--- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp
+++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
@@ -161,6 +161,13 @@ void llvm::setKCFIType(Module &M, Function &F, StringRef 
MangledType) {
   MDNode::get(Ctx, MDB.createConstant(ConstantInt::get(
Type::getInt32Ty(Ctx),
static_cast(xxHash64(MangledType));
+  // If the module was compiled with -fpatchable-function-entry, ensure
+  // we use the same patchable-function-prefix.
+  if (auto *MD = mdconst::extract_or_null(
+  M.getModuleFlag("kcfi-offset"))) {
+if (unsigned Offset = MD->getZExtValue())
+  F.addFnAttr("patchable-function-prefix", std::to_string(Offset));
+  }
 }
 
 FunctionCallee

diff  --git a/llvm/test/Instrumentation/AddressSanitizer/kcfi-offset.ll 
b/llvm/test/Instrumentation/AddressSanitizer/kcfi-offset.ll
new file mode 100644
index 0..b5d103c073998
--- /dev/null
+++ b/llvm/test/Instrumentation/AddressSanitizer/kcfi-offset.ll
@@ -0,0 +1,15 @@
+;; Test that we set patchable-function-prefix for asan.module_ctor when 
kcfi-offset is defined.
+
+; RUN: opt < %s -passes=asan -S | FileCheck %s
+
+; CHECK: @llvm.global_ctors = {{.*}}{ i32 1, ptr @asan.module_ctor, ptr 
@asan.module_ctor }
+
+; CHECK: define internal void @asan.module_ctor()
+; CHECK-SAME: #[[#ATTR:]]
+; CHECK-SAME: !kcfi_type
+
+; CHECK: attributes #[[#ATTR]] = { {{.*}} "patchable-function-prefix"="3" }
+
+!llvm.module.flags = !{!0, !1}
+!0 = !{i32

[clang] [RISCV] Implement shadow stack on shadow stack mode with Zicfiss. (PR #68075)

2023-10-12 Thread Sami Tolvanen via cfe-commits

samitolvanen wrote:

The patch basically changes the ShadowCallStack back-end to emit an 
sspush/sspopchk instead of the usual SCS push/pop, which seems like a 
reasonable approach to me. However, it would be helpful to mention the 
dependency on `-fsanitize=shadow-call-stack` in the commit message, and you 
should also update [the 
documentation](https://clang.llvm.org/docs/ShadowCallStack.html).

https://github.com/llvm/llvm-project/pull/68075
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [RISCV] Implement shadow stack on shadow stack mode with Zicfiss. (PR #68075)

2023-10-13 Thread Sami Tolvanen via cfe-commits


@@ -106,9 +111,14 @@ static void emitSCSEpilogue(MachineFunction &MF, 
MachineBasicBlock &MBB,
   CSI, [&](CalleeSavedInfo &CSR) { return CSR.getReg() == RAReg; }))
 return;
 
+  const RISCVInstrInfo *TII = STI.getInstrInfo();
+  if (STI.hasFeature(RISCV::FeatureStdExtZicfiss)) {

samitolvanen wrote:

> > Do we need an enable other than just the feature being in -march? The 
> > shadow stack pointer has to be set up when the application starts. Is this 
> > done by the kernel?
> > My concern is that if your -mcpu supports Zicfiss, but the kernel doesn't, 
> > this will generate code that doesn't work.
> 
> oh, that's good point...let me check how other target do

If the kernel doesn't support Zicfiss, it presumably also hasn't enabled the 
extension for U-mode. Therefore, my understanding is that the application 
loader can simply skip shadow stack setup for the program, including the 
`prctl` (which would fail with `-EINVAL`), and since the Zicfiss (Zimop) 
instructions are no-ops when the extension is disabled, the program would run 
normally, just without shadow stacks. Does this sound correct?

https://github.com/llvm/llvm-project/pull/68075
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [RISCV] Implement shadow stack on shadow stack mode with Zicfiss. (PR #68075)

2023-10-17 Thread Sami Tolvanen via cfe-commits


@@ -106,9 +111,14 @@ static void emitSCSEpilogue(MachineFunction &MF, 
MachineBasicBlock &MBB,
   CSI, [&](CalleeSavedInfo &CSR) { return CSR.getReg() == RAReg; }))
 return;
 
+  const RISCVInstrInfo *TII = STI.getInstrInfo();
+  if (STI.hasFeature(RISCV::FeatureStdExtZicfiss)) {

samitolvanen wrote:

> Today, if you use software SCS on a platform without support they just fail, 
> since the SCS won't be setup and gp(probably) points to invalid memory. Is it 
> unreasonable to have it work the same in this case?

Sounds reasonable to me, but having a flag that allows one to explicitly select 
between software and hardware shadow stacks is still a good idea IMO.

> WDYT about phrasing this an an opt-out flag, like `-force-software-scs`, and 
> using a helper function, like :

For sanitizers, extra flags have typically been something like 
`-fsanitize-[sanitizer]-[flag]`, e.g. 
`-fsanitize-cfi-icall-generalize-pointers`:

https://clang.llvm.org/docs/ControlFlowIntegrity.html#indirect-function-call-checking

> It also occurs to me that X86 is getting/has backward edge CFI, right? how do 
> we enable that in the x86 backend? How is GCC planning to spell these 
> options, since I would suppose there needs to be some level of compatibility.

X86 uses the `-fcf-protection` flag for backward-edge at least, and AArch64 
uses `-mbranch-protection` for both backward-edge (PAC) and forward-edge (BTI). 
It would be great not to invent another command line option specifically for 
RISC-V, so I quite like the idea of reusing the existing ShadowCallStack 
front-end for hardware shadow stacks too.

https://github.com/llvm/llvm-project/pull/68075
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 9306352 - [Clang] Emit KCFI type hashes for member functions

2023-07-07 Thread Sami Tolvanen via cfe-commits

Author: Sami Tolvanen
Date: 2023-07-07T16:50:30Z
New Revision: 930635271f810316f48bd1aa78935acf36a08f8f

URL: 
https://github.com/llvm/llvm-project/commit/930635271f810316f48bd1aa78935acf36a08f8f
DIFF: 
https://github.com/llvm/llvm-project/commit/930635271f810316f48bd1aa78935acf36a08f8f.diff

LOG: [Clang] Emit KCFI type hashes for member functions

With `-fsanitize=kcfi`, Clang currently won't emit type hashes for
C++ member functions, which leads to check failures if they are
indirectly called. As there's no reason to exclude member functions
in CodeGenModule::setKCFIType, emit type hashes also for them to fix
member function pointer calls with KCFI, and add a test to confirm
that types are emitted correctly.

Added: 


Modified: 
clang/lib/CodeGen/CodeGenModule.cpp
clang/test/CodeGen/kcfi.c

Removed: 




diff  --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 6ea499958695d4..b5d26395ebba6a 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2610,9 +2610,6 @@ void 
CodeGenModule::CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD,
 }
 
 void CodeGenModule::setKCFIType(const FunctionDecl *FD, llvm::Function *F) {
-  if (isa(FD) && !cast(FD)->isStatic())
-return;
-
   llvm::LLVMContext &Ctx = F->getContext();
   llvm::MDBuilder MDB(Ctx);
   F->setMetadata(llvm::LLVMContext::MD_kcfi_type,

diff  --git a/clang/test/CodeGen/kcfi.c b/clang/test/CodeGen/kcfi.c
index 1adf6df92a6543..f6b2e4b398aa7c 100644
--- a/clang/test/CodeGen/kcfi.c
+++ b/clang/test/CodeGen/kcfi.c
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=kcfi 
-o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=kcfi 
-x c++ -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=kcfi 
-x c++ -o - %s | FileCheck %s --check-prefixes=CHECK,MEMBER
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=kcfi 
-fpatchable-function-entry-offset=3 -o - %s | FileCheck %s 
--check-prefixes=CHECK,OFFSET
 #if !__has_feature(kcfi)
 #error Missing kcfi?
@@ -54,7 +54,21 @@ int test(void) {
  f6();
 }
 
+#ifdef __cplusplus
+struct A {
+  // MEMBER-DAG: define{{.*}} void @_ZN1A1fEv(ptr{{.*}} %this){{.*}} 
!kcfi_type ![[#TYPE3:]]
+  void f() {}
+};
+
+void test_member_call(void) {
+  void (A::* p)() = &A::f;
+  // MEMBER-DAG: call void %[[#]](ptr{{.*}} [ "kcfi"(i32 [[#%d,HASH3:]]) ]
+  (A().*p)();
+}
+#endif
+
 // CHECK-DAG: ![[#]] = !{i32 4, !"kcfi", i32 1}
 // OFFSET-DAG: ![[#]] = !{i32 4, !"kcfi-offset", i32 3}
 // CHECK-DAG: ![[#TYPE]] = !{i32 [[#HASH]]}
 // CHECK-DAG: ![[#TYPE2]] = !{i32 [[#%d,HASH2:]]}
+// MEMBER-DAG: ![[#TYPE3]] = !{i32 [[#HASH3]]}



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 5a3d6ce - [Clang][Driver] Add KCFI to SupportsCoverage

2022-11-22 Thread Sami Tolvanen via cfe-commits

Author: Sami Tolvanen
Date: 2022-11-22T18:20:04Z
New Revision: 5a3d6ce956c44384920557b455b4db2bb0ab2fad

URL: 
https://github.com/llvm/llvm-project/commit/5a3d6ce956c44384920557b455b4db2bb0ab2fad
DIFF: 
https://github.com/llvm/llvm-project/commit/5a3d6ce956c44384920557b455b4db2bb0ab2fad.diff

LOG: [Clang][Driver] Add KCFI to SupportsCoverage

Allow `-fsanitize=kcfi` to be enabled with `-fsanitize-coverage=` modes
such as `trace-{pc,cmp}`.

Link: https://github.com/ClangBuiltLinux/linux/issues/1743

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D138458

Added: 


Modified: 
clang/lib/Driver/SanitizerArgs.cpp
clang/test/CodeGen/sanitize-coverage.c
clang/test/Driver/fsanitize-coverage.c

Removed: 




diff  --git a/clang/lib/Driver/SanitizerArgs.cpp 
b/clang/lib/Driver/SanitizerArgs.cpp
index e88cfaed1c4e8..af27dbc92c8e6 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -53,7 +53,7 @@ static const SanitizerMask SupportsCoverage =
 SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
 SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero |
 SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack |
-SanitizerKind::Thread | SanitizerKind::ObjCCast;
+SanitizerKind::Thread | SanitizerKind::ObjCCast | SanitizerKind::KCFI;
 static const SanitizerMask RecoverableByDefault =
 SanitizerKind::Undefined | SanitizerKind::Integer |
 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |

diff  --git a/clang/test/CodeGen/sanitize-coverage.c 
b/clang/test/CodeGen/sanitize-coverage.c
index 984076fed0ce4..cb1ed939d4a93 100644
--- a/clang/test/CodeGen/sanitize-coverage.c
+++ b/clang/test/CodeGen/sanitize-coverage.c
@@ -4,8 +4,10 @@
 // RUN: %clang %s -target x86_64-unknown-linux-gnu -emit-llvm -S 
-fsanitize=memory -fsanitize-coverage=trace-pc,trace-cmp -o - | FileCheck 
%s --check-prefixes=CHECK,MSAN
 // RUN: %clang %s -target x86_64-unknown-linux-gnu -emit-llvm -S 
-fsanitize=thread -fsanitize-coverage=trace-pc,trace-cmp -o - | FileCheck 
%s --check-prefixes=CHECK,TSAN
 // RUN: %clang %s -target x86_64-unknown-linux-gnu -emit-llvm -S 
-fsanitize=undefined  -fsanitize-coverage=trace-pc,trace-cmp -o - | FileCheck 
%s --check-prefixes=CHECK,UBSAN
+// RUN: %clang %s -target x86_64-unknown-linux-gnu -emit-llvm -S 
-fsanitize=kcfi   -fsanitize-coverage=trace-pc,trace-cmp -o - | FileCheck 
%s --check-prefixes=CHECK,KCFI
 
 int x[10];
+extern void (*f)(void);
 
 // CHECK-LABEL: define dso_local void @foo(
 void foo(int n) {
@@ -18,6 +20,8 @@ void foo(int n) {
   // UBSAN-DAG: call void @__ubsan_handle
   if (n)
 x[n] = 42;
+  // KCFI-DAG: call void %[[#]]() [ "kcfi"(i32 {{.*}}) ]
+  f();
 }
 
 static inline __attribute__((__always_inline__)) void always_inlined_fn(int n) 
{
@@ -42,6 +46,8 @@ __attribute__((no_sanitize("coverage"))) void 
test_no_sanitize_coverage(int n) {
   // UBSAN-DAG: call void @__ubsan_handle
   if (n)
 x[n] = 42;
+  // KCFI-DAG: call void %[[#]]() [ "kcfi"(i32 {{.*}}) ]
+  f();
 }
 
 
@@ -80,6 +86,14 @@ void test_no_sanitize_separate(int n) {
 x[n] = 42;
 }
 
+// CHECK-LABEL: define dso_local void @test_no_sanitize_kcfi(
+__attribute__((no_sanitize("kcfi", "coverage")))
+void test_no_sanitize_kcfi(void) {
+  // CHECK-NOT: call void @__sanitizer_cov_trace
+  // KCFI-NOT: call void %[[#]]() [ "kcfi"(i32 {{.*}}) ]
+  f();
+}
+
 // CHECK-LABEL: define dso_local void @test_no_sanitize_always_inline(
 __attribute__((no_sanitize("coverage")))
 void test_no_sanitize_always_inline(int n) {

diff  --git a/clang/test/Driver/fsanitize-coverage.c 
b/clang/test/Driver/fsanitize-coverage.c
index d18321d77d55f..16853ed7d04aa 100644
--- a/clang/test/Driver/fsanitize-coverage.c
+++ b/clang/test/Driver/fsanitize-coverage.c
@@ -16,6 +16,7 @@
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=bool 
-fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s 
--check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=dataflow 
-fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s 
--check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=thread 
-fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s 
--check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kcfi 
-fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s 
--check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
 // RUN: %clang -target %itanium_abi_triple -fsanitize=float-divide-by-zero 
-fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s 
--check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
 // RUN: %clang -target x86_64-linux-gnu 
-fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s 
--check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
 // CHECK-SANITIZE-COVERAGE-FUNC: fsanitize-coverage-type=

[clang] cacd3e7 - Add generic KCFI operand bundle lowering

2022-11-22 Thread Sami Tolvanen via cfe-commits

Author: Sami Tolvanen
Date: 2022-11-22T23:01:18Z
New Revision: cacd3e73d7f87ef3593443271ab3f170d0360934

URL: 
https://github.com/llvm/llvm-project/commit/cacd3e73d7f87ef3593443271ab3f170d0360934
DIFF: 
https://github.com/llvm/llvm-project/commit/cacd3e73d7f87ef3593443271ab3f170d0360934.diff

LOG: Add generic KCFI operand bundle lowering

The KCFI sanitizer emits "kcfi" operand bundles to indirect
call instructions, which the LLVM back-end lowers into an
architecture-specific type check with a known machine instruction
sequence. Currently, KCFI operand bundle lowering is supported only
on 64-bit X86 and AArch64 architectures.

As a lightweight forward-edge CFI implementation that doesn't
require LTO is also useful for non-Linux low-level targets on
other machine architectures, add a generic KCFI operand bundle
lowering pass that's only used when back-end lowering support is not
available and allows -fsanitize=kcfi to be enabled in Clang on all
architectures.

This relands commit eb2a57ebc7aaad551af30462097a9e06c96db925 with
fixes.

Reviewed By: nickdesaulniers, MaskRay

Differential Revision: https://reviews.llvm.org/D135411

Added: 
llvm/include/llvm/Transforms/Instrumentation/KCFI.h
llvm/lib/Transforms/Instrumentation/KCFI.cpp
llvm/test/Transforms/KCFI/kcfi-patchable-function-prefix.ll
llvm/test/Transforms/KCFI/kcfi.ll

Modified: 
clang/lib/CodeGen/BackendUtil.cpp
clang/lib/Driver/ToolChain.cpp
llvm/include/llvm/InitializePasses.h
llvm/lib/Passes/PassBuilder.cpp
llvm/lib/Passes/PassRegistry.def
llvm/lib/Transforms/Instrumentation/CMakeLists.txt
llvm/utils/gn/secondary/llvm/lib/Transforms/Instrumentation/BUILD.gn

Removed: 




diff  --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index 77b0c5b15da7d..99a30077e8fe1 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -72,6 +72,7 @@
 #include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
 #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
 #include "llvm/Transforms/Instrumentation/InstrProfiling.h"
+#include "llvm/Transforms/Instrumentation/KCFI.h"
 #include "llvm/Transforms/Instrumentation/MemProfiler.h"
 #include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
 #include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
@@ -644,6 +645,31 @@ static OptimizationLevel mapToLevel(const CodeGenOptions 
&Opts) {
   }
 }
 
+static void addKCFIPass(const Triple &TargetTriple, const LangOptions 
&LangOpts,
+PassBuilder &PB) {
+  // If the back-end supports KCFI operand bundle lowering, skip KCFIPass.
+  if (TargetTriple.getArch() == llvm::Triple::x86_64 ||
+  TargetTriple.isAArch64(64))
+return;
+
+  // Ensure we lower KCFI operand bundles with -O0.
+  PB.registerOptimizerLastEPCallback(
+  [&](ModulePassManager &MPM, OptimizationLevel Level) {
+if (Level == OptimizationLevel::O0 &&
+LangOpts.Sanitize.has(SanitizerKind::KCFI))
+  MPM.addPass(createModuleToFunctionPassAdaptor(KCFIPass()));
+  });
+
+  // When optimizations are requested, run KCIFPass after InstCombine to
+  // avoid unnecessary checks.
+  PB.registerPeepholeEPCallback(
+  [&](FunctionPassManager &FPM, OptimizationLevel Level) {
+if (Level != OptimizationLevel::O0 &&
+LangOpts.Sanitize.has(SanitizerKind::KCFI))
+  FPM.addPass(KCFIPass());
+  });
+}
+
 static void addSanitizers(const Triple &TargetTriple,
   const CodeGenOptions &CodeGenOpts,
   const LangOptions &LangOpts, PassBuilder &PB) {
@@ -946,8 +972,10 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
 
 // Don't add sanitizers if we are here from ThinLTO PostLink. That already
 // done on PreLink stage.
-if (!IsThinLTOPostLink)
+if (!IsThinLTOPostLink) {
   addSanitizers(TargetTriple, CodeGenOpts, LangOpts, PB);
+  addKCFIPass(TargetTriple, LangOpts, PB);
+}
 
 if (Optional Options = getGCOVOptions(CodeGenOpts, LangOpts))
   PB.registerPipelineStartEPCallback(

diff  --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index a1efa1feb3673..1624dbf8bc063 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -1088,7 +1088,7 @@ SanitizerMask ToolChain::getSupportedSanitizers() const {
~SanitizerKind::Function) |
   (SanitizerKind::CFI & ~SanitizerKind::CFIICall) |
   SanitizerKind::CFICastStrict | SanitizerKind::FloatDivideByZero |
-  SanitizerKind::UnsignedIntegerOverflow |
+  SanitizerKind::KCFI | SanitizerKind::UnsignedIntegerOverflow |
   SanitizerKind::UnsignedShiftBase | SanitizerKind::ImplicitConversion |
   SanitizerKind::Nullability | SanitizerKind::LocalBounds;
   if (getTriple().getArch() == llvm::Triple::x86 ||
@@ -1096,9 +1096,6 @@ SanitizerM

[clang] 62fa708 - [RISCV] Implement KCFI operand bundle lowering

2023-06-23 Thread Sami Tolvanen via cfe-commits

Author: Sami Tolvanen
Date: 2023-06-23T18:25:24Z
New Revision: 62fa708ceb027713b386c7e0efda994f8bdc27e2

URL: 
https://github.com/llvm/llvm-project/commit/62fa708ceb027713b386c7e0efda994f8bdc27e2
DIFF: 
https://github.com/llvm/llvm-project/commit/62fa708ceb027713b386c7e0efda994f8bdc27e2.diff

LOG: [RISCV] Implement KCFI operand bundle lowering

With `-fsanitize=kcfi` (Kernel Control-Flow Integrity), Clang emits
"kcfi" operand bundles to indirect call instructions. Similarly to
the target-specific lowering added in D119296, implement KCFI operand
bundle lowering for RISC-V.

This patch disables the generic KCFI pass for RISC-V in Clang, and
adds the KCFI machine function pass in `RISCVPassConfig::addPreSched`
to emit target-specific `KCFI_CHECK` pseudo instructions before calls
that have KCFI operand bundles. The machine function pass also bundles
the instructions to ensure we emit the checks immediately before the
calls, which is not possible with the generic pass.

`KCFI_CHECK` instructions are lowered in `RISCVAsmPrinter` to a
contiguous code sequence that traps if the expected hash in the
operand bundle doesn't match the hash before the target function
address. This patch emits an `ebreak` instruction for error handling
to match the Linux kernel's `BUG()` implementation. Just like for X86,
we also emit trap locations to a `.kcfi_traps` section to support
error handling, as we cannot embed additional information to the trap
instruction itself.

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D148385

Added: 
llvm/test/CodeGen/RISCV/kcfi-isel.mir
llvm/test/CodeGen/RISCV/kcfi-patchable-function-prefix.ll
llvm/test/CodeGen/RISCV/kcfi.ll
llvm/test/CodeGen/RISCV/kcfi.mir

Modified: 
clang/lib/CodeGen/BackendUtil.cpp
llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
llvm/lib/Target/RISCV/RISCVISelLowering.h
llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
llvm/lib/Target/RISCV/RISCVInstrInfo.h
llvm/lib/Target/RISCV/RISCVInstrInfo.td
llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
llvm/test/CodeGen/RISCV/O0-pipeline.ll
llvm/test/CodeGen/RISCV/O3-pipeline.ll

Removed: 




diff  --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index f7a174a5fe462..d00c5654a190c 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -631,7 +631,7 @@ static void addKCFIPass(const Triple &TargetTriple, const 
LangOptions &LangOpts,
 PassBuilder &PB) {
   // If the back-end supports KCFI operand bundle lowering, skip KCFIPass.
   if (TargetTriple.getArch() == llvm::Triple::x86_64 ||
-  TargetTriple.isAArch64(64))
+  TargetTriple.isAArch64(64) || TargetTriple.isRISCV())
 return;
 
   // Ensure we lower KCFI operand bundles with -O0.

diff  --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp 
b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
index 9f4d363f83ef2..f7d11e921c7de 100644
--- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -19,6 +19,7 @@
 #include "RISCVMachineFunctionInfo.h"
 #include "RISCVTargetMachine.h"
 #include "TargetInfo/RISCVTargetInfo.h"
+#include "llvm/ADT/APInt.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/BinaryFormat/ELF.h"
 #include "llvm/CodeGen/AsmPrinter.h"
@@ -72,6 +73,7 @@ class RISCVAsmPrinter : public AsmPrinter {
   typedef std::tuple HwasanMemaccessTuple;
   std::map HwasanMemaccessSymbols;
   void LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI);
+  void LowerKCFI_CHECK(const MachineInstr &MI);
   void EmitHwasanMemaccessSymbols(Module &M);
 
   // Wrapper needed for tblgenned pseudo lowering.
@@ -150,6 +152,9 @@ void RISCVAsmPrinter::emitInstruction(const MachineInstr 
*MI) {
   case RISCV::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
 LowerHWASAN_CHECK_MEMACCESS(*MI);
 return;
+  case RISCV::KCFI_CHECK:
+LowerKCFI_CHECK(*MI);
+return;
   case RISCV::PseudoRVVInitUndefM1:
   case RISCV::PseudoRVVInitUndefM2:
   case RISCV::PseudoRVVInitUndefM4:
@@ -305,6 +310,92 @@ void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const 
MachineInstr &MI) {
   EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr));
 }
 
+void RISCVAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
+  Register AddrReg = MI.getOperand(0).getReg();
+  assert(std::next(MI.getIterator())->isCall() &&
+ "KCFI_CHECK not followed by a call instruction");
+  assert(std::next(MI.getIterator())->getOperand(0).getReg() == AddrReg &&
+ "KCFI_CHECK call target doesn't match call operand");
+
+  // Temporary registers for comparing the hashes. If a register is used
+  // for the call target, or reserved by the user, we can clobber another
+  // temporary register as the check is immediately followed by the
+  // call. The check defaults to X6/X7, but can fall back t

[clang] e809ebe - Revert "[RISCV] Implement KCFI operand bundle lowering"

2023-06-23 Thread Sami Tolvanen via cfe-commits

Author: Sami Tolvanen
Date: 2023-06-23T21:42:57Z
New Revision: e809ebeb6c8b4986cc82542cffd07a453bfac66c

URL: 
https://github.com/llvm/llvm-project/commit/e809ebeb6c8b4986cc82542cffd07a453bfac66c
DIFF: 
https://github.com/llvm/llvm-project/commit/e809ebeb6c8b4986cc82542cffd07a453bfac66c.diff

LOG: Revert "[RISCV] Implement KCFI operand bundle lowering"

This reverts commit 62fa708ceb027713b386c7e0efda994f8bdc27e2.

Reverting to investigate -verify-machineinstrs errors in MIR tests.

Added: 


Modified: 
clang/lib/CodeGen/BackendUtil.cpp
llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
llvm/lib/Target/RISCV/RISCVISelLowering.h
llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
llvm/lib/Target/RISCV/RISCVInstrInfo.h
llvm/lib/Target/RISCV/RISCVInstrInfo.td
llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
llvm/test/CodeGen/RISCV/O0-pipeline.ll
llvm/test/CodeGen/RISCV/O3-pipeline.ll

Removed: 
llvm/test/CodeGen/RISCV/kcfi-isel.mir
llvm/test/CodeGen/RISCV/kcfi-patchable-function-prefix.ll
llvm/test/CodeGen/RISCV/kcfi.ll
llvm/test/CodeGen/RISCV/kcfi.mir



diff  --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index d00c5654a190c..f7a174a5fe462 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -631,7 +631,7 @@ static void addKCFIPass(const Triple &TargetTriple, const 
LangOptions &LangOpts,
 PassBuilder &PB) {
   // If the back-end supports KCFI operand bundle lowering, skip KCFIPass.
   if (TargetTriple.getArch() == llvm::Triple::x86_64 ||
-  TargetTriple.isAArch64(64) || TargetTriple.isRISCV())
+  TargetTriple.isAArch64(64))
 return;
 
   // Ensure we lower KCFI operand bundles with -O0.

diff  --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp 
b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
index f7d11e921c7de..9f4d363f83ef2 100644
--- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -19,7 +19,6 @@
 #include "RISCVMachineFunctionInfo.h"
 #include "RISCVTargetMachine.h"
 #include "TargetInfo/RISCVTargetInfo.h"
-#include "llvm/ADT/APInt.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/BinaryFormat/ELF.h"
 #include "llvm/CodeGen/AsmPrinter.h"
@@ -73,7 +72,6 @@ class RISCVAsmPrinter : public AsmPrinter {
   typedef std::tuple HwasanMemaccessTuple;
   std::map HwasanMemaccessSymbols;
   void LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI);
-  void LowerKCFI_CHECK(const MachineInstr &MI);
   void EmitHwasanMemaccessSymbols(Module &M);
 
   // Wrapper needed for tblgenned pseudo lowering.
@@ -152,9 +150,6 @@ void RISCVAsmPrinter::emitInstruction(const MachineInstr 
*MI) {
   case RISCV::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
 LowerHWASAN_CHECK_MEMACCESS(*MI);
 return;
-  case RISCV::KCFI_CHECK:
-LowerKCFI_CHECK(*MI);
-return;
   case RISCV::PseudoRVVInitUndefM1:
   case RISCV::PseudoRVVInitUndefM2:
   case RISCV::PseudoRVVInitUndefM4:
@@ -310,92 +305,6 @@ void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const 
MachineInstr &MI) {
   EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr));
 }
 
-void RISCVAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
-  Register AddrReg = MI.getOperand(0).getReg();
-  assert(std::next(MI.getIterator())->isCall() &&
- "KCFI_CHECK not followed by a call instruction");
-  assert(std::next(MI.getIterator())->getOperand(0).getReg() == AddrReg &&
- "KCFI_CHECK call target doesn't match call operand");
-
-  // Temporary registers for comparing the hashes. If a register is used
-  // for the call target, or reserved by the user, we can clobber another
-  // temporary register as the check is immediately followed by the
-  // call. The check defaults to X6/X7, but can fall back to X28-X31 if
-  // needed.
-  unsigned ScratchRegs[] = {RISCV::X6, RISCV::X7};
-  unsigned NextReg = RISCV::X28;
-  auto isRegAvailable = [&](unsigned Reg) {
-return Reg != AddrReg && !STI->isRegisterReservedByUser(Reg);
-  };
-  for (auto &Reg : ScratchRegs) {
-if (isRegAvailable(Reg))
-  continue;
-while (!isRegAvailable(NextReg))
-  ++NextReg;
-Reg = NextReg++;
-if (Reg > RISCV::X31)
-  report_fatal_error("Unable to find scratch registers for KCFI_CHECK");
-  }
-
-  if (AddrReg == RISCV::X0) {
-// Checking X0 makes no sense. Instead of emitting a load, zero
-// ScratchRegs[0].
-EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)
- .addReg(ScratchRegs[0])
- .addReg(RISCV::X0)
- .addImm(0));
-  } else {
-// Adjust the offset for patchable-function-prefix. This assumes that
-// patchable-function-prefix is the same for all functions.
-int NopSize = STI->hasStdExtCOrZca() ? 2 : 4;
-

[clang] 83835e2 - [RISCV] Implement KCFI operand bundle lowering

2023-06-23 Thread Sami Tolvanen via cfe-commits

Author: Sami Tolvanen
Date: 2023-06-23T22:57:56Z
New Revision: 83835e22c7cd50c0e9b836cc359b6c59985b921f

URL: 
https://github.com/llvm/llvm-project/commit/83835e22c7cd50c0e9b836cc359b6c59985b921f
DIFF: 
https://github.com/llvm/llvm-project/commit/83835e22c7cd50c0e9b836cc359b6c59985b921f.diff

LOG: [RISCV] Implement KCFI operand bundle lowering

With `-fsanitize=kcfi` (Kernel Control-Flow Integrity), Clang emits
"kcfi" operand bundles to indirect call instructions. Similarly to
the target-specific lowering added in D119296, implement KCFI operand
bundle lowering for RISC-V.

This patch disables the generic KCFI pass for RISC-V in Clang, and
adds the KCFI machine function pass in `RISCVPassConfig::addPreSched`
to emit target-specific `KCFI_CHECK` pseudo instructions before calls
that have KCFI operand bundles. The machine function pass also bundles
the instructions to ensure we emit the checks immediately before the
calls, which is not possible with the generic pass.

`KCFI_CHECK` instructions are lowered in `RISCVAsmPrinter` to a
contiguous code sequence that traps if the expected hash in the
operand bundle doesn't match the hash before the target function
address. This patch emits an `ebreak` instruction for error handling
to match the Linux kernel's `BUG()` implementation. Just like for X86,
we also emit trap locations to a `.kcfi_traps` section to support
error handling, as we cannot embed additional information to the trap
instruction itself.

Relands commit 62fa708ceb027713b386c7e0efda994f8bdc27e2 with fixed
tests.

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D148385

Added: 
llvm/test/CodeGen/RISCV/kcfi-isel-mir.ll
llvm/test/CodeGen/RISCV/kcfi-mir.ll
llvm/test/CodeGen/RISCV/kcfi-patchable-function-prefix.ll
llvm/test/CodeGen/RISCV/kcfi.ll

Modified: 
clang/lib/CodeGen/BackendUtil.cpp
llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
llvm/lib/Target/RISCV/RISCVISelLowering.h
llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
llvm/lib/Target/RISCV/RISCVInstrInfo.h
llvm/lib/Target/RISCV/RISCVInstrInfo.td
llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
llvm/test/CodeGen/RISCV/O0-pipeline.ll
llvm/test/CodeGen/RISCV/O3-pipeline.ll

Removed: 




diff  --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index f7a174a5fe462..d00c5654a190c 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -631,7 +631,7 @@ static void addKCFIPass(const Triple &TargetTriple, const 
LangOptions &LangOpts,
 PassBuilder &PB) {
   // If the back-end supports KCFI operand bundle lowering, skip KCFIPass.
   if (TargetTriple.getArch() == llvm::Triple::x86_64 ||
-  TargetTriple.isAArch64(64))
+  TargetTriple.isAArch64(64) || TargetTriple.isRISCV())
 return;
 
   // Ensure we lower KCFI operand bundles with -O0.

diff  --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp 
b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
index 9f4d363f83ef2..f7d11e921c7de 100644
--- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -19,6 +19,7 @@
 #include "RISCVMachineFunctionInfo.h"
 #include "RISCVTargetMachine.h"
 #include "TargetInfo/RISCVTargetInfo.h"
+#include "llvm/ADT/APInt.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/BinaryFormat/ELF.h"
 #include "llvm/CodeGen/AsmPrinter.h"
@@ -72,6 +73,7 @@ class RISCVAsmPrinter : public AsmPrinter {
   typedef std::tuple HwasanMemaccessTuple;
   std::map HwasanMemaccessSymbols;
   void LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI);
+  void LowerKCFI_CHECK(const MachineInstr &MI);
   void EmitHwasanMemaccessSymbols(Module &M);
 
   // Wrapper needed for tblgenned pseudo lowering.
@@ -150,6 +152,9 @@ void RISCVAsmPrinter::emitInstruction(const MachineInstr 
*MI) {
   case RISCV::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
 LowerHWASAN_CHECK_MEMACCESS(*MI);
 return;
+  case RISCV::KCFI_CHECK:
+LowerKCFI_CHECK(*MI);
+return;
   case RISCV::PseudoRVVInitUndefM1:
   case RISCV::PseudoRVVInitUndefM2:
   case RISCV::PseudoRVVInitUndefM4:
@@ -305,6 +310,92 @@ void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const 
MachineInstr &MI) {
   EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr));
 }
 
+void RISCVAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
+  Register AddrReg = MI.getOperand(0).getReg();
+  assert(std::next(MI.getIterator())->isCall() &&
+ "KCFI_CHECK not followed by a call instruction");
+  assert(std::next(MI.getIterator())->getOperand(0).getReg() == AddrReg &&
+ "KCFI_CHECK call target doesn't match call operand");
+
+  // Temporary registers for comparing the hashes. If a register is used
+  // for the call target, or reserved by the user, we can clobber another
+  // temporary register as the check is immedia

[clang] 71c7313 - Add CFI integer types normalization

2023-02-08 Thread Sami Tolvanen via cfe-commits

Author: Ramon de C Valle
Date: 2023-02-08T22:24:19Z
New Revision: 71c7313f42d2b6063fea09854cf4fc46fd0627e1

URL: 
https://github.com/llvm/llvm-project/commit/71c7313f42d2b6063fea09854cf4fc46fd0627e1
DIFF: 
https://github.com/llvm/llvm-project/commit/71c7313f42d2b6063fea09854cf4fc46fd0627e1.diff

LOG: Add CFI integer types normalization

This commit adds a new option (i.e.,
`-fsanitize-cfi-icall-normalize-integers`) for normalizing integer types
as vendor extended types for cross-language LLVM CFI/KCFI support with
other languages that can't represent and encode C/C++ integer types.

Specifically, integer types are encoded as their defined representations
(e.g., 8-bit signed integer, 16-bit signed integer, 32-bit signed
integer, ...) for compatibility with languages that define
explicitly-sized integer types (e.g., i8, i16, i32, ..., in Rust).

``-fsanitize-cfi-icall-normalize-integers`` is compatible with
``-fsanitize-cfi-icall-generalize-pointers``.

This helps with providing cross-language CFI support with the Rust
compiler and is an alternative solution for the issue described and
alternatives proposed in the RFC
https://github.com/rust-lang/rfcs/pull/3296.

For more information about LLVM CFI/KCFI and cross-language LLVM
CFI/KCFI support for the Rust compiler, see the design document in the
tracking issue https://github.com/rust-lang/rust/issues/89653.

Relands b1e9ab7438a098a18fecda88fc87ef4ccadfcf1e with fixes.

Reviewed By: pcc, samitolvanen

Differential Revision: https://reviews.llvm.org/D139395

Added: 
clang/test/CodeGen/cfi-icall-normalize.c
clang/test/CodeGen/cfi-icall-normalize2.c
clang/test/CodeGen/kcfi-normalize.c

Modified: 
clang/docs/ControlFlowIntegrity.rst
clang/docs/UsersManual.rst
clang/include/clang/AST/Mangle.h
clang/include/clang/Basic/CodeGenOptions.def
clang/include/clang/Driver/Options.td
clang/include/clang/Driver/SanitizerArgs.h
clang/lib/AST/ItaniumMangle.cpp
clang/lib/AST/MicrosoftMangle.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/Driver/SanitizerArgs.cpp

Removed: 




diff  --git a/clang/docs/ControlFlowIntegrity.rst 
b/clang/docs/ControlFlowIntegrity.rst
index ef47b1c5b4b2b..f375199f40617 100644
--- a/clang/docs/ControlFlowIntegrity.rst
+++ b/clang/docs/ControlFlowIntegrity.rst
@@ -236,6 +236,25 @@ long as the qualifiers for the type they point to match. 
For example, ``char*``,
 ``-fsanitize-cfi-icall-generalize-pointers`` is not compatible with
 ``-fsanitize-cfi-cross-dso``.
 
+.. _cfi-icall-experimental-normalize-integers:
+
+``-fsanitize-cfi-icall-experimental-normalize-integers``
+
+
+This option enables normalizing integer types as vendor extended types for
+cross-language LLVM CFI/KCFI support with other languages that can't represent
+and encode C/C++ integer types.
+
+Specifically, integer types are encoded as their defined representations (e.g.,
+8-bit signed integer, 16-bit signed integer, 32-bit signed integer, ...) for
+compatibility with languages that define explicitly-sized integer types (e.g.,
+i8, i16, i32, ..., in Rust).
+
+``-fsanitize-cfi-icall-experimental-normalize-integers`` is compatible with
+``-fsanitize-cfi-icall-generalize-pointers``.
+
+This option is currently experimental.
+
 .. _cfi-canonical-jump-tables:
 
 ``-fsanitize-cfi-canonical-jump-tables``

diff  --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index 18e1e9aaca2c4..0d5e960050c25 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -1992,6 +1992,14 @@ are listed below.
checked by Control Flow Integrity indirect call checking. See
:doc:`ControlFlowIntegrity` for more details.
 
+.. option:: -fsanitize-cfi-icall-experimental-normalize-integers
+
+   Normalize integers in return and argument types in function type signatures
+   checked by Control Flow Integrity indirect call checking. See
+   :doc:`ControlFlowIntegrity` for more details.
+
+   This option is currently experimental.
+
 .. option:: -fstrict-vtable-pointers
 
Enable optimizations based on the strict rules for overwriting polymorphic

diff  --git a/clang/include/clang/AST/Mangle.h 
b/clang/include/clang/AST/Mangle.h
index 9662a33c61cb7..c04bcc7f01cb4 100644
--- a/clang/include/clang/AST/Mangle.h
+++ b/clang/include/clang/AST/Mangle.h
@@ -140,7 +140,8 @@ class MangleContext {
 unsigned ManglingNumber,
 raw_ostream &) = 0;
   virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0;
-  virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0;
+  virtual void mangleCXXRTTIName(QualType T, raw_ostream &,
+ bool NormalizeIntegers = false) = 0;
   virtual void mangleStringLiteral(const StringLiteral *SL, raw_ostream &) = 0;
   virtual void mangleMSGuidDecl(const MSG

[clang] a851d46 - [Clang][Driver] Fix integer normalization with KCFI

2023-02-15 Thread Sami Tolvanen via cfe-commits

Author: Sami Tolvanen
Date: 2023-02-16T00:21:31Z
New Revision: a851d46e07c1234a0763b4630c8475c73208e776

URL: 
https://github.com/llvm/llvm-project/commit/a851d46e07c1234a0763b4630c8475c73208e776
DIFF: 
https://github.com/llvm/llvm-project/commit/a851d46e07c1234a0763b4630c8475c73208e776.diff

LOG: [Clang][Driver] Fix integer normalization with KCFI

Commit 71c7313f42d2b6063fea09854cf4fc46fd0627e1 added integer
normalization for CFI, but doesn't correctly pass the argument
with -fsanitize=kcfi. Set CfiICallNormalizeIntegers also with
SanitizerKind::KCFI to fix the issue.

Added: 


Modified: 
clang/lib/Driver/SanitizerArgs.cpp

Removed: 




diff  --git a/clang/lib/Driver/SanitizerArgs.cpp 
b/clang/lib/Driver/SanitizerArgs.cpp
index 7f7ad238c89f4..390faef0dbdf1 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -726,8 +726,11 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
  options::OPT_fno_sanitize_cfi_canonical_jump_tables, 
true);
   }
 
-  if (AllAddedKinds & SanitizerKind::KCFI && DiagnoseErrors) {
-if (AllAddedKinds & SanitizerKind::CFI)
+  if (AllAddedKinds & SanitizerKind::KCFI) {
+CfiICallNormalizeIntegers =
+Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
+
+if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)
   D.Diag(diag::err_drv_argument_not_allowed_with)
   << "-fsanitize=kcfi"
   << lastArgumentForMask(D, Args, SanitizerKind::CFI);



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 5a64a82 - [Driver] Allow -fsanitize=kcfi with -fsanitize-minimal-runtime

2023-06-05 Thread Sami Tolvanen via cfe-commits

Author: Sami Tolvanen
Date: 2023-06-05T20:39:45Z
New Revision: 5a64a826b9f0efab4ba7a8cdab4857794bbf07f3

URL: 
https://github.com/llvm/llvm-project/commit/5a64a826b9f0efab4ba7a8cdab4857794bbf07f3
DIFF: 
https://github.com/llvm/llvm-project/commit/5a64a826b9f0efab4ba7a8cdab4857794bbf07f3.diff

LOG: [Driver] Allow -fsanitize=kcfi with -fsanitize-minimal-runtime

Having both UBSan with the minimal runtime and KCFI enabled can be
useful in low-level software. As there are no conflicts between the
flags, add KCFI to the list of compatible sanitizers.

Added: 


Modified: 
clang/lib/Driver/SanitizerArgs.cpp

Removed: 




diff  --git a/clang/lib/Driver/SanitizerArgs.cpp 
b/clang/lib/Driver/SanitizerArgs.cpp
index 91efe7f5488be..65c0bbeecc3b6 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -77,7 +77,7 @@ static const SanitizerMask CFIClasses =
 static const SanitizerMask CompatibleWithMinimalRuntime =
 TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack |
 SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |
-SanitizerKind::MemtagGlobals;
+SanitizerKind::MemtagGlobals | SanitizerKind::KCFI;
 
 enum CoverageFeature {
   CoverageFunc = 1 << 0,



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] fix kcfi doesn't take effect when callee function has no input parameter (PR #106677)

2024-08-30 Thread Sami Tolvanen via cfe-commits


@@ -2813,6 +2813,11 @@ void CodeGenFunction::EmitKCFIOperandBundle(
   Callee.getAbstractInfo().getCalleeFunctionProtoType();
   if (FP)
 Bundles.emplace_back("kcfi", CGM.CreateKCFITypeId(FP->desugar()));
+  else {
+ASTContext &context = this->getContext();
+QualType voidType = context.VoidTy;

samitolvanen wrote:

`VoidTy` doesn't seem like an appropriate type for a function even if it 
doesn't have a parameter type list. We still want to distinguish between 
different return types, right?

Also, please add a matching test when you make a change. You could probably add 
a test case for this to `clang/test/CodeGen/kcfi.c`.

https://github.com/llvm/llvm-project/pull/106677
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] fix kcfi doesn't take effect when callee function has no input parameter (PR #106677)

2024-08-30 Thread Sami Tolvanen via cfe-commits

samitolvanen wrote:

> If a function is declared without a prototype (pre-C23), it doesn't mean it 
> has a void argument list; it means the argument list is undeclared. So you 
> can't just assume the argument list is void; you have to compute the argument 
> types from the actual arguments passed to the call.

Agreed, that would the best solution here.

> Or you could just forbid unprototyped functions in KCFI mode, If you don't 
> want to deal with the edge cases here (i.e. -Werror=strict-prototypes).

I'm fine with this option too. However, I assume the author has a use case for 
KCFI in an existing code base, which uses unprototyped functions.

https://github.com/llvm/llvm-project/pull/106677
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] ec2e26e - [Clang] Add __builtin_function_start

2021-12-20 Thread Sami Tolvanen via cfe-commits

Author: Sami Tolvanen
Date: 2021-12-20T12:55:33-08:00
New Revision: ec2e26eaf63558934f5b73a6e530edc453cf9508

URL: 
https://github.com/llvm/llvm-project/commit/ec2e26eaf63558934f5b73a6e530edc453cf9508
DIFF: 
https://github.com/llvm/llvm-project/commit/ec2e26eaf63558934f5b73a6e530edc453cf9508.diff

LOG: [Clang] Add __builtin_function_start

Control-Flow Integrity (CFI) replaces references to address-taken
functions with pointers to the CFI jump table. This is a problem
for low-level code, such as operating system kernels, which may
need the address of an actual function body without the jump table
indirection.

This change adds the __builtin_function_start() builtin, which
accepts an argument that can be constant-evaluated to a function,
and returns the address of the function body.

Link: https://github.com/ClangBuiltLinux/linux/issues/1353

Depends on D108478

Reviewed By: pcc, rjmccall

Differential Revision: https://reviews.llvm.org/D108479

Added: 
clang/test/CodeGen/builtin-function-start.cpp

Modified: 
clang/docs/LanguageExtensions.rst
clang/include/clang/AST/Expr.h
clang/include/clang/Basic/Builtins.def
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/AST/Expr.cpp
clang/lib/AST/ExprConstant.cpp
clang/lib/CodeGen/CGBuiltin.cpp
clang/lib/CodeGen/CGExprConstant.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/CodeGen/CodeGenModule.h
clang/lib/Sema/SemaChecking.cpp
clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
clang/test/SemaCXX/builtins.cpp

Removed: 




diff  --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index 24e85d336ef13..a47625e4a8dd2 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2517,6 +2517,48 @@ object that overloads ``operator&``.
 return __builtin_addressof(value);
   }
 
+``__builtin_function_start``
+-
+
+``__builtin_function_start`` returns the address of a function body.
+
+**Syntax**:
+
+.. code-block:: c++
+
+  void *__builtin_function_start(function)
+
+**Example of use**:
+
+.. code-block:: c++
+
+  void a() {}
+  void *p = __builtin_function_start(a);
+
+  class A {
+  public:
+void a(int n);
+void a();
+  };
+
+  void A::a(int n) {}
+  void A::a() {}
+
+  void *pa1 = __builtin_function_start((void(A::*)(int)) &A::a);
+  void *pa2 = __builtin_function_start((void(A::*)()) &A::a);
+
+**Description**:
+
+The ``__builtin_function_start`` builtin accepts an argument that can be
+constant-evaluated to a function, and returns the address of the function
+body.  This builtin is not supported on all targets.
+
+The returned pointer may 
diff er from the normally taken function address
+and is not safe to call.  For example, with ``-fsanitize=cfi``, taking a
+function address produces a callable pointer to a CFI jump table, while
+``__builtin_function_start`` returns an address that fails
+:doc:`cfi-icall` checks.
+
 ``__builtin_operator_new`` and ``__builtin_operator_delete``
 
 

diff  --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2c63406fba18d..e2c36e12393fa 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -572,6 +572,12 @@ class Expr : public ValueStmt {
   bool isConstantInitializer(ASTContext &Ctx, bool ForRef,
  const Expr **Culprit = nullptr) const;
 
+  /// If this expression is an unambiguous reference to a single declaration,
+  /// in the style of __builtin_function_start, return that declaration.  Note
+  /// that this may return a non-static member function or field in C++ if this
+  /// expression is a member pointer constant.
+  const ValueDecl *getAsBuiltinConstantDeclRef(const ASTContext &Context) 
const;
+
   /// EvalStatus is a struct with detailed info about an evaluation in 
progress.
   struct EvalStatus {
 /// Whether the evaluated expression has side effects.

diff  --git a/clang/include/clang/Basic/Builtins.def 
b/clang/include/clang/Basic/Builtins.def
index 7ef550e5d81af..f57635e010dce 100644
--- a/clang/include/clang/Basic/Builtins.def
+++ b/clang/include/clang/Basic/Builtins.def
@@ -1575,6 +1575,7 @@ BUILTIN(__builtin_smulll_overflow, "bSLLiCSLLiCSLLi*", 
"n")
 
 // Clang builtins (not available in GCC).
 BUILTIN(__builtin_addressof, "v*v&", "nct")
+BUILTIN(__builtin_function_start, "v*v&", "nct")
 BUILTIN(__builtin_operator_new, "v*z", "tc")
 BUILTIN(__builtin_operator_delete, "vv*", "tn")
 BUILTIN(__builtin_char_memchr, "c*cC*iz", "n")

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c26dbbbf1f697..875e639cb2beb 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -838,6 +838,9 @@ def wa

[clang] [llvm] Fix KCFI types for generated functions with integer normalization (PR #104826)

2024-08-19 Thread Sami Tolvanen via cfe-commits

https://github.com/samitolvanen created 
https://github.com/llvm/llvm-project/pull/104826

With -fsanitize-cfi-icall-experimental-normalize-integers, Clang appends 
".normalized" to KCFI types in CodeGenModule::CreateKCFITypeId, which changes 
type hashes also for functions that don't have integer types in their 
signatures. However, llvm::setKCFIType does not take integer normalization into 
account, which means LLVM generated functions with KCFI types, e.g. sanitizer 
constructors, will fail KCFI checks when integer normalization is enabled in 
Clang.

Add a kcfi-normalized module flag to indicate integer normalization is used, 
and append ".normalized" to KCFI types also in llvm::setKCFIType to fix the 
type mismatch.

cc @rcvalle 

>From 0f7dfc3f908651a70602f4f64a0ae06616544eeb Mon Sep 17 00:00:00 2001
From: Sami Tolvanen 
Date: Fri, 16 Aug 2024 20:45:05 +
Subject: [PATCH] Fix KCFI types for generated functions with integer
 normalization

With -fsanitize-cfi-icall-experimental-normalize-integers, Clang
appends ".normalized" to KCFI types in CodeGenModule::CreateKCFITypeId,
which changes type hashes also for functions that don't have integer
types in their signatures. However, llvm::setKCFIType does not take
integer normalization into account, which means LLVM generated
functions with KCFI types, e.g. sanitizer constructors, will fail KCFI
checks when integer normalization is enabled in Clang.

Add a kcfi-normalized module flag to indicate integer normalization is
used, and append ".normalized" to KCFI types also in llvm::setKCFIType
to fix the type mismatch.
---
 clang/lib/CodeGen/CodeGenModule.cpp   |  2 ++
 clang/test/CodeGen/kcfi-normalize.c   |  1 +
 llvm/lib/Transforms/Utils/ModuleUtils.cpp | 12 +++-
 3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 0b61ef0f89989c..7eca77dc9a86fe 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1136,6 +1136,8 @@ void CodeGenModule::Release() {
 
   if (LangOpts.Sanitize.has(SanitizerKind::KCFI)) {
 getModule().addModuleFlag(llvm::Module::Override, "kcfi", 1);
+if (CodeGenOpts.SanitizeCfiICallNormalizeIntegers)
+  getModule().addModuleFlag(llvm::Module::Override, "kcfi-normalized", 1);
 // KCFI assumes patchable-function-prefix is the same for all indirectly
 // called functions. Store the expected offset for code generation.
 if (CodeGenOpts.PatchableFunctionEntryOffset)
diff --git a/clang/test/CodeGen/kcfi-normalize.c 
b/clang/test/CodeGen/kcfi-normalize.c
index 7660c908a7bdd5..62b907dbfb9286 100644
--- a/clang/test/CodeGen/kcfi-normalize.c
+++ b/clang/test/CodeGen/kcfi-normalize.c
@@ -28,6 +28,7 @@ void baz(void (*fn)(int, int, int), int arg1, int arg2, int 
arg3) {
 fn(arg1, arg2, arg3);
 }
 
+// CHECK: ![[#]] = !{i32 4, !"kcfi-normalized", i32 1}
 // CHECK: ![[TYPE1]] = !{i32 -1143117868}
 // CHECK: ![[TYPE2]] = !{i32 -460921415}
 // CHECK: ![[TYPE3]] = !{i32 -333839615}
diff --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp 
b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
index 309cf8e70b979c..de8f00f415c357 100644
--- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp
+++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
@@ -205,11 +205,13 @@ void llvm::setKCFIType(Module &M, Function &F, StringRef 
MangledType) {
   // Matches CodeGenModule::CreateKCFITypeId in Clang.
   LLVMContext &Ctx = M.getContext();
   MDBuilder MDB(Ctx);
-  F.setMetadata(
-  LLVMContext::MD_kcfi_type,
-  MDNode::get(Ctx, MDB.createConstant(ConstantInt::get(
-   Type::getInt32Ty(Ctx),
-   static_cast(xxHash64(MangledType));
+  std::string Type = MangledType.str();
+  if (M.getModuleFlag("kcfi-normalized"))
+Type += ".normalized";
+  F.setMetadata(LLVMContext::MD_kcfi_type,
+MDNode::get(Ctx, MDB.createConstant(ConstantInt::get(
+ Type::getInt32Ty(Ctx),
+ static_cast(xxHash64(Type));
   // If the module was compiled with -fpatchable-function-entry, ensure
   // we use the same patchable-function-prefix.
   if (auto *MD = mdconst::extract_or_null(

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] Fix KCFI types for generated functions with integer normalization (PR #104826)

2024-08-20 Thread Sami Tolvanen via cfe-commits

https://github.com/samitolvanen updated 
https://github.com/llvm/llvm-project/pull/104826

>From 0f7dfc3f908651a70602f4f64a0ae06616544eeb Mon Sep 17 00:00:00 2001
From: Sami Tolvanen 
Date: Fri, 16 Aug 2024 20:45:05 +
Subject: [PATCH 1/3] Fix KCFI types for generated functions with integer
 normalization

With -fsanitize-cfi-icall-experimental-normalize-integers, Clang
appends ".normalized" to KCFI types in CodeGenModule::CreateKCFITypeId,
which changes type hashes also for functions that don't have integer
types in their signatures. However, llvm::setKCFIType does not take
integer normalization into account, which means LLVM generated
functions with KCFI types, e.g. sanitizer constructors, will fail KCFI
checks when integer normalization is enabled in Clang.

Add a kcfi-normalized module flag to indicate integer normalization is
used, and append ".normalized" to KCFI types also in llvm::setKCFIType
to fix the type mismatch.
---
 clang/lib/CodeGen/CodeGenModule.cpp   |  2 ++
 clang/test/CodeGen/kcfi-normalize.c   |  1 +
 llvm/lib/Transforms/Utils/ModuleUtils.cpp | 12 +++-
 3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 0b61ef0f89989c..7eca77dc9a86fe 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1136,6 +1136,8 @@ void CodeGenModule::Release() {
 
   if (LangOpts.Sanitize.has(SanitizerKind::KCFI)) {
 getModule().addModuleFlag(llvm::Module::Override, "kcfi", 1);
+if (CodeGenOpts.SanitizeCfiICallNormalizeIntegers)
+  getModule().addModuleFlag(llvm::Module::Override, "kcfi-normalized", 1);
 // KCFI assumes patchable-function-prefix is the same for all indirectly
 // called functions. Store the expected offset for code generation.
 if (CodeGenOpts.PatchableFunctionEntryOffset)
diff --git a/clang/test/CodeGen/kcfi-normalize.c 
b/clang/test/CodeGen/kcfi-normalize.c
index 7660c908a7bdd5..62b907dbfb9286 100644
--- a/clang/test/CodeGen/kcfi-normalize.c
+++ b/clang/test/CodeGen/kcfi-normalize.c
@@ -28,6 +28,7 @@ void baz(void (*fn)(int, int, int), int arg1, int arg2, int 
arg3) {
 fn(arg1, arg2, arg3);
 }
 
+// CHECK: ![[#]] = !{i32 4, !"kcfi-normalized", i32 1}
 // CHECK: ![[TYPE1]] = !{i32 -1143117868}
 // CHECK: ![[TYPE2]] = !{i32 -460921415}
 // CHECK: ![[TYPE3]] = !{i32 -333839615}
diff --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp 
b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
index 309cf8e70b979c..de8f00f415c357 100644
--- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp
+++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
@@ -205,11 +205,13 @@ void llvm::setKCFIType(Module &M, Function &F, StringRef 
MangledType) {
   // Matches CodeGenModule::CreateKCFITypeId in Clang.
   LLVMContext &Ctx = M.getContext();
   MDBuilder MDB(Ctx);
-  F.setMetadata(
-  LLVMContext::MD_kcfi_type,
-  MDNode::get(Ctx, MDB.createConstant(ConstantInt::get(
-   Type::getInt32Ty(Ctx),
-   static_cast(xxHash64(MangledType));
+  std::string Type = MangledType.str();
+  if (M.getModuleFlag("kcfi-normalized"))
+Type += ".normalized";
+  F.setMetadata(LLVMContext::MD_kcfi_type,
+MDNode::get(Ctx, MDB.createConstant(ConstantInt::get(
+ Type::getInt32Ty(Ctx),
+ static_cast(xxHash64(Type));
   // If the module was compiled with -fpatchable-function-entry, ensure
   // we use the same patchable-function-prefix.
   if (auto *MD = mdconst::extract_or_null(

>From d4bc7f8c95b116ccf6418f05073efcf2e0de7c90 Mon Sep 17 00:00:00 2001
From: Sami Tolvanen 
Date: Tue, 20 Aug 2024 18:23:11 +
Subject: [PATCH 2/3] amend! Fix KCFI types for generated functions with
 integer normalization

Fix KCFI types for generated functions with integer normalization

With -fsanitize-cfi-icall-experimental-normalize-integers, Clang
appends ".normalized" to KCFI types in CodeGenModule::CreateKCFITypeId,
which changes type hashes also for functions that don't have integer
types in their signatures. However, llvm::setKCFIType does not take
integer normalization into account, which means LLVM generated
functions with KCFI types, e.g. sanitizer constructors, will fail KCFI
checks when integer normalization is enabled in Clang.

Add a cfi-normalize-integers module flag to indicate integer
normalization is used, and append ".normalized" to KCFI types also in
llvm::setKCFIType to fix the type mismatch.
---
 clang/lib/CodeGen/CodeGenModule.cpp   | 7 +--
 clang/test/CodeGen/kcfi-normalize.c   | 2 +-
 llvm/lib/Transforms/Utils/ModuleUtils.cpp | 2 +-
 3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 7eca77dc9a86fe..0d3b896af8aa39 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1134,10 +1134,13

[clang] [llvm] Fix KCFI types for generated functions with integer normalization (PR #104826)

2024-08-20 Thread Sami Tolvanen via cfe-commits

samitolvanen wrote:

> How about changing the module flag name to "cfi-normalize-integers" to be 
> more consistent with the naming convention used

Sure, renamed.


https://github.com/llvm/llvm-project/pull/104826
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] Fix KCFI types for generated functions with integer normalization (PR #104826)

2024-08-20 Thread Sami Tolvanen via cfe-commits

samitolvanen wrote:

> LG. It's best to have a test for the LLVM generated function, not just reuse 
> kcfi-normalize.c whose module flags could be puzzling for readers.

I think we still need to test that Clang adds the module flag, but I added 
another test for the GCOV functions to make sure the hash is expected with and 
without integer normalization. PTAL.

https://github.com/llvm/llvm-project/pull/104826
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] Fix KCFI types for generated functions with integer normalization (PR #104826)

2024-08-20 Thread Sami Tolvanen via cfe-commits

https://github.com/samitolvanen closed 
https://github.com/llvm/llvm-project/pull/104826
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] Fix KCFI types for generated functions with integer normalization (PR #104826)

2024-10-28 Thread Sami Tolvanen via cfe-commits

samitolvanen wrote:

/cherry-pick e1c36bde0551977d4b2efae032af6dfc4b2b3936

https://github.com/llvm/llvm-project/pull/104826
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] Fix KCFI types for generated functions with integer normalization (PR #104826)

2024-10-28 Thread Sami Tolvanen via cfe-commits

samitolvanen wrote:

It would be nice to get this cherry-picked to 19.x, so the Rust kernel folks 
don't have to wait for LLVM 20: 
https://lore.kernel.org/lkml/202410281414.c351044e-oliver.s...@intel.com/

https://github.com/llvm/llvm-project/pull/104826
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] Fix KCFI types for generated functions with integer normalization (PR #104826)

2024-10-28 Thread Sami Tolvanen via cfe-commits

https://github.com/samitolvanen milestoned 
https://github.com/llvm/llvm-project/pull/104826
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] Fix KCFI types for generated functions with integer normalization (PR #104826)

2024-10-28 Thread Sami Tolvanen via cfe-commits

samitolvanen wrote:

/cherry-pick e1c36bde0551977d4b2efae032af6dfc4b2b3936

https://github.com/llvm/llvm-project/pull/104826
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [X86] Enhance kCFI type IDs with a 3-bit arity indicator. (PR #117121)

2024-11-25 Thread Sami Tolvanen via cfe-commits

samitolvanen wrote:

While this overall looks like a nice improvement to me, changing the hashing 
scheme is going to break compatibility with Rust. I would suggest moving this 
change behind a command line flag, so the kernel can choose to enable it only 
if Rust support isn't enabled, or if we have a rustc that also supports this 
hashing scheme.

https://github.com/llvm/llvm-project/pull/117121
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [X86] Enhance kCFI type IDs with a 3-bit arity indicator. (PR #117121)

2024-11-25 Thread Sami Tolvanen via cfe-commits

samitolvanen wrote:

> Actually, I think this code was introduced to address a compatibility issue 
> with KASAN, which apparently must generate KCFI-enabled code without clang. I 
> found this explanation at 
> [3b14862](https://github.com/llvm/llvm-project/commit/3b14862f0a968dc079530acbce4f2ca4aa7c1492)
>  and 
> [ClangBuiltLinux/linux#1742](https://github.com/ClangBuiltLinux/linux/issues/1742).

Yes, this is needed for LLVM generated functions in general. KASAN is one use 
case, GCOV is another.


https://github.com/llvm/llvm-project/pull/117121
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [X86] Enhance kCFI type IDs with a 3-bit arity indicator. (PR #117121)

2024-11-26 Thread Sami Tolvanen via cfe-commits

samitolvanen wrote:

> Sami, I'm guessing you're mainly talking about rustc and clang needing to use 
> llvm versions that agree on the kCFI implementation in use?

Correct. Both compilers must use the same hashing scheme for cross-language 
indirect calls to work, so unconditionally changing how X86 type hashes are 
calculated in Clang breaks compatibility with current versions of rustc. Using 
compiler versions to figure out which scheme is being used is tedious, so we 
should have a better way to figure this out in Kconfig.

> Either way, it would be nice to have some way to set the hashing method being 
> used, or at least, a way to query which hashing strategy is used. We are 
> going to want logic in Kconfig to ensure that rustc and clang use the same 
> strategy, or at least a way to detect when they don't so we can fail the 
> build with a good error message.

Exactly. I would prefer to have a command line option for this, perhaps 
something similar to 
[-fsanitize-cfi-icall-experimental-normalize-integers](https://clang.llvm.org/docs/ControlFlowIntegrity.html#fsanitize-cfi-icall-experimental-normalize-integers),
 or even a flag that accepts the scheme to use as an argument. As long as we 
default to the original scheme to avoid breaking compatibility with other KCFI 
implementations.

https://github.com/llvm/llvm-project/pull/117121
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [X86] Enhance kCFI type IDs with a 3-bit arity indicator. (PR #117121)

2024-11-26 Thread Sami Tolvanen via cfe-commits

samitolvanen wrote:

> > AFAIK the use case for KCFI is very narrow: the x86-64 Linux kernel.
> 
> At the very least, it's also used in the arm64 Linux Kernel.

Linux also supports KCFI on 32-bit ARM and RISC-V. However, this change seems 
to only affect X86.

https://github.com/llvm/llvm-project/pull/117121
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [X86] Extend kCFI with a 3-bit arity indicator (PR #121070)

2025-02-03 Thread Sami Tolvanen via cfe-commits

https://github.com/samitolvanen approved this pull request.

Thank you for adding the command line flag. I agree that this should be 
sufficient to address compatibility concerns.

https://github.com/llvm/llvm-project/pull/121070
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [X86] Extend kCFI with a 3-bit arity indicator (PR #121070)

2025-01-10 Thread Sami Tolvanen via cfe-commits


@@ -254,6 +254,7 @@ FEATURE(is_trivially_constructible, LangOpts.CPlusPlus)
 FEATURE(is_trivially_copyable, LangOpts.CPlusPlus)
 FEATURE(is_union, LangOpts.CPlusPlus)
 FEATURE(kcfi, LangOpts.Sanitize.has(SanitizerKind::KCFI))
+FEATURE(kcfi_x86_arity, LangOpts.Sanitize.has(SanitizerKind::KCFI))

samitolvanen wrote:

Encoding arity information in the register argument solves the hash 
compatibility issue, so I definitely prefer this approach over 
https://github.com/llvm/llvm-project/pull/117121. As you noted, the FineIBT 
patching code still needs to know whether both compilers emit arity 
information, and while using `__has_feature` in C should be sufficient, how 
would the rustc feature test look like? A quick search didn't find any Kconfig 
examples for this. I assume we would need a Kconfig variable to pass this 
information to C code, but perhaps there are better options?

https://github.com/llvm/llvm-project/pull/121070
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [X86] Extend kCFI with a 3-bit arity indicator (PR #121070)

2025-01-22 Thread Sami Tolvanen via cfe-commits

samitolvanen wrote:

> A gentle reminder to please review this PR.

Overall this looks fine to me, but I was hoping to get an answer to my question 
about how the Kconfig detection is actually going to be implemented: 
https://github.com/llvm/llvm-project/pull/121070#discussion_r1911688455

https://github.com/llvm/llvm-project/pull/121070
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [X86] Extend kCFI with a 3-bit arity indicator (PR #121070)

2025-01-22 Thread Sami Tolvanen via cfe-commits

samitolvanen wrote:

> And AFAIK there's no other users of kCFI besides the Linux kernel (but please 
> correct me if I'm wrong).

There are firmware projects that use KCFI, but AFAIK none of them run on x86. 
I'm also fairly certain that only Linux performs runtime patching based on the 
code sequence we emit, so I'm not particularly concerned about breaking other 
KCFI users with this change.

https://github.com/llvm/llvm-project/pull/121070
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] Support alternative sections for patchable function entries (PR #131230)

2025-03-13 Thread Sami Tolvanen via cfe-commits

https://github.com/samitolvanen created 
https://github.com/llvm/llvm-project/pull/131230

With -fpatchable-function-entry (or the patchable_function_entry function 
attribute), we emit records of patchable entry locations to the 
__patchable_function_entries section. Add an additional parameter to the 
command line option that allows one to specify a different default section name 
for the records, and an identical parameter to the function attribute that 
allows one to override the section used.

The main use case for this change is the Linux kernel using prefix NOPs for 
ftrace, and thus depending on__patchable_function_entries to locate traceable 
functions. Functions that are not traceable currently disable entry NOPs using 
the function attribute, but this creates a compatibility issue with 
-fsanitize=kcfi, which expects all indirectly callable functions to have a type 
hash prefix at the same offset from the function entry.

Adding a section parameter would allow the kernel to distinguish between 
traceable and non-traceable functions by adding entry records to separate 
sections while maintaining a stable function prefix layout for all functions. 
LKML discussion:

https://lore.kernel.org/lkml/y1qezk%2fa41pkl...@hirez.programming.kicks-ass.net/

>From 4b6ab779b3e892ae9b4859fbbc928b6821ea8198 Mon Sep 17 00:00:00 2001
From: Sami Tolvanen 
Date: Thu, 6 Mar 2025 22:59:16 +
Subject: [PATCH] Support alternative sections for patchable function entries

With -fpatchable-function-entry (or the patchable_function_entry
function attribute), we emit records of patchable entry locations to
the __patchable_function_entries section. Add an additional parameter
to the command line option that allows one to specify a different
default section name for the records, and an identical parameter to
the function attribute that allows one to override the section used.

The main use case for this change is the Linux kernel using prefix
NOPs for ftrace, and thus depending on__patchable_function_entries to
locate traceable functions. Functions that are not traceable currently
disable entry NOPs using the function attribute, but this creates a
compatibility issue with -fsanitize=kcfi, which expects all indirectly
callable functions to have a type hash prefix at the same offset from
the function entry.

Adding a section parameter would allow the kernel to distinguish
between traceable and non-traceable functions by adding entry records
to separate sections while maintaining a stable function prefix layout
for all functions. LKML discussion:

https://lore.kernel.org/lkml/y1qezk%2fa41pkl...@hirez.programming.kicks-ass.net/
---
 clang/include/clang/Basic/Attr.td |  3 +-
 clang/include/clang/Basic/AttrDocs.td | 10 +++--
 clang/include/clang/Basic/CodeGenOptions.h|  4 ++
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/include/clang/Driver/Options.td | 19 +++--
 clang/lib/CodeGen/CodeGenFunction.cpp |  6 +++
 clang/lib/Driver/ToolChains/Clang.cpp |  8 +++-
 clang/lib/Sema/SemaDeclAttr.cpp   | 24 +--
 .../patchable-function-entry-section.c| 41 +++
 clang/test/Driver/fpatchable-function-entry.c |  3 ++
 .../test/Sema/patchable-function-entry-attr.c |  8 +++-
 llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp| 12 --
 llvm/lib/IR/Verifier.cpp  |  5 +++
 .../CodeGen/X86/patchable-function-entry.ll   | 13 ++
 .../invalid-patchable-function-entry.ll   |  4 ++
 15 files changed, 146 insertions(+), 18 deletions(-)
 create mode 100644 clang/test/CodeGen/patchable-function-entry-section.c

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 4d34346460561..19e63ba9c4ad7 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -932,7 +932,8 @@ def PatchableFunctionEntry
"riscv64", "x86", "x86_64", "ppc", "ppc64"]>> {
   let Spellings = [GCC<"patchable_function_entry">];
   let Subjects = SubjectList<[Function, ObjCMethod]>;
-  let Args = [UnsignedArgument<"Count">, DefaultIntArgument<"Offset", 0>];
+  let Args = [UnsignedArgument<"Count">, DefaultIntArgument<"Offset", 0>,
+  StringArgument<"Section", /* optional */ 1>];
   let Documentation = [PatchableFunctionEntryDocs];
 }
 
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 34e7ff9612859..c354d95b515e3 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -6502,10 +6502,12 @@ only N==1 is supported.
 def PatchableFunctionEntryDocs : Documentation {
   let Category = DocCatFunction;
   let Content = [{
-``__attribute__((patchable_function_entry(N,M)))`` is used to generate M NOPs
-before the function entry and N-M NOPs after the function entry. This attribute
-takes precedence over the command line option 
``-fpatchable-function-entry=N,M``.
-``M`` defaults to 0 if omi

[clang] [llvm] Support alternative sections for patchable function entries (PR #131230)

2025-03-13 Thread Sami Tolvanen via cfe-commits

samitolvanen wrote:

@MaskRay here's a draft implementation of the patchable function entry 
extension [discussed in 
LKML](https://lore.kernel.org/lkml/y1qezk%2fa41pkl...@hirez.programming.kicks-ass.net/)
 a couple of years ago. Could you please take a look and see if this seems 
reasonable?

https://github.com/llvm/llvm-project/pull/131230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] Support alternative sections for patchable function entries (PR #131230)

2025-04-05 Thread Sami Tolvanen via cfe-commits

https://github.com/samitolvanen closed 
https://github.com/llvm/llvm-project/pull/131230
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits