Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -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.
 *
 * 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,
			     __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 fname *fname, *new_fn;
@@ -396,17 +401,17 @@ int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
	p = &info->root.rb_node;

	/* 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);
	if (!new_fn)
		return -ENOMEM;
	new_fn->hash = hash;
	new_fn->minor_hash = minor_hash;
	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;
	memcpy(new_fn->name, dirent->name, dirent->name_len);
	new_fn->name[dirent->name_len] = 0;
	memcpy(new_fn->name, ent_name->name, ent_name->len);
	new_fn->name[ent_name->len] = 0;

	while (*p) {
		parent = *p;
+3 −2
Original line number Diff line number Diff line
@@ -2143,7 +2143,8 @@ extern int __ext4_check_dir_entry(const char *, unsigned int, struct inode *,
					(de), (bh), (buf), (size), (offset)))
extern int ext4_htree_store_dirent(struct file *dir_file, __u32 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 int ext4_find_dest_de(struct inode *dir, struct inode *inode,
			     struct buffer_head *bh,
+5 −2
Original line number Diff line number Diff line
@@ -1327,6 +1327,7 @@ int htree_inlinedir_to_tree(struct file *dir_file,
	struct ext4_iloc iloc;
	void *dir_buf = NULL;
	struct ext4_dir_entry_2 fake;
	struct ext4_str tmp_str;

	ret = ext4_get_inode_loc(inode, &iloc);
	if (ret)
@@ -1398,8 +1399,10 @@ int htree_inlinedir_to_tree(struct file *dir_file,
			continue;
		if (de->inode == 0)
			continue;
		err = ext4_htree_store_dirent(dir_file,
				   hinfo->hash, hinfo->minor_hash, de);
		tmp_str.name = de->name;
		tmp_str.len = de->name_len;
		err = ext4_htree_store_dirent(dir_file, hinfo->hash,
					      hinfo->minor_hash, de, &tmp_str);
		if (err) {
			count = err;
			goto out;
+17 −4
Original line number Diff line number Diff line
@@ -877,6 +877,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
	struct buffer_head *bh;
	struct ext4_dir_entry_2 *de, *top;
	int err = 0, count = 0;
	struct ext4_str tmp_str;

	dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n",
							(unsigned long)block));
@@ -903,8 +904,11 @@ static int htree_dirblock_to_tree(struct file *dir_file,
			continue;
		if (de->inode == 0)
			continue;
		if ((err = ext4_htree_store_dirent(dir_file,
				   hinfo->hash, hinfo->minor_hash, de)) != 0) {
		tmp_str.name = de->name;
		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);
			return err;
		}
@@ -934,6 +938,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
	int count = 0;
	int ret, err;
	__u32 hashval;
	struct ext4_str tmp_str;

	dxtrace(printk(KERN_DEBUG "In htree_fill_tree, start hash: %x:%x\n",
		       start_hash, start_minor_hash));
@@ -969,14 +974,22 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
	/* Add '.' and '..' from the htree header */
	if (!start_hash && !start_minor_hash) {
		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;
		count++;
	}
	if (start_hash < 2 || (start_hash ==2 && start_minor_hash==0)) {
		de = (struct ext4_dir_entry_2 *) frames[0].bh->b_data;
		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;
		count++;
	}