blob: 2aff3ef1e8faecd8216f33e7d353a4e9dcb53e64 [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 Kortchinskya2b715f2017-11-14 16:14:53 +000020SANITIZER_INTERFACE_WEAK_DEF(const char*, __scudo_default_options, void);
Kostya Serebryany707894b2016-08-02 22:25:38 +000021
Kostya Serebryany712fc982016-06-07 01:20:26 +000022namespace __scudo {
23
Kostya Kortchinskya2b715f2017-11-14 16:14:53 +000024static Flags ScudoFlags; // Use via getFlags().
Kostya Serebryany712fc982016-06-07 01:20:26 +000025
26void Flags::setDefaults() {
27#define SCUDO_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
28#include "scudo_flags.inc"
29#undef SCUDO_FLAG
30}
31
32static void RegisterScudoFlags(FlagParser *parser, Flags *f) {
33#define SCUDO_FLAG(Type, Name, DefaultValue, Description) \
34 RegisterFlag(parser, #Name, Description, &f->Name);
35#include "scudo_flags.inc"
36#undef SCUDO_FLAG
37}
38
Kostya Kortchinskya2b715f2017-11-14 16:14:53 +000039static const char *getScudoDefaultOptions() {
Kostya Serebryany707894b2016-08-02 22:25:38 +000040 return (&__scudo_default_options) ? __scudo_default_options() : "";
41}
42
Kostya Serebryany712fc982016-06-07 01:20:26 +000043void initFlags() {
44 SetCommonFlagsDefaults();
45 {
46 CommonFlags cf;
47 cf.CopyFrom(*common_flags());
48 cf.exitcode = 1;
49 OverrideCommonFlags(cf);
50 }
51 Flags *f = getFlags();
52 f->setDefaults();
53
Kostya Serebryany707894b2016-08-02 22:25:38 +000054 FlagParser ScudoParser;
55 RegisterScudoFlags(&ScudoParser, f);
56 RegisterCommonFlags(&ScudoParser);
Kostya Serebryany712fc982016-06-07 01:20:26 +000057
Kostya Serebryany707894b2016-08-02 22:25:38 +000058 // Override from user-specified string.
Kostya Kortchinskya2b715f2017-11-14 16:14:53 +000059 ScudoParser.ParseString(getScudoDefaultOptions());
Kostya Serebryany707894b2016-08-02 22:25:38 +000060
61 // Override from environment.
62 ScudoParser.ParseString(GetEnv("SCUDO_OPTIONS"));
Kostya Serebryany712fc982016-06-07 01:20:26 +000063
64 InitializeCommonFlags();
65
66 // Sanity checks and default settings for the Quarantine parameters.
67
Kostya Kortchinsky2d944052017-07-24 15:29:38 +000068 if (f->QuarantineSizeMb >= 0) {
69 // Backward compatible logic if QuarantineSizeMb is set.
70 if (f->QuarantineSizeKb >= 0) {
71 dieWithMessage("ERROR: please use either QuarantineSizeMb (deprecated) "
72 "or QuarantineSizeKb, but not both\n");
73 }
74 if (f->QuarantineChunksUpToSize >= 0) {
75 dieWithMessage("ERROR: QuarantineChunksUpToSize cannot be used in "
76 " conjunction with the deprecated QuarantineSizeMb option\n");
77 }
78 // If everything is in order, update QuarantineSizeKb accordingly.
79 f->QuarantineSizeKb = f->QuarantineSizeMb * 1024;
80 } else {
81 // Otherwise proceed with the new options.
82 if (f->QuarantineSizeKb < 0) {
83 const int DefaultQuarantineSizeKb = FIRST_32_SECOND_64(64, 256);
84 f->QuarantineSizeKb = DefaultQuarantineSizeKb;
85 }
86 if (f->QuarantineChunksUpToSize < 0) {
87 const int DefaultQuarantineChunksUpToSize = FIRST_32_SECOND_64(512, 2048);
88 f->QuarantineChunksUpToSize = DefaultQuarantineChunksUpToSize;
89 }
Kostya Serebryany712fc982016-06-07 01:20:26 +000090 }
Kostya Kortchinsky2d944052017-07-24 15:29:38 +000091
92 // We enforce an upper limit for the chunk quarantine threshold of 4Mb.
93 if (f->QuarantineChunksUpToSize > (4 * 1024 * 1024)) {
94 dieWithMessage("ERROR: the chunk quarantine threshold is too large\n");
95 }
96
97 // We enforce an upper limit for the quarantine size of 32Mb.
98 if (f->QuarantineSizeKb > (32 * 1024)) {
Kostya Serebryany712fc982016-06-07 01:20:26 +000099 dieWithMessage("ERROR: the quarantine size is too large\n");
100 }
Kostya Kortchinsky2d944052017-07-24 15:29:38 +0000101
Kostya Serebryany712fc982016-06-07 01:20:26 +0000102 if (f->ThreadLocalQuarantineSizeKb < 0) {
Kostya Kortchinsky2d944052017-07-24 15:29:38 +0000103 const int DefaultThreadLocalQuarantineSizeKb = FIRST_32_SECOND_64(16, 64);
Kostya Serebryany712fc982016-06-07 01:20:26 +0000104 f->ThreadLocalQuarantineSizeKb = DefaultThreadLocalQuarantineSizeKb;
105 }
Kostya Kortchinsky2d944052017-07-24 15:29:38 +0000106 // And an upper limit of 8Mb for the thread quarantine cache.
107 if (f->ThreadLocalQuarantineSizeKb > (8 * 1024)) {
Kostya Serebryany712fc982016-06-07 01:20:26 +0000108 dieWithMessage("ERROR: the per thread quarantine cache size is too "
Kostya Kortchinsky2d944052017-07-24 15:29:38 +0000109 "large\n");
Kostya Serebryany712fc982016-06-07 01:20:26 +0000110 }
Kostya Kortchinsky2d944052017-07-24 15:29:38 +0000111 if (f->ThreadLocalQuarantineSizeKb == 0 && f->QuarantineSizeKb > 0) {
Kostya Kortchinsky8d6257b2017-02-03 20:49:42 +0000112 dieWithMessage("ERROR: ThreadLocalQuarantineSizeKb can be set to 0 only "
Kostya Kortchinsky2d944052017-07-24 15:29:38 +0000113 "when QuarantineSizeKb is set to 0\n");
Kostya Kortchinsky8d6257b2017-02-03 20:49:42 +0000114 }
Kostya Serebryany712fc982016-06-07 01:20:26 +0000115}
116
117Flags *getFlags() {
Kostya Serebryany707894b2016-08-02 22:25:38 +0000118 return &ScudoFlags;
Kostya Serebryany712fc982016-06-07 01:20:26 +0000119}
120
Kostya Kortchinsky1148dc52016-11-30 17:32:20 +0000121} // namespace __scudo