From febdfd6046e37c48e4a1d4debee829a8e59df25e Mon Sep 17 00:00:00 2001 From: Christopher Hoffman Date: Fri, 1 Dec 2023 17:18:03 +0000 Subject: [PATCH] client: On fscrypt enabled directories, only allow read/write to files in dir when unlocked. Client should not be able to read/write the encrypted payload. Signed-off-by: Christopher Hoffman --- src/client/Client.cc | 24 ++++++++++++++++++++++++ src/client/Client.h | 1 + src/client/Inode.h | 5 ++++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index 6bf8013449a..f1091be20ff 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -6325,6 +6325,9 @@ int Client::may_open(const InodeRef& in, int flags, const UserPerm& perms) ldout(cct, 20) << __func__ << " " << *in << "; " << perms << dendl; unsigned want = 0; + if (!in->is_dir() && is_inode_locked(in)) + return -ENOKEY; + if ((flags & O_ACCMODE) == O_WRONLY) want = CLIENT_MAY_WRITE; else if ((flags & O_ACCMODE) == O_RDWR) @@ -6364,6 +6367,7 @@ out: int Client::may_lookup(const InodeRef& dir, const UserPerm& perms) { ldout(cct, 20) << __func__ << " " << *dir << "; " << perms << dendl; + int r = _getattr_for_perm(dir, perms); if (r < 0) goto out; @@ -6377,6 +6381,9 @@ out: int Client::may_create(const InodeRef& dir, const UserPerm& perms) { ldout(cct, 20) << __func__ << " " << *dir << "; " << perms << dendl; + if (dir->is_dir() && is_inode_locked(dir)) + return -ENOKEY; + int r = _getattr_for_perm(dir, perms); if (r < 0) goto out; @@ -16187,6 +16194,18 @@ int Client::ll_rmdir(Inode *in, const char *name, const UserPerm& perms) return _rmdir(in, name, perms); } +bool Client::is_inode_locked(Inode *to_check) +{ + if (to_check && to_check->fscrypt_ctx) { + FSCryptKeyHandlerRef kh; + int r = fscrypt->get_key_store().find(to_check->fscrypt_ctx->master_key_identifier, kh); + if (r < 0) { + return true; + } + } + return false; +} + int Client::_rename(Inode *fromdir, const char *fromname, Inode *todir, const char *toname, const UserPerm& perm, std::string alternate_name) { ldout(cct, 8) << "_rename(" << fromdir->ino << " " << fromname << " to " @@ -16223,6 +16242,11 @@ int Client::_rename(Inode *fromdir, const char *fromname, Inode *todir, const ch return -EINVAL; } + bool source_locked = is_inode_locked(fromdir); + bool dest_locked = is_inode_locked(todir); + if (source_locked || dest_locked) + return -ENOKEY; + if (wdr_from.diri->snapid != wdr_to.diri->snapid) return -EXDEV; diff --git a/src/client/Client.h b/src/client/Client.h index f97bb4517b1..c31b107c223 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -1997,6 +1997,7 @@ private: int _link(Inode *diri_from, const char* path_from, Inode* diri_to, const char* path_to, const UserPerm& perm, std::string alternate_name); int _unlink(Inode *dir, const char *name, const UserPerm& perm); + bool is_inode_locked(Inode *to_check); int _rename(Inode *olddir, const char *oname, Inode *ndir, const char *nname, const UserPerm& perm, std::string alternate_name); int _mkdir(const walk_dentry_result& wdr, mode_t mode, const UserPerm& perm, InodeRef *inp = 0, const std::map &metadata={}, diff --git a/src/client/Inode.h b/src/client/Inode.h index a99f3732257..7bd223e0171 100644 --- a/src/client/Inode.h +++ b/src/client/Inode.h @@ -140,6 +140,7 @@ struct Inode : RefCountedObject { uint32_t mode = 0; uid_t uid = 0; gid_t gid = 0; + uint32_t i_flags; // nlink int32_t nlink = 0; @@ -195,7 +196,9 @@ struct Inode : RefCountedObject { bool is_symlink() const { return (mode & S_IFMT) == S_IFLNK; } bool is_dir() const { return (mode & S_IFMT) == S_IFDIR; } bool is_file() const { return (mode & S_IFMT) == S_IFREG; } - bool is_encrypted() const { return (mode & S_ENCRYPTED) == S_ENCRYPTED; } + + // use i_flags as 1 << 14 will overlap with other mode bits. + bool is_encrypted() const { return (i_flags & S_ENCRYPTED) == S_ENCRYPTED; } bool has_dir_layout() const { return layout != file_layout_t(); -- 2.39.5