aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2015-04-12 00:56:26 -0400
committerTheodore Ts'o <tytso@mit.edu>2015-04-12 00:56:26 -0400
commit2f61830ae33e2944ad66bb8bb40916f534b2e494 (patch)
tree7bd66dc3c940e88bea7b01db6b15199e25e5716e
parentd5d0e8c7203a41c01ba05f4e053e16a94ce3c2e1 (diff)
ext4 crypto: teach ext4_htree_store_dirent() to store decrypted filenames
For encrypted directories, we need to pass in a separate parameter for the decrypted filename, since the directory entry contains the encrypted filename. Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--fs/ext4/dir.c15
-rw-r--r--fs/ext4/ext4.h5
-rw-r--r--fs/ext4/inline.c7
-rw-r--r--fs/ext4/namei.c21
4 files changed, 35 insertions, 13 deletions
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index 9e1e9e7869cb..315f13ad382e 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -382,10 +382,15 @@ void ext4_htree_free_dir_info(struct dir_private_info *p)
382 382
383/* 383/*
384 * Given a directory entry, enter it into the fname rb tree. 384 * Given a directory entry, enter it into the fname rb tree.
385 *
386 * When filename encryption is enabled, the dirent will hold the
387 * encrypted filename, while the htree will hold decrypted filename.
388 * The decrypted filename is passed in via ent_name. parameter.
385 */ 389 */
386int ext4_htree_store_dirent(struct file *dir_file, __u32 hash, 390int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
387 __u32 minor_hash, 391 __u32 minor_hash,
388 struct ext4_dir_entry_2 *dirent) 392 struct ext4_dir_entry_2 *dirent,
393 struct ext4_str *ent_name)
389{ 394{
390 struct rb_node **p, *parent = NULL; 395 struct rb_node **p, *parent = NULL;
391 struct fname *fname, *new_fn; 396 struct fname *fname, *new_fn;
@@ -396,17 +401,17 @@ int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
396 p = &info->root.rb_node; 401 p = &info->root.rb_node;
397 402
398 /* Create and allocate the fname structure */ 403 /* Create and allocate the fname structure */
399 len = sizeof(struct fname) + dirent->name_len + 1; 404 len = sizeof(struct fname) + ent_name->len + 1;
400 new_fn = kzalloc(len, GFP_KERNEL); 405 new_fn = kzalloc(len, GFP_KERNEL);
401 if (!new_fn) 406 if (!new_fn)
402 return -ENOMEM; 407 return -ENOMEM;
403 new_fn->hash = hash; 408 new_fn->hash = hash;
404 new_fn->minor_hash = minor_hash; 409 new_fn->minor_hash = minor_hash;
405 new_fn->inode = le32_to_cpu(dirent->inode); 410 new_fn->inode = le32_to_cpu(dirent->inode);
406 new_fn->name_len = dirent->name_len; 411 new_fn->name_len = ent_name->len;
407 new_fn->file_type = dirent->file_type; 412 new_fn->file_type = dirent->file_type;
408 memcpy(new_fn->name, dirent->name, dirent->name_len); 413 memcpy(new_fn->name, ent_name->name, ent_name->len);
409 new_fn->name[dirent->name_len] = 0; 414 new_fn->name[ent_name->len] = 0;
410 415
411 while (*p) { 416 while (*p) {
412 parent = *p; 417 parent = *p;
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 3462532b227f..ba75838f3588 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2142,8 +2142,9 @@ extern int __ext4_check_dir_entry(const char *, unsigned int, struct inode *,
2142 unlikely(__ext4_check_dir_entry(__func__, __LINE__, (dir), (filp), \ 2142 unlikely(__ext4_check_dir_entry(__func__, __LINE__, (dir), (filp), \
2143 (de), (bh), (buf), (size), (offset))) 2143 (de), (bh), (buf), (size), (offset)))
2144extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash, 2144extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
2145 __u32 minor_hash, 2145 __u32 minor_hash,
2146 struct ext4_dir_entry_2 *dirent); 2146 struct ext4_dir_entry_2 *dirent,
2147 struct ext4_str *ent_name);
2147extern void ext4_htree_free_dir_info(struct dir_private_info *p); 2148extern void ext4_htree_free_dir_info(struct dir_private_info *p);
2148extern int ext4_find_dest_de(struct inode *dir, struct inode *inode, 2149extern int ext4_find_dest_de(struct inode *dir, struct inode *inode,
2149 struct buffer_head *bh, 2150 struct buffer_head *bh,
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index 8b64d715e476..661f0b8dcfe0 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -1327,6 +1327,7 @@ int htree_inlinedir_to_tree(struct file *dir_file,
1327 struct ext4_iloc iloc; 1327 struct ext4_iloc iloc;
1328 void *dir_buf = NULL; 1328 void *dir_buf = NULL;
1329 struct ext4_dir_entry_2 fake; 1329 struct ext4_dir_entry_2 fake;
1330 struct ext4_str tmp_str;
1330 1331
1331 ret = ext4_get_inode_loc(inode, &iloc); 1332 ret = ext4_get_inode_loc(inode, &iloc);
1332 if (ret) 1333 if (ret)
@@ -1398,8 +1399,10 @@ int htree_inlinedir_to_tree(struct file *dir_file,
1398 continue; 1399 continue;
1399 if (de->inode == 0) 1400 if (de->inode == 0)
1400 continue; 1401 continue;
1401 err = ext4_htree_store_dirent(dir_file, 1402 tmp_str.name = de->name;
1402 hinfo->hash, hinfo->minor_hash, de); 1403 tmp_str.len = de->name_len;
1404 err = ext4_htree_store_dirent(dir_file, hinfo->hash,
1405 hinfo->minor_hash, de, &tmp_str);
1403 if (err) { 1406 if (err) {
1404 count = err; 1407 count = err;
1405 goto out; 1408 goto out;
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 77a63ff4aeb9..8cef115ee64a 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -877,6 +877,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
877 struct buffer_head *bh; 877 struct buffer_head *bh;
878 struct ext4_dir_entry_2 *de, *top; 878 struct ext4_dir_entry_2 *de, *top;
879 int err = 0, count = 0; 879 int err = 0, count = 0;
880 struct ext4_str tmp_str;
880 881
881 dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n", 882 dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n",
882 (unsigned long)block)); 883 (unsigned long)block));
@@ -903,8 +904,11 @@ static int htree_dirblock_to_tree(struct file *dir_file,
903 continue; 904 continue;
904 if (de->inode == 0) 905 if (de->inode == 0)
905 continue; 906 continue;
906 if ((err = ext4_htree_store_dirent(dir_file, 907 tmp_str.name = de->name;
907 hinfo->hash, hinfo->minor_hash, de)) != 0) { 908 tmp_str.len = de->name_len;
909 err = ext4_htree_store_dirent(dir_file,
910 hinfo->hash, hinfo->minor_hash, de, &tmp_str);
911 if (err != 0) {
908 brelse(bh); 912 brelse(bh);
909 return err; 913 return err;
910 } 914 }
@@ -934,6 +938,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
934 int count = 0; 938 int count = 0;
935 int ret, err; 939 int ret, err;
936 __u32 hashval; 940 __u32 hashval;
941 struct ext4_str tmp_str;
937 942
938 dxtrace(printk(KERN_DEBUG "In htree_fill_tree, start hash: %x:%x\n", 943 dxtrace(printk(KERN_DEBUG "In htree_fill_tree, start hash: %x:%x\n",
939 start_hash, start_minor_hash)); 944 start_hash, start_minor_hash));
@@ -969,14 +974,22 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
969 /* Add '.' and '..' from the htree header */ 974 /* Add '.' and '..' from the htree header */
970 if (!start_hash && !start_minor_hash) { 975 if (!start_hash && !start_minor_hash) {
971 de = (struct ext4_dir_entry_2 *) frames[0].bh->b_data; 976 de = (struct ext4_dir_entry_2 *) frames[0].bh->b_data;
972 if ((err = ext4_htree_store_dirent(dir_file, 0, 0, de)) != 0) 977 tmp_str.name = de->name;
978 tmp_str.len = de->name_len;
979 err = ext4_htree_store_dirent(dir_file, 0, 0,
980 de, &tmp_str);
981 if (err != 0)
973 goto errout; 982 goto errout;
974 count++; 983 count++;
975 } 984 }
976 if (start_hash < 2 || (start_hash ==2 && start_minor_hash==0)) { 985 if (start_hash < 2 || (start_hash ==2 && start_minor_hash==0)) {
977 de = (struct ext4_dir_entry_2 *) frames[0].bh->b_data; 986 de = (struct ext4_dir_entry_2 *) frames[0].bh->b_data;
978 de = ext4_next_entry(de, dir->i_sb->s_blocksize); 987 de = ext4_next_entry(de, dir->i_sb->s_blocksize);
979 if ((err = ext4_htree_store_dirent(dir_file, 2, 0, de)) != 0) 988 tmp_str.name = de->name;
989 tmp_str.len = de->name_len;
990 err = ext4_htree_store_dirent(dir_file, 2, 0,
991 de, &tmp_str);
992 if (err != 0)
980 goto errout; 993 goto errout;
981 count++; 994 count++;
982 } 995 }