]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
common/buffer: fix SIGABRT in rebuild_aligned_size_and_memory 42112/head
authorYin Congmin <congmin.yin@intel.com>
Wed, 30 Jun 2021 08:56:23 +0000 (16:56 +0800)
committerYin Congmin <congmin.yin@intel.com>
Fri, 9 Jul 2021 10:00:44 +0000 (18:00 +0800)
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>
src/common/buffer.cc
src/test/bufferlist.cc

index 548abc458fdc67ca81be0776d41ab80c3521e9d5..def1c52af01bd26c64bd0206c536167988604bec 100644 (file)
@@ -1258,8 +1258,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 9993c53e9f0a158688131b05898c0966df0dcf9c..4d830f6e97e1c7364b2a0c8597520dbc06530a53 100644 (file)
@@ -1848,6 +1848,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) {