blob: ab94afac9f9fa802569004b0e374d742fc1742bb [file] [log] [blame]
Kostya Serebryany712fc982016-06-07 01:20:26 +00001//===-- 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_utils.h"
16
17#include "sanitizer_common/sanitizer_flags.h"
18#include "sanitizer_common/sanitizer_flag_parser.h"
19
Kostya Serebryany707894b2016-08-02 22:25:38 +000020extern "C" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
21const char* __scudo_default_options();
22
Kostya Serebryany712fc982016-06-07 01:20:26 +000023namespace __scudo {
24
Kostya Serebryany707894b2016-08-02 22:25:38 +000025Flags ScudoFlags; // Use via getFlags().
Kostya Serebryany712fc982016-06-07 01:20:26 +000026
27void Flags::setDefaults() {
28#define SCUDO_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
29#include "scudo_flags.inc"
30#undef SCUDO_FLAG
31}
32
33static void RegisterScudoFlags(FlagParser *parser, Flags *f) {
34#define SCUDO_FLAG(Type, Name, DefaultValue, Description) \
35 RegisterFlag(parser, #Name, Description, &f->Name);
36#include "scudo_flags.inc"
37#undef SCUDO_FLAG
38}
39
Kostya Serebryany707894b2016-08-02 22:25:38 +000040static const char *callGetScudoDefaultOptions() {
41 return (&__scudo_default_options) ? __scudo_default_options() : "";
42}
43
Kostya Serebryany712fc982016-06-07 01:20:26 +000044void initFlags() {
45 SetCommonFlagsDefaults();
46 {
47 CommonFlags cf;
48 cf.CopyFrom(*common_flags());
49 cf.exitcode = 1;
50 OverrideCommonFlags(cf);
51 }
52 Flags *f = getFlags();
53 f->setDefaults();
54
Kostya Serebryany707894b2016-08-02 22:25:38 +000055 FlagParser ScudoParser;
56 RegisterScudoFlags(&ScudoParser, f);
57 RegisterCommonFlags(&ScudoParser);
Kostya Serebryany712fc982016-06-07 01:20:26 +000058
Kostya Serebryany707894b2016-08-02 22:25:38 +000059 // Override from user-specified string.
60 const char *ScudoDefaultOptions = callGetScudoDefaultOptions();
61 ScudoParser.ParseString(ScudoDefaultOptions);
62
63 // Override from environment.
64 ScudoParser.ParseString(GetEnv("SCUDO_OPTIONS"));
Kostya Serebryany712fc982016-06-07 01:20:26 +000065
66 InitializeCommonFlags();
67
68 // Sanity checks and default settings for the Quarantine parameters.
69
Kostya Kortchinsky2d944052017-07-24 15:29:38 +000070 if (f->QuarantineSizeMb >= 0) {
71 // Backward compatible logic if QuarantineSizeMb is set.
72 if (f->QuarantineSizeKb >= 0) {
73 dieWithMessage("ERROR: please use either QuarantineSizeMb (deprecated) "
74 "or QuarantineSizeKb, but not both\n");
75 }
76 if (f->QuarantineChunksUpToSize >= 0) {
77 dieWithMessage("ERROR: QuarantineChunksUpToSize cannot be used in "
78 " conjunction with the deprecated QuarantineSizeMb option\n");
79 }
80 // If everything is in order, update QuarantineSizeKb accordingly.
81 f->QuarantineSizeKb = f->QuarantineSizeMb * 1024;
82 } else {
83 // Otherwise proceed with the new options.
84 if (f->QuarantineSizeKb < 0) {
85 const int DefaultQuarantineSizeKb = FIRST_32_SECOND_64(64, 256);
86 f->QuarantineSizeKb = DefaultQuarantineSizeKb;
87 }
88 if (f->QuarantineChunksUpToSize < 0) {
89 const int DefaultQuarantineChunksUpToSize = FIRST_32_SECOND_64(512, 2048);
90 f->QuarantineChunksUpToSize = DefaultQuarantineChunksUpToSize;
91 }
Kostya Serebryany712fc982016-06-07 01:20:26 +000092 }
Kostya Kortchinsky2d944052017-07-24 15:29:38 +000093
94 // We enforce an upper limit for the chunk quarantine threshold of 4Mb.
95 if (f->QuarantineChunksUpToSize > (4 * 1024 * 1024)) {
96 dieWithMessage("ERROR: the chunk quarantine threshold is too large\n");
97 }
98
99 // We enforce an upper limit for the quarantine size of 32Mb.
100 if (f->QuarantineSizeKb > (32 * 1024)) {
Kostya Serebryany712fc982016-06-07 01:20:26 +0000101 dieWithMessage("ERROR: the quarantine size is too large\n");
102 }
Kostya Kortchinsky2d944052017-07-24 15:29:38 +0000103
Kostya Serebryany712fc982016-06-07 01:20:26 +0000104 if (f->ThreadLocalQuarantineSizeKb < 0) {
Kostya Kortchinsky2d944052017-07-24 15:29:38 +0000105 const int DefaultThreadLocalQuarantineSizeKb = FIRST_32_SECOND_64(16, 64);
Kostya Serebryany712fc982016-06-07 01:20:26 +0000106 f->ThreadLocalQuarantineSizeKb = DefaultThreadLocalQuarantineSizeKb;
107 }
Kostya Kortchinsky2d944052017-07-24 15:29:38 +0000108 // And an upper limit of 8Mb for the thread quarantine cache.
109 if (f->ThreadLocalQuarantineSizeKb > (8 * 1024)) {
Kostya Serebryany712fc982016-06-07 01:20:26 +0000110 dieWithMessage("ERROR: the per thread quarantine cache size is too "
Kostya Kortchinsky2d944052017-07-24 15:29:38 +0000111 "large\n");
Kostya Serebryany712fc982016-06-07 01:20:26 +0000112 }
Kostya Kortchinsky2d944052017-07-24 15:29:38 +0000113 if (f->ThreadLocalQuarantineSizeKb == 0 && f->QuarantineSizeKb > 0) {
Kostya Kortchinsky8d6257b2017-02-03 20:49:42 +0000114 dieWithMessage("ERROR: ThreadLocalQuarantineSizeKb can be set to 0 only "
Kostya Kortchinsky2d944052017-07-24 15:29:38 +0000115 "when QuarantineSizeKb is set to 0\n");
Kostya Kortchinsky8d6257b2017-02-03 20:49:42 +0000116 }
Kostya Serebryany712fc982016-06-07 01:20:26 +0000117}
118
119Flags *getFlags() {
Kostya Serebryany707894b2016-08-02 22:25:38 +0000120 return &ScudoFlags;
Kostya Serebryany712fc982016-06-07 01:20:26 +0000121}
122
Kostya Kortchinsky1148dc52016-11-30 17:32:20 +0000123} // namespace __scudo