]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: additional protection for out-of-bounds EC reads 18413/head
authorJason Dillaman <dillaman@redhat.com>
Mon, 2 Oct 2017 21:28:04 +0000 (17:28 -0400)
committerKarol Mroz <kmroz@suse.de>
Fri, 20 Oct 2017 01:20:51 +0000 (18:20 -0700)
Fixes: http://tracker.ceph.com/issues/21629
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
(cherry picked from commit 881f2a02aecef0cd6bf8ec3e5045b76c8441e832)

src/osd/PrimaryLogPG.cc
src/test/librados/misc.cc

index c079c1b1fc314ace0c2934ead9422f2b299eea47..32ef1ed885a264089d543cc971a6e3255bfcc0b1 100644 (file)
@@ -4716,13 +4716,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<uint32_t> maybe_crc;
     if (oi.is_data_digest() && op.checksum.offset == 0 &&
         op.checksum.length >= oi.size) {
index ea4d3e713e7aca1400faf08a4c53209275841bd1..f7ce348b0a0f863e77d95147709e053ac6aec4df 100644 (file)
@@ -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));
+}