From 61c5957b30f807f5eab4c072deb00f19433f0a46 Mon Sep 17 00:00:00 2001 From: Mykola Golub Date: Thu, 2 Feb 2017 11:11:35 +0100 Subject: [PATCH] rbd-nbd: check /sys/block/nbdX/size to ensure kernel mapped correctly Fixes: http://tracker.ceph.com/issues/18335 Signed-off-by: Mykola Golub (cherry picked from commit 596e5ea8a5df72002672eef0a6d20572ca6f60f0) --- qa/workunits/rbd/rbd-nbd.sh | 4 --- src/tools/rbd_nbd/rbd-nbd.cc | 50 +++++++++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/qa/workunits/rbd/rbd-nbd.sh b/qa/workunits/rbd/rbd-nbd.sh index 513b6dacb10ee..348d9c177f95d 100755 --- a/qa/workunits/rbd/rbd-nbd.sh +++ b/qa/workunits/rbd/rbd-nbd.sh @@ -4,7 +4,6 @@ POOL=rbd IMAGE=testrbdnbd$$ -TOO_LARGE_IMAGE=${IMAGE}_large SIZE=64 DATA= DEV= @@ -50,7 +49,6 @@ setup() DATA=${TEMPDIR}/data dd if=/dev/urandom of=${DATA} bs=1M count=${SIZE} rbd --dest-pool ${POOL} --no-progress import ${DATA} ${IMAGE} - rbd -p ${POOL} create ${TOO_LARGE_IMAGE} --size 3T } function cleanup() @@ -68,7 +66,6 @@ function cleanup() done rbd -p ${POOL} remove ${IMAGE} fi - rbd -p ${POOL} remove ${TOO_LARGE_IMAGE} } function expect_false() @@ -91,7 +88,6 @@ then fi expect_false _sudo rbd-nbd map INVALIDIMAGE expect_false _sudo rbd-nbd --device INVALIDDEV map ${IMAGE} -expect_false _sudo rbd-nbd map ${TOO_LARGE_IMAGE} # map test using the first unused device DEV=`_sudo rbd-nbd map ${POOL}/${IMAGE}` diff --git a/src/tools/rbd_nbd/rbd-nbd.cc b/src/tools/rbd_nbd/rbd-nbd.cc index 04a747cbf9a67..006cc54cc1fd5 100644 --- a/src/tools/rbd_nbd/rbd-nbd.cc +++ b/src/tools/rbd_nbd/rbd-nbd.cc @@ -49,6 +49,7 @@ #include "include/rados/librados.hpp" #include "include/rbd/librbd.hpp" +#include "include/stringify.h" #include "include/xlist.h" #define dout_subsys ceph_subsys_rbd @@ -76,6 +77,8 @@ static int nbds_max = 0; static int max_part = 255; static bool exclusive = false; +#define RBD_NBD_BLKSIZE 512UL + #ifdef CEPH_BIG_ENDIAN #define ntohll(a) (a) #elif defined(CEPH_LITTLE_ENDIAN) @@ -466,6 +469,28 @@ static int open_device(const char* path, bool try_load_moudle = false) return nbd; } +static int check_device_size(int nbd_index, unsigned long expected_size) +{ + unsigned long size = 0; + std::string path = "/sys/block/nbd" + stringify(nbd_index) + "/size"; + std::ifstream ifs; + ifs.open(path.c_str(), std::ifstream::in); + if (!ifs.is_open()) { + cerr << "rbd-nbd: failed to open " << path << std::endl; + return -EINVAL; + } + ifs >> size; + size *= RBD_NBD_BLKSIZE; + + if (size != expected_size) { + cerr << "rbd-nbd: kernel reported invalid device size (" << size + << ", expected " << expected_size << ")" << std::endl; + return -EINVAL; + } + + return 0; +} + static int do_map() { int r; @@ -479,6 +504,7 @@ static int do_map() unsigned long flags; unsigned long size; + int index = 0; int fd[2]; int nbd; @@ -514,7 +540,6 @@ static int do_map() if (devpath.empty()) { char dev[64]; - int index = 0; while (true) { snprintf(dev, sizeof(dev), "/dev/nbd%d", index); @@ -536,6 +561,12 @@ static int do_map() break; } } else { + r = sscanf(devpath.c_str(), "/dev/nbd%d", &index); + if (r < 0) { + cerr << "rbd-nbd: invalid device path: " << devpath + << " (expected /dev/nbd{num})" << std::endl; + goto close_fd; + } nbd = open_device(devpath.c_str(), true); if (nbd < 0) { r = nbd; @@ -591,27 +622,32 @@ static int do_map() if (r < 0) goto close_nbd; - r = ioctl(nbd, NBD_SET_BLKSIZE, 512UL); + r = ioctl(nbd, NBD_SET_BLKSIZE, RBD_NBD_BLKSIZE); if (r < 0) { r = -errno; goto close_nbd; } - size = info.size; - - if (size > (1UL << 32) * 512) { + if (info.size > ULONG_MAX) { r = -EFBIG; - cerr << "rbd-nbd: image is too large (" << prettybyte_t(size) << ", max is " - << prettybyte_t((1UL << 32) * 512) << ")" << std::endl; + cerr << "rbd-nbd: image is too large (" << prettybyte_t(info.size) + << ", max is " << prettybyte_t(ULONG_MAX) << ")" << std::endl; goto close_nbd; } + size = info.size; + r = ioctl(nbd, NBD_SET_SIZE, size); if (r < 0) { r = -errno; goto close_nbd; } + r = check_device_size(index, size); + if (r < 0) { + goto close_nbd; + } + ioctl(nbd, NBD_SET_FLAGS, flags); read_only = snapname.empty() ? 0 : 1; -- 2.39.5