From 818c354a43ca83be10daa1f0cd251635b57371b9 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Wed, 15 Nov 2017 09:09:15 -0500 Subject: [PATCH] librbd: prevent overflow of discard API result code Prevent discard/writesame lengths larger than 2GB. Fixes: http://tracker.ceph.com/issues/21966 Signed-off-by: Jason Dillaman (cherry picked from commit 3effd324db181e625665be33b5c6529dca723cc5) Conflicts: PendingReleaseNotes src/librbd/librbd.cc: i chosed to pick code from 3effd32 in order to prevent discard/writesame against lengths larger than 2GB. `len` used in picked code was already in luminous. so it's safe to pick. --- PendingReleaseNotes | 13 +++++++++++++ src/librbd/librbd.cc | 14 +++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/PendingReleaseNotes b/PendingReleaseNotes index b46d1dce10090..34d2cab0cec1b 100644 --- a/PendingReleaseNotes +++ b/PendingReleaseNotes @@ -38,3 +38,16 @@ make the number of PGs per OSD exceed the configured ``mon_max_pg_per_osd`` limit. The option can be adjusted if it is really necessary to create a pool with more PGs. + +* There was a bug in the PG mapping behavior of the new *upmap* + feature. If you made use of this feature (e.g., via the `ceph osd + pg-upmap-items` command), we recommend that all mappings be removed (via + the `ceph osd rm-pg-upmap-items` command) before upgrading to this + point release. + +13.0.0 +------ + +* The RBD C API's rbd_discard method now enforces a maximum length of + 2GB to match the C++ API's Image::discard method. This restriction + prevents overflow of the result code. diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index 31889b822a6d9..db07e5e2275bb 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -1507,7 +1507,8 @@ namespace librbd { tracepoint(librbd, writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len, bl.length() <= 0 ? NULL : bl.c_str(), bl.length(), op_flags); - if (bl.length() <= 0 || len % bl.length()) { + if (bl.length() <= 0 || len % bl.length() || + len > std::numeric_limits::max()) { tracepoint(librbd, writesame_exit, -EINVAL); return -EINVAL; } @@ -3450,7 +3451,13 @@ extern "C" ssize_t rbd_write2(rbd_image_t image, uint64_t ofs, size_t len, extern "C" int rbd_discard(rbd_image_t image, uint64_t ofs, uint64_t len) { librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; - tracepoint(librbd, discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len); + tracepoint(librbd, discard_enter, ictx, ictx->name.c_str(), + ictx->snap_name.c_str(), ictx->read_only, ofs, len); + if (len > std::numeric_limits::max()) { + tracepoint(librbd, discard_exit, -EINVAL); + return -EINVAL; + } + int r = ictx->io_work_queue->discard(ofs, len, ictx->skip_partial_discard); tracepoint(librbd, discard_exit, r); return r; @@ -3463,7 +3470,8 @@ extern "C" ssize_t rbd_writesame(rbd_image_t image, uint64_t ofs, size_t len, tracepoint(librbd, writesame_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, ofs, len, data_len <= 0 ? NULL : buf, data_len, op_flags); - if (data_len <= 0 || len % data_len) { + if (data_len == 0 || len % data_len || + len > std::numeric_limits::max()) { tracepoint(librbd, writesame_exit, -EINVAL); return -EINVAL; } -- 2.39.5