From 05a49aeeb3897a41e26d005c5143fdfe739d5c1b Mon Sep 17 00:00:00 2001 From: Yin Congmin Date: Wed, 30 Jun 2021 16:56:23 +0800 Subject: [PATCH] common/buffer: fix SIGABRT in rebuild_aligned_size_and_memory 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 --- src/common/buffer.cc | 8 ++++++-- src/test/bufferlist.cc | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/common/buffer.cc b/src/common/buffer.cc index 548abc458fdc6..def1c52af01bd 100644 --- a/src/common/buffer.cc +++ b/src/common/buffer.cc @@ -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; diff --git a/src/test/bufferlist.cc b/src/test/bufferlist.cc index 9993c53e9f0a1..4d830f6e97e1c 100644 --- a/src/test/bufferlist.cc +++ b/src/test/bufferlist.cc @@ -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) { -- 2.39.5