]> Git Repo - linux.git/commitdiff
Merge tag 'fscrypt_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
authorLinus Torvalds <[email protected]>
Sun, 4 Feb 2018 18:43:12 +0000 (10:43 -0800)
committerLinus Torvalds <[email protected]>
Sun, 4 Feb 2018 18:43:12 +0000 (10:43 -0800)
Pull fscrypt updates from Ted Ts'o:
 "Refactor support for encrypted symlinks to move common code to fscrypt"

Ted also points out about the merge:
 "This makes the f2fs symlink code use the fscrypt_encrypt_symlink()
  from the fscrypt tree. This will end up dropping the kzalloc() ->
  f2fs_kzalloc() change, which means the fscrypt-specific allocation
  won't get tested by f2fs's kmalloc error injection system; which is
  fine"

* tag 'fscrypt_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/fscrypt: (26 commits)
  fscrypt: fix build with pre-4.6 gcc versions
  fscrypt: remove 'ci' parameter from fscrypt_put_encryption_info()
  fscrypt: document symlink length restriction
  fscrypt: fix up fscrypt_fname_encrypted_size() for internal use
  fscrypt: define fscrypt_fname_alloc_buffer() to be for presented names
  fscrypt: calculate NUL-padding length in one place only
  fscrypt: move fscrypt_symlink_data to fscrypt_private.h
  fscrypt: remove fscrypt_fname_usr_to_disk()
  ubifs: switch to fscrypt_get_symlink()
  ubifs: switch to fscrypt ->symlink() helper functions
  ubifs: free the encrypted symlink target
  f2fs: switch to fscrypt_get_symlink()
  f2fs: switch to fscrypt ->symlink() helper functions
  ext4: switch to fscrypt_get_symlink()
  ext4: switch to fscrypt ->symlink() helper functions
  fscrypt: new helper function - fscrypt_get_symlink()
  fscrypt: new helper functions for ->symlink()
  fscrypt: trim down fscrypt.h includes
  fscrypt: move fscrypt_is_dot_dotdot() to fs/crypto/fname.c
  fscrypt: move fscrypt_valid_enc_modes() to fscrypt_private.h
  ...

1  2 
fs/ext4/namei.c
fs/ext4/super.c
fs/f2fs/inode.c
fs/f2fs/namei.c
fs/ubifs/dir.c
fs/ubifs/file.c

diff --combined fs/ext4/namei.c
index 9aa1deb1a5256daf58dddf15b9c269b6c0969a9b,727675794a45e9ab3fcaa0bbde6f799fa5b8d67b..b1f21e3a076327df20e5218451ff1feec7e3a13f
@@@ -34,7 -34,6 +34,7 @@@
  #include <linux/quotaops.h>
  #include <linux/buffer_head.h>
  #include <linux/bio.h>
 +#include <linux/iversion.h>
  #include "ext4.h"
  #include "ext4_jbd2.h"
  
@@@ -2960,7 -2959,7 +2960,7 @@@ static int ext4_rmdir(struct inode *dir
                             "empty directory '%.*s' has too many links (%u)",
                             dentry->d_name.len, dentry->d_name.name,
                             inode->i_nlink);
 -      inode->i_version++;
 +      inode_inc_iversion(inode);
        clear_nlink(inode);
        /* There's no need to set i_disksize: the fact that i_nlink is
         * zero will ensure that the right thing happens during any
@@@ -3057,39 -3056,19 +3057,19 @@@ static int ext4_symlink(struct inode *d
        struct inode *inode;
        int err, len = strlen(symname);
        int credits;
-       bool encryption_required;
        struct fscrypt_str disk_link;
-       struct fscrypt_symlink_data *sd = NULL;
  
        if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb))))
                return -EIO;
  
-       disk_link.len = len + 1;
-       disk_link.name = (char *) symname;
-       encryption_required = (ext4_encrypted_inode(dir) ||
-                              DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb)));
-       if (encryption_required) {
-               err = fscrypt_get_encryption_info(dir);
-               if (err)
-                       return err;
-               if (!fscrypt_has_encryption_key(dir))
-                       return -ENOKEY;
-               disk_link.len = (fscrypt_fname_encrypted_size(dir, len) +
-                                sizeof(struct fscrypt_symlink_data));
-               sd = kzalloc(disk_link.len, GFP_KERNEL);
-               if (!sd)
-                       return -ENOMEM;
-       }
-       if (disk_link.len > dir->i_sb->s_blocksize) {
-               err = -ENAMETOOLONG;
-               goto err_free_sd;
-       }
+       err = fscrypt_prepare_symlink(dir, symname, len, dir->i_sb->s_blocksize,
+                                     &disk_link);
+       if (err)
+               return err;
  
        err = dquot_initialize(dir);
        if (err)
-               goto err_free_sd;
+               return err;
  
        if ((disk_link.len > EXT4_N_BLOCKS * 4)) {
                /*
        if (IS_ERR(inode)) {
                if (handle)
                        ext4_journal_stop(handle);
-               err = PTR_ERR(inode);
-               goto err_free_sd;
+               return PTR_ERR(inode);
        }
  
-       if (encryption_required) {
-               struct qstr istr;
-               struct fscrypt_str ostr =
-                       FSTR_INIT(sd->encrypted_path, disk_link.len);
-               istr.name = (const unsigned char *) symname;
-               istr.len = len;
-               err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr);
+       if (IS_ENCRYPTED(inode)) {
+               err = fscrypt_encrypt_symlink(inode, symname, len, &disk_link);
                if (err)
                        goto err_drop_inode;
-               sd->len = cpu_to_le16(ostr.len);
-               disk_link.name = (char *) sd;
                inode->i_op = &ext4_encrypted_symlink_inode_operations;
        }
  
        if ((disk_link.len > EXT4_N_BLOCKS * 4)) {
-               if (!encryption_required)
+               if (!IS_ENCRYPTED(inode))
                        inode->i_op = &ext4_symlink_inode_operations;
                inode_nohighmem(inode);
                ext4_set_aops(inode);
        } else {
                /* clear the extent format for fast symlink */
                ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS);
-               if (!encryption_required) {
+               if (!IS_ENCRYPTED(inode)) {
                        inode->i_op = &ext4_fast_symlink_inode_operations;
                        inode->i_link = (char *)&EXT4_I(inode)->i_data;
                }
  
        if (handle)
                ext4_journal_stop(handle);
-       kfree(sd);
-       return err;
+       goto out_free_encrypted_link;
  err_drop_inode:
        if (handle)
                ext4_journal_stop(handle);
        clear_nlink(inode);
        unlock_new_inode(inode);
        iput(inode);
- err_free_sd:
-       kfree(sd);
+ out_free_encrypted_link:
+       if (disk_link.name != (unsigned char *)symname)
+               kfree(disk_link.name);
        return err;
  }
  
@@@ -3222,9 -3193,9 +3194,9 @@@ static int ext4_link(struct dentry *old
        if (err)
                return err;
  
 -       if ((ext4_test_inode_flag(dir, EXT4_INODE_PROJINHERIT)) &&
 -         (!projid_eq(EXT4_I(dir)->i_projid,
 -                     EXT4_I(old_dentry->d_inode)->i_projid)))
 +      if ((ext4_test_inode_flag(dir, EXT4_INODE_PROJINHERIT)) &&
 +          (!projid_eq(EXT4_I(dir)->i_projid,
 +                      EXT4_I(old_dentry->d_inode)->i_projid)))
                return -EXDEV;
  
        err = dquot_initialize(dir);
@@@ -3366,7 -3337,7 +3338,7 @@@ static int ext4_setent(handle_t *handle
        ent->de->inode = cpu_to_le32(ino);
        if (ext4_has_feature_filetype(ent->dir->i_sb))
                ent->de->file_type = file_type;
 -      ent->dir->i_version++;
 +      inode_inc_iversion(ent->dir);
        ent->dir->i_ctime = ent->dir->i_mtime =
                current_time(ent->dir);
        ext4_mark_inode_dirty(handle, ent->dir);
diff --combined fs/ext4/super.c
index 899e6faf33815ac297ebaa6522ecbd6703464659,152d05d983f6e666be203a0a313625227ff06d38..421222ec350956ae3e0925d481b0c978b3b37b59
@@@ -1,4 -1,3 +1,4 @@@
 +// SPDX-License-Identifier: GPL-2.0
  /*
   *  linux/fs/ext4/super.c
   *
@@@ -41,7 -40,6 +41,7 @@@
  #include <linux/dax.h>
  #include <linux/cleancache.h>
  #include <linux/uaccess.h>
 +#include <linux/iversion.h>
  
  #include <linux/kthread.h>
  #include <linux/freezer.h>
@@@ -744,7 -742,6 +744,7 @@@ __acquires(bitlock
        }
  
        ext4_unlock_group(sb, grp);
 +      ext4_commit_super(sb, 1);
        ext4_handle_error(sb);
        /*
         * We only get here in the ERRORS_RO case; relocking the group
@@@ -873,6 -870,7 +873,6 @@@ static void ext4_put_super(struct super
        ext4_unregister_li_request(sb);
        ext4_quota_off_umount(sb);
  
 -      flush_workqueue(sbi->rsv_conversion_wq);
        destroy_workqueue(sbi->rsv_conversion_wq);
  
        if (sbi->s_journal) {
@@@ -969,7 -967,7 +969,7 @@@ static struct inode *ext4_alloc_inode(s
        if (!ei)
                return NULL;
  
 -      ei->vfs_inode.i_version = 1;
 +      inode_set_iversion(&ei->vfs_inode, 1);
        spin_lock_init(&ei->i_raw_lock);
        INIT_LIST_HEAD(&ei->i_prealloc_list);
        spin_lock_init(&ei->i_prealloc_lock);
@@@ -1038,13 -1036,11 +1038,13 @@@ static void init_once(void *foo
  
  static int __init init_inodecache(void)
  {
 -      ext4_inode_cachep = kmem_cache_create("ext4_inode_cache",
 -                                           sizeof(struct ext4_inode_info),
 -                                           0, (SLAB_RECLAIM_ACCOUNT|
 -                                              SLAB_MEM_SPREAD|SLAB_ACCOUNT),
 -                                           init_once);
 +      ext4_inode_cachep = kmem_cache_create_usercopy("ext4_inode_cache",
 +                              sizeof(struct ext4_inode_info), 0,
 +                              (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD|
 +                                      SLAB_ACCOUNT),
 +                              offsetof(struct ext4_inode_info, i_data),
 +                              sizeof_field(struct ext4_inode_info, i_data),
 +                              init_once);
        if (ext4_inode_cachep == NULL)
                return -ENOMEM;
        return 0;
@@@ -1073,9 -1069,7 +1073,7 @@@ void ext4_clear_inode(struct inode *ino
                jbd2_free_inode(EXT4_I(inode)->jinode);
                EXT4_I(inode)->jinode = NULL;
        }
- #ifdef CONFIG_EXT4_FS_ENCRYPTION
-       fscrypt_put_encryption_info(inode, NULL);
- #endif
+       fscrypt_put_encryption_info(inode);
  }
  
  static struct inode *ext4_nfs_get_inode(struct super_block *sb,
@@@ -2680,7 -2674,7 +2678,7 @@@ static ext4_fsblk_t descriptor_loc(stru
         * compensate.
         */
        if (sb->s_blocksize == 1024 && nr == 0 &&
 -          le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) == 0)
 +          le32_to_cpu(sbi->s_es->s_first_data_block) == 0)
                has_super++;
  
        return (has_super + ext4_group_first_block_no(sb, bg));
@@@ -3125,7 -3119,7 +3123,7 @@@ int ext4_register_li_request(struct sup
  {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct ext4_li_request *elr = NULL;
 -      ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
 +      ext4_group_t ngroups = sbi->s_groups_count;
        int ret = 0;
  
        mutex_lock(&ext4_li_mtx);
@@@ -4840,7 -4834,7 +4838,7 @@@ static int ext4_sync_fs(struct super_bl
        bool needs_barrier = false;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
  
 -      if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
 +      if (unlikely(ext4_forced_shutdown(sbi)))
                return 0;
  
        trace_ext4_sync_fs(sb, wait);
diff --combined fs/f2fs/inode.c
index 89c838bfb06789a8c7ba339b1968b5e8adb0bcca,22a5607a051837266c9c9d1722f65c3e36cd3758..205add3d0f3a0538751cb0281083e52c8ddd4ef2
@@@ -22,9 -22,6 +22,9 @@@
  
  void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync)
  {
 +      if (is_inode_flag_set(inode, FI_NEW_INODE))
 +              return;
 +
        if (f2fs_inode_dirtied(inode, sync))
                return;
  
@@@ -278,12 -275,6 +278,12 @@@ static int do_read_inode(struct inode *
                i_projid = F2FS_DEF_PROJID;
        fi->i_projid = make_kprojid(&init_user_ns, i_projid);
  
 +      if (f2fs_has_extra_attr(inode) && f2fs_sb_has_inode_crtime(sbi->sb) &&
 +                      F2FS_FITS_IN_INODE(ri, fi->i_extra_isize, i_crtime)) {
 +              fi->i_crtime.tv_sec = le64_to_cpu(ri->i_crtime);
 +              fi->i_crtime.tv_nsec = le32_to_cpu(ri->i_crtime_nsec);
 +      }
 +
        f2fs_put_page(node_page, 1);
  
        stat_inc_inline_xattr(inode);
@@@ -369,15 -360,14 +369,15 @@@ retry
        return inode;
  }
  
 -int update_inode(struct inode *inode, struct page *node_page)
 +void update_inode(struct inode *inode, struct page *node_page)
  {
        struct f2fs_inode *ri;
        struct extent_tree *et = F2FS_I(inode)->extent_tree;
  
 -      f2fs_inode_synced(inode);
 -
        f2fs_wait_on_page_writeback(node_page, NODE, true);
 +      set_page_dirty(node_page);
 +
 +      f2fs_inode_synced(inode);
  
        ri = F2FS_INODE(node_page);
  
                                                F2FS_I(inode)->i_projid);
                        ri->i_projid = cpu_to_le32(i_projid);
                }
 +
 +              if (f2fs_sb_has_inode_crtime(F2FS_I_SB(inode)->sb) &&
 +                      F2FS_FITS_IN_INODE(ri, F2FS_I(inode)->i_extra_isize,
 +                                                              i_crtime)) {
 +                      ri->i_crtime =
 +                              cpu_to_le64(F2FS_I(inode)->i_crtime.tv_sec);
 +                      ri->i_crtime_nsec =
 +                              cpu_to_le32(F2FS_I(inode)->i_crtime.tv_nsec);
 +              }
        }
  
        __set_inode_rdev(inode, ri);
        if (inode->i_nlink == 0)
                clear_inline_node(node_page);
  
 -      return set_page_dirty(node_page);
  }
  
 -int update_inode_page(struct inode *inode)
 +void update_inode_page(struct inode *inode)
  {
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        struct page *node_page;
 -      int ret = 0;
  retry:
        node_page = get_node_page(sbi, inode->i_ino);
        if (IS_ERR(node_page)) {
                } else if (err != -ENOENT) {
                        f2fs_stop_checkpoint(sbi, false);
                }
 -              return 0;
 +              return;
        }
 -      ret = update_inode(inode, node_page);
 +      update_inode(inode, node_page);
        f2fs_put_page(node_page, 1);
 -      return ret;
  }
  
  int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
@@@ -585,7 -569,7 +585,7 @@@ no_delete
                        !exist_written_data(sbi, inode->i_ino, ORPHAN_INO));
        }
  out_clear:
-       fscrypt_put_encryption_info(inode, NULL);
+       fscrypt_put_encryption_info(inode);
        clear_inode(inode);
  }
  
diff --combined fs/f2fs/namei.c
index c4c94c7e9f4fb332a6684d4d46b1efb232d27742,37816d2ebb93dfda5d8e5ec00154f2d6d0df12d4..b68e7b03959f5b7cc67d2b6f9b94715d517fac14
@@@ -50,8 -50,7 +50,8 @@@ static struct inode *f2fs_new_inode(str
  
        inode->i_ino = ino;
        inode->i_blocks = 0;
 -      inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
 +      inode->i_mtime = inode->i_atime = inode->i_ctime =
 +                      F2FS_I(inode)->i_crtime = current_time(inode);
        inode->i_generation = sbi->s_next_generation++;
  
        err = insert_inode_locked(inode);
        if (err)
                goto fail_drop;
  
 +      set_inode_flag(inode, FI_NEW_INODE);
 +
        /* If the directory encrypted, then we should encrypt the inode. */
        if (f2fs_encrypted_inode(dir) && f2fs_may_encrypt(inode))
                f2fs_set_encrypted_inode(inode);
  
 -      set_inode_flag(inode, FI_NEW_INODE);
 -
        if (f2fs_sb_has_extra_attr(sbi->sb)) {
                set_inode_flag(inode, FI_EXTRA_ATTR);
                F2FS_I(inode)->i_extra_isize = F2FS_TOTAL_EXTRA_ATTR_SIZE;
@@@ -241,9 -240,9 +241,9 @@@ static int f2fs_link(struct dentry *old
        if (unlikely(f2fs_cp_error(sbi)))
                return -EIO;
  
 -      if (f2fs_encrypted_inode(dir) &&
 -                      !fscrypt_has_permitted_context(dir, inode))
 -              return -EPERM;
 +      err = fscrypt_prepare_link(old_dentry, dir, dentry);
 +      if (err)
 +              return err;
  
        if (is_inode_flag_set(dir, FI_PROJ_INHERIT) &&
                        (!projid_eq(F2FS_I(dir)->i_projid,
@@@ -358,9 -357,20 +358,9 @@@ static struct dentry *f2fs_lookup(struc
  
        trace_f2fs_lookup_start(dir, dentry, flags);
  
 -      if (f2fs_encrypted_inode(dir)) {
 -              err = fscrypt_get_encryption_info(dir);
 -
 -              /*
 -               * DCACHE_ENCRYPTED_WITH_KEY is set if the dentry is
 -               * created while the directory was encrypted and we
 -               * don't have access to the key.
 -               */
 -              if (fscrypt_has_encryption_key(dir))
 -                      fscrypt_set_encrypted_dentry(dentry);
 -              fscrypt_set_d_op(dentry);
 -              if (err && err != -ENOKEY)
 -                      goto out;
 -      }
 +      err = fscrypt_prepare_lookup(dir, dentry, flags);
 +      if (err)
 +              goto out;
  
        if (dentry->d_name.len > F2FS_NAME_LEN) {
                err = -ENAMETOOLONG;
@@@ -486,27 -496,16 +486,16 @@@ static int f2fs_symlink(struct inode *d
        struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
        struct inode *inode;
        size_t len = strlen(symname);
-       struct fscrypt_str disk_link = FSTR_INIT((char *)symname, len + 1);
-       struct fscrypt_symlink_data *sd = NULL;
+       struct fscrypt_str disk_link;
        int err;
  
        if (unlikely(f2fs_cp_error(sbi)))
                return -EIO;
  
-       if (f2fs_encrypted_inode(dir)) {
-               err = fscrypt_get_encryption_info(dir);
-               if (err)
-                       return err;
-               if (!fscrypt_has_encryption_key(dir))
-                       return -ENOKEY;
-               disk_link.len = (fscrypt_fname_encrypted_size(dir, len) +
-                               sizeof(struct fscrypt_symlink_data));
-       }
-       if (disk_link.len > dir->i_sb->s_blocksize)
-               return -ENAMETOOLONG;
+       err = fscrypt_prepare_symlink(dir, symname, len, dir->i_sb->s_blocksize,
+                                     &disk_link);
+       if (err)
+               return err;
  
        err = dquot_initialize(dir);
        if (err)
        if (IS_ERR(inode))
                return PTR_ERR(inode);
  
-       if (f2fs_encrypted_inode(inode))
+       if (IS_ENCRYPTED(inode))
                inode->i_op = &f2fs_encrypted_symlink_inode_operations;
        else
                inode->i_op = &f2fs_symlink_inode_operations;
        f2fs_lock_op(sbi);
        err = f2fs_add_link(dentry, inode);
        if (err)
-               goto out;
+               goto out_handle_failed_inode;
        f2fs_unlock_op(sbi);
        alloc_nid_done(sbi, inode->i_ino);
  
-       if (f2fs_encrypted_inode(inode)) {
-               struct qstr istr = QSTR_INIT(symname, len);
-               struct fscrypt_str ostr;
-               sd = f2fs_kzalloc(sbi, disk_link.len, GFP_NOFS);
-               if (!sd) {
-                       err = -ENOMEM;
-                       goto err_out;
-               }
-               err = fscrypt_get_encryption_info(inode);
-               if (err)
-                       goto err_out;
-               if (!fscrypt_has_encryption_key(inode)) {
-                       err = -ENOKEY;
-                       goto err_out;
-               }
-               ostr.name = sd->encrypted_path;
-               ostr.len = disk_link.len;
-               err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr);
-               if (err)
-                       goto err_out;
-               sd->len = cpu_to_le16(ostr.len);
-               disk_link.name = (char *)sd;
-       }
+       err = fscrypt_encrypt_symlink(inode, symname, len, &disk_link);
+       if (err)
+               goto err_out;
  
        err = page_symlink(inode, disk_link.name, disk_link.len);
  
@@@ -584,12 -558,14 +548,14 @@@ err_out
                f2fs_unlink(dir, dentry);
        }
  
-       kfree(sd);
        f2fs_balance_fs(sbi, true);
-       return err;
- out:
+       goto out_free_encrypted_link;
+ out_handle_failed_inode:
        handle_failed_inode(inode);
+ out_free_encrypted_link:
+       if (disk_link.name != (unsigned char *)symname)
+               kfree(disk_link.name);
        return err;
  }
  
@@@ -790,6 -766,18 +756,6 @@@ static int f2fs_rename(struct inode *ol
        if (unlikely(f2fs_cp_error(sbi)))
                return -EIO;
  
 -      if ((f2fs_encrypted_inode(old_dir) &&
 -                      !fscrypt_has_encryption_key(old_dir)) ||
 -                      (f2fs_encrypted_inode(new_dir) &&
 -                      !fscrypt_has_encryption_key(new_dir)))
 -              return -ENOKEY;
 -
 -      if ((old_dir != new_dir) && f2fs_encrypted_inode(new_dir) &&
 -                      !fscrypt_has_permitted_context(new_dir, old_inode)) {
 -              err = -EPERM;
 -              goto out;
 -      }
 -
        if (is_inode_flag_set(new_dir, FI_PROJ_INHERIT) &&
                        (!projid_eq(F2FS_I(new_dir)->i_projid,
                        F2FS_I(old_dentry->d_inode)->i_projid)))
                }
                f2fs_i_links_write(old_dir, false);
        }
 +      add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO);
  
        f2fs_unlock_op(sbi);
  
@@@ -981,6 -968,18 +947,6 @@@ static int f2fs_cross_rename(struct ino
        if (unlikely(f2fs_cp_error(sbi)))
                return -EIO;
  
 -      if ((f2fs_encrypted_inode(old_dir) &&
 -                      !fscrypt_has_encryption_key(old_dir)) ||
 -                      (f2fs_encrypted_inode(new_dir) &&
 -                      !fscrypt_has_encryption_key(new_dir)))
 -              return -ENOKEY;
 -
 -      if ((f2fs_encrypted_inode(old_dir) || f2fs_encrypted_inode(new_dir)) &&
 -                      (old_dir != new_dir) &&
 -                      (!fscrypt_has_permitted_context(new_dir, old_inode) ||
 -                       !fscrypt_has_permitted_context(old_dir, new_inode)))
 -              return -EPERM;
 -
        if ((is_inode_flag_set(new_dir, FI_PROJ_INHERIT) &&
                        !projid_eq(F2FS_I(new_dir)->i_projid,
                        F2FS_I(old_dentry->d_inode)->i_projid)) ||
        }
        f2fs_mark_inode_dirty_sync(new_dir, false);
  
 +      add_ino_entry(sbi, old_dir->i_ino, TRANS_DIR_INO);
 +      add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO);
 +
        f2fs_unlock_op(sbi);
  
        if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir))
@@@ -1123,16 -1119,9 +1089,16 @@@ static int f2fs_rename2(struct inode *o
                        struct inode *new_dir, struct dentry *new_dentry,
                        unsigned int flags)
  {
 +      int err;
 +
        if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
                return -EINVAL;
  
 +      err = fscrypt_prepare_rename(old_dir, old_dentry, new_dir, new_dentry,
 +                                   flags);
 +      if (err)
 +              return err;
 +
        if (flags & RENAME_EXCHANGE) {
                return f2fs_cross_rename(old_dir, old_dentry,
                                         new_dir, new_dentry);
@@@ -1148,68 -1137,20 +1114,20 @@@ static const char *f2fs_encrypted_get_l
                                           struct inode *inode,
                                           struct delayed_call *done)
  {
-       struct page *cpage = NULL;
-       char *caddr, *paddr = NULL;
-       struct fscrypt_str cstr = FSTR_INIT(NULL, 0);
-       struct fscrypt_str pstr = FSTR_INIT(NULL, 0);
-       struct fscrypt_symlink_data *sd;
-       u32 max_size = inode->i_sb->s_blocksize;
-       int res;
+       struct page *page;
+       const char *target;
  
        if (!dentry)
                return ERR_PTR(-ECHILD);
  
-       res = fscrypt_get_encryption_info(inode);
-       if (res)
-               return ERR_PTR(res);
-       cpage = read_mapping_page(inode->i_mapping, 0, NULL);
-       if (IS_ERR(cpage))
-               return ERR_CAST(cpage);
-       caddr = page_address(cpage);
-       /* Symlink is encrypted */
-       sd = (struct fscrypt_symlink_data *)caddr;
-       cstr.name = sd->encrypted_path;
-       cstr.len = le16_to_cpu(sd->len);
-       /* this is broken symlink case */
-       if (unlikely(cstr.len == 0)) {
-               res = -ENOENT;
-               goto errout;
-       }
-       if ((cstr.len + sizeof(struct fscrypt_symlink_data) - 1) > max_size) {
-               /* Symlink data on the disk is corrupted */
-               res = -EIO;
-               goto errout;
-       }
-       res = fscrypt_fname_alloc_buffer(inode, cstr.len, &pstr);
-       if (res)
-               goto errout;
-       res = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr);
-       if (res)
-               goto errout;
-       /* this is broken symlink case */
-       if (unlikely(pstr.name[0] == 0)) {
-               res = -ENOENT;
-               goto errout;
-       }
-       paddr = pstr.name;
-       /* Null-terminate the name */
-       paddr[pstr.len] = '\0';
+       page = read_mapping_page(inode->i_mapping, 0, NULL);
+       if (IS_ERR(page))
+               return ERR_CAST(page);
  
-       put_page(cpage);
-       set_delayed_call(done, kfree_link, paddr);
-       return paddr;
- errout:
-       fscrypt_fname_free_buffer(&pstr);
-       put_page(cpage);
-       return ERR_PTR(res);
+       target = fscrypt_get_symlink(inode, page_address(page),
+                                    inode->i_sb->s_blocksize, done);
+       put_page(page);
+       return target;
  }
  
  const struct inode_operations f2fs_encrypted_symlink_inode_operations = {
diff --combined fs/ubifs/dir.c
index a2ea4856e67b127e97b56d505f2b694df1f57d1a,518c1025588132be23ea11dd44edac971f8aaa56..9d7fb88e172e3d2f17acff5a72f432a8d3e5bddd
@@@ -220,9 -220,20 +220,9 @@@ static struct dentry *ubifs_lookup(stru
  
        dbg_gen("'%pd' in dir ino %lu", dentry, dir->i_ino);
  
 -      if (ubifs_crypt_is_encrypted(dir)) {
 -              err = fscrypt_get_encryption_info(dir);
 -
 -              /*
 -               * DCACHE_ENCRYPTED_WITH_KEY is set if the dentry is
 -               * created while the directory was encrypted and we
 -               * have access to the key.
 -               */
 -              if (fscrypt_has_encryption_key(dir))
 -                      fscrypt_set_encrypted_dentry(dentry);
 -              fscrypt_set_d_op(dentry);
 -              if (err && err != -ENOKEY)
 -                      return ERR_PTR(err);
 -      }
 +      err = fscrypt_prepare_lookup(dir, dentry, flags);
 +      if (err)
 +              return ERR_PTR(err);
  
        err = fscrypt_setup_filename(dir, &dentry->d_name, 1, &nm);
        if (err)
@@@ -732,9 -743,9 +732,9 @@@ static int ubifs_link(struct dentry *ol
        ubifs_assert(inode_is_locked(dir));
        ubifs_assert(inode_is_locked(inode));
  
 -      if (ubifs_crypt_is_encrypted(dir) &&
 -          !fscrypt_has_permitted_context(dir, inode))
 -              return -EPERM;
 +      err = fscrypt_prepare_link(old_dentry, dir, dentry);
 +      if (err)
 +              return err;
  
        err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
        if (err)
@@@ -1138,38 -1149,24 +1138,24 @@@ static int ubifs_symlink(struct inode *
        struct ubifs_info *c = dir->i_sb->s_fs_info;
        int err, len = strlen(symname);
        int sz_change = CALC_DENT_SIZE(len);
-       struct fscrypt_str disk_link = FSTR_INIT((char *)symname, len + 1);
-       struct fscrypt_symlink_data *sd = NULL;
+       struct fscrypt_str disk_link;
        struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
                                        .new_ino_d = ALIGN(len, 8),
                                        .dirtied_ino = 1 };
        struct fscrypt_name nm;
  
-       if (ubifs_crypt_is_encrypted(dir)) {
-               err = fscrypt_get_encryption_info(dir);
-               if (err)
-                       goto out_budg;
-               if (!fscrypt_has_encryption_key(dir)) {
-                       err = -EPERM;
-                       goto out_budg;
-               }
+       dbg_gen("dent '%pd', target '%s' in dir ino %lu", dentry,
+               symname, dir->i_ino);
  
-               disk_link.len = (fscrypt_fname_encrypted_size(dir, len) +
-                               sizeof(struct fscrypt_symlink_data));
-       }
+       err = fscrypt_prepare_symlink(dir, symname, len, UBIFS_MAX_INO_DATA,
+                                     &disk_link);
+       if (err)
+               return err;
  
        /*
         * Budget request settings: new inode, new direntry and changing parent
         * directory inode.
         */
-       dbg_gen("dent '%pd', target '%s' in dir ino %lu", dentry,
-               symname, dir->i_ino);
-       if (disk_link.len > UBIFS_MAX_INO_DATA)
-               return -ENAMETOOLONG;
        err = ubifs_budget_space(c, &req);
        if (err)
                return err;
                goto out_inode;
        }
  
-       if (ubifs_crypt_is_encrypted(dir)) {
-               struct qstr istr = QSTR_INIT(symname, len);
-               struct fscrypt_str ostr;
-               sd = kzalloc(disk_link.len, GFP_NOFS);
-               if (!sd) {
-                       err = -ENOMEM;
-                       goto out_inode;
-               }
-               ostr.name = sd->encrypted_path;
-               ostr.len = disk_link.len;
-               err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr);
-               if (err) {
-                       kfree(sd);
+       if (IS_ENCRYPTED(inode)) {
+               disk_link.name = ui->data; /* encrypt directly into ui->data */
+               err = fscrypt_encrypt_symlink(inode, symname, len, &disk_link);
+               if (err)
                        goto out_inode;
-               }
-               sd->len = cpu_to_le16(ostr.len);
-               disk_link.name = (char *)sd;
        } else {
+               memcpy(ui->data, disk_link.name, disk_link.len);
                inode->i_link = ui->data;
        }
  
-       memcpy(ui->data, disk_link.name, disk_link.len);
-       ((char *)ui->data)[disk_link.len - 1] = '\0';
        /*
         * The terminating zero byte is not written to the flash media and it
         * is put just to make later in-memory string processing simpler. Thus,
-        * data length is @len, not @len + %1.
+        * data length is @disk_link.len - 1, not @disk_link.len.
         */
        ui->data_len = disk_link.len - 1;
        inode->i_size = ubifs_inode(inode)->ui_size = disk_link.len - 1;
                goto out_cancel;
        mutex_unlock(&dir_ui->ui_mutex);
  
-       ubifs_release_budget(c, &req);
        insert_inode_hash(inode);
        d_instantiate(dentry, inode);
-       fscrypt_free_filename(&nm);
-       return 0;
+       err = 0;
+       goto out_fname;
  
  out_cancel:
        dir->i_size -= sz_change;
@@@ -1342,6 -1320,12 +1309,6 @@@ static int do_rename(struct inode *old_
        if (unlink)
                ubifs_assert(inode_is_locked(new_inode));
  
 -      if (old_dir != new_dir) {
 -              if (ubifs_crypt_is_encrypted(new_dir) &&
 -                  !fscrypt_has_permitted_context(new_dir, old_inode))
 -                      return -EPERM;
 -      }
 -
        if (unlink && is_dir) {
                err = ubifs_check_dir_empty(new_inode);
                if (err)
@@@ -1556,6 -1540,13 +1523,6 @@@ static int ubifs_xrename(struct inode *
  
        ubifs_assert(fst_inode && snd_inode);
  
 -      if ((ubifs_crypt_is_encrypted(old_dir) ||
 -          ubifs_crypt_is_encrypted(new_dir)) &&
 -          (old_dir != new_dir) &&
 -          (!fscrypt_has_permitted_context(new_dir, fst_inode) ||
 -           !fscrypt_has_permitted_context(old_dir, snd_inode)))
 -              return -EPERM;
 -
        err = fscrypt_setup_filename(old_dir, &old_dentry->d_name, 0, &fst_nm);
        if (err)
                return err;
@@@ -1600,19 -1591,12 +1567,19 @@@ static int ubifs_rename(struct inode *o
                        struct inode *new_dir, struct dentry *new_dentry,
                        unsigned int flags)
  {
 +      int err;
 +
        if (flags & ~(RENAME_NOREPLACE | RENAME_WHITEOUT | RENAME_EXCHANGE))
                return -EINVAL;
  
        ubifs_assert(inode_is_locked(old_dir));
        ubifs_assert(inode_is_locked(new_dir));
  
 +      err = fscrypt_prepare_rename(old_dir, old_dentry, new_dir, new_dentry,
 +                                   flags);
 +      if (err)
 +              return err;
 +
        if (flags & RENAME_EXCHANGE)
                return ubifs_xrename(old_dir, old_dentry, new_dir, new_dentry);
  
diff --combined fs/ubifs/file.c
index 9fe194a4fa9ba5a80aa36ff3b37fa4ec78452544,3cfc578c42eade80cef2e3669808e61f153325c3..cf348ba9923858927d6f19a92b65985184285dc3
@@@ -1284,9 -1284,13 +1284,9 @@@ int ubifs_setattr(struct dentry *dentry
        if (err)
                return err;
  
 -      if (ubifs_crypt_is_encrypted(inode) && (attr->ia_valid & ATTR_SIZE)) {
 -              err = fscrypt_get_encryption_info(inode);
 -              if (err)
 -                      return err;
 -              if (!fscrypt_has_encryption_key(inode))
 -                      return -ENOKEY;
 -      }
 +      err = fscrypt_prepare_setattr(dentry, attr);
 +      if (err)
 +              return err;
  
        if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size < inode->i_size)
                /* Truncation to a smaller size */
@@@ -1625,53 -1629,50 +1625,21 @@@ static int ubifs_file_mmap(struct file 
        return 0;
  }
  
 -static int ubifs_file_open(struct inode *inode, struct file *filp)
 -{
 -      int ret;
 -      struct dentry *dir;
 -      struct ubifs_info *c = inode->i_sb->s_fs_info;
 -
 -      if (ubifs_crypt_is_encrypted(inode)) {
 -              ret = fscrypt_get_encryption_info(inode);
 -              if (ret)
 -                      return -EACCES;
 -              if (!fscrypt_has_encryption_key(inode))
 -                      return -ENOKEY;
 -      }
 -
 -      dir = dget_parent(file_dentry(filp));
 -      if (ubifs_crypt_is_encrypted(d_inode(dir)) &&
 -                      !fscrypt_has_permitted_context(d_inode(dir), inode)) {
 -              ubifs_err(c, "Inconsistent encryption contexts: %lu/%lu",
 -                        (unsigned long) d_inode(dir)->i_ino,
 -                        (unsigned long) inode->i_ino);
 -              dput(dir);
 -              ubifs_ro_mode(c, -EPERM);
 -              return -EPERM;
 -      }
 -      dput(dir);
 -
 -      return 0;
 -}
 -
  static const char *ubifs_get_link(struct dentry *dentry,
                                            struct inode *inode,
                                            struct delayed_call *done)
  {
-       int err;
-       struct fscrypt_symlink_data *sd;
        struct ubifs_inode *ui = ubifs_inode(inode);
-       struct fscrypt_str cstr;
-       struct fscrypt_str pstr;
  
-       if (!ubifs_crypt_is_encrypted(inode))
+       if (!IS_ENCRYPTED(inode))
                return ui->data;
  
        if (!dentry)
                return ERR_PTR(-ECHILD);
  
-       err = fscrypt_get_encryption_info(inode);
-       if (err)
-               return ERR_PTR(err);
-       sd = (struct fscrypt_symlink_data *)ui->data;
-       cstr.name = sd->encrypted_path;
-       cstr.len = le16_to_cpu(sd->len);
-       if (cstr.len == 0)
-               return ERR_PTR(-ENOENT);
-       if ((cstr.len + sizeof(struct fscrypt_symlink_data) - 1) > ui->data_len)
-               return ERR_PTR(-EIO);
-       err = fscrypt_fname_alloc_buffer(inode, cstr.len, &pstr);
-       if (err)
-               return ERR_PTR(err);
-       err = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr);
-       if (err) {
-               fscrypt_fname_free_buffer(&pstr);
-               return ERR_PTR(err);
-       }
-       pstr.name[pstr.len] = '\0';
-       set_delayed_call(done, kfree_link, pstr.name);
-       return pstr.name;
+       return fscrypt_get_symlink(inode, ui->data, ui->data_len, done);
  }
  
  const struct address_space_operations ubifs_file_address_operations = {
        .readpage       = ubifs_readpage,
        .writepage      = ubifs_writepage,
@@@ -1713,7 -1714,7 +1681,7 @@@ const struct file_operations ubifs_file
        .unlocked_ioctl = ubifs_ioctl,
        .splice_read    = generic_file_splice_read,
        .splice_write   = iter_file_splice_write,
 -      .open           = ubifs_file_open,
 +      .open           = fscrypt_file_open,
  #ifdef CONFIG_COMPAT
        .compat_ioctl   = ubifs_compat_ioctl,
  #endif
This page took 0.119351 seconds and 4 git commands to generate.