From 775244af0d2ae1ff6df671f106672c711e3fa7e8 Mon Sep 17 00:00:00 2001 From: Chunsong Feng Date: Fri, 29 Nov 2019 13:00:34 +0800 Subject: [PATCH] msg/async/dpdk: Fix the overflow while parsing dpdk coremask coremask supports up to 256 bits in DPDK19.05, using stoull in dpdk::eal:init limits coremask up to 64 bits. Parse coremask by hex character from low to high. Fixes: https://tracker.ceph.com/issues/43044 Signed-off-by: Hu Ye Signed-off-by: Chunsong Feng Signed-off-by: luo rixin --- src/msg/async/dpdk/dpdk_rte.cc | 39 ++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/src/msg/async/dpdk/dpdk_rte.cc b/src/msg/async/dpdk/dpdk_rte.cc index 9f9d343b51a..96cf896f823 100644 --- a/src/msg/async/dpdk/dpdk_rte.cc +++ b/src/msg/async/dpdk/dpdk_rte.cc @@ -45,6 +45,36 @@ namespace dpdk { return std::bitset{n}.count(); } + static int hex2bitcount(unsigned char c) + { + int val; + + if (isdigit(c)) + val = c - '0'; + else if (isupper(c)) + val = c - 'A' + 10; + else + val = c - 'a' + 10; + return bitcount(val); + } + + static int coremask_bitcount(const char *buf) + { + int count = 0; + + if (buf[0] == '0' && + ((buf[1] == 'x') || (buf[1] == 'X'))) + buf += 2; + + for (int i = 0; buf[i] != '\0'; i++) { + char c = buf[i]; + if (isxdigit(c) == 0) + return -EINVAL; + count += hex2bitcount(c); + } + return count; + } + int eal::init(CephContext *c) { if (initialized) { @@ -52,11 +82,12 @@ namespace dpdk { } bool done = false; - auto num = std::stoull(c->_conf.get_val("ms_dpdk_coremask"), - nullptr, 16); - unsigned int coremaskbit = bitcount(num); + auto coremask = c->_conf.get_val("ms_dpdk_coremask"); + int coremaskbit = coremask_bitcount(coremask.c_str()); - ceph_assert(coremaskbit > c->_conf->ms_async_op_threads); + if (coremaskbit <= 0 + || static_cast(coremaskbit) < c->_conf->ms_async_op_threads) + return -EINVAL; t = std::thread([&]() { // TODO: Inherit these from the app parameters - "opts" -- 2.39.5