summaryrefslogtreecommitdiffstats
path: root/fs/ext4/namei.c
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk@kernel.org>2016-07-10 14:01:03 -0400
committerTheodore Ts'o <tytso@mit.edu>2016-07-10 14:01:03 -0400
commita7550b30ab709ffb9bbe48669adf7d8556f3698f (patch)
tree5ed986d93b2df41cad68bdfa0851604bb039d1d1 /fs/ext4/namei.c
parentff0031d848a0cd7002606f9feef958de8d5edf19 (diff)
downloadlinux-a7550b30ab709ffb9bbe48669adf7d8556f3698f.tar.bz2
ext4 crypto: migrate into vfs's crypto engine
This patch removes the most parts of internal crypto codes. And then, it modifies and adds some ext4-specific crypt codes to use the generic facility. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/namei.c')
-rw-r--r--fs/ext4/namei.c131
1 files changed, 63 insertions, 68 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 94d22e78a7dd..4637c439ca54 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -611,19 +611,19 @@ static struct stats dx_show_leaf(struct inode *dir,
#ifdef CONFIG_EXT4_FS_ENCRYPTION
int len;
char *name;
- struct ext4_str fname_crypto_str
- = {.name = NULL, .len = 0};
+ struct fscrypt_str fname_crypto_str =
+ FSTR_INIT(NULL, 0);
int res = 0;
name = de->name;
len = de->name_len;
- if (ext4_encrypted_inode(inode))
- res = ext4_get_encryption_info(dir);
+ if (ext4_encrypted_inode(dir))
+ res = fscrypt_get_encryption_info(dir);
if (res) {
printk(KERN_WARNING "Error setting up"
" fname crypto: %d\n", res);
}
- if (ctx == NULL) {
+ if (!fscrypt_has_encryption_key(dir)) {
/* Directory is not encrypted */
ext4fs_dirhash(de->name,
de->name_len, &h);
@@ -632,19 +632,21 @@ static struct stats dx_show_leaf(struct inode *dir,
(unsigned) ((char *) de
- base));
} else {
+ struct fscrypt_str de_name =
+ FSTR_INIT(name, len);
+
/* Directory is encrypted */
- res = ext4_fname_crypto_alloc_buffer(
- ctx, de->name_len,
+ res = fscrypt_fname_alloc_buffer(
+ dir, len,
&fname_crypto_str);
- if (res < 0) {
+ if (res < 0)
printk(KERN_WARNING "Error "
"allocating crypto "
"buffer--skipping "
"crypto\n");
- ctx = NULL;
- }
- res = ext4_fname_disk_to_usr(ctx, NULL, de,
- &fname_crypto_str);
+ res = fscrypt_fname_disk_to_usr(dir,
+ 0, 0, &de_name,
+ &fname_crypto_str);
if (res < 0) {
printk(KERN_WARNING "Error "
"converting filename "
@@ -661,8 +663,8 @@ static struct stats dx_show_leaf(struct inode *dir,
printk("%*.s:(E)%x.%u ", len, name,
h.hash, (unsigned) ((char *) de
- base));
- ext4_fname_crypto_free_buffer(
- &fname_crypto_str);
+ fscrypt_fname_free_buffer(
+ &fname_crypto_str);
}
#else
int len = de->name_len;
@@ -951,7 +953,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
struct buffer_head *bh;
struct ext4_dir_entry_2 *de, *top;
int err = 0, count = 0;
- struct ext4_str fname_crypto_str = {.name = NULL, .len = 0}, tmp_str;
+ struct fscrypt_str fname_crypto_str = FSTR_INIT(NULL, 0), tmp_str;
dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n",
(unsigned long)block));
@@ -966,12 +968,12 @@ static int htree_dirblock_to_tree(struct file *dir_file,
#ifdef CONFIG_EXT4_FS_ENCRYPTION
/* Check if the directory is encrypted */
if (ext4_encrypted_inode(dir)) {
- err = ext4_get_encryption_info(dir);
+ err = fscrypt_get_encryption_info(dir);
if (err < 0) {
brelse(bh);
return err;
}
- err = ext4_fname_crypto_alloc_buffer(dir, EXT4_NAME_LEN,
+ err = fscrypt_fname_alloc_buffer(dir, EXT4_NAME_LEN,
&fname_crypto_str);
if (err < 0) {
brelse(bh);
@@ -1002,10 +1004,13 @@ static int htree_dirblock_to_tree(struct file *dir_file,
&tmp_str);
} else {
int save_len = fname_crypto_str.len;
+ struct fscrypt_str de_name = FSTR_INIT(de->name,
+ de->name_len);
/* Directory is encrypted */
- err = ext4_fname_disk_to_usr(dir, hinfo, de,
- &fname_crypto_str);
+ err = fscrypt_fname_disk_to_usr(dir, hinfo->hash,
+ hinfo->minor_hash, &de_name,
+ &fname_crypto_str);
if (err < 0) {
count = err;
goto errout;
@@ -1024,7 +1029,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
errout:
brelse(bh);
#ifdef CONFIG_EXT4_FS_ENCRYPTION
- ext4_fname_crypto_free_buffer(&fname_crypto_str);
+ fscrypt_fname_free_buffer(&fname_crypto_str);
#endif
return count;
}
@@ -1049,7 +1054,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
int count = 0;
int ret, err;
__u32 hashval;
- struct ext4_str tmp_str;
+ struct fscrypt_str tmp_str;
dxtrace(printk(KERN_DEBUG "In htree_fill_tree, start hash: %x:%x\n",
start_hash, start_minor_hash));
@@ -1562,26 +1567,23 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
struct ext4_dir_entry_2 *de;
struct buffer_head *bh;
- if (ext4_encrypted_inode(dir)) {
- int res = ext4_get_encryption_info(dir);
+ if (ext4_encrypted_inode(dir)) {
+ int res = fscrypt_get_encryption_info(dir);
/*
- * This should be a properly defined flag for
- * dentry->d_flags when we uplift this to the VFS.
- * d_fsdata is set to (void *) 1 if if the dentry is
+ * 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.
+ * have access to the key.
*/
- dentry->d_fsdata = NULL;
- if (ext4_encryption_info(dir))
- dentry->d_fsdata = (void *) 1;
- d_set_d_op(dentry, &ext4_encrypted_d_ops);
- if (res && res != -ENOKEY)
- return ERR_PTR(res);
- }
+ if (fscrypt_has_encryption_key(dir))
+ fscrypt_set_encrypted_dentry(dentry);
+ fscrypt_set_d_op(dentry);
+ if (res && res != -ENOKEY)
+ return ERR_PTR(res);
+ }
- if (dentry->d_name.len > EXT4_NAME_LEN)
- return ERR_PTR(-ENAMETOOLONG);
+ if (dentry->d_name.len > EXT4_NAME_LEN)
+ return ERR_PTR(-ENAMETOOLONG);
bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
if (IS_ERR(bh))
@@ -1608,11 +1610,9 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
}
if (!IS_ERR(inode) && ext4_encrypted_inode(dir) &&
(S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) &&
- !ext4_is_child_context_consistent_with_parent(dir,
- inode)) {
+ !fscrypt_has_permitted_context(dir, inode)) {
int nokey = ext4_encrypted_inode(inode) &&
- !ext4_encryption_info(inode);
-
+ !fscrypt_has_encryption_key(inode);
iput(inode);
if (nokey)
return ERR_PTR(-ENOKEY);
@@ -2689,30 +2689,30 @@ out_stop:
/*
* routine to check that the specified directory is empty (for rmdir)
*/
-int ext4_empty_dir(struct inode *inode)
+bool ext4_empty_dir(struct inode *inode)
{
unsigned int offset;
struct buffer_head *bh;
struct ext4_dir_entry_2 *de, *de1;
struct super_block *sb;
- int err = 0;
if (ext4_has_inline_data(inode)) {
int has_inline_data = 1;
+ int ret;
- err = empty_inline_dir(inode, &has_inline_data);
+ ret = empty_inline_dir(inode, &has_inline_data);
if (has_inline_data)
- return err;
+ return ret;
}
sb = inode->i_sb;
if (inode->i_size < EXT4_DIR_REC_LEN(1) + EXT4_DIR_REC_LEN(2)) {
EXT4_ERROR_INODE(inode, "invalid size");
- return 1;
+ return true;
}
bh = ext4_read_dirblock(inode, 0, EITHER);
if (IS_ERR(bh))
- return 1;
+ return true;
de = (struct ext4_dir_entry_2 *) bh->b_data;
de1 = ext4_next_entry(de, sb->s_blocksize);
@@ -2721,7 +2721,7 @@ int ext4_empty_dir(struct inode *inode)
strcmp(".", de->name) || strcmp("..", de1->name)) {
ext4_warning_inode(inode, "directory missing '.' and/or '..'");
brelse(bh);
- return 1;
+ return true;
}
offset = ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize) +
ext4_rec_len_from_disk(de1->rec_len, sb->s_blocksize);
@@ -2729,12 +2729,11 @@ int ext4_empty_dir(struct inode *inode)
while (offset < inode->i_size) {
if ((void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
unsigned int lblock;
- err = 0;
brelse(bh);
lblock = offset >> EXT4_BLOCK_SIZE_BITS(sb);
bh = ext4_read_dirblock(inode, lblock, EITHER);
if (IS_ERR(bh))
- return 1;
+ return true;
de = (struct ext4_dir_entry_2 *) bh->b_data;
}
if (ext4_check_dir_entry(inode, NULL, de, bh,
@@ -2746,13 +2745,13 @@ int ext4_empty_dir(struct inode *inode)
}
if (le32_to_cpu(de->inode)) {
brelse(bh);
- return 0;
+ return false;
}
offset += ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize);
de = ext4_next_entry(de, sb->s_blocksize);
}
brelse(bh);
- return 1;
+ return true;
}
/*
@@ -3075,8 +3074,8 @@ static int ext4_symlink(struct inode *dir,
int err, len = strlen(symname);
int credits;
bool encryption_required;
- struct ext4_str disk_link;
- struct ext4_encrypted_symlink_data *sd = NULL;
+ struct fscrypt_str disk_link;
+ struct fscrypt_symlink_data *sd = NULL;
disk_link.len = len + 1;
disk_link.name = (char *) symname;
@@ -3084,13 +3083,13 @@ static int ext4_symlink(struct inode *dir,
encryption_required = (ext4_encrypted_inode(dir) ||
DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb)));
if (encryption_required) {
- err = ext4_get_encryption_info(dir);
+ err = fscrypt_get_encryption_info(dir);
if (err)
return err;
- if (ext4_encryption_info(dir) == NULL)
+ if (!fscrypt_has_encryption_key(dir))
return -EPERM;
- disk_link.len = (ext4_fname_encrypted_size(dir, len) +
- sizeof(struct ext4_encrypted_symlink_data));
+ 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;
@@ -3138,13 +3137,12 @@ static int ext4_symlink(struct inode *dir,
if (encryption_required) {
struct qstr istr;
- struct ext4_str ostr;
+ struct fscrypt_str ostr =
+ FSTR_INIT(sd->encrypted_path, disk_link.len);
istr.name = (const unsigned char *) symname;
istr.len = len;
- ostr.name = sd->encrypted_path;
- ostr.len = disk_link.len;
- err = ext4_fname_usr_to_disk(inode, &istr, &ostr);
+ err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr);
if (err < 0)
goto err_drop_inode;
sd->len = cpu_to_le16(ostr.len);
@@ -3233,7 +3231,7 @@ static int ext4_link(struct dentry *old_dentry,
if (inode->i_nlink >= EXT4_LINK_MAX)
return -EMLINK;
if (ext4_encrypted_inode(dir) &&
- !ext4_is_child_context_consistent_with_parent(dir, inode))
+ !fscrypt_has_permitted_context(dir, inode))
return -EPERM;
if ((ext4_test_inode_flag(dir, EXT4_INODE_PROJINHERIT)) &&
@@ -3556,8 +3554,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
if ((old.dir != new.dir) &&
ext4_encrypted_inode(new.dir) &&
- !ext4_is_child_context_consistent_with_parent(new.dir,
- old.inode)) {
+ !fscrypt_has_permitted_context(new.dir, old.inode)) {
retval = -EPERM;
goto end_rename;
}
@@ -3729,10 +3726,8 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
if ((ext4_encrypted_inode(old_dir) ||
ext4_encrypted_inode(new_dir)) &&
(old_dir != new_dir) &&
- (!ext4_is_child_context_consistent_with_parent(new_dir,
- old.inode) ||
- !ext4_is_child_context_consistent_with_parent(old_dir,
- new.inode)))
+ (!fscrypt_has_permitted_context(new_dir, old.inode) ||
+ !fscrypt_has_permitted_context(old_dir, new.inode)))
return -EPERM;
if ((ext4_test_inode_flag(new_dir, EXT4_INODE_PROJINHERIT) &&