]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rados: Parse command-line arguments strictly
authorAdam Crume <adamcrume@gmail.com>
Thu, 9 Oct 2014 21:04:34 +0000 (14:04 -0700)
committerAdam Crume <adamcrume@gmail.com>
Thu, 9 Oct 2014 21:04:34 +0000 (14:04 -0700)
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 <adamcrume@gmail.com>
src/tools/rados/rados.cc

index 183b3e7da22d61231ddbe55150340bf4e3e04252..487a99f19f5ea70d092ed1c85c090c83807d7b3d 100644 (file)
@@ -193,6 +193,32 @@ static void usage_exit()
 }
 
 
+template <typename I, typename T>
+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 <typename I, typename T>
+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<const char*> &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;