add patch remove-unused-mode-parameter
[ext4-patch-queue.git] / old-patches / crypto-add-ioctls-to-backup-crypto-metadata
blob36dff0eb53bb2df1738af10b65cf885714aceabe
1 ext4 crypto: add ioctls to allow backup of encryption metadata
3 Add new ioctls which allow for the metadata of encrypted files (both
4 the filename and the crypto policy) to be backed up and restored.
6 [ Included fix from Dan Carpenter for a missing mutex_unlock. ]
8 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
9 Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
10 ---
11  fs/ext4/crypto_key.c    | 127 +++++++++++++++++++++++++++++++++-
12  fs/ext4/crypto_policy.c |  10 +++
13  fs/ext4/ext4.h          |  25 ++++++-
14  fs/ext4/ext4_crypto.h   |  14 ++++
15  fs/ext4/ialloc.c        |   5 +-
16  fs/ext4/ioctl.c         | 113 +++++++++++++++++++++++++++++++
17  fs/ext4/namei.c         | 307 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
18  7 files changed, 571 insertions(+), 30 deletions(-)
20 diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c
21 index 0129d68..865e41d 100644
22 --- a/fs/ext4/crypto_key.c
23 +++ b/fs/ext4/crypto_key.c
24 @@ -11,11 +11,12 @@
25  #include <crypto/skcipher.h>
26  #include <keys/encrypted-type.h>
27  #include <keys/user-type.h>
28 +#include <linux/crc16.h>
29  #include <linux/random.h>
30  #include <linux/scatterlist.h>
31  #include <uapi/linux/keyctl.h>
33 -#include "ext4.h"
34 +#include "ext4_jbd2.h"
35  #include "xattr.h"
37  static void derive_crypt_complete(struct crypto_async_request *req, int rc)
38 @@ -272,3 +273,127 @@ int ext4_has_encryption_key(struct inode *inode)
40         return (ei->i_crypt_info != NULL);
41  }
43 +int ext4_get_encryption_metadata(struct inode *inode,
44 +                                struct ext4_rw_enc_mdata *mdata)
46 +       unsigned char *cp = mdata->buf;
47 +       size_t size = mdata->u.len;
48 +       loff_t isize;
49 +       int res;
51 +       if (size < sizeof(struct ext4_encryption_context) + 12)
52 +               return -EINVAL;
54 +       if (!inode_owner_or_capable(inode) && !capable(CAP_SYS_ADMIN))
55 +               return -EACCES;
57 +       *cp++ = 'e';
58 +       *cp++ = '5';
59 +       *cp++ = 0;
60 +       *cp++ = 0;
61 +       isize = i_size_read(inode);
62 +       *((u32 *)cp) = cpu_to_le32(isize & 0xFFFFFFFF);
63 +       cp += 4;
64 +       *((u32 *)cp) = cpu_to_le32(isize >> 32);
65 +       cp += 4;
66 +       size -= 12;
68 +       res = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
69 +                            EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
70 +                            cp, size);
72 +       if (res < 0)
73 +               return res;
74 +       if (res > size)
75 +               return -ENOSPC;
77 +       mdata->u.len = res + 12;
79 +       *((u16 *) &mdata->buf[2]) = cpu_to_le16(crc16(~0, mdata->buf, mdata->u.len));
80 +       return 0;
83 +int ext4_set_encryption_metadata(struct inode *inode,
84 +                                struct ext4_rw_enc_mdata *mdata)
86 +       struct ext4_encryption_context *ctx;
87 +       unsigned char *cp = mdata->buf;
88 +       handle_t *handle = NULL;
89 +       loff_t size;
90 +       unsigned bs = inode->i_sb->s_blocksize;
91 +       int res;
92 +       u16 crc;
94 +       if (!inode_owner_or_capable(inode) && !capable(CAP_SYS_ADMIN))
95 +               return -EACCES;
97 +       if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
98 +               return -EINVAL;
100 +       if (mdata->u.len != sizeof(struct ext4_encryption_context) + 12)
101 +               return -EINVAL;
103 +       if (cp[0] != 'e' || cp[1] != '5')
104 +               return -EINVAL;
105 +       crc = le16_to_cpu(*(u16 *)(cp+2));
106 +       cp[2] = cp[3] = 0;
107 +       cp += 4;
109 +       if (crc != crc16(~0, mdata->buf, mdata->u.len))
110 +               return -EINVAL;
112 +       size = le32_to_cpu(*(u32 *) cp);
113 +       cp += 4;
114 +       size += ((u64) le32_to_cpu(*(u32 *) cp)) << 32;
115 +       cp += 4;
117 +       ctx = (struct ext4_encryption_context *) cp;
118 +       res = ext4_validate_encryption_context(ctx);
119 +       if (res)
120 +               return res;
122 +       res = ext4_convert_inline_data(inode);
123 +       if (res)
124 +               return res;
126 +       res = filemap_write_and_wait(&inode->i_data);
127 +       if (res)
128 +               return res;
130 +       mutex_lock(&inode->i_mutex);
131 +       if (S_ISREG(inode->i_mode) &&
132 +           round_up(size, bs) != round_up(i_size_read(inode), bs)) {
133 +               res = -EINVAL;
134 +               goto errout;
135 +       }
137 +       handle = ext4_journal_start(inode, EXT4_HT_MISC,
138 +                                   ext4_jbd2_credits_xattr(inode));
139 +       if (IS_ERR(handle)) {
140 +               res = PTR_ERR(handle);
141 +               goto errout;
142 +       }
143 +       res = ext4_xattr_set(inode, EXT4_XATTR_INDEX_ENCRYPTION,
144 +                            EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, ctx,
145 +                            sizeof(struct ext4_encryption_context), 0);
146 +       if (res < 0)
147 +               goto errout;
148 +       ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
149 +       ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
151 +       if (S_ISREG(inode->i_mode)) {
152 +               i_size_write(inode, size);
153 +               EXT4_I(inode)->i_disksize = size;
154 +       }
155 +       res = ext4_mark_inode_dirty(handle, inode);
156 +       if (res)
157 +               EXT4_ERROR_INODE(inode, "Failed to mark inode dirty");
158 +       else
159 +               res = ext4_get_encryption_info(inode);
160 +errout:
161 +       mutex_unlock(&inode->i_mutex);
162 +       if (handle)
163 +               ext4_journal_stop(handle);
164 +       return res;
166 diff --git a/fs/ext4/crypto_policy.c b/fs/ext4/crypto_policy.c
167 index ad05069..08565f5 100644
168 --- a/fs/ext4/crypto_policy.c
169 +++ b/fs/ext4/crypto_policy.c
170 @@ -180,6 +180,16 @@ int ext4_is_child_context_consistent_with_parent(struct inode *parent,
171                 (parent_ci->ci_flags == child_ci->ci_flags));
174 +int ext4_validate_encryption_context(struct ext4_encryption_context *ctx)
176 +       if ((ctx->format != EXT4_ENCRYPTION_CONTEXT_FORMAT_V1) ||
177 +           !ext4_valid_contents_enc_mode(ctx->contents_encryption_mode) ||
178 +           !ext4_valid_filenames_enc_mode(ctx->filenames_encryption_mode) ||
179 +           (ctx->flags & ~EXT4_POLICY_FLAGS_VALID))
180 +               return -EINVAL;
181 +       return 0;
184  /**
185   * ext4_inherit_context() - Sets a child context from its parent
186   * @parent: Parent inode from which the context is inherited.
187 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
188 index 9a92f8b..bb2c31d 100644
189 --- a/fs/ext4/ext4.h
190 +++ b/fs/ext4/ext4.h
191 @@ -637,6 +637,10 @@ enum {
192  #define EXT4_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct ext4_encryption_policy)
193  #define EXT4_IOC_GET_ENCRYPTION_PWSALT _IOW('f', 20, __u8[16])
194  #define EXT4_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct ext4_encryption_policy)
195 +#define EXT4_IOC_GET_ENCRYPTION_METADATA _IOWR('f', 22, struct ext4_encrypted_metadata)
196 +#define EXT4_IOC_SET_ENCRYPTION_METADATA _IOR('f', 23, struct ext4_encrypted_metadata)
197 +#define EXT4_IOC_GET_ENCRYPTED_FILENAME        _IOWR('f', 24, struct ext4_encrypted_metadata)
198 +#define EXT4_IOC_SET_ENCRYPTED_FILENAME        _IOR('f', 25, struct ext4_encrypted_metadata)
200  #ifndef FS_IOC_FSGETXATTR
201  /* Until the uapi changes get merged for project quota... */
202 @@ -2294,6 +2298,7 @@ ext4_fsblk_t ext4_inode_to_goal_block(struct inode *);
203  /* crypto_policy.c */
204  int ext4_is_child_context_consistent_with_parent(struct inode *parent,
205                                                  struct inode *child);
206 +int ext4_validate_encryption_context(struct ext4_encryption_context *ctx);
207  int ext4_inherit_context(struct inode *parent, struct inode *child);
208  void ext4_to_hex(char *dst, char *src, size_t src_size);
209  int ext4_process_policy(const struct ext4_encryption_policy *policy,
210 @@ -2380,6 +2385,10 @@ static inline void ext4_fname_free_filename(struct ext4_filename *fname) { }
211  void ext4_free_crypt_info(struct ext4_crypt_info *ci);
212  void ext4_free_encryption_info(struct inode *inode, struct ext4_crypt_info *ci);
213  int _ext4_get_encryption_info(struct inode *inode);
214 +int ext4_set_encryption_metadata(struct inode *inode,
215 +                                struct ext4_rw_enc_mdata *mdata);
216 +int ext4_get_encryption_metadata(struct inode *inode,
217 +                                struct ext4_rw_enc_mdata *mdata);
219  #ifdef CONFIG_EXT4_FS_ENCRYPTION
220  int ext4_has_encryption_key(struct inode *inode);
221 @@ -2469,18 +2478,24 @@ extern int ext4fs_dirhash(const char *name, int len, struct
222                           dx_hash_info *hinfo);
224  /* ialloc.c */
225 +#define EXT4_NEW_INODE_NOENCRYPT       0x0001
226  extern struct inode *__ext4_new_inode(handle_t *, struct inode *, umode_t,
227                                       const struct qstr *qstr, __u32 goal,
228                                       uid_t *owner, int handle_type,
229 -                                     unsigned int line_no, int nblocks);
230 +                                     unsigned int line_no, int nblocks,
231 +                                     int flags);
233  #define ext4_new_inode(handle, dir, mode, qstr, goal, owner) \
234         __ext4_new_inode((handle), (dir), (mode), (qstr), (goal), (owner), \
235 -                        0, 0, 0)
236 +                        0, 0, 0, 0)
237  #define ext4_new_inode_start_handle(dir, mode, qstr, goal, owner, \
238                                     type, nblocks)                  \
239         __ext4_new_inode(NULL, (dir), (mode), (qstr), (goal), (owner), \
240 -                        (type), __LINE__, (nblocks))
241 +                        (type), __LINE__, (nblocks), 0)
242 +#define ext4_new_inode_start_handle_flags(dir, mode, qstr, goal, owner, \
243 +                                         type, nblocks, flags)         \
244 +       __ext4_new_inode(NULL, (dir), (mode), (qstr), (goal), (owner), \
245 +                        (type), __LINE__, (nblocks), (flags))
248  extern void ext4_free_inode(handle_t *, struct inode *);
249 @@ -2621,6 +2636,10 @@ extern int ext4_generic_delete_entry(handle_t *handle,
250                                      int buf_size,
251                                      int csum_size);
252  extern int ext4_empty_dir(struct inode *inode);
253 +extern int ext4_get_encrypted_filename(struct file *filp,
254 +                                      struct ext4_rw_enc_mdata *mdata);
255 +extern int ext4_set_encrypted_filename(struct inode *dir,
256 +                                      struct ext4_rw_enc_mdata *efn);
258  /* resize.c */
259  extern int ext4_group_add(struct super_block *sb,
260 diff --git a/fs/ext4/ext4_crypto.h b/fs/ext4/ext4_crypto.h
261 index 1f73c29..600da7e 100644
262 --- a/fs/ext4/ext4_crypto.h
263 +++ b/fs/ext4/ext4_crypto.h
264 @@ -156,4 +156,18 @@ static inline u32 encrypted_symlink_data_len(u32 l)
265         return (l + sizeof(struct ext4_encrypted_symlink_data) - 1);
268 +/**
269 + * Structure used for communicating encrypted metadata with userspace
270 + */
271 +struct ext4_encrypted_metadata {
272 +       s32 fd;                 /* Only used by EXT4_IOC_SET_ENCRYPTED_FILENAME */
273 +       u32 len;
274 +       unsigned char __user *data;
277 +/* In-kernel structure */
278 +struct ext4_rw_enc_mdata {
279 +       struct ext4_encrypted_metadata u;
280 +       unsigned char *buf;
282  #endif /* _EXT4_CRYPTO_H */
283 diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
284 index 237b877..e96e4ae 100644
285 --- a/fs/ext4/ialloc.c
286 +++ b/fs/ext4/ialloc.c
287 @@ -742,7 +742,7 @@ out:
288  struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
289                                umode_t mode, const struct qstr *qstr,
290                                __u32 goal, uid_t *owner, int handle_type,
291 -                              unsigned int line_no, int nblocks)
292 +                              unsigned int line_no, int nblocks, int flags)
294         struct super_block *sb;
295         struct buffer_head *inode_bitmap_bh = NULL;
296 @@ -764,7 +764,8 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
297         if (!dir || !dir->i_nlink)
298                 return ERR_PTR(-EPERM);
300 -       if ((ext4_encrypted_inode(dir) ||
301 +       if (!(flags & EXT4_NEW_INODE_NOENCRYPT) &&
302 +           (ext4_encrypted_inode(dir) ||
303              DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb))) &&
304             (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) {
305                 err = ext4_get_encryption_info(dir);
306 diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
307 index eae5917..65d38e9 100644
308 --- a/fs/ext4/ioctl.c
309 +++ b/fs/ext4/ioctl.c
310 @@ -435,6 +435,39 @@ static inline unsigned long ext4_xflags_to_iflags(__u32 xflags)
311         return iflags;
314 +#ifdef CONFIG_EXT4_FS_ENCRYPTION
315 +static int read_user_mdata(unsigned long arg,
316 +                          struct ext4_rw_enc_mdata *mdata)
318 +       if (copy_from_user(&mdata->u,
319 +                          (struct ext4_encrypted_metadata __user *)arg,
320 +                          sizeof(struct ext4_encrypted_metadata)))
321 +               return -EFAULT;
322 +       /* Sanity check, as nothing should need to be this big */
323 +       if (mdata->u.len > PAGE_SIZE)
324 +               return -EINVAL;
325 +       mdata->buf = kmalloc(mdata->u.len, GFP_KERNEL);
326 +       if (!mdata->buf)
327 +               return -ENOMEM;
328 +       if (copy_from_user(mdata->buf, mdata->u.data, mdata->u.len))
329 +               return -EFAULT;
330 +       return 0;
334 +static int write_user_mdata(unsigned long arg,
335 +                         struct ext4_rw_enc_mdata *mdata)
337 +       if (copy_to_user(mdata->u.data, mdata->buf, mdata->u.len))
338 +               return -EFAULT;
339 +       if (copy_to_user((struct ext4_encrypted_metadata __user *)arg,
340 +                          &mdata->u,
341 +                          sizeof(struct ext4_encrypted_metadata)))
342 +               return -EFAULT;
343 +       return 0;
345 +#endif
347  long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
349         struct inode *inode = file_inode(filp);
350 @@ -896,6 +929,83 @@ encryption_policy_out:
352                 return 0;
353         }
354 +       case EXT4_IOC_GET_ENCRYPTION_METADATA: {
355 +#ifdef CONFIG_EXT4_FS_ENCRYPTION
356 +               struct ext4_rw_enc_mdata mdata;
357 +               int err = 0;
359 +               if (!ext4_encrypted_inode(inode))
360 +                       return -ENOENT;
362 +               err = read_user_mdata(arg, &mdata);
363 +               if (err)
364 +                       return err;
365 +               err = ext4_get_encryption_metadata(inode, &mdata);
366 +               if (!err)
367 +                       err = write_user_mdata(arg, &mdata);
368 +               kfree(mdata.buf);
369 +               return err;
370 +#else
371 +               return -EOPNOTSUPP;
372 +#endif
373 +       }
374 +       case EXT4_IOC_SET_ENCRYPTION_METADATA: {
375 +#ifdef CONFIG_EXT4_FS_ENCRYPTION
376 +               struct ext4_rw_enc_mdata mdata;
377 +               int err = 0;
379 +               if (ext4_encrypted_inode(inode))
380 +                       return -EINVAL;
381 +               err = read_user_mdata(arg, &mdata);
382 +               if (err)
383 +                       return err;
384 +               err = mnt_want_write_file(filp);
385 +               if (!err)
386 +                       err = ext4_set_encryption_metadata(inode, &mdata);
387 +               mnt_drop_write_file(filp);
388 +               kfree(mdata.buf);
389 +               return err;
390 +#else
391 +               return -EOPNOTSUPP;
392 +#endif
393 +       }
394 +       case EXT4_IOC_GET_ENCRYPTED_FILENAME: {
395 +#ifdef CONFIG_EXT4_FS_ENCRYPTION
396 +               struct ext4_rw_enc_mdata mdata;
397 +               int err = 0;
399 +               if (!ext4_encrypted_inode(inode))
400 +                       return -ENOENT;
401 +               err = read_user_mdata(arg, &mdata);
402 +               if (err)
403 +                       return err;
404 +               err = ext4_get_encrypted_filename(filp, &mdata);
405 +               if (!err)
406 +                       err = write_user_mdata(arg, &mdata);
407 +               kfree(mdata.buf);
408 +               return err;
409 +#else
410 +               return -EOPNOTSUPP;
411 +#endif
412 +       }
413 +       case EXT4_IOC_SET_ENCRYPTED_FILENAME: {
414 +#ifdef CONFIG_EXT4_FS_ENCRYPTION
415 +               struct ext4_rw_enc_mdata mdata;
416 +               int err = 0;
418 +               err = read_user_mdata(arg, &mdata);
419 +               if (err)
420 +                       return err;
421 +               err = mnt_want_write_file(filp);
422 +               if (!err)
423 +                       err = ext4_set_encrypted_filename(inode, &mdata);
424 +               mnt_drop_write_file(filp);
425 +               kfree(mdata.buf);
426 +               return err;
427 +#else
428 +               return -EOPNOTSUPP;
429 +#endif
430 +       }
431         default:
432                 return -ENOTTY;
433         }
434 @@ -962,6 +1072,9 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
435         case EXT4_IOC_SET_ENCRYPTION_POLICY:
436         case EXT4_IOC_GET_ENCRYPTION_PWSALT:
437         case EXT4_IOC_GET_ENCRYPTION_POLICY:
438 +       case EXT4_IOC_GET_ENCRYPTION_METADATA:
439 +       case EXT4_IOC_SET_ENCRYPTION_METADATA:
440 +       case EXT4_IOC_GET_ENCRYPTED_FILENAME:
441                 break;
442         default:
443                 return -ENOIOCTLCMD;
444 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
445 index c07422d..32edbe3 100644
446 --- a/fs/ext4/namei.c
447 +++ b/fs/ext4/namei.c
448 @@ -33,6 +33,8 @@
449  #include <linux/quotaops.h>
450  #include <linux/buffer_head.h>
451  #include <linux/bio.h>
452 +#include <linux/crc16.h>
453 +#include <linux/file.h>
454  #include "ext4.h"
455  #include "ext4_jbd2.h"
457 @@ -2075,24 +2077,16 @@ out_frames:
460  /*
461 - *     ext4_add_entry()
462 - *
463 - * adds a file entry to the specified directory, using the same
464 - * semantics as ext4_find_entry(). It returns NULL if it failed.
465 - *
466 - * NOTE!! The inode part of 'de' is left at 0 - which means you
467 - * may not sleep between calling this and putting something into
468 - * the entry, as someone else might have used it while you slept.
469 + * Add a directory entry to a directory, given the filename and the
470 + * inode it will point to.
471   */
472 -static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
473 -                         struct inode *inode)
474 +static int ext4_add_fname(handle_t *handle, struct inode *dir,
475 +                         struct ext4_filename *fname, struct inode *inode)
477 -       struct inode *dir = d_inode(dentry->d_parent);
478         struct buffer_head *bh = NULL;
479         struct ext4_dir_entry_2 *de;
480         struct ext4_dir_entry_tail *t;
481         struct super_block *sb;
482 -       struct ext4_filename fname;
483         int     retval;
484         int     dx_fallback=0;
485         unsigned blocksize;
486 @@ -2104,15 +2098,9 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
488         sb = dir->i_sb;
489         blocksize = sb->s_blocksize;
490 -       if (!dentry->d_name.len)
491 -               return -EINVAL;
493 -       retval = ext4_fname_setup_filename(dir, &dentry->d_name, 0, &fname);
494 -       if (retval)
495 -               return retval;
497         if (ext4_has_inline_data(dir)) {
498 -               retval = ext4_try_add_inline_entry(handle, &fname, dir, inode);
499 +               retval = ext4_try_add_inline_entry(handle, fname, dir, inode);
500                 if (retval < 0)
501                         goto out;
502                 if (retval == 1) {
503 @@ -2122,7 +2110,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
504         }
506         if (is_dx(dir)) {
507 -               retval = ext4_dx_add_entry(handle, &fname, dir, inode);
508 +               retval = ext4_dx_add_entry(handle, fname, dir, inode);
509                 if (!retval || (retval != ERR_BAD_DX_DIR))
510                         goto out;
511                 ext4_clear_inode_flag(dir, EXT4_INODE_INDEX);
512 @@ -2137,14 +2125,14 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
513                         bh = NULL;
514                         goto out;
515                 }
516 -               retval = add_dirent_to_buf(handle, &fname, dir, inode,
517 +               retval = add_dirent_to_buf(handle, fname, dir, inode,
518                                            NULL, bh);
519                 if (retval != -ENOSPC)
520                         goto out;
522                 if (blocks == 1 && !dx_fallback &&
523                     ext4_has_feature_dir_index(sb)) {
524 -                       retval = make_indexed_dir(handle, &fname, dir,
525 +                       retval = make_indexed_dir(handle, fname, dir,
526                                                   inode, bh);
527                         bh = NULL; /* make_indexed_dir releases bh */
528                         goto out;
529 @@ -2166,9 +2154,8 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
530                 initialize_dirent_tail(t, blocksize);
531         }
533 -       retval = add_dirent_to_buf(handle, &fname, dir, inode, de, bh);
534 +       retval = add_dirent_to_buf(handle, fname, dir, inode, de, bh);
535  out:
536 -       ext4_fname_free_filename(&fname);
537         brelse(bh);
538         if (retval == 0)
539                 ext4_set_inode_state(inode, EXT4_STATE_NEWENTRY);
540 @@ -2176,6 +2163,29 @@ out:
543  /*
544 + * Create a directory entry associated with the specified dentry and
545 + * inode.
546 + */
547 +static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
548 +                         struct inode *inode)
550 +       struct inode *dir = d_inode(dentry->d_parent);
551 +       struct ext4_filename fname;
552 +       int     retval;
554 +       if (!dentry->d_name.len)
555 +               return -EINVAL;
557 +       retval = ext4_fname_setup_filename(dir, &dentry->d_name, 0, &fname);
558 +       if (retval)
559 +               return retval;
561 +       retval = ext4_add_fname(handle, dir, &fname, inode);
562 +       ext4_fname_free_filename(&fname);
563 +       return retval;
567   * Returns 0 for success, or a negative error value
568   */
569  static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
570 @@ -3905,3 +3915,252 @@ const struct inode_operations ext4_special_inode_operations = {
571         .get_acl        = ext4_get_acl,
572         .set_acl        = ext4_set_acl,
573  };
575 +int ext4_get_encrypted_filename(struct file *filp,
576 +                               struct ext4_rw_enc_mdata *mdata)
578 +       unsigned char *cp = mdata->buf;
579 +       struct dentry *dentry = filp->f_path.dentry;
580 +       struct inode *inode = file_inode(filp);
581 +       struct inode *dir = dentry->d_parent->d_inode;
582 +       struct buffer_head *bh;
583 +       struct ext4_dir_entry_2 *de;
584 +       int isdir = S_ISDIR(inode->i_mode);
585 +       int len = isdir ? 10 : 4;
586 +       int ret;
588 +       if (!dir || !ext4_encrypted_inode(dir))
589 +               return -EINVAL;
591 +       if (!inode_owner_or_capable(dir) && !capable(CAP_SYS_ADMIN))
592 +               return -EACCES;
594 +       if (mdata->u.len < len)
595 +               return -ENOSPC;
597 +       *cp++ = 'e';
598 +       *cp++ = isdir ? 'd' : 'f';
599 +       *cp++ = 0;
600 +       *cp++ = 0;
602 +       if (isdir) {
603 +               *((u32 *)cp) = cpu_to_le32(inode->i_mode);
604 +               cp += 4;
605 +               ret = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
606 +                                    EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
607 +                                    NULL, 0);
608 +               if (ret < 0)
609 +                       return ret;
610 +               *((u16 *)cp) = cpu_to_le16((u16) ret);
611 +               cp += 2;
613 +               len += ret;
614 +               if (mdata->u.len < len)
615 +                       return -ENOSPC;
616 +               ret = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
617 +                                    EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
618 +                                    cp, ret);
619 +               if (ret < 0)
620 +                       return ret;
621 +               cp += ret;
622 +       }
624 +       bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
625 +       if (IS_ERR(bh))
626 +               return PTR_ERR(bh);
627 +       if (de == NULL)
628 +               return -ENOENT;
630 +       len += de->name_len;
631 +       if (mdata->u.len < len)
632 +               return -ENOSPC;
634 +       mdata->u.len = len;
635 +       memcpy(cp, de->name, de->name_len);
636 +       *((u16 *) &mdata->buf[2]) = cpu_to_le16(crc16(~0, mdata->buf,
637 +                                                     mdata->u.len));
638 +       return 0;
641 +int ext4_set_encrypted_filename(struct inode *dir,
642 +                               struct ext4_rw_enc_mdata *mdata)
644 +       struct ext4_encryption_context *ctx = NULL;
645 +       struct ext4_filename            fname;
646 +       unsigned char                   *cp = mdata->buf;
647 +       struct inode                    *inode = NULL;
648 +       struct fd                       fd;
649 +       handle_t                        *handle = NULL;
650 +       umode_t                         mode;
651 +       u16                             crc, xlen, credits;
652 +       int                             retval = 0, retries = 0, do_retry = 0;
653 +       int                             len = mdata->u.len;
655 +       if (!dir || !ext4_encrypted_inode(dir))
656 +               return -EINVAL;
658 +       retval = inode_permission(dir, MAY_WRITE | MAY_EXEC);
659 +       if (retval)
660 +               return retval;
662 +       if (len < 4)
663 +               return -EINVAL;
665 +       if (cp[0] != 'e' ||
666 +           cp[1] != ((mdata->u.fd == -1) ? 'd' : 'f'))
667 +               return -EINVAL;
668 +       crc = le16_to_cpu(*(u16 *)(cp+2));
669 +       cp[2] = cp[3] = 0;
670 +       cp += 4; len -= 4;
672 +       if (crc != crc16(~0, mdata->buf, mdata->u.len))
673 +               return -EINVAL;
675 +       if ((len < EXT4_CRYPTO_BLOCK_SIZE) || (len > EXT4_NAME_LEN + 1))
676 +               return -EINVAL;
678 +       retval = dquot_initialize(dir);
679 +       if (retval)
680 +               return retval;
682 +       credits = (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
683 +                  EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2);
685 +       if (mdata->u.fd >= 0) {
686 +               fd = fdget(mdata->u.fd);
687 +               if (!fd.file)
688 +                       return -EBADF;
689 +               inode = file_inode(fd.file);
690 +               mode = inode->i_mode;
691 +               retval = -EISDIR;
692 +               if (S_ISDIR(mode))
693 +                       goto out;
694 +       } else if (mdata->u.fd == -1) {
695 +               /* do an encrypted mkdir */
696 +               fd.file = NULL;
697 +               if (EXT4_DIR_LINK_MAX(dir))
698 +                       return -EMLINK;
699 +               if (len < 6)
700 +                       return -EINVAL;
701 +               mode = le32_to_cpu(*(u32 *)cp);
702 +               cp += 4;
703 +               xlen = le16_to_cpu(*(u16 *)cp);
704 +               cp += 2; len -= 6;
706 +               if (len < xlen ||
707 +                   xlen != sizeof(struct ext4_encryption_context))
708 +                       return -EINVAL;
710 +               ctx = (struct ext4_encryption_context *) cp;
711 +               retval = ext4_validate_encryption_context(ctx);
712 +               if (retval)
713 +                       return retval;
714 +               cp += xlen; len -= xlen;
716 +               /* credits for the mkdir and xattr set */
717 +               credits += (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
718 +                           EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
719 +                           ext4_jbd2_credits_xattr(dir));
720 +       retry:
721 +               inode = ext4_new_inode_start_handle_flags(dir, mode, NULL, 0,
722 +                                       NULL, EXT4_HT_DIR, credits,
723 +                                       EXT4_NEW_INODE_NOENCRYPT);
724 +               handle = ext4_journal_current_handle();
725 +               if (IS_ERR(inode)) {
726 +                       retval = PTR_ERR(inode);
727 +                       inode = NULL;
728 +                       goto out;
729 +               }
730 +               inode->i_op = &ext4_dir_inode_operations;
731 +               inode->i_fop = &ext4_dir_operations;
732 +               retval = ext4_init_new_dir(handle, dir, inode);
733 +               if (retval)
734 +                       goto out;
736 +               retval = ext4_xattr_set_handle(handle, inode,
737 +                               EXT4_XATTR_INDEX_ENCRYPTION,
738 +                               EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, ctx,
739 +                               sizeof(struct ext4_encryption_context),
740 +                               fd.file ? XATTR_REPLACE : XATTR_CREATE);
741 +               if (retval)
742 +                       goto out;
743 +               ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
744 +               ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
746 +               goto insert_fname;
747 +       } else
748 +               return -EINVAL;
751 +       if ((mode & S_ISUID) ||
752 +           ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))) {
753 +               /*
754 +                * root or the inode owner can link even in the case
755 +                * of "unsafe" hard link sources.  See
756 +                * safe_hardlink_sources() in fs/namei.c
757 +                */
758 +               if (!inode_owner_or_capable(inode) && !capable(CAP_SYS_ADMIN)) {
759 +                       retval = -EACCES;
760 +                       goto out;
761 +               }
762 +       }
764 +       retval = inode_permission(inode, MAY_READ | MAY_WRITE);
765 +       if (!retval && !inode_owner_or_capable(inode) &&
766 +           !capable(CAP_SYS_ADMIN))
767 +               goto out;
769 +       handle = ext4_journal_start(dir, EXT4_HT_DIR,
770 +               (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
771 +                EXT4_INDEX_EXTRA_TRANS_BLOCKS) + 2);
772 +       if (IS_ERR(handle)) {
773 +               retval = PTR_ERR(handle);
774 +               goto out;
775 +       }
777 +insert_fname:
778 +       if (!ext4_is_child_context_consistent_with_parent(dir, inode)) {
779 +               retval = -EPERM;
780 +               goto out;
781 +       }
783 +       memset(&fname, 0, sizeof(fname));
784 +       fname.disk_name.name = cp;
785 +       fname.disk_name.len = len;
786 +       retval = ext4_add_fname(handle, dir, &fname, inode);
787 +       if (retval)
788 +               goto out;
790 +       if (fd.file)
791 +               ext4_inc_count(handle, inode);
792 +       ext4_mark_inode_dirty(handle, inode);
793 +       if (!fd.file)
794 +               ext4_inc_count(handle, dir);
795 +       ext4_update_dx_flag(dir);
796 +       ext4_mark_inode_dirty(handle, dir);
797 +       if (fd.file == NULL) {
798 +               unlock_new_inode(inode);
799 +               iput(inode);
800 +       }
802 +out:
803 +       if (fd.file)
804 +               fdput(fd);
805 +       else if (retval && inode && (mdata->u.fd == -1)) {
806 +               /* need to undo a failed attempted mkdir */
807 +               clear_nlink(inode);
808 +               unlock_new_inode(inode);
809 +               ext4_mark_inode_dirty(handle, inode);
810 +               iput(inode);
811 +               if (retval == -ENOSPC &&
812 +                   ext4_should_retry_alloc(dir->i_sb, &retries))
813 +                       do_retry++;
814 +       }
815 +       if (handle)
816 +               ext4_journal_stop(handle);
817 +       if (do_retry) {
818 +               do_retry = 0;
819 +               goto retry;
820 +       }
821 +       return retval;