[sanitizer] Implement a __asan_default_options() equivalent for Scudo
authorKostya Serebryany <kcc@google.com>
Tue, 2 Aug 2016 22:25:38 +0000 (22:25 +0000)
committerKostya Serebryany <kcc@google.com>
Tue, 2 Aug 2016 22:25:38 +0000 (22:25 +0000)
Summary:
Currently, the Scudo Hardened Allocator only gets its flags via the SCUDO_OPTIONS environment variable.
With this patch, we offer the opportunity for programs to define their own options via __scudo_default_options() which behaves like __asan_default_options() (weak symbol).
A relevant test has been added as well, and the documentation updated accordingly.
I also used this patch as an opportunity to rename a few variables to comply with the LLVM naming scheme, and replaced a use of Report with dieWithMessage for consistency (and to avoid a callback).

Reviewers: llvm-commits, kcc

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

llvm-svn: 277536

compiler-rt/lib/scudo/scudo_allocator.cpp
compiler-rt/lib/scudo/scudo_flags.cpp
compiler-rt/lib/scudo/scudo_termination.cpp
compiler-rt/lib/scudo/scudo_utils.cpp
compiler-rt/test/scudo/options.cpp [new file with mode: 0644]
llvm/docs/ScudoHardenedAllocator.rst

index 3ad499a..ceb7bbd 100644 (file)
@@ -76,7 +76,7 @@ struct UnpackedHeader {
   u64 Offset        : 20; // Offset from the beginning of the backend
                           // allocation to the beginning chunk itself, in
                           // multiples of MinAlignment. See comment about its
-                          // maximum value and test in Initialize.
+                          // maximum value and test in init().
   u64 Unused_1_     : 28;
   u16 Salt          : 16;
 };
index 430dcd2..f0d2088 100644 (file)
 #include "sanitizer_common/sanitizer_flags.h"
 #include "sanitizer_common/sanitizer_flag_parser.h"
 
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+const char* __scudo_default_options();
+
 namespace __scudo {
 
-Flags scudo_flags_dont_use_directly;  // use via flags().
+Flags ScudoFlags;  // Use via getFlags().
 
 void Flags::setDefaults() {
 #define SCUDO_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
@@ -34,6 +37,10 @@ static void RegisterScudoFlags(FlagParser *parser, Flags *f) {
 #undef SCUDO_FLAG
 }
 
+static const char *callGetScudoDefaultOptions() {
+  return (&__scudo_default_options) ? __scudo_default_options() : "";
+}
+
 void initFlags() {
   SetCommonFlagsDefaults();
   {
@@ -45,11 +52,16 @@ void initFlags() {
   Flags *f = getFlags();
   f->setDefaults();
 
-  FlagParser scudo_parser;
-  RegisterScudoFlags(&scudo_parser, f);
-  RegisterCommonFlags(&scudo_parser);
+  FlagParser ScudoParser;
+  RegisterScudoFlags(&ScudoParser, f);
+  RegisterCommonFlags(&ScudoParser);
+
+  // Override from user-specified string.
+  const char *ScudoDefaultOptions = callGetScudoDefaultOptions();
+  ScudoParser.ParseString(ScudoDefaultOptions);
 
-  scudo_parser.ParseString(GetEnv("SCUDO_OPTIONS"));
+  // Override from environment.
+  ScudoParser.ParseString(GetEnv("SCUDO_OPTIONS"));
 
   InitializeCommonFlags();
 
@@ -75,7 +87,7 @@ void initFlags() {
 }
 
 Flags *getFlags() {
-  return &scudo_flags_dont_use_directly;
+  return &ScudoFlags;
 }
 
 }
index 32421d3..a533383 100644 (file)
 ///
 //===----------------------------------------------------------------------===//
 
+#include "scudo_utils.h"
+
 #include "sanitizer_common/sanitizer_common.h"
 
 namespace __sanitizer {
 
-bool AddDieCallback(DieCallbackType callback) { return true; }
+bool AddDieCallback(DieCallbackType Callback) { return true; }
 
-bool RemoveDieCallback(DieCallbackType callback) { return true; }
+bool RemoveDieCallback(DieCallbackType Callback) { return true; }
 
-void SetUserDieCallback(DieCallbackType callback) {}
+void SetUserDieCallback(DieCallbackType Callback) {}
 
 void NORETURN Die() {
   if (common_flags()->abort_on_error)
@@ -31,11 +33,10 @@ void NORETURN Die() {
 
 void SetCheckFailedCallback(CheckFailedCallbackType callback) {}
 
-void NORETURN CheckFailed(const char *file, int line, const char *cond,
-                          u64 v1, u64 v2) {
-  Report("Sanitizer CHECK failed: %s:%d %s (%lld, %lld)\n", file, line, cond,
-                                                            v1, v2);
-  Die();
+void NORETURN CheckFailed(const char *File, int Line, const char *Condition,
+                          u64 Value1, u64 Value2) {
+  __scudo::dieWithMessage("Scudo CHECK failed: %s:%d %s (%lld, %lld)\n",
+                          File, Line, Condition, Value1, Value2);
 }
 
 } // namespace __sanitizer
index 6b96e84..f45569e 100644 (file)
@@ -33,7 +33,7 @@ extern int VSNPrintf(char *buff, int buff_length, const char *format,
 namespace __scudo {
 
 FORMAT(1, 2)
-void dieWithMessage(const char *Format, ...) {
+void NORETURN dieWithMessage(const char *Format, ...) {
   // Our messages are tiny, 128 characters is more than enough.
   char Message[128];
   va_list Args;
diff --git a/compiler-rt/test/scudo/options.cpp b/compiler-rt/test/scudo/options.cpp
new file mode 100644 (file)
index 0000000..bccf7c8
--- /dev/null
@@ -0,0 +1,25 @@
+// RUN: %clang_scudo %s -o %t
+// RUN:                                              %run %t 2>&1
+// RUN: SCUDO_OPTIONS=DeallocationTypeMismatch=0     %run %t 2>&1
+// RUN: SCUDO_OPTIONS=DeallocationTypeMismatch=1 not %run %t 2>&1 | FileCheck %s
+
+// Tests that the options can be passed using getScudoDefaultOptions, and that
+// the environment ones take precedence over them.
+
+#include <stdlib.h>
+#include <malloc.h>
+
+extern "C" const char* __scudo_default_options() {
+  return "DeallocationTypeMismatch=0";  // Defaults to true in scudo_flags.inc.
+}
+
+int main(int argc, char **argv)
+{
+  int *p = (int *)malloc(16);
+  if (!p)
+    return 1;
+  delete p;
+  return 0;
+}
+
+// CHECK: ERROR: allocation type mismatch on address
index 5bc390e..2c8493a 100644 (file)
@@ -89,10 +89,33 @@ functions.
 
 Options
 -------
-Several aspects of the allocator can be configured through environment options,
-following the usual ASan options syntax, through the variable SCUDO_OPTIONS.
+Several aspects of the allocator can be configured through the following ways:
+
+- by defining a __scudo_default_options function in one's program that returns
+  the options string to be parsed. Said function must have the following
+  prototype: ``extern "C" const char* __scudo_default_options()``.
+
+- through the environment variable SCUDO_OPTIONS, containing the options string
+  to be parsed. Options defined this way will override any definition made
+  through __scudo_default_options;
+
+The options string follows a syntax similar to ASan, where distinct options
+can be assigned in the same string, separated by colons.
+
+For example, using the environment variable:
+
+.. code::
+
+  SCUDO_OPTIONS="DeleteSizeMismatch=1:QuarantineSizeMb=16" ./a.out
+
+Or using the function:
+
+.. code::
+
+  extern "C" const char *__scudo_default_options() {
+    return "DeleteSizeMismatch=1:QuarantineSizeMb=16";
+  }
 
-For example: SCUDO_OPTIONS="DeleteSizeMismatch=1:QuarantineSizeMb=16".
 
 The following options are available: