From dc18e7a0d79643e5a97607d45efce5975780a794 Mon Sep 17 00:00:00 2001 From: Colin Patrick McCabe Date: Fri, 15 Oct 2010 12:16:41 -0700 Subject: [PATCH] osd mon: validate arguments before marking lost Signed-off-by: Colin McCabe --- src/mon/Monitor.cc | 52 +++++++++++++++++++++++++++++++++++++++++++ src/mon/Monitor.h | 2 ++ src/mon/OSDMonitor.cc | 12 ++++++---- 3 files changed, 62 insertions(+), 4 deletions(-) diff --git a/src/mon/Monitor.cc b/src/mon/Monitor.cc index 54a387edba03c..7cce9b8f20ac8 100644 --- a/src/mon/Monitor.cc +++ b/src/mon/Monitor.cc @@ -59,6 +59,11 @@ #include "config.h" +#include +#include +#include +#include + #define DOUT_SUBSYS mon #undef dout_prefix #define dout_prefix _prefix(this) @@ -1145,3 +1150,50 @@ bool Monitor::ms_verify_authorizer(Connection *con, int peer_type, return true; }; +static long long strict_strtoll(const char *str, int base, std::string *err) +{ + char *endptr; + errno = 0; /* To distinguish success/failure after call (see man page) */ + long long ret = strtoll(str, &endptr, base); + + if ((errno == ERANGE && (ret == LLONG_MAX || ret == LLONG_MIN)) + || (errno != 0 && ret == 0)) { + ostringstream oss; + oss << "strict_strtoll: integer underflow or overflow parsing '" << str << "'"; + *err = oss.str(); + return 0; + } + if (endptr == str) { + ostringstream oss; + oss << "strict_strtoll: expected integer, got: '" << str << "'"; + *err = oss.str(); + return 0; + } + if (*endptr != '\0') { + ostringstream oss; + oss << "strict_strtoll: garbage at end of string. got: '" << str << "'"; + *err = oss.str(); + return 0; + } + return ret; +} + +int strict_strtol(const char *str, int base, std::string *err) +{ + long long ret = strict_strtoll(str, base, err); + if (!err->empty()) + return 0; + if (ret <= INT_MIN) { + ostringstream oss; + oss << "strict_strtol: integer underflow parsing '" << str << "'"; + *err = oss.str(); + return 0; + } + if (ret >= INT_MAX) { + ostringstream oss; + oss << "strict_strtol: integer overflow parsing '" << str << "'"; + *err = oss.str(); + return 0; + } + return static_cast(ret); +} diff --git a/src/mon/Monitor.h b/src/mon/Monitor.h index 3b4746f3ad0a2..fcf61b8ee1d73 100644 --- a/src/mon/Monitor.h +++ b/src/mon/Monitor.h @@ -238,6 +238,8 @@ public: LogClient *get_logclient() { return &logclient; } }; +int strict_strtol(const char *str, int base, std::string *err); + #define CEPH_MON_FEATURE_INCOMPAT_BASE CompatSet::Feature (1, "initial feature set (~v.18)") extern const CompatSet::Feature ceph_mon_feature_compat[]; extern const CompatSet::Feature ceph_mon_feature_ro_compat[]; diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc index 5ab2d9555eebf..18c0b1cad40fe 100644 --- a/src/mon/OSDMonitor.cc +++ b/src/mon/OSDMonitor.cc @@ -1359,10 +1359,14 @@ bool OSDMonitor::prepare_command(MMonCommand *m) } } else if (m->cmd[1] == "lost" && m->cmd.size() >= 3) { - long osd = strtol(m->cmd[2].c_str(), 0, 10); - if (m->cmd.size() < 4 || - m->cmd[3] != "--yes-i-really-mean-it") { - ss << "are you SURE? this might mean real, permanent data loss. pass --yes-i-really-mean-it if you really do."; + string err; + int osd = strict_strtol(m->cmd[2].c_str(), 10, &err); + if (!err.empty()) { + ss << err; + } + else if ((m->cmd.size() < 4) || m->cmd[3] != "--yes-i-really-mean-it") { + ss << "are you SURE? this might mean real, permanent data loss. pass " + "--yes-i-really-mean-it if you really do."; } else if (!osdmap.exists(osd) || !osdmap.is_down(osd)) { ss << "osd" << osd << " is not down or doesn't exist"; -- 2.39.5