]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: check image size on crypto format
authorOr Ozeri <oro@il.ibm.com>
Thu, 24 Dec 2020 21:35:33 +0000 (23:35 +0200)
committerOr Ozeri <oro@il.ibm.com>
Tue, 5 Jan 2021 18:28:04 +0000 (20:28 +0200)
This commit adds a check to verify that an image is big enough before crypto formatting it.

Signed-off-by: Or Ozeri <oro@il.ibm.com>
src/librbd/crypto/luks/FormatRequest.cc
src/test/librbd/crypto/luks/test_mock_FormatRequest.cc

index 7bf77dff8862620ba2d3d84c672a22e293b8ec76..205c118d779f13b9aa048b48cdb7645635c8f569 100644 (file)
@@ -92,6 +92,17 @@ void FormatRequest<I>::send() {
     return;
   }
 
+  m_image_ctx->image_lock.lock_shared();
+  uint64_t image_size = m_image_ctx->get_image_size(CEPH_NOSNAP);
+  m_image_ctx->image_lock.unlock_shared();
+
+  if (m_header.get_data_offset() >= image_size) {
+    lderr(m_image_ctx->cct) << "image is too small. format requires more than "
+                            << m_header.get_data_offset() << " bytes" << dendl;
+    finish(-ENOSPC);
+    return;
+  }
+
   // add keyslot (volume key encrypted with passphrase)
   r = m_header.add_keyslot(m_passphrase.c_str(), m_passphrase.size());
   if (r != 0) {
index 36f99fef6d36ae77445ff81d3d253f8440328a04..0b7c71e262918a619b0c4a71122d46e940692098 100644 (file)
@@ -29,6 +29,7 @@ struct TestMockCryptoLuksFormatRequest : public TestMockFixture {
   typedef FormatRequest<librbd::MockImageCtx> MockFormatRequest;
 
   const size_t OBJECT_SIZE = 4 * 1024 * 1024;
+  const size_t IMAGE_SIZE = 1024 * 1024 * 1024;
   const char* passphrase_cstr = "password";
   std::string passphrase = passphrase_cstr;
 
@@ -60,6 +61,11 @@ struct TestMockCryptoLuksFormatRequest : public TestMockFixture {
     EXPECT_CALL(*mock_image_ctx->io_object_dispatcher, exists(
             io::OBJECT_DISPATCH_LAYER_CRYPTO)).WillOnce(Return(exists));
   }
+                         
+  void expect_get_image_size(uint64_t image_size) {
+    EXPECT_CALL(*mock_image_ctx, get_image_size(CEPH_NOSNAP)).WillOnce(Return(
+            image_size));
+  }
 
   void expect_image_write() {
     EXPECT_CALL(*mock_image_ctx->io_image_dispatcher, send(_))
@@ -114,6 +120,7 @@ TEST_F(TestMockCryptoLuksFormatRequest, LUKS1) {
           on_finish, true);
   expect_crypto_layer_exists_check();
   expect_get_object_size();
+  expect_get_image_size(IMAGE_SIZE);
   expect_image_write();
   mock_format_request->send();
   ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
@@ -129,6 +136,7 @@ TEST_F(TestMockCryptoLuksFormatRequest, AES128) {
           on_finish, true);
   expect_crypto_layer_exists_check();
   expect_get_object_size();
+  expect_get_image_size(IMAGE_SIZE);
   expect_image_write();
   mock_format_request->send();
   ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
@@ -144,6 +152,7 @@ TEST_F(TestMockCryptoLuksFormatRequest, AES256) {
           on_finish, true);
   expect_crypto_layer_exists_check();
   expect_get_object_size();
+  expect_get_image_size(IMAGE_SIZE);
   expect_image_write();
   mock_format_request->send();
   ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
@@ -162,6 +171,17 @@ TEST_F(TestMockCryptoLuksFormatRequest, CryptoAlreadyLoaded) {
   ASSERT_EQ(-EEXIST, finished_cond.wait());
 }
 
+TEST_F(TestMockCryptoLuksFormatRequest, ImageTooSmall) {
+  auto mock_format_request = MockFormatRequest::create(
+          mock_image_ctx, RBD_ENCRYPTION_FORMAT_LUKS2,
+          RBD_ENCRYPTION_ALGORITHM_AES256, std::move(passphrase), on_finish,
+          true);
+  expect_get_object_size();
+  expect_get_image_size(1024*1024);
+  mock_format_request->send();
+  ASSERT_EQ(-ENOSPC, finished_cond.wait());
+}
+
 TEST_F(TestMockCryptoLuksFormatRequest, WriteFail) {
   auto mock_format_request = MockFormatRequest::create(
           mock_image_ctx, DiskEncryptionFormat::DISK_ENCRYPTION_FORMAT_LUKS2,
@@ -169,6 +189,7 @@ TEST_F(TestMockCryptoLuksFormatRequest, WriteFail) {
           on_finish, true);
   expect_crypto_layer_exists_check();
   expect_get_object_size();
+  expect_get_image_size(IMAGE_SIZE);
   expect_image_write();
   mock_format_request->send();
   ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));