1 ext4 crypto: insert encrypted filenames into a leaf directory block
3 From: Michael Halcrow <mhalcrow@google.com>
5 Signed-off-by: Uday Savagaonkar <savagaon@google.com>
6 Signed-off-by: Ildar Muslukhov <ildarm@google.com>
7 Signed-off-by: Michael Halcrow <mhalcrow@google.com>
8 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
10 fs/ext4/ext4.h | 4 +++-
11 fs/ext4/inline.c | 7 +++++--
12 fs/ext4/namei.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
13 3 files changed, 79 insertions(+), 13 deletions(-)
15 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
16 index 7229159..08d2930 100644
19 @@ -2136,9 +2136,11 @@ extern int ext4_find_dest_de(struct inode *dir, struct inode *inode,
20 void *buf, int buf_size,
21 const char *name, int namelen,
22 struct ext4_dir_entry_2 **dest_de);
23 -void ext4_insert_dentry(struct inode *inode,
24 +int ext4_insert_dentry(struct inode *dir,
25 + struct inode *inode,
26 struct ext4_dir_entry_2 *de,
28 + const struct qstr *iname,
29 const char *name, int namelen);
30 static inline void ext4_update_dx_flag(struct inode *inode)
32 diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
33 index 056ef06..0dc619b 100644
34 --- a/fs/ext4/inline.c
35 +++ b/fs/ext4/inline.c
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
41 +#include <linux/fiemap.h>
43 #include "ext4_jbd2.h"
47 -#include <linux/fiemap.h>
49 #define EXT4_XATTR_SYSTEM_DATA "data"
50 #define EXT4_MIN_INLINE_DATA_SIZE ((sizeof(__le32) * EXT4_N_BLOCKS))
51 @@ -1014,7 +1016,8 @@ static int ext4_add_dirent_to_inline(handle_t *handle,
52 err = ext4_journal_get_write_access(handle, iloc->bh);
55 - ext4_insert_dentry(inode, de, inline_size, name, namelen);
56 + ext4_insert_dentry(dir, inode, de, inline_size, &dentry->d_name,
59 ext4_show_inline_dir(dir, iloc->bh, inline_start, inline_size);
61 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
62 index 57cae22..f3234d4 100644
65 @@ -1663,19 +1663,49 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
69 -void ext4_insert_dentry(struct inode *inode,
70 - struct ext4_dir_entry_2 *de,
72 - const char *name, int namelen)
73 +int ext4_insert_dentry(struct inode *dir,
74 + struct inode *inode,
75 + struct ext4_dir_entry_2 *de,
77 + const struct qstr *iname,
78 + const char *name, int namelen)
82 + struct ext4_fname_crypto_ctx *ctx = NULL;
83 + struct ext4_str fname_crypto_str = {.name = NULL, .len = 0};
84 + struct ext4_str tmp_str;
87 + ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN);
90 + /* By default, the input name would be written to the disk */
91 + tmp_str.name = (unsigned char *)name;
92 + tmp_str.len = namelen;
94 + /* Directory is encrypted */
95 + res = ext4_fname_crypto_alloc_buffer(ctx, EXT4_NAME_LEN,
98 + ext4_put_fname_crypto_ctx(&ctx);
101 + res = ext4_fname_usr_to_disk(ctx, iname, &fname_crypto_str);
103 + ext4_put_fname_crypto_ctx(&ctx);
104 + ext4_fname_crypto_free_buffer(&fname_crypto_str);
107 + tmp_str.name = fname_crypto_str.name;
108 + tmp_str.len = fname_crypto_str.len;
111 nlen = EXT4_DIR_REC_LEN(de->name_len);
112 rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);
114 struct ext4_dir_entry_2 *de1 =
115 - (struct ext4_dir_entry_2 *)((char *)de + nlen);
116 + (struct ext4_dir_entry_2 *)((char *)de + nlen);
117 de1->rec_len = ext4_rec_len_to_disk(rlen - nlen, buf_size);
118 de->rec_len = ext4_rec_len_to_disk(nlen, buf_size);
120 @@ -1683,9 +1713,14 @@ void ext4_insert_dentry(struct inode *inode,
121 de->file_type = EXT4_FT_UNKNOWN;
122 de->inode = cpu_to_le32(inode->i_ino);
123 ext4_set_de_type(inode->i_sb, de, inode->i_mode);
124 - de->name_len = namelen;
125 - memcpy(de->name, name, namelen);
126 + de->name_len = tmp_str.len;
128 + memcpy(de->name, tmp_str.name, tmp_str.len);
129 + ext4_put_fname_crypto_ctx(&ctx);
130 + ext4_fname_crypto_free_buffer(&fname_crypto_str);
135 * Add a new entry into a directory (leaf) block. If de is non-NULL,
136 * it points to a directory entry which is guaranteed to be large
137 @@ -1722,8 +1757,12 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
141 - /* By now the buffer is marked for journaling */
142 - ext4_insert_dentry(inode, de, blocksize, name, namelen);
143 + /* By now the buffer is marked for journaling. Due to crypto operations,
144 + * the following function call may fail */
145 + err = ext4_insert_dentry(dir, inode, de, blocksize, &dentry->d_name,
151 * XXX shouldn't update any times until successful
152 @@ -1755,8 +1794,13 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
153 struct inode *inode, struct buffer_head *bh)
155 struct inode *dir = dentry->d_parent->d_inode;
156 +#ifdef CONFIG_EXT4_FS_ENCRYPTION
157 + struct ext4_fname_crypto_ctx *ctx = NULL;
160 const char *name = dentry->d_name.name;
161 int namelen = dentry->d_name.len;
163 struct buffer_head *bh2;
164 struct dx_root *root;
165 struct dx_frame frames[2], *frame;
166 @@ -1770,7 +1814,13 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
167 struct dx_hash_info hinfo;
169 struct fake_dirent *fde;
173 +#ifdef CONFIG_EXT4_FS_ENCRYPTION
174 + ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN);
176 + return PTR_ERR(ctx);
179 if (ext4_has_metadata_csum(inode->i_sb))
180 csum_size = sizeof(struct ext4_dir_entry_tail);
181 @@ -1837,7 +1887,18 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
182 if (hinfo.hash_version <= DX_HASH_TEA)
183 hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned;
184 hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
185 +#ifdef CONFIG_EXT4_FS_ENCRYPTION
186 + res = ext4_fname_usr_to_hash(ctx, &dentry->d_name, &hinfo);
188 + ext4_put_fname_crypto_ctx(&ctx);
189 + ext4_mark_inode_dirty(handle, dir);
193 + ext4_put_fname_crypto_ctx(&ctx);
195 ext4fs_dirhash(name, namelen, &hinfo);
197 memset(frames, 0, sizeof(frames));
199 frame->entries = entries;