From: Jason Dillaman Date: Mon, 2 Oct 2017 21:28:04 +0000 (-0400) Subject: osd: additional protection for out-of-bounds EC reads X-Git-Tag: v13.0.1~670^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=881f2a02aecef0cd6bf8ec3e5045b76c8441e832;p=ceph-ci.git osd: additional protection for out-of-bounds EC reads Fixes: http://tracker.ceph.com/issues/21629 Signed-off-by: Jason Dillaman --- diff --git a/src/osd/PrimaryLogPG.cc b/src/osd/PrimaryLogPG.cc index 9c85f3b1694..ee91de74640 100644 --- a/src/osd/PrimaryLogPG.cc +++ b/src/osd/PrimaryLogPG.cc @@ -4618,13 +4618,28 @@ int PrimaryLogPG::do_extent_cmp(OpContext *ctx, OSDOp& osd_op) dout(20) << __func__ << dendl; ceph_osd_op& op = osd_op.op; - if (!ctx->obs->exists || ctx->obs->oi.is_whiteout()) { + auto& oi = ctx->new_obs.oi; + uint64_t size = oi.size; + if ((oi.truncate_seq < op.extent.truncate_seq) && + (op.extent.offset + op.extent.length > op.extent.truncate_size)) { + size = op.extent.truncate_size; + } + + if (op.extent.offset >= size) { + op.extent.length = 0; + } else if (op.extent.offset + op.extent.length > size) { + op.extent.length = size - op.extent.offset; + } + + if (op.extent.length == 0) { + dout(20) << __func__ << " zero length extent" << dendl; + return finish_extent_cmp(osd_op, bufferlist{}); + } else if (!ctx->obs->exists || ctx->obs->oi.is_whiteout()) { dout(20) << __func__ << " object DNE" << dendl; return finish_extent_cmp(osd_op, {}); } else if (pool.info.require_rollback()) { // If there is a data digest and it is possible we are reading // entire object, pass the digest. - auto& oi = ctx->new_obs.oi; boost::optional maybe_crc; if (oi.is_data_digest() && op.checksum.offset == 0 && op.checksum.length >= oi.size) { diff --git a/src/test/librados/misc.cc b/src/test/librados/misc.cc index ea4d3e713e7..f7ce348b0a0 100644 --- a/src/test/librados/misc.cc +++ b/src/test/librados/misc.cc @@ -28,6 +28,7 @@ using std::string; typedef RadosTest LibRadosMisc; typedef RadosTestPP LibRadosMiscPP; +typedef RadosTestECPP LibRadosMiscECPP; TEST(LibRadosMiscVersion, Version) { int major, minor, extra; @@ -1356,3 +1357,24 @@ TEST_F(LibRadosMiscPP, Applications) { ASSERT_EQ(0, ioctx.application_metadata_list("app1", &meta)); ASSERT_EQ(expected_meta, meta); } + +TEST_F(LibRadosMiscECPP, CompareExtentRange) { + bufferlist bl1; + bl1.append("ceph"); + ObjectWriteOperation write; + write.write(0, bl1); + ASSERT_EQ(0, ioctx.operate("foo", &write)); + + bufferlist bl2; + bl2.append("ph"); + bl2.append(std::string(2, '\0')); + ObjectReadOperation read1; + read1.cmpext(2, bl2, nullptr); + ASSERT_EQ(0, ioctx.operate("foo", &read1, nullptr)); + + bufferlist bl3; + bl3.append(std::string(4, '\0')); + ObjectReadOperation read2; + read2.cmpext(2097152, bl3, nullptr); + ASSERT_EQ(0, ioctx.operate("foo", &read2, nullptr)); +}