mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 22:21:42 +00:00
ext4 crypto: enable filename encryption
Signed-off-by: Uday Savagaonkar <savagaon@google.com> Signed-off-by: Ildar Muslukhov <ildarm@google.com> Signed-off-by: Michael Halcrow <mhalcrow@google.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
parent
1f3862b557
commit
4461471107
@ -108,7 +108,10 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
|
||||
int err;
|
||||
struct inode *inode = file_inode(file);
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct buffer_head *bh = NULL;
|
||||
int dir_has_error = 0;
|
||||
struct ext4_fname_crypto_ctx *enc_ctx = NULL;
|
||||
struct ext4_str fname_crypto_str = {.name = NULL, .len = 0};
|
||||
|
||||
if (is_dx_dir(inode)) {
|
||||
err = ext4_dx_readdir(file, ctx);
|
||||
@ -125,17 +128,28 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
|
||||
|
||||
if (ext4_has_inline_data(inode)) {
|
||||
int has_inline_data = 1;
|
||||
int ret = ext4_read_inline_dir(file, ctx,
|
||||
err = ext4_read_inline_dir(file, ctx,
|
||||
&has_inline_data);
|
||||
if (has_inline_data)
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
enc_ctx = ext4_get_fname_crypto_ctx(inode, EXT4_NAME_LEN);
|
||||
if (IS_ERR(enc_ctx))
|
||||
return PTR_ERR(enc_ctx);
|
||||
if (enc_ctx) {
|
||||
err = ext4_fname_crypto_alloc_buffer(enc_ctx, EXT4_NAME_LEN,
|
||||
&fname_crypto_str);
|
||||
if (err < 0) {
|
||||
ext4_put_fname_crypto_ctx(&enc_ctx);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
offset = ctx->pos & (sb->s_blocksize - 1);
|
||||
|
||||
while (ctx->pos < inode->i_size) {
|
||||
struct ext4_map_blocks map;
|
||||
struct buffer_head *bh = NULL;
|
||||
|
||||
map.m_lblk = ctx->pos >> EXT4_BLOCK_SIZE_BITS(sb);
|
||||
map.m_len = 1;
|
||||
@ -178,6 +192,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
|
||||
(unsigned long long)ctx->pos);
|
||||
ctx->pos += sb->s_blocksize - offset;
|
||||
brelse(bh);
|
||||
bh = NULL;
|
||||
continue;
|
||||
}
|
||||
set_buffer_verified(bh);
|
||||
@ -224,25 +239,44 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
|
||||
offset += ext4_rec_len_from_disk(de->rec_len,
|
||||
sb->s_blocksize);
|
||||
if (le32_to_cpu(de->inode)) {
|
||||
if (!dir_emit(ctx, de->name,
|
||||
de->name_len,
|
||||
le32_to_cpu(de->inode),
|
||||
get_dtype(sb, de->file_type))) {
|
||||
brelse(bh);
|
||||
return 0;
|
||||
if (enc_ctx == NULL) {
|
||||
/* Directory is not encrypted */
|
||||
if (!dir_emit(ctx, de->name,
|
||||
de->name_len,
|
||||
le32_to_cpu(de->inode),
|
||||
get_dtype(sb, de->file_type)))
|
||||
goto done;
|
||||
} else {
|
||||
/* Directory is encrypted */
|
||||
err = ext4_fname_disk_to_usr(enc_ctx,
|
||||
de, &fname_crypto_str);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
if (!dir_emit(ctx,
|
||||
fname_crypto_str.name, err,
|
||||
le32_to_cpu(de->inode),
|
||||
get_dtype(sb, de->file_type)))
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
ctx->pos += ext4_rec_len_from_disk(de->rec_len,
|
||||
sb->s_blocksize);
|
||||
}
|
||||
offset = 0;
|
||||
if ((ctx->pos < inode->i_size) && !dir_relax(inode))
|
||||
goto done;
|
||||
brelse(bh);
|
||||
if (ctx->pos < inode->i_size) {
|
||||
if (!dir_relax(inode))
|
||||
return 0;
|
||||
}
|
||||
bh = NULL;
|
||||
offset = 0;
|
||||
}
|
||||
return 0;
|
||||
done:
|
||||
err = 0;
|
||||
errout:
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
ext4_put_fname_crypto_ctx(&enc_ctx);
|
||||
ext4_fname_crypto_free_buffer(&fname_crypto_str);
|
||||
#endif
|
||||
brelse(bh);
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline int is_32bit_api(void)
|
||||
|
@ -1033,11 +1033,28 @@ got:
|
||||
ext4_set_inode_state(inode, EXT4_STATE_NEW);
|
||||
|
||||
ei->i_extra_isize = EXT4_SB(sb)->s_want_extra_isize;
|
||||
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
if ((sbi->s_file_encryption_mode == EXT4_ENCRYPTION_MODE_INVALID) &&
|
||||
(sbi->s_dir_encryption_mode == EXT4_ENCRYPTION_MODE_INVALID)) {
|
||||
ei->i_inline_off = 0;
|
||||
if (EXT4_HAS_INCOMPAT_FEATURE(sb,
|
||||
EXT4_FEATURE_INCOMPAT_INLINE_DATA))
|
||||
ext4_set_inode_state(inode,
|
||||
EXT4_STATE_MAY_INLINE_DATA);
|
||||
} else {
|
||||
/* Inline data and encryption are incompatible
|
||||
* We turn off inline data since encryption is enabled */
|
||||
ei->i_inline_off = 1;
|
||||
if (EXT4_HAS_INCOMPAT_FEATURE(sb,
|
||||
EXT4_FEATURE_INCOMPAT_INLINE_DATA))
|
||||
ext4_clear_inode_state(inode,
|
||||
EXT4_STATE_MAY_INLINE_DATA);
|
||||
}
|
||||
#else
|
||||
ei->i_inline_off = 0;
|
||||
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_INLINE_DATA))
|
||||
ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
|
||||
|
||||
#endif
|
||||
ret = inode;
|
||||
err = dquot_alloc_inode(inode);
|
||||
if (err)
|
||||
|
Loading…
Reference in New Issue
Block a user