1 //===-- scudo_flags.cpp -----------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// 10 /// Hardened Allocator flag parsing logic. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #include "scudo_flags.h" 15 #include "scudo_interface_internal.h" 16 #include "scudo_utils.h" 17 18 #include "sanitizer_common/sanitizer_flags.h" 19 #include "sanitizer_common/sanitizer_flag_parser.h" 20 21 namespace __scudo { 22 23 static Flags ScudoFlags; // Use via getFlags(). 24 25 void Flags::setDefaults() { 26 #define SCUDO_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; 27 #include "scudo_flags.inc" 28 #undef SCUDO_FLAG 29 } 30 31 static void RegisterScudoFlags(FlagParser *parser, Flags *f) { 32 #define SCUDO_FLAG(Type, Name, DefaultValue, Description) \ 33 RegisterFlag(parser, #Name, Description, &f->Name); 34 #include "scudo_flags.inc" 35 #undef SCUDO_FLAG 36 } 37 38 static const char *getCompileDefinitionScudoDefaultOptions() { 39 #ifdef SCUDO_DEFAULT_OPTIONS 40 return SANITIZER_STRINGIFY(SCUDO_DEFAULT_OPTIONS); 41 #else 42 return ""; 43 #endif 44 } 45 46 static const char *getScudoDefaultOptions() { 47 return (&__scudo_default_options) ? __scudo_default_options() : ""; 48 } 49 50 void initFlags() { 51 SetCommonFlagsDefaults(); 52 { 53 CommonFlags cf; 54 cf.CopyFrom(*common_flags()); 55 cf.exitcode = 1; 56 OverrideCommonFlags(cf); 57 } 58 Flags *f = getFlags(); 59 f->setDefaults(); 60 61 FlagParser ScudoParser; 62 RegisterScudoFlags(&ScudoParser, f); 63 RegisterCommonFlags(&ScudoParser); 64 65 // Override from compile definition. 66 ScudoParser.ParseString(getCompileDefinitionScudoDefaultOptions()); 67 68 // Override from user-specified string. 69 ScudoParser.ParseString(getScudoDefaultOptions()); 70 71 // Override from environment. 72 ScudoParser.ParseString(GetEnv("SCUDO_OPTIONS")); 73 74 InitializeCommonFlags(); 75 76 // Sanity checks and default settings for the Quarantine parameters. 77 78 if (f->QuarantineSizeMb >= 0) { 79 // Backward compatible logic if QuarantineSizeMb is set. 80 if (f->QuarantineSizeKb >= 0) { 81 dieWithMessage("ERROR: please use either QuarantineSizeMb (deprecated) " 82 "or QuarantineSizeKb, but not both\n"); 83 } 84 if (f->QuarantineChunksUpToSize >= 0) { 85 dieWithMessage("ERROR: QuarantineChunksUpToSize cannot be used in " 86 " conjunction with the deprecated QuarantineSizeMb option\n"); 87 } 88 // If everything is in order, update QuarantineSizeKb accordingly. 89 f->QuarantineSizeKb = f->QuarantineSizeMb * 1024; 90 } else { 91 // Otherwise proceed with the new options. 92 if (f->QuarantineSizeKb < 0) { 93 const int DefaultQuarantineSizeKb = FIRST_32_SECOND_64(64, 256); 94 f->QuarantineSizeKb = DefaultQuarantineSizeKb; 95 } 96 if (f->QuarantineChunksUpToSize < 0) { 97 const int DefaultQuarantineChunksUpToSize = FIRST_32_SECOND_64(512, 2048); 98 f->QuarantineChunksUpToSize = DefaultQuarantineChunksUpToSize; 99 } 100 } 101 102 // We enforce an upper limit for the chunk quarantine threshold of 4Mb. 103 if (f->QuarantineChunksUpToSize > (4 * 1024 * 1024)) { 104 dieWithMessage("ERROR: the chunk quarantine threshold is too large\n"); 105 } 106 107 // We enforce an upper limit for the quarantine size of 32Mb. 108 if (f->QuarantineSizeKb > (32 * 1024)) { 109 dieWithMessage("ERROR: the quarantine size is too large\n"); 110 } 111 112 if (f->ThreadLocalQuarantineSizeKb < 0) { 113 const int DefaultThreadLocalQuarantineSizeKb = FIRST_32_SECOND_64(16, 64); 114 f->ThreadLocalQuarantineSizeKb = DefaultThreadLocalQuarantineSizeKb; 115 } 116 // And an upper limit of 8Mb for the thread quarantine cache. 117 if (f->ThreadLocalQuarantineSizeKb > (8 * 1024)) { 118 dieWithMessage("ERROR: the per thread quarantine cache size is too " 119 "large\n"); 120 } 121 if (f->ThreadLocalQuarantineSizeKb == 0 && f->QuarantineSizeKb > 0) { 122 dieWithMessage("ERROR: ThreadLocalQuarantineSizeKb can be set to 0 only " 123 "when QuarantineSizeKb is set to 0\n"); 124 } 125 } 126 127 Flags *getFlags() { 128 return &ScudoFlags; 129 } 130 131 } // namespace __scudo 132 133 #if !SANITIZER_SUPPORTS_WEAK_HOOKS 134 SANITIZER_INTERFACE_WEAK_DEF(const char*, __scudo_default_options, void) { 135 return ""; 136 } 137 #endif 138