[RFC 01/12] Add documentation for randstruct attributes

2019-03-08 Thread Connor Kuehl via cfe-commits
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

2019-03-08 Thread Connor Kuehl via cfe-commits
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

2019-03-08 Thread Connor Kuehl via cfe-commits
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

2019-03-08 Thread Connor Kuehl via cfe-commits
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

2019-03-08 Thread Connor Kuehl via cfe-commits
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

2019-03-08 Thread Connor Kuehl via cfe-commits
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

2019-03-08 Thread Connor Kuehl via cfe-commits
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

2019-03-08 Thread Connor Kuehl via cfe-commits
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

2019-03-08 Thread Connor Kuehl via cfe-commits
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

2019-03-08 Thread Connor Kuehl via cfe-commits
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

2019-03-08 Thread Connor Kuehl via cfe-commits
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

2019-03-08 Thread Connor Kuehl via cfe-commits
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

2019-03-08 Thread Connor Kuehl via cfe-commits
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

2019-03-12 Thread Connor Kuehl via cfe-commits
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