This is an automated email from the ASF dual-hosted git repository. bmahler pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mesos.git
commit 0c5c0935fdad1345aa110252380d56207880b619 Author: Benjamin Mahler <[email protected]> AuthorDate: Tue Oct 8 23:47:52 2019 -0400 Added quota config validation for large numbers. Per MESOS-10008, large scalar values overflow and can crash the master. This patch imposes maximums for guarantees and limits well below the overflow point, to prevent this from happening. Review: https://reviews.apache.org/r/71595 --- src/master/quota.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/master/quota.cpp b/src/master/quota.cpp index 4ecd326..a9ae3aa 100644 --- a/src/master/quota.cpp +++ b/src/master/quota.cpp @@ -214,6 +214,63 @@ Option<Error> validate(const QuotaConfig& config) return Error("Invalid 'QuotaConfig.role': " + error->message); } + // Before we validate the scalars, we need to check for + // our maximum supported quota values. Otherwise, they + // will surface as a generic overflow error in the scalar + // validation below. + // + // The underlying fixed precision logic used for + // Value::Scalar overflows between: + // + // 9,223,372,036,854,774 and (ditto) + 1.0 + // + // double d = 9223372036854774; + // d += 1.0; + // Value::scalar s, zero; + // s.set_value(d); + // s < zero == true; // overflow! + // + // This works out to ~9 zettabytes (given we use megabytes + // as the base unit), we set a limit of 1 exabyte, and we + // can increase this later if needed. + // + // We also impose a limit on cpu, ports and other types of + // 1 trillion. + + const int64_t exabyteInMegabytes = 1024ll * 1024ll * 1024ll * 1024ll; + const int64_t otherLimit = 1000ll * 1000ll * 1000ll * 1000ll; + + auto validateTooLarge = [&]( + const Map<string, Value::Scalar>& m) -> Option<Error> { + foreach (auto&& pair, m) { + if (pair.first == "mem" || pair.first == "disk") { + if (pair.second.value() > exabyteInMegabytes) { + return Error( + "{'" + pair.first + "': " + stringify(pair.second) + "}" + " is invalid: values greater than 1 exabyte" + " (" + stringify(exabyteInMegabytes) + ") are not supported"); + } + } else if (pair.second.value() > otherLimit) { + return Error( + "{'" + pair.first + "': " + stringify(pair.second) + "}" + " is invalid: values greater than 1 trillion" + " (" + stringify(otherLimit) + ") are not supported"); + } + } + + return None(); + }; + + error = validateTooLarge(config.guarantees()); + if (error.isSome()) { + return Error("Invalid 'QuotaConfig.guarantees': " + error->message); + } + + error = validateTooLarge(config.limits()); + if (error.isSome()) { + return Error("Invalid 'QuotaConfig.limits': " + error->message); + } + // Validate scalar values. foreach (auto&& guarantee, config.guarantees()) { Option<Error> error =
