From 42bc52dbe06a7893990498e76c33d10f4d3725dc Mon Sep 17 00:00:00 2001 From: Christopher Hoffman Date: Thu, 23 Jan 2025 20:22:10 +0000 Subject: [PATCH] client: Use symlink_plain for decrypted fscrypt name Use symlink_plain for only the value of a decrypted fscrypt dname. Signed-off-by: Christopher Hoffman --- src/client/Client.cc | 29 ++++++++++++++++++----------- src/client/Inode.h | 2 +- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index c868acd477c..4a366e561e3 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -1813,8 +1813,6 @@ Inode* Client::insert_trace(MetaRequest *request, MetaSession *session) ldout(cct, 0) << __FILE__ << ":" << __LINE__ << ": failed to decrypt symlink (r=" << ret << ")" << dendl; } in->symlink_plain = slname; - } else { - in->symlink_plain = in->symlink; } } } @@ -7636,8 +7634,6 @@ int Client::_do_lookup(const InodeRef& dir, const string& name, int mask, ldout(cct, 0) << __FILE__ << ":" << __LINE__ << ": failed to decrypt symlink (r=" << ret << ")" << dendl; } inode->symlink_plain = slname; - } else { - inode->symlink_plain = inode->symlink; } } @@ -8219,14 +8215,25 @@ int Client::_readlink(const InodeRef& diri, const char* relpath, char *buf, size r = size; auto fscrypt_denc = fscrypt->get_fname_denc(in->fscrypt_ctx, &in->fscrypt_key_validator, true); - if (fscrypt_denc && in->symlink_plain.empty()) { - string dname; - int ret = fscrypt_denc->get_decrypted_symlink(in->symlink, &dname); - if (ret < 0) { - ldout(cct, 0) << __FILE__ << ":" << __LINE__ << ": failed to decrypt symlink (r=" << ret << ")" << dendl; + + //There are three states a symlink could be in + // 1. Encrypted symlink not yet decrypted into memory + // 2. Encrypted symlink decrypted into memory + // 3. Regular symlink + if (fscrypt_denc) { + if (in->symlink_plain.empty()) { + string dname; + int ret = fscrypt_denc->get_decrypted_symlink(in->symlink, &dname); + if (ret < 0) { + ldout(cct, 0) << __FILE__ << ":" << __LINE__ << ": failed to decrypt symlink (r=" << ret << ")" << dendl; + } + memcpy(buf, dname.c_str(), dname.size()); + r = dname.size(); + } else { + // already buffered, copy plaintext to buf + memcpy(buf, in->symlink_plain.c_str(), in->symlink_plain.length()); + r = in->symlink_plain.length(); } - memcpy(buf, dname.c_str(), dname.size()); - r = dname.size(); } else { memcpy(buf, in->symlink.c_str(), r); } diff --git a/src/client/Inode.h b/src/client/Inode.h index a0d2fa519da..1ed80c540c2 100644 --- a/src/client/Inode.h +++ b/src/client/Inode.h @@ -272,7 +272,7 @@ struct Inode : RefCountedObject { uint64_t ll_ref = 0; // separate ref count for ll client xlist dentries; // if i'm linked to a dentry. std::string symlink; // symlink content, if it's a symlink - std::string symlink_plain; // decoded symlink (in-memory only) + std::string symlink_plain; // decrypted/decoded symlink (in-memory only) std::map xattrs; std::map fragmap; // known frag -> mds mappings std::map> frag_repmap; // non-auth mds mappings -- 2.39.5