Sync ext4 encryption as of commit dffd334e4d7134
[ext4-patch-queue.git] / partial-update-to-namei.c-for-fname-crypto
blob62749db05fc01c18b01d8048090e40a778cddac9
1 ext4 crypto: partial update to namei.c for fname crypto
3 From: Michael Halcrow <mhalcrow@google.com>
5 Modifies dx_show_leaf and dx_probe to support fname encryption.
6 Filename encryption not yet enabled.
8 Change-Id: I2058ea5cf6c3920a05c75e42acb2baab631fa1e8
9 Signed-off-by: Uday Savagaonkar <savagaon@google.com>
10 Signed-off-by: Ildar Muslukhov <ildarm@google.com>
11 Signed-off-by: Michael Halcrow <mhalcrow@google.com>
12 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
13 ---
14  fs/ext4/namei.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
15  1 file changed, 101 insertions(+), 8 deletions(-)
17 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
18 index f3234d4..8fcda60 100644
19 --- a/fs/ext4/namei.c
20 +++ b/fs/ext4/namei.c
21 @@ -588,8 +588,10 @@ struct stats
22         unsigned bcount;
23  };
25 -static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext4_dir_entry_2 *de,
26 -                                int size, int show_names)
27 +static struct stats dx_show_leaf(struct inode *dir,
28 +                               struct dx_hash_info *hinfo,
29 +                               struct ext4_dir_entry_2 *de,
30 +                               int size, int show_names)
31  {
32         unsigned names = 0, space = 0;
33         char *base = (char *) de;
34 @@ -602,12 +604,80 @@ static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext4_dir_ent
35                 {
36                         if (show_names)
37                         {
38 +#ifdef CONFIG_EXT4_FS_ENCRYPTION
39 +                               int len;
40 +                               char *name;
41 +                               struct ext4_str fname_crypto_str
42 +                                       = {.name = NULL, .len = 0};
43 +                               struct ext4_fname_crypto_ctx *ctx = NULL;
44 +                               int res;
46 +                               name  = de->name;
47 +                               len = de->name_len;
48 +                               ctx = ext4_get_fname_crypto_ctx(dir,
49 +                                                               EXT4_NAME_LEN);
50 +                               if (IS_ERR(ctx)) {
51 +                                       printk(KERN_WARNING "Error acquiring"
52 +                                       " crypto ctxt--skipping crypto\n");
53 +                                       ctx = NULL;
54 +                               }
55 +                               if (ctx == NULL) {
56 +                                       /* Directory is not encrypted */
57 +                                       ext4fs_dirhash(de->name,
58 +                                               de->name_len, &h);
59 +                                       printk("%*.s:(U)%x.%u ", len,
60 +                                              name, h.hash,
61 +                                              (unsigned) ((char *) de
62 +                                                          - base));
63 +                               } else {
64 +                                       /* Directory is encrypted */
65 +                                       res = ext4_fname_crypto_alloc_buffer(
66 +                                               ctx, de->name_len,
67 +                                               &fname_crypto_str);
68 +                                       if (res < 0) {
69 +                                               printk(KERN_WARNING "Error "
70 +                                                       "allocating crypto "
71 +                                                       "buffer--skipping "
72 +                                                       "crypto\n");
73 +                                               ext4_put_fname_crypto_ctx(&ctx);
74 +                                               ctx = NULL;
75 +                                       }
76 +                                       res = ext4_fname_disk_to_usr(ctx, de,
77 +                                                       &fname_crypto_str);
78 +                                       if (res < 0) {
79 +                                               printk(KERN_WARNING "Error "
80 +                                                       "converting filename "
81 +                                                       "from disk to usr"
82 +                                                       "\n");
83 +                                               name = "??";
84 +                                               len = 2;
85 +                                       } else {
86 +                                               name = fname_crypto_str.name;
87 +                                               len = fname_crypto_str.len;
88 +                                       }
89 +                                       res = ext4_fname_disk_to_hash(ctx, de,
90 +                                                                     &h);
91 +                                       if (res < 0) {
92 +                                               printk(KERN_WARNING "Error "
93 +                                                       "converting filename "
94 +                                                       "from disk to htree"
95 +                                                       "\n");
96 +                                               h.hash = 0xDEADBEEF;
97 +                                       }
98 +                                       printk("%*.s:(E)%x.%u ", len, name,
99 +                                              h.hash, (unsigned) ((char *) de
100 +                                                                  - base));
101 +                                       ext4_put_fname_crypto_ctx(&ctx);
102 +                                       ext4_fname_crypto_free_buffer(
103 +                                               &fname_crypto_str);
104 +                               }
105 +#else
106                                 int len = de->name_len;
107                                 char *name = de->name;
108 -                               while (len--) printk("%c", *name++);
109                                 ext4fs_dirhash(de->name, de->name_len, &h);
110 -                               printk(":%x.%u ", h.hash,
111 +                               printk("%*.s:%x.%u ", len, name, h.hash,
112                                        (unsigned) ((char *) de - base));
113 +#endif
114                         }
115                         space += EXT4_DIR_REC_LEN(de->name_len);
116                         names++;
117 @@ -625,7 +695,6 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
118         unsigned count = dx_get_count(entries), names = 0, space = 0, i;
119         unsigned bcount = 0;
120         struct buffer_head *bh;
121 -       int err;
122         printk("%i indexed blocks...\n", count);
123         for (i = 0; i < count; i++, entries++)
124         {
125 @@ -639,7 +708,8 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
126                         continue;
127                 stats = levels?
128                    dx_show_entries(hinfo, dir, ((struct dx_node *) bh->b_data)->entries, levels - 1):
129 -                  dx_show_leaf(hinfo, (struct ext4_dir_entry_2 *) bh->b_data, blocksize, 0);
130 +                  dx_show_leaf(dir, hinfo, (struct ext4_dir_entry_2 *)
131 +                       bh->b_data, blocksize, 0);
132                 names += stats.names;
133                 space += stats.space;
134                 bcount += stats.bcount;
135 @@ -689,8 +759,28 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
136         if (hinfo->hash_version <= DX_HASH_TEA)
137                 hinfo->hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned;
138         hinfo->seed = EXT4_SB(dir->i_sb)->s_hash_seed;
139 +#ifdef CONFIG_EXT4_FS_ENCRYPTION
140 +       if (d_name) {
141 +               struct ext4_fname_crypto_ctx *ctx = NULL;
142 +               int res;
144 +               /* Check if the directory is encrypted */
145 +               ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN);
146 +               if (IS_ERR(ctx)) {
147 +                       ret_err = ERR_PTR(PTR_ERR(ctx));
148 +                       goto fail;
149 +               }
150 +               res = ext4_fname_usr_to_hash(ctx, d_name, hinfo);
151 +               if (res < 0) {
152 +                       ret_err = ERR_PTR(res);
153 +                       goto fail;
154 +               }
155 +               ext4_put_fname_crypto_ctx(&ctx);
156 +       }
157 +#else
158         if (d_name)
159                 ext4fs_dirhash(d_name->name, d_name->len, hinfo);
160 +#endif
161         hash = hinfo->hash;
163         if (root->info.unused_flags & 1) {
164 @@ -775,6 +865,7 @@ fail:
165                 brelse(frame->bh);
166                 frame--;
167         }
169         if (ret_err == ERR_PTR(ERR_BAD_DX_DIR))
170                 ext4_warning(dir->i_sb,
171                              "Corrupt dir inode %lu, running e2fsck is "
172 @@ -1602,8 +1693,10 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
173                 initialize_dirent_tail(t, blocksize);
174         }
176 -       dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data1, blocksize, 1));
177 -       dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data2, blocksize, 1));
178 +       dxtrace(dx_show_leaf(dir, hinfo, (struct ext4_dir_entry_2 *) data1,
179 +                       blocksize, 1));
180 +       dxtrace(dx_show_leaf(dir, hinfo, (struct ext4_dir_entry_2 *) data2,
181 +                       blocksize, 1));
183         /* Which block gets the new entry? */
184         if (hinfo->hash >= hash2) {