blob: ad50800c473bf716ffdf97cb1b02e0cf7a519a82 [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"
Kostya Kortchinsky4223af42018-01-30 17:59:49 +000015#include "scudo_interface_internal.h"
Kostya Serebryany712fc982016-06-07 01:20:26 +000016#include "scudo_utils.h"
17
18#include "sanitizer_common/sanitizer_flags.h"
19#include "sanitizer_common/sanitizer_flag_parser.h"
20
21namespace __scudo {
22
Kostya Kortchinskya2b715f2017-11-14 16:14:53 +000023static Flags ScudoFlags; // Use via getFlags().
Kostya Serebryany712fc982016-06-07 01:20:26 +000024
25void Flags::setDefaults() {
26#define SCUDO_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
27#include "scudo_flags.inc"
28#undef SCUDO_FLAG
29}
30
31static 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
Kostya Kortchinskya2b715f2017-11-14 16:14:53 +000038static const char *getScudoDefaultOptions() {
Kostya Serebryany707894b2016-08-02 22:25:38 +000039 return (&__scudo_default_options) ? __scudo_default_options() : "";
40}
41
Kostya Serebryany712fc982016-06-07 01:20:26 +000042void initFlags() {
43 SetCommonFlagsDefaults();
44 {
45 CommonFlags cf;
46 cf.CopyFrom(*common_flags());
47 cf.exitcode = 1;
48 OverrideCommonFlags(cf);
49 }
50 Flags *f = getFlags();
51 f->setDefaults();
52
Kostya Serebryany707894b2016-08-02 22:25:38 +000053 FlagParser ScudoParser;
54 RegisterScudoFlags(&ScudoParser, f);
55 RegisterCommonFlags(&ScudoParser);
Kostya Serebryany712fc982016-06-07 01:20:26 +000056
Kostya Serebryany707894b2016-08-02 22:25:38 +000057 // Override from user-specified string.
Kostya Kortchinskya2b715f2017-11-14 16:14:53 +000058 ScudoParser.ParseString(getScudoDefaultOptions());
Kostya Serebryany707894b2016-08-02 22:25:38 +000059
60 // Override from environment.
61 ScudoParser.ParseString(GetEnv("SCUDO_OPTIONS"));
Kostya Serebryany712fc982016-06-07 01:20:26 +000062
63 InitializeCommonFlags();
64
65 // Sanity checks and default settings for the Quarantine parameters.
66
Kostya Kortchinsky2d944052017-07-24 15:29:38 +000067 if (f->QuarantineSizeMb >= 0) {
68 // Backward compatible logic if QuarantineSizeMb is set.
69 if (f->QuarantineSizeKb >= 0) {
70 dieWithMessage("ERROR: please use either QuarantineSizeMb (deprecated) "
71 "or QuarantineSizeKb, but not both\n");
72 }
73 if (f->QuarantineChunksUpToSize >= 0) {
74 dieWithMessage("ERROR: QuarantineChunksUpToSize cannot be used in "
75 " conjunction with the deprecated QuarantineSizeMb option\n");
76 }
77 // If everything is in order, update QuarantineSizeKb accordingly.
78 f->QuarantineSizeKb = f->QuarantineSizeMb * 1024;
79 } else {
80 // Otherwise proceed with the new options.
81 if (f->QuarantineSizeKb < 0) {
82 const int DefaultQuarantineSizeKb = FIRST_32_SECOND_64(64, 256);
83 f->QuarantineSizeKb = DefaultQuarantineSizeKb;
84 }
85 if (f->QuarantineChunksUpToSize < 0) {
86 const int DefaultQuarantineChunksUpToSize = FIRST_32_SECOND_64(512, 2048);
87 f->QuarantineChunksUpToSize = DefaultQuarantineChunksUpToSize;
88 }
Kostya Serebryany712fc982016-06-07 01:20:26 +000089 }
Kostya Kortchinsky2d944052017-07-24 15:29:38 +000090
91 // We enforce an upper limit for the chunk quarantine threshold of 4Mb.
92 if (f->QuarantineChunksUpToSize > (4 * 1024 * 1024)) {
93 dieWithMessage("ERROR: the chunk quarantine threshold is too large\n");
94 }
95
96 // We enforce an upper limit for the quarantine size of 32Mb.
97 if (f->QuarantineSizeKb > (32 * 1024)) {
Kostya Serebryany712fc982016-06-07 01:20:26 +000098 dieWithMessage("ERROR: the quarantine size is too large\n");
99 }
Kostya Kortchinsky2d944052017-07-24 15:29:38 +0000100
Kostya Serebryany712fc982016-06-07 01:20:26 +0000101 if (f->ThreadLocalQuarantineSizeKb < 0) {
Kostya Kortchinsky2d944052017-07-24 15:29:38 +0000102 const int DefaultThreadLocalQuarantineSizeKb = FIRST_32_SECOND_64(16, 64);
Kostya Serebryany712fc982016-06-07 01:20:26 +0000103 f->ThreadLocalQuarantineSizeKb = DefaultThreadLocalQuarantineSizeKb;
104 }
Kostya Kortchinsky2d944052017-07-24 15:29:38 +0000105 // And an upper limit of 8Mb for the thread quarantine cache.
106 if (f->ThreadLocalQuarantineSizeKb > (8 * 1024)) {
Kostya Serebryany712fc982016-06-07 01:20:26 +0000107 dieWithMessage("ERROR: the per thread quarantine cache size is too "
Kostya Kortchinsky2d944052017-07-24 15:29:38 +0000108 "large\n");
Kostya Serebryany712fc982016-06-07 01:20:26 +0000109 }
Kostya Kortchinsky2d944052017-07-24 15:29:38 +0000110 if (f->ThreadLocalQuarantineSizeKb == 0 && f->QuarantineSizeKb > 0) {
Kostya Kortchinsky8d6257b2017-02-03 20:49:42 +0000111 dieWithMessage("ERROR: ThreadLocalQuarantineSizeKb can be set to 0 only "
Kostya Kortchinsky2d944052017-07-24 15:29:38 +0000112 "when QuarantineSizeKb is set to 0\n");
Kostya Kortchinsky8d6257b2017-02-03 20:49:42 +0000113 }
Kostya Serebryany712fc982016-06-07 01:20:26 +0000114}
115
116Flags *getFlags() {
Kostya Serebryany707894b2016-08-02 22:25:38 +0000117 return &ScudoFlags;
Kostya Serebryany712fc982016-06-07 01:20:26 +0000118}
119
Kostya Kortchinsky1148dc52016-11-30 17:32:20 +0000120} // namespace __scudo
Kostya Kortchinsky4223af42018-01-30 17:59:49 +0000121
122#if !SANITIZER_SUPPORTS_WEAK_HOOKS
123SANITIZER_INTERFACE_WEAK_DEF(const char*, __scudo_default_options, void) {
124 return "";
125}
126#endif