Refactor support for encrypted symlinks to move common code to fscrypt.

-----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCAAdFiEEK2m5VNv+CHkogTfJ8vlZVpUNgaMFAlp2R3AACgkQ8vlZVpUN
 gaOIdAgApEdlFR2Gf93z2hMj5HxVL5rjkuPJVtVkKu0eH2HMQJyxNmjymrRfuFmM
 8W1CrEvVKi5Aj6r8q4KHIdVV247Ya0SVEhLwKM0LX4CvlZUXmwgCmZ/MPDTXA1eq
 C4vPVuJAuSNGNVYDlDs3+NiMHINGNVnBVQQFSPBP9P+iNWPD7o486712qaF8maVn
 RbfbQ2rWtOIRdlAOD1U5WqgQku59lOsmHk2pc0+X4LHCZFpMoaO80JVjENPAw+BF
 daRt6TX+WljMyx6DRIaszqau876CJhe/tqlZcCLOkpXZP0jJS13yodp26dVQmjCh
 w8YdiY7uHK2D+S/8eyj7h7DIwzu3vg==
 =ZjQP
 -----END PGP SIGNATURE-----

Merge tag 'fscrypt_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/fscrypt

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
  ...
This commit is contained in:
Linus Torvalds 2018-02-04 10:43:12 -08:00
commit 3462ac5703
17 changed files with 500 additions and 500 deletions

View file

@ -585,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);
}

View file

@ -486,27 +486,16 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
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)
@ -516,7 +505,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
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;
@ -526,38 +515,13 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
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 +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;
}
@ -1148,68 +1114,20 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry,
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);
page = read_mapping_page(inode->i_mapping, 0, NULL);
if (IS_ERR(page))
return ERR_CAST(page);
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';
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 = {