[RFC 01/12] Add documentation for randstruct attributes
Co-authored-by: Cole Nixon Co-authored-by: Connor Kuehl Co-authored-by: James Foster Co-authored-by: Jeff Takahashi Co-authored-by: Jordan Cantrell Co-authored-by: Nikk Forbus Co-authored-by: Tim Pugh --- clang/include/clang/Basic/AttrDocs.td | 45 +++ 1 file changed, 45 insertions(+) diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index a9835cbeeed..a94e995ac14 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -4116,3 +4116,48 @@ it will be automatically applied to overrides if the method is virtual. The attribute can also be written using C++11 syntax: ``[[mig::server_routine]]``. }]; } + +def ClangRandstructDocs : Documentation { + let Category = DocCatVariable; + let Heading = "randomize_layout, no_randomize_layout"; + let Content = [{ +The attributes ``randomize_layout`` and ``no_randomize_layout`` can be applied +to a record. + +``randomize_layout`` instructs the compiler to randomize the memory layout +of the member variables of the record. + +Conversely, ``no_randomize_layout`` is used to indicate that if using the +automatic strucuture selection feature of the Randstruct implementation, the +compiler should not shuffle the members of the record. + +In the event that a record is labeled with both attributes, the compiler will +emit a warning indicating that these two cannot be used on the same record. +The default behavior in this case is to not randomize the struct, as the +attribute ``no_randomize_layout`` takes precedence over ``randomize_layout``. +This is implementation defined behavior. + +.. code-block:: c + + // Indicates that this struct should be randomized by Randstruct implementation. + struct s { +char *a; +char *b; +char *c; + }__attribute__((randomize_layout)); + + // Indicates that this struct should NOT be randomized by Randstruct implementation. + struct s { +char *a; +char *b; +char *c; + }__attribute__((no_randomize_layout)); + + // Emits compiler warning. Struct is NOT randomized by Randstruct implementation. + struct s { +char *a; +char *b; +char *c; + }__attribute__((randomize_layout)) __attribute__((no_randomize_layout)); +}]; +} -- 2.17.1 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[RFC 02/12] Add randomize_layout attribute and handler
Co-authored-by: Cole Nixon Co-authored-by: Connor Kuehl Co-authored-by: James Foster Co-authored-by: Jeff Takahashi Co-authored-by: Jordan Cantrell Co-authored-by: Nikk Forbus Co-authored-by: Tim Pugh --- clang/include/clang/Basic/Attr.td | 7 +++ clang/lib/Sema/SemaDeclAttr.cpp| 3 +++ .../Misc/pragma-attribute-supported-attributes-list.test | 1 + 3 files changed, 11 insertions(+) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 523b89d0fcc..2d44d14ad6d 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3214,3 +3214,10 @@ def ObjCExternallyRetained : InheritableAttr { let Subjects = SubjectList<[NonParmVar, Function, Block, ObjCMethod]>; let Documentation = [ObjCExternallyRetainedDocs]; } + +def RandomizeLayout : InheritableAttr { + let Spellings = [GCC<"randomize_layout">, Declspec<"randomize_layout">, +Keyword<"randomize_layout">]; + let Subjects = SubjectList<[Record]>; + let Documentation = [ClangRandstructDocs]; +} diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index c97d0bc819f..5de9125b44f 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6966,6 +6966,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleSimpleAttributeWithExclusions(S, D, AL); break; + case ParsedAttr::AT_RandomizeLayout: +handleSimpleAttribute(S, D, AL); +break; case ParsedAttr::AT_CodeSeg: handleCodeSegAttr(S, D, AL); break; diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 9a7e65d2b24..b4bc1b3112f 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -118,6 +118,7 @@ // CHECK-NEXT: Overloadable (SubjectMatchRule_function) // CHECK-NEXT: ParamTypestate (SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: PassObjectSize (SubjectMatchRule_variable_is_parameter) +// CHECK-NEXT: RandomizeLayout (SubjectMatchRule_record) // CHECK-NEXT: RenderScriptKernel (SubjectMatchRule_function) // CHECK-NEXT: ReqdWorkGroupSize (SubjectMatchRule_function) // CHECK-NEXT: RequireConstantInit (SubjectMatchRule_variable_is_global) -- 2.17.1 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[RFC 00/12] Introduce struct layout randomization feature
This patch set introduces structure field layout randomization into the Clang compiler. The Randstruct feature is a compile-time hardening technique that randomizes the field layout for designated structures of a code base. Admittedly, this is mostly useful for closed-source releases of code (since the randomization seed would be available for public and open source application s). However, this patch set also enhances Clang’s feature parity with that of GCC which already has the Randstruct feature. This patch set is a from-scratch reimplementation of the Randstruct feature that was originally ported to GCC. The patches for this implementation in GCC can be found here: https://www.openwall.com/lists/kernel-hardening/2017/04/06/14. This feature identifies structures for randomization in two ways. The first method targets structures that are manually marked with the new “randomize_layout” attribute. The second is an optional feature that will automatically select and randomize structures that are found to consist entirely of function pointers. This automatic selection feature can be extended to include other vulnerable structure types that are safe to randomize as they are identified. You can also opt a specific structure out of this feature with the “no_randomize_layout” attribute. Automatic structure selection is enabled with the “-randstruct-auto” compiler flag. By default, Randstruct seeds on the empty string, but a seed can be supplied with the “-randstruct-seed=” command line argument. This entire patch set is the sum total of an undergraduate computer science capstone team’s effort. Portland State University Clang Randstruct Capstone Team (Fall 2018-Winter 2019): Co-authored-by: Cole Nixon Co-authored-by: Connor Kuehl Co-authored-by: James Foster Co-authored-by: Jeff Takahashi Co-authored-by: Jordan Cantrell Co-authored-by: Nikk Forbus Co-authored-by: Tim Pugh Connor Kuehl (12): Add documentation for randstruct attributes Add randomize_layout attribute and handler Add no_randomize_layout attribute and handler Add randomize_layout warning for unions Add warning for mutually exclusive attributes Add globals to store command line arguments in Add randstruct-seed compiler argument Add automatic structure selection compiler switch Implement record field randomization algorithms Fix: Set tail pointer to null in field list Forward declare RecordFieldReorganizer Wire up Randstruct; intercept and randomize clang/include/clang/AST/Decl.h| 1 + clang/include/clang/AST/DeclBase.h| 2 + clang/include/clang/AST/RandstructSeed.h | 8 + .../clang/AST/RecordFieldReorganizer.h| 59 clang/include/clang/Basic/Attr.td | 14 + clang/include/clang/Basic/AttrDocs.td | 45 +++ .../include/clang/Basic/DiagnosticASTKinds.td | 5 + clang/include/clang/Driver/CC1Options.td | 2 + clang/include/clang/Driver/Options.td | 4 + clang/lib/AST/CMakeLists.txt | 1 + clang/lib/AST/DeclBase.cpp| 3 + clang/lib/AST/RecordFieldReorganizer.cpp | 257 ++ clang/lib/AST/RecordLayoutBuilder.cpp | 20 ++ clang/lib/Driver/ToolChains/Clang.cpp | 10 + clang/lib/Frontend/CompilerInvocation.cpp | 8 + clang/lib/Sema/SemaDeclAttr.cpp | 6 + ...a-attribute-supported-attributes-list.test | 2 + 17 files changed, 447 insertions(+) create mode 100644 clang/include/clang/AST/RandstructSeed.h create mode 100644 clang/include/clang/AST/RecordFieldReorganizer.h create mode 100644 clang/lib/AST/RecordFieldReorganizer.cpp -- 2.17.1 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[RFC 03/12] Add no_randomize_layout attribute and handler
Co-authored-by: Cole Nixon Co-authored-by: Connor Kuehl Co-authored-by: James Foster Co-authored-by: Jeff Takahashi Co-authored-by: Jordan Cantrell Co-authored-by: Nikk Forbus Co-authored-by: Tim Pugh --- clang/include/clang/Basic/Attr.td | 7 +++ clang/lib/Sema/SemaDeclAttr.cpp| 3 +++ .../Misc/pragma-attribute-supported-attributes-list.test | 1 + 3 files changed, 11 insertions(+) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 2d44d14ad6d..be1000c2067 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3221,3 +3221,10 @@ def RandomizeLayout : InheritableAttr { let Subjects = SubjectList<[Record]>; let Documentation = [ClangRandstructDocs]; } + +def NoRandomizeLayout : InheritableAttr { + let Spellings = [GCC<"no_randomize_layout">, Declspec<"no_randomize_layout">, +Keyword<"no_randomize_layout">]; + let Subjects = SubjectList<[Record]>; + let Documentation = [ClangRandstructDocs]; +} diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 5de9125b44f..8e533e13a03 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6969,6 +6969,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_RandomizeLayout: handleSimpleAttribute(S, D, AL); break; + case ParsedAttr::AT_NoRandomizeLayout: +handleSimpleAttribute(S, D, AL); +break; case ParsedAttr::AT_CodeSeg: handleCodeSegAttr(S, D, AL); break; diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index b4bc1b3112f..6bf4dd74a04 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -81,6 +81,7 @@ // CHECK-NEXT: NoInstrumentFunction (SubjectMatchRule_function) // CHECK-NEXT: NoMicroMips (SubjectMatchRule_function) // CHECK-NEXT: NoMips16 (SubjectMatchRule_function) +// CHECK-NEXT: NoRandomizeLayout (SubjectMatchRule_record) // CHECK-NEXT: NoSanitize (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global) // CHECK-NEXT: NoSanitizeSpecific (SubjectMatchRule_function, SubjectMatchRule_variable_is_global) // CHECK-NEXT: NoSpeculativeLoadHardening (SubjectMatchRule_function, SubjectMatchRule_objc_method) -- 2.17.1 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[RFC 04/12] Add randomize_layout warning for unions
There is no technical advantage to randomizing the order fields within unions as they all share the same offset. Co-authored-by: Cole Nixon Co-authored-by: Connor Kuehl Co-authored-by: James Foster Co-authored-by: Jeff Takahashi Co-authored-by: Jordan Cantrell Co-authored-by: Nikk Forbus Co-authored-by: Tim Pugh --- clang/include/clang/Basic/DiagnosticASTKinds.td | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index c2a390fa465..406325d3677 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -343,4 +343,6 @@ def warn_padded_struct_size : Warning< InGroup, DefaultIgnore; def warn_unnecessary_packed : Warning< "packed attribute is unnecessary for %0">, InGroup, DefaultIgnore; +def warn_randomize_attr_union : Warning< + "union declared with 'randomize_layout' attribute">, InGroup>; } -- 2.17.1 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[RFC 07/12] Add randstruct-seed compiler argument
To create reproducible builds, the randstruct feature can (and should) operate on a seed provided at compile time. Co-authored-by: Cole Nixon Co-authored-by: Connor Kuehl Co-authored-by: James Foster Co-authored-by: Jeff Takahashi Co-authored-by: Jordan Cantrell Co-authored-by: Nikk Forbus Co-authored-by: Tim Pugh --- clang/include/clang/Driver/CC1Options.td | 2 ++ clang/include/clang/Driver/Options.td | 1 + clang/lib/Driver/ToolChains/Clang.cpp | 6 ++ clang/lib/Frontend/CompilerInvocation.cpp | 5 + 4 files changed, 14 insertions(+) diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index f4f8fae39e3..541a8e74a0c 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -422,6 +422,8 @@ def fcaret_diagnostics_max_lines : HelpText<"Set the maximum number of source lines to show in a caret diagnostic">; def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"">, HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">; +def randstruct_seed : Separate<["-"], "randstruct-seed">, MetaVarName<"">, + HelpText<"Randomization seed for random struct layouts">; def verify_EQ : CommaJoined<["-"], "verify=">, MetaVarName<"">, HelpText<"Verify diagnostic output using comment directives that start with" diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 81e4ce75b02..735ec11e221 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1267,6 +1267,7 @@ def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">, def fmerge_all_constants : Flag<["-"], "fmerge-all-constants">, Group, Flags<[CC1Option, CoreOption]>, HelpText<"Allow merging of constants">; def fmessage_length_EQ : Joined<["-"], "fmessage-length=">, Group; +def randstruct_seed_EQ : Joined<["-"], "randstruct-seed=">, Group; def fms_extensions : Flag<["-"], "fms-extensions">, Group, Flags<[CC1Option, CoreOption]>, HelpText<"Accept some non-standard constructs supported by the Microsoft compiler">; def fms_compatibility : Flag<["-"], "fms-compatibility">, Group, Flags<[CC1Option, CoreOption]>, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 3bc7412911b..52daed9fe36 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4427,6 +4427,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(Twine(N))); } + // -randstruct-seed parent process + if (Arg *A = Args.getLastArg(options::OPT_randstruct_seed_EQ)) { +CmdArgs.push_back( "-randstruct-seed" ); +CmdArgs.push_back(A->getValue(0)); + } + // -fvisibility= and -fvisibility-ms-compat are of a piece. if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ, options::OPT_fvisibility_ms_compat)) { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 1cd1cb1ff47..b4423dabbe7 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -6,6 +6,7 @@ // //===--===// +#include "clang/AST/RandstructSeed.h" #include "clang/Frontend/CompilerInvocation.h" #include "TestModuleFileExtension.h" #include "clang/Basic/Builtins.h" @@ -1673,6 +1674,10 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::PluginAction; Opts.ActionName = A->getValue(); } + // child process handle arguments + if (const Arg* A = Args.getLastArg(OPT_randstruct_seed)) { +RandstructSeed = A->getValue(0); + } Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin); for (const auto *AA : Args.filtered(OPT_plugin_arg)) Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1)); -- 2.17.1 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[RFC 06/12] Add globals to store command line arguments in
Co-authored-by: Cole Nixon Co-authored-by: Connor Kuehl Co-authored-by: James Foster Co-authored-by: Jeff Takahashi Co-authored-by: Jordan Cantrell Co-authored-by: Nikk Forbus Co-authored-by: Tim Pugh --- clang/include/clang/AST/RandstructSeed.h | 8 clang/lib/AST/CMakeLists.txt | 1 + clang/lib/AST/RecordFieldReorganizer.cpp | 19 +++ 3 files changed, 28 insertions(+) create mode 100644 clang/include/clang/AST/RandstructSeed.h create mode 100644 clang/lib/AST/RecordFieldReorganizer.cpp diff --git a/clang/include/clang/AST/RandstructSeed.h b/clang/include/clang/AST/RandstructSeed.h new file mode 100644 index 000..eefdd8916f4 --- /dev/null +++ b/clang/include/clang/AST/RandstructSeed.h @@ -0,0 +1,8 @@ +#ifndef RANDSTRUCTSEED_H +#define RANDSTRUCTSEED_H +#include +namespace clang { +extern std::string RandstructSeed; +extern bool RandstructAutoSelect; +} +#endif diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index 570ca718acf..08acf687971 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -44,6 +44,7 @@ add_clang_library(clangAST InheritViz.cpp ItaniumCXXABI.cpp ItaniumMangle.cpp + RecordFieldReorganizer.cpp Mangle.cpp MicrosoftCXXABI.cpp MicrosoftMangle.cpp diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp new file mode 100644 index 000..c7ab9cd16d4 --- /dev/null +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -0,0 +1,19 @@ +//===- RecordFieldReorganizer.cpp - Implementation for field reorder -*- C++ +//-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// Contains the implementation for RecordDecl field reordering. +// +//===--===// + +#include "clang/AST/RandstructSeed.h" + +namespace clang { +std::string RandstructSeed = ""; +bool RandstructAutoSelect = false; +} // namespace clang -- 2.17.1 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[RFC 05/12] Add warning for mutually exclusive attributes
Co-authored-by: Cole Nixon Co-authored-by: Connor Kuehl Co-authored-by: James Foster Co-authored-by: Jeff Takahashi Co-authored-by: Jordan Cantrell Co-authored-by: Nikk Forbus Co-authored-by: Tim Pugh --- clang/include/clang/Basic/DiagnosticASTKinds.td | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index 406325d3677..e0970a7b145 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -345,4 +345,7 @@ def warn_unnecessary_packed : Warning< "packed attribute is unnecessary for %0">, InGroup, DefaultIgnore; def warn_randomize_attr_union : Warning< "union declared with 'randomize_layout' attribute">, InGroup>; +def warn_randomize_attr_conflict : Warning< + "struct declared with 'randomize_layout' and 'no_randomize_layout' attributes; " + "attribute 'no_randomize_layout' takes precedence">, InGroup>; } -- 2.17.1 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[RFC 12/12] Wire up Randstruct; intercept and randomize
Co-authored-by: Cole Nixon Co-authored-by: Connor Kuehl Co-authored-by: James Foster Co-authored-by: Jeff Takahashi Co-authored-by: Jordan Cantrell Co-authored-by: Nikk Forbus Co-authored-by: Tim Pugh --- clang/lib/AST/RecordLayoutBuilder.cpp | 20 1 file changed, 20 insertions(+) diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 99b7cbd0224..4bdf467db4d 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -6,6 +6,7 @@ // //===--===// +#include "clang/AST/RandstructSeed.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" @@ -15,6 +16,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" +#include "clang/AST/RecordFieldReorganizer.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/SmallSet.h" #include "llvm/Support/Format.h" @@ -2984,6 +2986,24 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { const ASTRecordLayout *NewEntry = nullptr; + bool ShouldBeRandomized = D->getAttr() != nullptr; + bool NotToBeRandomized = D->getAttr() != nullptr; + bool AutoSelectable = RandstructAutoSelect && Randstruct::isTriviallyRandomizable(D); + + if (ShouldBeRandomized && NotToBeRandomized) { +getDiagnostics().Report(D->getLocation(), diag::warn_randomize_attr_conflict); + } + + if (ShouldBeRandomized && D->isUnion()) { + getDiagnostics().Report(D->getLocation(), diag::warn_randomize_attr_union); + NotToBeRandomized = true; + } + + if (!NotToBeRandomized && (ShouldBeRandomized || AutoSelectable)) { +Randstruct randstruct(RandstructSeed); +randstruct.reorganizeFields(*this,D); + } + if (isMsLayout(*this)) { MicrosoftRecordLayoutBuilder Builder(*this); if (const auto *RD = dyn_cast(D)) { -- 2.17.1 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[RFC 08/12] Add automatic structure selection compiler switch
This compiler switch allows the Randstruct feature to automatically select structures to randomize even if they're not decorated with the randomize_layout attribute. Structures can "opt out" of selection by using the no_randomize_layout attribute while this feature is active. Co-authored-by: Cole Nixon Co-authored-by: Connor Kuehl Co-authored-by: James Foster Co-authored-by: Jeff Takahashi Co-authored-by: Jordan Cantrell Co-authored-by: Nikk Forbus Co-authored-by: Tim Pugh --- clang/include/clang/Driver/Options.td | 3 +++ clang/lib/Driver/ToolChains/Clang.cpp | 4 clang/lib/Frontend/CompilerInvocation.cpp | 3 +++ 3 files changed, 10 insertions(+) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 735ec11e221..33bc2e1bb58 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1760,6 +1760,9 @@ def freroll_loops : Flag<["-"], "freroll-loops">, Group, HelpText<"Turn on loop reroller">, Flags<[CC1Option]>; def fno_reroll_loops : Flag<["-"], "fno-reroll-loops">, Group, HelpText<"Turn off loop reroller">; +def randstruct_auto : Flag<["-"], "randstruct-auto">, + HelpText<"Enable automatic structure selection for field randomization; " + "Disable for specific structures with attribute no_randomize_layout">, Flags<[CC1Option]>; def ftrigraphs : Flag<["-"], "ftrigraphs">, Group, HelpText<"Process trigraph sequences">, Flags<[CC1Option]>; def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 52daed9fe36..bfc383b8d78 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4433,6 +4433,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue(0)); } + if (Arg *A = Args.getLastArg(options::OPT_randstruct_auto)) { +CmdArgs.push_back( "-randstruct-auto" ); + } + // -fvisibility= and -fvisibility-ms-compat are of a piece. if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ, options::OPT_fvisibility_ms_compat)) { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index b4423dabbe7..c3f4ea83d6c 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1678,6 +1678,9 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, if (const Arg* A = Args.getLastArg(OPT_randstruct_seed)) { RandstructSeed = A->getValue(0); } + if (const Arg* A = Args.getLastArg(OPT_randstruct_auto)) { +RandstructAutoSelect = true; + } Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin); for (const auto *AA : Args.filtered(OPT_plugin_arg)) Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1)); -- 2.17.1 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[RFC 11/12] Forward declare RecordFieldReorganizer
Co-authored-by: Cole Nixon Co-authored-by: Connor Kuehl Co-authored-by: James Foster Co-authored-by: Jeff Takahashi Co-authored-by: Jordan Cantrell Co-authored-by: Nikk Forbus Co-authored-by: Tim Pugh --- clang/include/clang/AST/Decl.h | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 2499efb8499..adf52c22283 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -65,6 +65,7 @@ class Module; class NamespaceDecl; class ParmVarDecl; class RecordDecl; +class RecordFieldReorganizer; class Stmt; class StringLiteral; class TagDecl; -- 2.17.1 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[RFC 09/12] Implement record field randomization algorithms
Co-authored-by: Cole Nixon Co-authored-by: Connor Kuehl Co-authored-by: James Foster Co-authored-by: Jeff Takahashi Co-authored-by: Jordan Cantrell Co-authored-by: Nikk Forbus Co-authored-by: Tim Pugh --- clang/include/clang/AST/DeclBase.h| 2 + .../clang/AST/RecordFieldReorganizer.h| 59 + clang/lib/AST/RecordFieldReorganizer.cpp | 238 ++ 3 files changed, 299 insertions(+) create mode 100644 clang/include/clang/AST/RecordFieldReorganizer.h diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 4b63e540d5d..b08acadc9ff 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -1270,6 +1270,8 @@ class DeclContext { friend class ExternalASTSource; /// For CreateStoredDeclsMap friend class DependentDiagnostic; + /// For fine-grained control of field order + friend class RecordFieldReorganizer; /// For hasNeedToReconcileExternalVisibleStorage, /// hasLazyLocalLexicalLookups, hasLazyExternalLexicalLookups friend class ASTWriter; diff --git a/clang/include/clang/AST/RecordFieldReorganizer.h b/clang/include/clang/AST/RecordFieldReorganizer.h new file mode 100644 index 000..fa29014348f --- /dev/null +++ b/clang/include/clang/AST/RecordFieldReorganizer.h @@ -0,0 +1,59 @@ +//===-- RecordFieldReorganizer.h - Interface for manipulating field order --*- +// C++ +//-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This header file contains the base class that defines an interface for +// manipulating a RecordDecl's field layouts. +// +//===--===// + +#ifndef LLVM_CLANG_LIB_AST_RECORDFIELDREORGANIZER_H +#define LLVM_CLANG_LIB_AST_RECORDFIELDREORGANIZER_H + +#include "Decl.h" +#include + +namespace clang { + +// FIXME: Find a better alternative to SmallVector with hardcoded size! + +class RecordFieldReorganizer { +public: + virtual ~RecordFieldReorganizer() = default; + void reorganizeFields(const ASTContext &C, const RecordDecl *D); + +protected: + virtual void reorganize(const ASTContext &C, const RecordDecl *D, + SmallVector &NewOrder) = 0; + +private: + void commit(const RecordDecl *D, + SmallVectorImpl &NewFieldOrder) const; +}; + +class Randstruct : public RecordFieldReorganizer { +public: + Randstruct(std::string seed) : Seq(seed.begin(), seed.end()), rng(Seq) {} + + /// Determines if the Record can be safely and easily randomized based on certain criteria (see implementation). + static bool isTriviallyRandomizable(const RecordDecl *D); +protected: + SmallVector randomize(SmallVector fields); + SmallVector perfrandomize(const ASTContext &ctx, + SmallVector fields); + virtual void reorganize(const ASTContext &C, const RecordDecl *D, + SmallVector &NewOrder) override; +private: + std::seed_seq Seq; + std::default_random_engine rng; +}; + +} // namespace clang + +#endif diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index c7ab9cd16d4..a37490d5784 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -11,9 +11,247 @@ // //===--===// +#include "clang/AST/RecordFieldReorganizer.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/RandstructSeed.h" +#include +#include +#include +#include +#include + +// FIXME: Find a better alternative to SmallVector with hardcoded size! + namespace clang { std::string RandstructSeed = ""; bool RandstructAutoSelect = false; + +void RecordFieldReorganizer::reorganizeFields(const ASTContext &C, + const RecordDecl *D) { + // Save original fields for asserting later that a subclass hasn't + // sabotaged the RecordDecl by removing or adding fields + std::set mutateGuard; + + SmallVector fields; + for (auto f : D->fields()) { +mutateGuard.insert(f); +fields.push_back(f); + } + // Now allow subclass implementations to reorder the fields + reorganize(C, D, fields); + + // Assert all fields are still present + assert(mutateGuard.size() == fields.size() && + "Field count altered after reorganization"); + for (auto f : fields) { +auto found = std::find(std::begin(mutateGuard), std::end(mutateGuard), f); +assert(found != std::end(mutateGuard) && + "Unknown field encountered after reorganization"); + } + + commit(D, fields); +} +void RecordFieldReorganizer::commit( +const RecordDecl *D, SmallVectorImpl &NewFieldOrder) const { +
[RFC 10/12] Fix: Set tail pointer to null in field list
Co-authored-by: Cole Nixon Co-authored-by: Connor Kuehl Co-authored-by: James Foster Co-authored-by: Jeff Takahashi Co-authored-by: Jordan Cantrell Co-authored-by: Nikk Forbus Co-authored-by: Tim Pugh --- clang/lib/AST/DeclBase.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index e1b5161b027..2694d596755 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -1258,6 +1258,9 @@ DeclContext::BuildDeclChain(ArrayRef Decls, PrevDecl = D; } + // The last one in the chain should have a null next! + PrevDecl->NextInContextAndBits.setPointer(nullptr); + return std::make_pair(FirstNewDecl, PrevDecl); } -- 2.17.1 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [RFC 00/12] Introduce struct layout randomization feature
Thank you for the heads up! I put the patchset on Phabricator and sent the RFC out to the cfe-dev mailing list. On 3/9/19 1:59 AM, Roman Lebedev wrote: You probably want to submit this patchset to phabricator. It will get lost in mailing list. On Sat, Mar 9, 2019 at 1:38 AM Connor Kuehl via cfe-commits wrote: This patch set introduces structure field layout randomization into the Clang compiler. The Randstruct feature is a compile-time hardening technique that randomizes the field layout for designated structures of a code base. Admittedly, this is mostly useful for closed-source releases of code (since the randomization seed would be available for public and open source application s). However, this patch set also enhances Clang’s feature parity with that of GCC which already has the Randstruct feature. This patch set is a from-scratch reimplementation of the Randstruct feature that was originally ported to GCC. The patches for this implementation in GCC can be found here: https://www.openwall.com/lists/kernel-hardening/2017/04/06/14. This feature identifies structures for randomization in two ways. The first method targets structures that are manually marked with the new “randomize_layout” attribute. The second is an optional feature that will automatically select and randomize structures that are found to consist entirely of function pointers. This automatic selection feature can be extended to include other vulnerable structure types that are safe to randomize as they are identified. You can also opt a specific structure out of this feature with the “no_randomize_layout” attribute. Automatic structure selection is enabled with the “-randstruct-auto” compiler flag. By default, Randstruct seeds on the empty string, but a seed can be supplied with the “-randstruct-seed=” command line argument. This entire patch set is the sum total of an undergraduate computer science capstone team’s effort. Portland State University Clang Randstruct Capstone Team (Fall 2018-Winter 2019): Co-authored-by: Cole Nixon Co-authored-by: Connor Kuehl Co-authored-by: James Foster Co-authored-by: Jeff Takahashi Co-authored-by: Jordan Cantrell Co-authored-by: Nikk Forbus Co-authored-by: Tim Pugh Connor Kuehl (12): Add documentation for randstruct attributes Add randomize_layout attribute and handler Add no_randomize_layout attribute and handler Add randomize_layout warning for unions Add warning for mutually exclusive attributes Add globals to store command line arguments in Add randstruct-seed compiler argument Add automatic structure selection compiler switch Implement record field randomization algorithms Fix: Set tail pointer to null in field list Forward declare RecordFieldReorganizer Wire up Randstruct; intercept and randomize clang/include/clang/AST/Decl.h| 1 + clang/include/clang/AST/DeclBase.h| 2 + clang/include/clang/AST/RandstructSeed.h | 8 + .../clang/AST/RecordFieldReorganizer.h| 59 clang/include/clang/Basic/Attr.td | 14 + clang/include/clang/Basic/AttrDocs.td | 45 +++ .../include/clang/Basic/DiagnosticASTKinds.td | 5 + clang/include/clang/Driver/CC1Options.td | 2 + clang/include/clang/Driver/Options.td | 4 + clang/lib/AST/CMakeLists.txt | 1 + clang/lib/AST/DeclBase.cpp| 3 + clang/lib/AST/RecordFieldReorganizer.cpp | 257 ++ clang/lib/AST/RecordLayoutBuilder.cpp | 20 ++ clang/lib/Driver/ToolChains/Clang.cpp | 10 + clang/lib/Frontend/CompilerInvocation.cpp | 8 + clang/lib/Sema/SemaDeclAttr.cpp | 6 + ...a-attribute-supported-attributes-list.test | 2 + 17 files changed, 447 insertions(+) create mode 100644 clang/include/clang/AST/RandstructSeed.h create mode 100644 clang/include/clang/AST/RecordFieldReorganizer.h create mode 100644 clang/lib/AST/RecordFieldReorganizer.cpp -- 2.17.1 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits