From: Christopher Hoffman Date: Tue, 17 Dec 2024 16:09:20 +0000 (+0000) Subject: test, client: implement tests for not supported FALLOC ops, use policy to determine... X-Git-Tag: testing/wip-vshankar-testing-20260120.085915-debug^2~13^2~97 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=5e693cbd9bde1c480fcc4c0cfa92fa49d176c171;p=ceph-ci.git test, client: implement tests for not supported FALLOC ops, use policy to determine the padding size for encrypted filename 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 Signed-off-by: Christopher Hoffman --- diff --git a/src/client/FSCrypt.cc b/src/client/FSCrypt.cc index 7cc6ec81723..b1ca273afce 100644 --- a/src/client/FSCrypt.cc +++ b/src/client/FSCrypt.cc @@ -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) { diff --git a/src/client/FSCrypt.h b/src/client/FSCrypt.h index b209941701c..53d3a8afa76 100644 --- a/src/client/FSCrypt.h +++ b/src/client/FSCrypt.h @@ -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; @@ -225,7 +231,6 @@ protected: std::vector 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; diff --git a/src/test/libcephfs/fscrypt.cc b/src/test/libcephfs/fscrypt.cc index f1c33b147cd..a7ce1c1001d 100644 --- a/src/test/libcephfs/fscrypt.cc +++ b/src/test/libcephfs/fscrypt.cc @@ -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();