diff mbox series

[v3,20/22] btrfs: adapt lookup for partially encrypted directories

Message ID b9ed56c4b9e254f10ea296dc013fb9a93f9b66e3.1666281277.git.sweettea-kernel@dorminy.me (mailing list archive)
State New, archived
Headers show
Series btrfs: add fscrypt integration | expand

Commit Message

Sweet Tea Dorminy Oct. 20, 2022, 4:58 p.m. UTC
With the possibility of partially encrypted directories, lookup needs to
try both the unencrypted and encrypted names.

Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
---
 fs/btrfs/dir-item.c | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c
index d49bc19b91da..dc95ac987006 100644
--- a/fs/btrfs/dir-item.c
+++ b/fs/btrfs/dir-item.c
@@ -469,21 +469,40 @@  struct btrfs_dir_item *btrfs_match_dir_item_fname(struct btrfs_fs_info *fs_info,
 	u32 cur = 0;
 	u32 this_len;
 	struct extent_buffer *leaf;
+	bool encrypted = (name->crypto_buf.name != NULL);
+	struct fscrypt_name unencrypted_name;
+
+	if (encrypted) {
+		unencrypted_name = (struct fscrypt_name){
+			.usr_fname = name->usr_fname,
+			.disk_name = {
+				.name = (unsigned char *)name->usr_fname->name,
+				.len = name->usr_fname->len,
+			},
+		};
+	}
 
 	leaf = path->nodes[0];
 	dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item);
 
 	total_len = btrfs_item_size(leaf, path->slots[0]);
 	while (cur < total_len) {
-		this_len = sizeof(*dir_item) +
-			btrfs_dir_name_len(leaf, dir_item) +
+		u64 dir_name_len = btrfs_dir_name_len(leaf, dir_item);
+
+		this_len = sizeof(*dir_item) + dir_name_len +
 			btrfs_dir_data_len(leaf, dir_item);
 		name_ptr = (unsigned long)(dir_item + 1);
 
 		if (btrfs_fscrypt_match_name(name, leaf, name_ptr,
-					     btrfs_dir_name_len(leaf, dir_item)))
+					     dir_name_len))
 			return dir_item;
 
+		if (encrypted &&
+		    btrfs_fscrypt_match_name(&unencrypted_name, leaf,
+					     name_ptr, dir_name_len)) {
+			return dir_item;
+		}
+
 		cur += this_len;
 		dir_item = (struct btrfs_dir_item *)((char *)dir_item +
 						     this_len);