Sync up with encryption patches
[ext4-patch-queue.git] / add-symlink-encryption
blob120ebfb35c0dcf730220feed80be042f1c308a1e
1 ext4 crypto: Add symlink encryption
3 Change-Id: Ic92ebe4c615721650ccaf16b3175c2f4e931af2d
4 Signed-off-by: Uday Savagaonkar <savagaon@google.com>
5 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
6 ---
7  fs/ext4/ext4.h        |  1 +
8  fs/ext4/ext4_crypto.h | 20 ++++++++++++
9  fs/ext4/inode.c       |  5 +--
10  fs/ext4/namei.c       | 85 +++++++++++++++++++++++++++++++++++++------------
11  fs/ext4/symlink.c     | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
12  5 files changed, 184 insertions(+), 23 deletions(-)
14 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
15 index 98a5617..c79db59 100644
16 --- a/fs/ext4/ext4.h
17 +++ b/fs/ext4/ext4.h
18 @@ -2221,6 +2221,7 @@ extern int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
19  extern int ext4_trim_fs(struct super_block *, struct fstrim_range *);
21  /* inode.c */
22 +int ext4_inode_is_fast_symlink(struct inode *inode);
23  struct buffer_head *ext4_getblk(handle_t *, struct inode *, ext4_lblk_t, int);
24  struct buffer_head *ext4_bread(handle_t *, struct inode *, ext4_lblk_t, int);
25  int ext4_get_block_write(struct inode *inode, sector_t iblock,
26 diff --git a/fs/ext4/ext4_crypto.h b/fs/ext4/ext4_crypto.h
27 index f7d46e8..c2ba35a 100644
28 --- a/fs/ext4/ext4_crypto.h
29 +++ b/fs/ext4/ext4_crypto.h
30 @@ -124,4 +124,24 @@ struct ext4_fname_crypto_ctx {
31         unsigned ctfm_key_is_ready : 1;
32  };
34 +/**
35 + * For encrypted symlinks, the ciphertext length is stored at the beginning
36 + * of the string in little-endian format.
37 + */
38 +struct ext4_encrypted_symlink_data {
39 +       __le16 len;
40 +       char encrypted_path[1];
41 +} __attribute__((__packed__));
43 +/**
44 + * This function is used to calculate the disk space required to
45 + * store a filename of length l in encrypted symlink format.
46 + */
47 +static inline u32 encrypted_symlink_data_len(u32 l)
49 +       if (l < EXT4_CRYPTO_BLOCK_SIZE)
50 +               l = EXT4_CRYPTO_BLOCK_SIZE;
51 +       return (l + sizeof(struct ext4_encrypted_symlink_data) - 1);
54  #endif /* _EXT4_CRYPTO_H */
55 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
56 index 9cc660c..a8e1975 100644
57 --- a/fs/ext4/inode.c
58 +++ b/fs/ext4/inode.c
59 @@ -141,7 +141,7 @@ static int ext4_meta_trans_blocks(struct inode *inode, int lblocks,
60  /*
61   * Test whether an inode is a fast symlink.
62   */
63 -static int ext4_inode_is_fast_symlink(struct inode *inode)
64 +int ext4_inode_is_fast_symlink(struct inode *inode)
65  {
66          int ea_blocks = EXT4_I(inode)->i_file_acl ?
67                 EXT4_CLUSTER_SIZE(inode->i_sb) >> 9 : 0;
68 @@ -4175,7 +4175,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
69                 inode->i_op = &ext4_dir_inode_operations;
70                 inode->i_fop = &ext4_dir_operations;
71         } else if (S_ISLNK(inode->i_mode)) {
72 -               if (ext4_inode_is_fast_symlink(inode)) {
73 +               if (ext4_inode_is_fast_symlink(inode) &&
74 +                   !ext4_encrypted_inode(inode)) {
75                         inode->i_op = &ext4_fast_symlink_inode_operations;
76                         nd_terminate_link(ei->i_data, inode->i_size,
77                                 sizeof(ei->i_data) - 1);
78 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
79 index ffd97aa..0e57e70 100644
80 --- a/fs/ext4/namei.c
81 +++ b/fs/ext4/namei.c
82 @@ -3185,16 +3185,24 @@ static int ext4_symlink(struct inode *dir,
83  {
84         handle_t *handle;
85         struct inode *inode;
86 -       int l, err, retries = 0;
87 +       int err, len = strlen(symname);
88         int credits;
89 +       bool encryption_required;
90 +       struct ext4_str disk_link;
91 +       struct ext4_encrypted_symlink_data *sd = NULL;
93 -       l = strlen(symname)+1;
94 -       if (l > dir->i_sb->s_blocksize)
95 +       disk_link.len = len + 1;
96 +       disk_link.name = (char *) symname;
98 +       encryption_required = ext4_encrypted_inode(dir);
99 +       if (encryption_required)
100 +               disk_link.len = encrypted_symlink_data_len(len) + 1;
101 +       if (disk_link.len > dir->i_sb->s_blocksize)
102                 return -ENAMETOOLONG;
104         dquot_initialize(dir);
106 -       if (l > EXT4_N_BLOCKS * 4) {
107 +       if ((disk_link.len > EXT4_N_BLOCKS * 4)) {
108                 /*
109                  * For non-fast symlinks, we just allocate inode and put it on
110                  * orphan list in the first transaction => we need bitmap,
111 @@ -3213,16 +3221,49 @@ static int ext4_symlink(struct inode *dir,
112                 credits = EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
113                           EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3;
114         }
115 -retry:
117         inode = ext4_new_inode_start_handle(dir, S_IFLNK|S_IRWXUGO,
118                                             &dentry->d_name, 0, NULL,
119                                             EXT4_HT_DIR, credits);
120         handle = ext4_journal_current_handle();
121 -       err = PTR_ERR(inode);
122 -       if (IS_ERR(inode))
123 -               goto out_stop;
124 +       if (IS_ERR(inode)) {
125 +               if (handle)
126 +                       ext4_journal_stop(handle);
127 +               return PTR_ERR(inode);
128 +       }
130 +       if (encryption_required) {
131 +               struct ext4_fname_crypto_ctx *ctx = NULL;
132 +               struct qstr istr;
133 +               struct ext4_str ostr;
135 +               sd = kzalloc(disk_link.len, GFP_NOFS);
136 +               if (!sd) {
137 +                       err = -ENOMEM;
138 +                       goto err_drop_inode;
139 +               }
140 +               err = ext4_inherit_context(dir, inode);
141 +               if (err)
142 +                       goto err_drop_inode;
143 +               ctx = ext4_get_fname_crypto_ctx(inode,
144 +                                               inode->i_sb->s_blocksize);
145 +               if (IS_ERR_OR_NULL(ctx)) {
146 +                       /* We just set the policy, so ctx should not be NULL */
147 +                       err = (ctx == NULL) ? -EIO : PTR_ERR(ctx);
148 +                       goto err_drop_inode;
149 +               }
150 +               istr.name = (const unsigned char *) symname;
151 +               istr.len = len;
152 +               ostr.name = sd->encrypted_path;
153 +               err = ext4_fname_usr_to_disk(ctx, &istr, &ostr);
154 +               ext4_put_fname_crypto_ctx(&ctx);
155 +               if (err < 0)
156 +                       goto err_drop_inode;
157 +               sd->len = cpu_to_le16(ostr.len);
158 +               disk_link.name = (char *) sd;
159 +       }
161 -       if (l > EXT4_N_BLOCKS * 4) {
162 +       if ((disk_link.len > EXT4_N_BLOCKS * 4)) {
163                 inode->i_op = &ext4_symlink_inode_operations;
164                 ext4_set_aops(inode);
165                 /*
166 @@ -3238,9 +3279,10 @@ retry:
167                 drop_nlink(inode);
168                 err = ext4_orphan_add(handle, inode);
169                 ext4_journal_stop(handle);
170 +               handle = NULL;
171                 if (err)
172                         goto err_drop_inode;
173 -               err = __page_symlink(inode, symname, l, 1);
174 +               err = __page_symlink(inode, disk_link.name, disk_link.len, 1);
175                 if (err)
176                         goto err_drop_inode;
177                 /*
178 @@ -3252,34 +3294,37 @@ retry:
179                                 EXT4_INDEX_EXTRA_TRANS_BLOCKS + 1);
180                 if (IS_ERR(handle)) {
181                         err = PTR_ERR(handle);
182 +                       handle = NULL;
183                         goto err_drop_inode;
184                 }
185                 set_nlink(inode, 1);
186                 err = ext4_orphan_del(handle, inode);
187 -               if (err) {
188 -                       ext4_journal_stop(handle);
189 -                       clear_nlink(inode);
190 +               if (err)
191                         goto err_drop_inode;
192 -               }
193         } else {
194                 /* clear the extent format for fast symlink */
195                 ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS);
196 -               inode->i_op = &ext4_fast_symlink_inode_operations;
197 -               memcpy((char *)&EXT4_I(inode)->i_data, symname, l);
198 -               inode->i_size = l-1;
199 +               inode->i_op = encryption_required ?
200 +                       &ext4_symlink_inode_operations :
201 +                       &ext4_fast_symlink_inode_operations;
202 +               memcpy((char *)&EXT4_I(inode)->i_data, disk_link.name,
203 +                      disk_link.len);
204 +               inode->i_size = disk_link.len - 1;
205         }
206         EXT4_I(inode)->i_disksize = inode->i_size;
207         err = ext4_add_nondir(handle, dentry, inode);
208         if (!err && IS_DIRSYNC(dir))
209                 ext4_handle_sync(handle);
211 -out_stop:
212         if (handle)
213                 ext4_journal_stop(handle);
214 -       if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
215 -               goto retry;
216 +       kfree(sd);
217         return err;
218  err_drop_inode:
219 +       if (handle)
220 +               ext4_journal_stop(handle);
221 +       kfree(sd);
222 +       clear_nlink(inode);
223         unlock_new_inode(inode);
224         iput(inode);
225         return err;
226 diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
227 index ff37119..3f72274 100644
228 --- a/fs/ext4/symlink.c
229 +++ b/fs/ext4/symlink.c
230 @@ -23,8 +23,97 @@
231  #include "ext4.h"
232  #include "xattr.h"
234 +#ifdef CONFIG_EXT4_FS_ENCRYPTION
235  static void *ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
237 +       struct page *cpage = NULL;
238 +       char *caddr, *paddr = NULL;
239 +       struct ext4_str cstr, pstr;
240 +       struct inode *inode = dentry->d_inode;
241 +       struct ext4_fname_crypto_ctx *ctx = NULL;
242 +       struct ext4_encrypted_symlink_data *sd;
243 +       loff_t size = min_t(loff_t, i_size_read(inode), PAGE_SIZE - 1);
244 +       int res;
245 +       u32 plen, max_size = inode->i_sb->s_blocksize;
247 +       if (!ext4_encrypted_inode(inode))
248 +               return page_follow_link_light(dentry, nd);
250 +       ctx = ext4_get_fname_crypto_ctx(inode, inode->i_sb->s_blocksize);
251 +       if (IS_ERR(ctx))
252 +               return ctx;
254 +       if (ext4_inode_is_fast_symlink(inode)) {
255 +               caddr = (char *) EXT4_I(dentry->d_inode)->i_data;
256 +               max_size = sizeof(EXT4_I(dentry->d_inode)->i_data);
257 +       } else {
258 +               cpage = read_mapping_page(inode->i_mapping, 0, NULL);
259 +               if (IS_ERR(cpage)) {
260 +                       ext4_put_fname_crypto_ctx(&ctx);
261 +                       return cpage;
262 +               }
263 +               caddr = kmap(cpage);
264 +               caddr[size] = 0;
265 +       }
267 +       /* Symlink is encrypted */
268 +       sd = (struct ext4_encrypted_symlink_data *)caddr;
269 +       cstr.name = sd->encrypted_path;
270 +       cstr.len  = le32_to_cpu(sd->len);
271 +       if ((cstr.len +
272 +            sizeof(struct ext4_encrypted_symlink_data) - 1) >
273 +           max_size) {
274 +               /* Symlink data on the disk is corrupted */
275 +               res = -EIO;
276 +               goto errout;
277 +       }
278 +       plen = (cstr.len < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2) ?
279 +               EXT4_FNAME_CRYPTO_DIGEST_SIZE*2 : cstr.len;
280 +       paddr = kmalloc(plen + 1, GFP_NOFS);
281 +       if (!paddr) {
282 +               res = -ENOMEM;
283 +               goto errout;
284 +       }
285 +       pstr.name = paddr;
286 +       res = _ext4_fname_disk_to_usr(ctx, &cstr, &pstr);
287 +       if (res < 0)
288 +               goto errout;
289 +       /* Null-terminate the name */
290 +       if (res <= plen)
291 +               paddr[res] = '\0';
292 +       nd_set_link(nd, paddr);
293 +       ext4_put_fname_crypto_ctx(&ctx);
294 +       if (cpage) {
295 +               kunmap(cpage);
296 +               page_cache_release(cpage);
297 +       }
298 +       return NULL;
299 +errout:
300 +       ext4_put_fname_crypto_ctx(&ctx);
301 +       if (cpage) {
302 +               kunmap(cpage);
303 +               page_cache_release(cpage);
304 +       }
305 +       kfree(paddr);
306 +       return ERR_PTR(res);
309 +static void ext4_put_link(struct dentry *dentry, struct nameidata *nd,
310 +                         void *cookie)
312 +       struct page *page = cookie;
314 +       if (!page) {
315 +               kfree(nd_get_link(nd));
316 +       } else {
317 +               kunmap(page);
318 +               page_cache_release(page);
319 +       }
321 +#endif
323 +static void *ext4_follow_fast_link(struct dentry *dentry, struct nameidata *nd)
325         struct ext4_inode_info *ei = EXT4_I(dentry->d_inode);
326         nd_set_link(nd, (char *) ei->i_data);
327         return NULL;
328 @@ -32,8 +121,13 @@ static void *ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
330  const struct inode_operations ext4_symlink_inode_operations = {
331         .readlink       = generic_readlink,
332 +#ifdef CONFIG_EXT4_FS_ENCRYPTION
333 +       .follow_link    = ext4_follow_link,
334 +       .put_link       = ext4_put_link,
335 +#else
336         .follow_link    = page_follow_link_light,
337         .put_link       = page_put_link,
338 +#endif
339         .setattr        = ext4_setattr,
340         .setxattr       = generic_setxattr,
341         .getxattr       = generic_getxattr,
342 @@ -43,7 +137,7 @@ const struct inode_operations ext4_symlink_inode_operations = {
344  const struct inode_operations ext4_fast_symlink_inode_operations = {
345         .readlink       = generic_readlink,
346 -       .follow_link    = ext4_follow_link,
347 +       .follow_link    = ext4_follow_fast_link,
348         .setattr        = ext4_setattr,
349         .setxattr       = generic_setxattr,
350         .getxattr       = generic_getxattr,