Commit 2f61830a authored by Theodore Ts'o's avatar Theodore Ts'o

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: default avatarTheodore Ts'o <tytso@mit.edu>
parent d5d0e8c7
...@@ -382,10 +382,15 @@ void ext4_htree_free_dir_info(struct dir_private_info *p) ...@@ -382,10 +382,15 @@ void ext4_htree_free_dir_info(struct dir_private_info *p)
/* /*
* Given a directory entry, enter it into the fname rb tree. * Given a directory entry, enter it into the fname rb tree.
*
* When filename encryption is enabled, the dirent will hold the
* encrypted filename, while the htree will hold decrypted filename.
* The decrypted filename is passed in via ent_name. parameter.
*/ */
int ext4_htree_store_dirent(struct file *dir_file, __u32 hash, int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
__u32 minor_hash, __u32 minor_hash,
struct ext4_dir_entry_2 *dirent) struct ext4_dir_entry_2 *dirent,
struct ext4_str *ent_name)
{ {
struct rb_node **p, *parent = NULL; struct rb_node **p, *parent = NULL;
struct fname *fname, *new_fn; struct fname *fname, *new_fn;
...@@ -396,17 +401,17 @@ int ext4_htree_store_dirent(struct file *dir_file, __u32 hash, ...@@ -396,17 +401,17 @@ int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
p = &info->root.rb_node; p = &info->root.rb_node;
/* Create and allocate the fname structure */ /* Create and allocate the fname structure */
len = sizeof(struct fname) + dirent->name_len + 1; len = sizeof(struct fname) + ent_name->len + 1;
new_fn = kzalloc(len, GFP_KERNEL); new_fn = kzalloc(len, GFP_KERNEL);
if (!new_fn) if (!new_fn)
return -ENOMEM; return -ENOMEM;
new_fn->hash = hash; new_fn->hash = hash;
new_fn->minor_hash = minor_hash; new_fn->minor_hash = minor_hash;
new_fn->inode = le32_to_cpu(dirent->inode); new_fn->inode = le32_to_cpu(dirent->inode);
new_fn->name_len = dirent->name_len; new_fn->name_len = ent_name->len;
new_fn->file_type = dirent->file_type; new_fn->file_type = dirent->file_type;
memcpy(new_fn->name, dirent->name, dirent->name_len); memcpy(new_fn->name, ent_name->name, ent_name->len);
new_fn->name[dirent->name_len] = 0; new_fn->name[ent_name->len] = 0;
while (*p) { while (*p) {
parent = *p; parent = *p;
......
...@@ -2142,8 +2142,9 @@ extern int __ext4_check_dir_entry(const char *, unsigned int, struct inode *, ...@@ -2142,8 +2142,9 @@ extern int __ext4_check_dir_entry(const char *, unsigned int, struct inode *,
unlikely(__ext4_check_dir_entry(__func__, __LINE__, (dir), (filp), \ unlikely(__ext4_check_dir_entry(__func__, __LINE__, (dir), (filp), \
(de), (bh), (buf), (size), (offset))) (de), (bh), (buf), (size), (offset)))
extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash, extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
__u32 minor_hash, __u32 minor_hash,
struct ext4_dir_entry_2 *dirent); struct ext4_dir_entry_2 *dirent,
struct ext4_str *ent_name);
extern void ext4_htree_free_dir_info(struct dir_private_info *p); extern void ext4_htree_free_dir_info(struct dir_private_info *p);
extern int ext4_find_dest_de(struct inode *dir, struct inode *inode, extern int ext4_find_dest_de(struct inode *dir, struct inode *inode,
struct buffer_head *bh, struct buffer_head *bh,
......
...@@ -1327,6 +1327,7 @@ int htree_inlinedir_to_tree(struct file *dir_file, ...@@ -1327,6 +1327,7 @@ int htree_inlinedir_to_tree(struct file *dir_file,
struct ext4_iloc iloc; struct ext4_iloc iloc;
void *dir_buf = NULL; void *dir_buf = NULL;
struct ext4_dir_entry_2 fake; struct ext4_dir_entry_2 fake;
struct ext4_str tmp_str;
ret = ext4_get_inode_loc(inode, &iloc); ret = ext4_get_inode_loc(inode, &iloc);
if (ret) if (ret)
...@@ -1398,8 +1399,10 @@ int htree_inlinedir_to_tree(struct file *dir_file, ...@@ -1398,8 +1399,10 @@ int htree_inlinedir_to_tree(struct file *dir_file,
continue; continue;
if (de->inode == 0) if (de->inode == 0)
continue; continue;
err = ext4_htree_store_dirent(dir_file, tmp_str.name = de->name;
hinfo->hash, hinfo->minor_hash, de); tmp_str.len = de->name_len;
err = ext4_htree_store_dirent(dir_file, hinfo->hash,
hinfo->minor_hash, de, &tmp_str);
if (err) { if (err) {
count = err; count = err;
goto out; goto out;
......
...@@ -877,6 +877,7 @@ static int htree_dirblock_to_tree(struct file *dir_file, ...@@ -877,6 +877,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
struct buffer_head *bh; struct buffer_head *bh;
struct ext4_dir_entry_2 *de, *top; struct ext4_dir_entry_2 *de, *top;
int err = 0, count = 0; int err = 0, count = 0;
struct ext4_str tmp_str;
dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n", dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n",
(unsigned long)block)); (unsigned long)block));
...@@ -903,8 +904,11 @@ static int htree_dirblock_to_tree(struct file *dir_file, ...@@ -903,8 +904,11 @@ static int htree_dirblock_to_tree(struct file *dir_file,
continue; continue;
if (de->inode == 0) if (de->inode == 0)
continue; continue;
if ((err = ext4_htree_store_dirent(dir_file, tmp_str.name = de->name;
hinfo->hash, hinfo->minor_hash, de)) != 0) { tmp_str.len = de->name_len;
err = ext4_htree_store_dirent(dir_file,
hinfo->hash, hinfo->minor_hash, de, &tmp_str);
if (err != 0) {
brelse(bh); brelse(bh);
return err; return err;
} }
...@@ -934,6 +938,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash, ...@@ -934,6 +938,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
int count = 0; int count = 0;
int ret, err; int ret, err;
__u32 hashval; __u32 hashval;
struct ext4_str tmp_str;
dxtrace(printk(KERN_DEBUG "In htree_fill_tree, start hash: %x:%x\n", dxtrace(printk(KERN_DEBUG "In htree_fill_tree, start hash: %x:%x\n",
start_hash, start_minor_hash)); start_hash, start_minor_hash));
...@@ -969,14 +974,22 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash, ...@@ -969,14 +974,22 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
/* Add '.' and '..' from the htree header */ /* Add '.' and '..' from the htree header */
if (!start_hash && !start_minor_hash) { if (!start_hash && !start_minor_hash) {
de = (struct ext4_dir_entry_2 *) frames[0].bh->b_data; de = (struct ext4_dir_entry_2 *) frames[0].bh->b_data;
if ((err = ext4_htree_store_dirent(dir_file, 0, 0, de)) != 0) tmp_str.name = de->name;
tmp_str.len = de->name_len;
err = ext4_htree_store_dirent(dir_file, 0, 0,
de, &tmp_str);
if (err != 0)
goto errout; goto errout;
count++; count++;
} }
if (start_hash < 2 || (start_hash ==2 && start_minor_hash==0)) { if (start_hash < 2 || (start_hash ==2 && start_minor_hash==0)) {
de = (struct ext4_dir_entry_2 *) frames[0].bh->b_data; de = (struct ext4_dir_entry_2 *) frames[0].bh->b_data;
de = ext4_next_entry(de, dir->i_sb->s_blocksize); de = ext4_next_entry(de, dir->i_sb->s_blocksize);
if ((err = ext4_htree_store_dirent(dir_file, 2, 0, de)) != 0) tmp_str.name = de->name;
tmp_str.len = de->name_len;
err = ext4_htree_store_dirent(dir_file, 2, 0,
de, &tmp_str);
if (err != 0)
goto errout; goto errout;
count++; count++;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment