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