From: Mykola Golub Date: Thu, 2 Feb 2017 10:11:35 +0000 (+0100) Subject: rbd-nbd: check /sys/block/nbdX/size to ensure kernel mapped correctly X-Git-Tag: v10.2.8~127^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=335b5fa4a9694620546422f9a02bdcc16549d7cc;p=ceph.git 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) Conflicts: qa/workunits/rbd/rbd-nbd.sh: the original commit removes TOO_LARGE_IMAGE test, do the same thing src/tools/rbd_nbd/rbd-nbd.cc: help git to add "include/stringify.h" Other changes: src/tools/rbd_nbd/rbd-nbd.cc: #include so the code compiles Signed-off-by: Alexey Sheplyakov --- diff --git a/qa/workunits/rbd/rbd-nbd.sh b/qa/workunits/rbd/rbd-nbd.sh index a414c4d0d641..1e08adee81fa 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 SUDO=sudo SIZE=64 DATA= @@ -17,7 +16,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 if [ `id -u` = 0 ] then @@ -40,7 +38,6 @@ function cleanup() done rbd -p ${POOL} remove ${IMAGE} fi - rbd -p ${POOL} remove ${TOO_LARGE_IMAGE} } function expect_false() @@ -63,7 +60,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 9d38cf1382b8..4479e31d5680 100644 --- a/src/tools/rbd_nbd/rbd-nbd.cc +++ b/src/tools/rbd_nbd/rbd-nbd.cc @@ -34,6 +34,7 @@ #include #include +#include #include #include "mon/MonClient.h" @@ -49,6 +50,7 @@ #include "include/rados/librados.hpp" #include "include/rbd/librbd.hpp" +#include "include/stringify.h" #define dout_subsys ceph_subsys_rbd #undef dout_prefix @@ -73,6 +75,8 @@ static bool readonly = false; static int nbds_max = 0; static int max_part = 255; +#define RBD_NBD_BLKSIZE 512UL + #ifdef CEPH_BIG_ENDIAN #define ntohll(a) (a) #elif defined(CEPH_LITTLE_ENDIAN) @@ -463,6 +467,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; @@ -476,6 +502,7 @@ static int do_map() unsigned long flags; unsigned long size; + int index = 0; int fd[2]; int nbd; @@ -510,7 +537,6 @@ static int do_map() if (devpath.empty()) { char dev[64]; - int index = 0; while (true) { snprintf(dev, sizeof(dev), "/dev/nbd%d", index); @@ -532,6 +558,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; @@ -578,27 +610,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;