1 ext4 crypto: teach ext4_htree_store_dirent() to store decrypted filenames
3 From: Theodore Ts'o <tytso@mit.edu>
5 For encrypted directories, we need to pass in a separate parameter for
6 the decrypted filename, since the directory entry contains the
9 Change-Id: I2d1a78e65cb81152cae108ce7faadc28b52e0abe
10 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
13 fs/ext4/dir.c | 15 ++++++++++-----
14 fs/ext4/ext4.h | 5 +++--
15 fs/ext4/inline.c | 7 +++++--
16 fs/ext4/namei.c | 21 +++++++++++++++++----
17 4 files changed, 35 insertions(+), 13 deletions(-)
19 diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
20 index c24143e..f67f955 100644
23 @@ -384,10 +384,15 @@ void ext4_htree_free_dir_info(struct dir_private_info *p)
26 * Given a directory entry, enter it into the fname rb tree.
28 + * When filename encryption is enabled, the dirent will hold the
29 + * encrypted filename, while the htree will hold decrypted filename.
30 + * The decrypted filename is passed in via ent_name. parameter.
32 int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
34 - struct ext4_dir_entry_2 *dirent)
35 + struct ext4_dir_entry_2 *dirent,
36 + struct ext4_str *ent_name)
38 struct rb_node **p, *parent = NULL;
39 struct fname *fname, *new_fn;
40 @@ -398,17 +403,17 @@ int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
41 p = &info->root.rb_node;
43 /* Create and allocate the fname structure */
44 - len = sizeof(struct fname) + dirent->name_len + 1;
45 + len = sizeof(struct fname) + ent_name->len + 1;
46 new_fn = kzalloc(len, GFP_KERNEL);
50 new_fn->minor_hash = minor_hash;
51 new_fn->inode = le32_to_cpu(dirent->inode);
52 - new_fn->name_len = dirent->name_len;
53 + new_fn->name_len = ent_name->len;
54 new_fn->file_type = dirent->file_type;
55 - memcpy(new_fn->name, dirent->name, dirent->name_len);
56 - new_fn->name[dirent->name_len] = 0;
57 + memcpy(new_fn->name, ent_name->name, ent_name->len);
58 + new_fn->name[ent_name->len] = 0;
62 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
63 index 89ca8a6..4da5c65 100644
66 @@ -2128,8 +2128,9 @@ extern int __ext4_check_dir_entry(const char *, unsigned int, struct inode *,
67 unlikely(__ext4_check_dir_entry(__func__, __LINE__, (dir), (filp), \
68 (de), (bh), (buf), (size), (offset)))
69 extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
71 - struct ext4_dir_entry_2 *dirent);
73 + struct ext4_dir_entry_2 *dirent,
74 + struct ext4_str *ent_name);
75 extern void ext4_htree_free_dir_info(struct dir_private_info *p);
76 extern int ext4_find_dest_de(struct inode *dir, struct inode *inode,
77 struct buffer_head *bh,
78 diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
79 index 4b143fe..056ef06 100644
80 --- a/fs/ext4/inline.c
81 +++ b/fs/ext4/inline.c
82 @@ -1327,6 +1327,7 @@ int htree_inlinedir_to_tree(struct file *dir_file,
83 struct ext4_iloc iloc;
85 struct ext4_dir_entry_2 fake;
86 + struct ext4_str tmp_str;
88 ret = ext4_get_inode_loc(inode, &iloc);
90 @@ -1398,8 +1399,10 @@ int htree_inlinedir_to_tree(struct file *dir_file,
94 - err = ext4_htree_store_dirent(dir_file,
95 - hinfo->hash, hinfo->minor_hash, de);
96 + tmp_str.name = de->name;
97 + tmp_str.len = de->name_len;
98 + err = ext4_htree_store_dirent(dir_file, hinfo->hash,
99 + hinfo->minor_hash, de, &tmp_str);
103 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
104 index 262aa1c..57cae22 100644
105 --- a/fs/ext4/namei.c
106 +++ b/fs/ext4/namei.c
107 @@ -880,6 +880,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
108 struct buffer_head *bh;
109 struct ext4_dir_entry_2 *de, *top;
110 int err = 0, count = 0;
111 + struct ext4_str tmp_str;
113 dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n",
114 (unsigned long)block));
115 @@ -906,8 +907,11 @@ static int htree_dirblock_to_tree(struct file *dir_file,
119 - if ((err = ext4_htree_store_dirent(dir_file,
120 - hinfo->hash, hinfo->minor_hash, de)) != 0) {
121 + tmp_str.name = de->name;
122 + tmp_str.len = de->name_len;
123 + err = ext4_htree_store_dirent(dir_file,
124 + hinfo->hash, hinfo->minor_hash, de, &tmp_str);
129 @@ -937,6 +941,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
133 + struct ext4_str tmp_str;
135 dxtrace(printk(KERN_DEBUG "In htree_fill_tree, start hash: %x:%x\n",
136 start_hash, start_minor_hash));
137 @@ -972,14 +977,22 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
138 /* Add '.' and '..' from the htree header */
139 if (!start_hash && !start_minor_hash) {
140 de = (struct ext4_dir_entry_2 *) frames[0].bh->b_data;
141 - if ((err = ext4_htree_store_dirent(dir_file, 0, 0, de)) != 0)
142 + tmp_str.name = de->name;
143 + tmp_str.len = de->name_len;
144 + err = ext4_htree_store_dirent(dir_file, 0, 0,
150 if (start_hash < 2 || (start_hash ==2 && start_minor_hash==0)) {
151 de = (struct ext4_dir_entry_2 *) frames[0].bh->b_data;
152 de = ext4_next_entry(de, dir->i_sb->s_blocksize);
153 - if ((err = ext4_htree_store_dirent(dir_file, 2, 0, de)) != 0)
154 + tmp_str.name = de->name;
155 + tmp_str.len = de->name_len;
156 + err = ext4_htree_store_dirent(dir_file, 2, 0,