]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
common/buffer: fix SIGABRT in rebuild_aligned_size_and_memory 42976/head
authorYin Congmin <congmin.yin@intel.com>
Wed, 30 Jun 2021 08:56:23 +0000 (16:56 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 30 Aug 2021 13:38:35 +0000 (15:38 +0200)
There is such a bl, which needs to satisfy two conditions:
1)all ptrs' length sum except last ptr is aligned with 4K;
2)the length of last ptr is 0.
This bl will cause stack corruption when calling
bufferlist::rebuild_aligned_size_and_memory().

Deal with this special scenario in rebuild_aligned_size_and_memory() to
solve the bug. And added a specialtest-case to reproduce this scenario.

Fixes: https://tracker.ceph.com/issues/51419
Signed-off-by: Yin Congmin <congmin.yin@intel.com>
(cherry picked from commit 05a49aeeb3897a41e26d005c5143fdfe739d5c1b)

src/common/buffer.cc
src/test/bufferlist.cc

index 406ca24a4a63c482f2a49095505f68c617fda514..31154c96fc7a616a356e8a2fa631fbc843d8f3f3 100644 (file)
@@ -1254,8 +1254,12 @@ static ceph::spinlock debug_lock;
             buffer::create_aligned(unaligned._len, align_memory)));
         had_to_rebuild = true;
       }
-      _buffers.insert_after(p_prev, *ptr_node::create(unaligned._buffers.front()).release());
-      _num += 1;
+      if (unaligned.get_num_buffers()) {
+        _buffers.insert_after(p_prev, *ptr_node::create(unaligned._buffers.front()).release());
+        _num += 1;
+      } else {
+        // a bufferlist containing only 0-length bptrs is rebuilt as empty
+      }
       ++p_prev;
     }
     return had_to_rebuild;
index 74d23de0bc181a7e45faadd8a26c1416443b44be..43c0f8031a116820e328b549d2c550382fae5cf3 100644 (file)
@@ -1731,6 +1731,23 @@ TEST(BufferList, rebuild_aligned_size_and_memory) {
   EXPECT_TRUE(bl.is_aligned(SIMD_ALIGN));
   EXPECT_TRUE(bl.is_n_align_sized(BUFFER_SIZE));
   EXPECT_EQ(3U, bl.get_num_buffers());
+
+  {
+    /* bug replicator, to test rebuild_aligned_size_and_memory() in the
+     * scenario where the first bptr is both size and memory aligned and
+     * the second is 0-length */
+    bl.clear();
+    bufferptr ptr1(buffer::create_aligned(4096, 4096));
+    bl.append(ptr1);
+    bufferptr ptr(10);
+    /* bl.back().length() must be 0 */
+    bl.append(ptr, 0, 0);
+    EXPECT_EQ(bl.get_num_buffers(), 2);
+    EXPECT_EQ(bl.back().length(), 0);
+    /* rebuild_aligned() calls rebuild_aligned_size_and_memory() */
+    bl.rebuild_aligned(4096);
+    EXPECT_EQ(bl.get_num_buffers(), 1);
+  }
 }
 
 TEST(BufferList, is_zero) {