Sync ext4 encryption as of commit dffd334e4d7134
[ext4-patch-queue.git] / teach-ext4_htree_store_dirent-to-store-decrypted-filenames
blob9f07b7054c6e9ce3b2bfd3e3fe462c44b73fc391
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
7 encrypted filename.
9 Change-Id: I2d1a78e65cb81152cae108ce7faadc28b52e0abe
10 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
12 ---
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
21 --- a/fs/ext4/dir.c
22 +++ b/fs/ext4/dir.c
23 @@ -384,10 +384,15 @@ void ext4_htree_free_dir_info(struct dir_private_info *p)
25  /*
26   * Given a directory entry, enter it into the fname rb tree.
27 + *
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.
31   */
32  int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
33                              __u32 minor_hash,
34 -                            struct ext4_dir_entry_2 *dirent)
35 +                           struct ext4_dir_entry_2 *dirent,
36 +                           struct ext4_str *ent_name)
37  {
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);
47         if (!new_fn)
48                 return -ENOMEM;
49         new_fn->hash = hash;
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;
60         while (*p) {
61                 parent = *p;
62 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
63 index 89ca8a6..4da5c65 100644
64 --- a/fs/ext4/ext4.h
65 +++ b/fs/ext4/ext4.h
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,
70 -                                   __u32 minor_hash,
71 -                                   struct ext4_dir_entry_2 *dirent);
72 +                               __u32 minor_hash,
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;
84         void *dir_buf = NULL;
85         struct ext4_dir_entry_2 fake;
86 +       struct ext4_str tmp_str;
88         ret = ext4_get_inode_loc(inode, &iloc);
89         if (ret)
90 @@ -1398,8 +1399,10 @@ int htree_inlinedir_to_tree(struct file *dir_file,
91                         continue;
92                 if (de->inode == 0)
93                         continue;
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);
100                 if (err) {
101                         count = err;
102                         goto out;
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,
116                         continue;
117                 if (de->inode == 0)
118                         continue;
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);
125 +               if (err != 0) {
126                         brelse(bh);
127                         return err;
128                 }
129 @@ -937,6 +941,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
130         int count = 0;
131         int ret, err;
132         __u32 hashval;
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,
145 +                                             de, &tmp_str);
146 +               if (err != 0)
147                         goto errout;
148                 count++;
149         }
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,
157 +                                             de, &tmp_str);
158 +               if (err != 0)
159                         goto errout;
160                 count++;
161         }