From: Adam Crume Date: Thu, 9 Oct 2014 21:04:34 +0000 (-0700) Subject: rados: Parse command-line arguments strictly X-Git-Tag: v0.88~80^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=3b9dcff7755a3ffcb9df8a06e6d0e525e77de641;p=ceph.git rados: Parse command-line arguments strictly Many integers were parsed with functions that silently ignored junk at the end of the string. Extra characters now cause errors. Fixes: 8983 Signed-off-by: Adam Crume --- diff --git a/src/tools/rados/rados.cc b/src/tools/rados/rados.cc index 183b3e7da22d..487a99f19f5e 100644 --- a/src/tools/rados/rados.cc +++ b/src/tools/rados/rados.cc @@ -193,6 +193,32 @@ static void usage_exit() } +template +static int rados_strtol(I &i, T *val) { + char* endptr = NULL; + *val = strtol(i->second.c_str(), &endptr, 10); + if (*endptr) { + cerr << "Invalid value for " << i->first << ": '" << i->second << "'" << std::endl; + return -EINVAL; + } else { + return 0; + } +} + + +template +static int rados_strtoll(I &i, T *val) { + char* endptr = NULL; + *val = strtoll(i->second.c_str(), &endptr, 10); + if (*endptr) { + cerr << "Invalid value for " << i->first << ": '" << i->second << "'" << std::endl; + return -EINVAL; + } else { + return 0; + } +} + + static int dump_data(std::string const &filename, bufferlist const &data) { int fd; @@ -952,7 +978,9 @@ static int do_lock_cmd(std::vector &nargs, } i = opts.find("lock-duration"); if (i != opts.end()) { - lock_duration = strtol(i->second.c_str(), NULL, 10); + if (rados_strtol(i, &lock_duration)) { + return -EINVAL; + } } i = opts.find("lock-type"); if (i != opts.end()) { @@ -1231,7 +1259,9 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, } i = opts.find("concurrent-ios"); if (i != opts.end()) { - concurrent_ios = strtol(i->second.c_str(), NULL, 10); + if (rados_strtol(i, &concurrent_ios)) { + return -EINVAL; + } } i = opts.find("run-name"); if (i != opts.end()) { @@ -1243,7 +1273,9 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, } i = opts.find("block-size"); if (i != opts.end()) { - op_size = strtol(i->second.c_str(), NULL, 10); + if (rados_strtol(i, &op_size)) { + return -EINVAL; + } } i = opts.find("snap"); if (i != opts.end()) { @@ -1251,47 +1283,69 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, } i = opts.find("snapid"); if (i != opts.end()) { - snapid = strtoll(i->second.c_str(), NULL, 10); + if (rados_strtoll(i, &snapid)) { + return -EINVAL; + } } i = opts.find("min-object-size"); if (i != opts.end()) { - min_obj_len = strtoll(i->second.c_str(), NULL, 10); + if (rados_strtoll(i, &min_obj_len)) { + return -EINVAL; + } } i = opts.find("max-object-size"); if (i != opts.end()) { - max_obj_len = strtoll(i->second.c_str(), NULL, 10); + if (rados_strtoll(i, &max_obj_len)) { + return -EINVAL; + } } i = opts.find("min-op-len"); if (i != opts.end()) { - min_op_len = strtoll(i->second.c_str(), NULL, 10); + if (rados_strtoll(i, &min_op_len)) { + return -EINVAL; + } } i = opts.find("max-op-len"); if (i != opts.end()) { - max_op_len = strtoll(i->second.c_str(), NULL, 10); + if (rados_strtoll(i, &max_op_len)) { + return -EINVAL; + } } i = opts.find("max-ops"); if (i != opts.end()) { - max_ops = strtoll(i->second.c_str(), NULL, 10); + if (rados_strtoll(i, &max_ops)) { + return -EINVAL; + } } i = opts.find("max-backlog"); if (i != opts.end()) { - max_backlog = strtoll(i->second.c_str(), NULL, 10); + if (rados_strtoll(i, &max_backlog)) { + return -EINVAL; + } } i = opts.find("target-throughput"); if (i != opts.end()) { - target_throughput = strtoll(i->second.c_str(), NULL, 10); + if (rados_strtoll(i, &target_throughput)) { + return -EINVAL; + } } i = opts.find("read-percent"); if (i != opts.end()) { - read_percent = strtoll(i->second.c_str(), NULL, 10); + if (rados_strtoll(i, &read_percent)) { + return -EINVAL; + } } i = opts.find("num-objects"); if (i != opts.end()) { - num_objs = strtoll(i->second.c_str(), NULL, 10); + if (rados_strtoll(i, &num_objs)) { + return -EINVAL; + } } i = opts.find("run-length"); if (i != opts.end()) { - run_length = strtol(i->second.c_str(), NULL, 10); + if (rados_strtol(i, &run_length)) { + return -EINVAL; + } } i = opts.find("show-time"); if (i != opts.end()) { @@ -1566,7 +1620,13 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, if (!pool_name || nargs.size() < 2) usage_exit(); - uint64_t new_auid = strtol(nargs[1], 0, 10); + char* endptr = NULL; + uint64_t new_auid = strtol(nargs[1], &endptr, 10); + if (*endptr) { + cerr << "Invalid value for new-auid: '" << nargs[1] << "'" << std::endl; + ret = -1; + goto out; + } ret = io_ctx.set_auid(new_auid); if (ret < 0) { cerr << "error changing auid on pool " << io_ctx.get_pool_name() << ':' @@ -1628,7 +1688,13 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, usage_exit(); string oid(nargs[1]); - long size = atol(nargs[2]); + char* endptr = NULL; + long size = strtoll(nargs[2], &endptr, 10); + if (*endptr) { + cerr << "Invalid value for size: '" << nargs[2] << "'" << std::endl; + ret = -EINVAL; + goto out; + } if (size < 0) { cerr << "error, cannot truncate to negative value" << std::endl; usage_exit(); @@ -2088,10 +2154,21 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, if (nargs.size() < 2) usage_exit(); if (nargs.size() > 2) { - auid = strtol(nargs[2], 0, 10); + char* endptr = NULL; + auid = strtol(nargs[2], &endptr, 10); + if (*endptr) { + cerr << "Invalid value for auid: '" << nargs[2] << "'" << std::endl; + ret = -EINVAL; + goto out; + } cerr << "setting auid:" << auid << std::endl; if (nargs.size() > 3) { - crush_rule = (__u8)strtol(nargs[3], 0, 10); + crush_rule = (__u8)strtol(nargs[3], &endptr, 10); + if (*endptr) { + cerr << "Invalid value for crush-rule: '" << nargs[3] << "'" << std::endl; + ret = -EINVAL; + goto out; + } cerr << "using crush rule " << (int)crush_rule << std::endl; } } @@ -2219,7 +2296,13 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, else if (strcmp(nargs[0], "bench") == 0) { if (!pool_name || nargs.size() < 3) usage_exit(); - int seconds = atoi(nargs[1]); + char* endptr = NULL; + int seconds = strtol(nargs[1], &endptr, 10); + if (*endptr) { + cerr << "Invalid value for seconds: '" << nargs[1] << "'" << std::endl; + ret = -EINVAL; + goto out; + } int operation = 0; if (strcmp(nargs[2], "write") == 0) operation = OP_WRITE;