]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
test, client: implement tests for not supported FALLOC ops, use policy to determine...
authorChristopher Hoffman <choffman@redhat.com>
Tue, 17 Dec 2024 16:09:20 +0000 (16:09 +0000)
committerChristopher Hoffman <choffman@redhat.com>
Wed, 5 Nov 2025 13:59:34 +0000 (13:59 +0000)
Adding test for not supported FALLOC ops on the encypted tree
Using policy to determine the padding length for encrypted file names and symlinks

Fixes: https://tracker.ceph.com/issues/64162
https://tracker.ceph.com/issues/64131
Author: Igor Golikov <igolikov@ibm.com>
Signed-off-by: Christopher Hoffman <choffman@redhat.com>
src/client/FSCrypt.cc
src/client/FSCrypt.h
src/test/libcephfs/fscrypt.cc

index 7cc6ec817232876c274f95de2507b318c4d4d69b..b1ca273afce080b5f04c4018aff21b90972a245c 100644 (file)
@@ -596,7 +596,6 @@ bool FSCryptDenc::do_setup_cipher(int enc_mode)
     init_cipher(EVP_CIPHER_fetch(NULL, opts.str, NULL), {} );
   }
 
-  padding = 4 << (ctx->flags & FSCRYPT_POLICY_FLAGS_PAD_MASK);
   key_size = opts.key_size;
   iv_size = opts.iv_size;
 
@@ -726,20 +725,27 @@ FSCryptDenc::~FSCryptDenc()
   EVP_CIPHER_CTX_free(cipher_ctx);
 }
 
+int FSCryptFNameDenc::get_encrypted_name_length(const int& plain_size) const
+{
+   int padding_size = ctx->get_filename_padding_bytes();
+   int padded_size = (plain_size + padding_size - 1) & ~ (padding_size - 1);
+   if (padded_size > NAME_MAX) {
+    padded_size = NAME_MAX;
+  }
+  return padded_size;
+}
+
 int FSCryptFNameDenc::get_encrypted_fname(const std::string& plain, std::string *encrypted, std::string *alt_name)
 {
   auto plain_size = plain.size();
-  int dec_size = (plain.size() + padding - 1) & ~(padding - 1); // FIXME, need to be based on policy
-  if (dec_size > NAME_MAX) {
-    dec_size = NAME_MAX;
-  }
+  auto filename_padded_size = get_encrypted_name_length(plain_size);
 
-  char orig[dec_size];
+  char orig[filename_padded_size];
   memcpy(orig, plain.c_str(), plain_size);
-  memset(orig + plain_size, 0, dec_size - plain_size);
+  memset(orig + plain_size, 0, filename_padded_size - plain_size);
 
   char enc_name[NAME_MAX + 64]; /* some extra just in case */
-  int r = encrypt(orig, dec_size,
+  int r = encrypt(orig, filename_padded_size,
                   enc_name, sizeof(enc_name));
 
   if (r < 0) {
@@ -805,14 +811,14 @@ struct fscrypt_slink_data {
 int FSCryptFNameDenc::get_encrypted_symlink(const std::string& plain, std::string *encrypted)
 {
   auto plain_size = plain.size();
-  int dec_size = (plain.size() + 31) & ~31; // FIXME, need to be based on policy
+  auto symlink_padded_size = get_encrypted_name_length(plain_size);
 
-  char orig[dec_size];
+  char orig[symlink_padded_size];
   memcpy(orig, plain.c_str(), plain_size);
-  memset(orig + plain_size, 0, dec_size - plain_size);
+  memset(orig + plain_size, 0, symlink_padded_size - plain_size);
 
   fscrypt_slink_data slink_data;
-  int r = encrypt(orig, dec_size,
+  int r = encrypt(orig, symlink_padded_size,
                   slink_data.enc, sizeof(slink_data.enc));
 
   if (r < 0) {
index b209941701cdc53a7b474d814d610495e6224a67..53d3a8afa765c23a668853ff96ff54f459dbbd50 100644 (file)
@@ -190,6 +190,12 @@ public:
     memset(dest->__reserved, 0, sizeof(dest->__reserved));
     memcpy(dest->master_key_identifier, master_key_identifier.raw, sizeof(master_key_identifier.raw));
   }
+
+  uint8_t get_filename_padding_bytes() const {
+      uint8_t padding_bits = flags & FSCRYPT_POLICY_FLAGS_PAD_MASK;
+      uint8_t padding_bytes = 4 << padding_bits;
+      return padding_bytes;
+  }
 };
 
 using FSCryptPolicyRef = std::shared_ptr<FSCryptPolicy>;
@@ -225,7 +231,6 @@ protected:
   std::vector<char> key;
   FSCryptIV iv;
 
-  int padding = 1;
   int key_size = 0;
   int iv_size = 0;
 
@@ -276,6 +281,8 @@ public:
 
   int get_encrypted_symlink(const std::string& plain, std::string *encrypted);
   int get_decrypted_symlink(const std::string& b64enc, std::string *decrypted);
+private:
+  int get_encrypted_name_length(const int& plain_size) const;
 };
 
 using FSCryptFNameDencRef = std::shared_ptr<FSCryptFNameDenc>;
index f1c33b147cd2c6ed6b15de2a0c55f0ba4b7c0dff..a7ce1c1001d19d9a3bf59a2e8f6ad703bb7d5c24 100644 (file)
@@ -950,6 +950,56 @@ TEST(FSCrypt, RemoveBusyCreate) {
   ceph_shutdown(cmount);
 }
 
+// this test verifies that fuse client doesn't support falloate ops
+// FALLOC_FL_COLLAPSE_RANGE, FALLOC_FL_COLLAPSE_RANGE, FALLOC_FL_INSERT_RANGE
+// if this test fails, it means that these ops has been impleneted AND we must reject these ops for encrypted files
+// see https://www.kernel.org/doc/html/v4.18/filesystems/fscrypt.html Access Semantics section
+TEST(FSCrypt, FallocateNotImplemented) {
+  struct ceph_fscrypt_key_identifier kid;
+  struct ceph_mount_info *cmount;
+  int r = init_mount(&cmount);
+  ASSERT_EQ(0, r);
+
+  // init fscrypt on dir
+  string dir_path = "dir1";
+  ceph_mkdir(cmount, dir_path.c_str(), 0777);
+  int fd = ceph_open(cmount, dir_path.c_str(), O_DIRECTORY, 0);
+  r = ceph_add_fscrypt_key(cmount, fscrypt_key, sizeof(fscrypt_key), &kid, 1299);
+  struct fscrypt_policy_v2 policy;
+  policy.version = 2;
+  policy.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS;
+  policy.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS;
+  policy.flags = FSCRYPT_POLICY_FLAGS_PAD_32;
+  memcpy(policy.master_key_identifier, kid.raw, FSCRYPT_KEY_IDENTIFIER_SIZE);
+  r = ceph_set_fscrypt_policy_v2(cmount, fd, &policy);
+  ceph_close(cmount, fd);
+
+  //add file to fscrypt enabled directory and write some data to the file
+  string file_name = "file1";
+  string file_path = "";
+  file_path.append(dir_path);
+  file_path.append("/");
+  file_path.append(file_name);
+  fd = ceph_open(cmount, file_path.c_str(), O_RDWR|O_CREAT|O_TRUNC, 0600);
+  r = ceph_write(cmount, fd, fscrypt_key, sizeof(fscrypt_key), 0);
+  ASSERT_EQ(32, r);
+
+  // try to fallocate opened file with non supported flags
+  r = ceph_fallocate(cmount, fd, FALLOC_FL_COLLAPSE_RANGE, 0, 64);
+  ASSERT_EQ(-EOPNOTSUPP, r);
+  r = ceph_fallocate(cmount, fd, FALLOC_FL_ZERO_RANGE, 0, 64);
+  ASSERT_EQ(-EOPNOTSUPP, r);
+  r = ceph_fallocate(cmount, fd, FALLOC_FL_INSERT_RANGE, 0, 64);
+  ASSERT_EQ(-EOPNOTSUPP, r);
+
+  // cleanup
+  ceph_close(cmount, fd);
+  ceph_unlink(cmount, file_path.c_str());
+  ceph_rmdir(cmount, dir_path.c_str());
+
+  ceph_shutdown(cmount);
+}
+
 int main(int argc, char **argv)
 {
   int r = update_root_mode();