Commit 8663da2c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4

Pull ext4 fixes from Ted Ts'o:
 "Some miscellaneous bug fixes and some final on-disk and ABI changes
  for ext4 encryption which provide better security and performance"

* tag 'for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
  ext4: fix growing of tiny filesystems
  ext4: move check under lock scope to close a race.
  ext4: fix data corruption caused by unwritten and delayed extents
  ext4 crypto: remove duplicated encryption mode definitions
  ext4 crypto: do not select from EXT4_FS_ENCRYPTION
  ext4 crypto: add padding to filenames before encrypting
  ext4 crypto: simplify and speed up filename encryption
parents 101a6fd3 2c869b26
......@@ -64,8 +64,8 @@ config EXT4_FS_SECURITY
If you are not using a security module that requires using
extended attributes for file security labels, say N.
config EXT4_FS_ENCRYPTION
bool "Ext4 Encryption"
config EXT4_ENCRYPTION
tristate "Ext4 Encryption"
depends on EXT4_FS
select CRYPTO_AES
select CRYPTO_CBC
......@@ -81,6 +81,11 @@ config EXT4_FS_ENCRYPTION
efficient since it avoids caching the encrypted and
decrypted pages in the page cache.
config EXT4_FS_ENCRYPTION
bool
default y
depends on EXT4_ENCRYPTION
config EXT4_DEBUG
bool "EXT4 debugging support"
depends on EXT4_FS
......
This diff is collapsed.
......@@ -110,6 +110,7 @@ int ext4_generate_encryption_key(struct inode *inode)
}
res = 0;
ei->i_crypt_policy_flags = ctx.flags;
if (S_ISREG(inode->i_mode))
crypt_key->mode = ctx.contents_encryption_mode;
else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
......
......@@ -37,6 +37,8 @@ static int ext4_is_encryption_context_consistent_with_policy(
return 0;
return (memcmp(ctx.master_key_descriptor, policy->master_key_descriptor,
EXT4_KEY_DESCRIPTOR_SIZE) == 0 &&
(ctx.flags ==
policy->flags) &&
(ctx.contents_encryption_mode ==
policy->contents_encryption_mode) &&
(ctx.filenames_encryption_mode ==
......@@ -56,25 +58,25 @@ static int ext4_create_encryption_context_from_policy(
printk(KERN_WARNING
"%s: Invalid contents encryption mode %d\n", __func__,
policy->contents_encryption_mode);
res = -EINVAL;
goto out;
return -EINVAL;
}
if (!ext4_valid_filenames_enc_mode(policy->filenames_encryption_mode)) {
printk(KERN_WARNING
"%s: Invalid filenames encryption mode %d\n", __func__,
policy->filenames_encryption_mode);
res = -EINVAL;
goto out;
return -EINVAL;
}
if (policy->flags & ~EXT4_POLICY_FLAGS_VALID)
return -EINVAL;
ctx.contents_encryption_mode = policy->contents_encryption_mode;
ctx.filenames_encryption_mode = policy->filenames_encryption_mode;
ctx.flags = policy->flags;
BUILD_BUG_ON(sizeof(ctx.nonce) != EXT4_KEY_DERIVATION_NONCE_SIZE);
get_random_bytes(ctx.nonce, EXT4_KEY_DERIVATION_NONCE_SIZE);
res = ext4_xattr_set(inode, EXT4_XATTR_INDEX_ENCRYPTION,
EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx,
sizeof(ctx), 0);
out:
if (!res)
ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
return res;
......@@ -115,6 +117,7 @@ int ext4_get_policy(struct inode *inode, struct ext4_encryption_policy *policy)
policy->version = 0;
policy->contents_encryption_mode = ctx.contents_encryption_mode;
policy->filenames_encryption_mode = ctx.filenames_encryption_mode;
policy->flags = ctx.flags;
memcpy(&policy->master_key_descriptor, ctx.master_key_descriptor,
EXT4_KEY_DESCRIPTOR_SIZE);
return 0;
......@@ -176,6 +179,7 @@ int ext4_inherit_context(struct inode *parent, struct inode *child)
EXT4_ENCRYPTION_MODE_AES_256_XTS;
ctx.filenames_encryption_mode =
EXT4_ENCRYPTION_MODE_AES_256_CTS;
ctx.flags = 0;
memset(ctx.master_key_descriptor, 0x42,
EXT4_KEY_DESCRIPTOR_SIZE);
res = 0;
......
......@@ -249,7 +249,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
} else {
/* Directory is encrypted */
err = ext4_fname_disk_to_usr(enc_ctx,
de, &fname_crypto_str);
NULL, de, &fname_crypto_str);
if (err < 0)
goto errout;
if (!dir_emit(ctx,
......
......@@ -911,6 +911,7 @@ struct ext4_inode_info {
/* on-disk additional length */
__u16 i_extra_isize;
char i_crypt_policy_flags;
/* Indicate the inline data space. */
u16 i_inline_off;
......@@ -1066,12 +1067,6 @@ extern void ext4_set_bits(void *bm, int cur, int len);
/* Metadata checksum algorithm codes */
#define EXT4_CRC32C_CHKSUM 1
/* Encryption algorithms */
#define EXT4_ENCRYPTION_MODE_INVALID 0
#define EXT4_ENCRYPTION_MODE_AES_256_XTS 1
#define EXT4_ENCRYPTION_MODE_AES_256_GCM 2
#define EXT4_ENCRYPTION_MODE_AES_256_CBC 3
/*
* Structure of the super block
*/
......@@ -2093,9 +2088,11 @@ u32 ext4_fname_crypto_round_up(u32 size, u32 blksize);
int ext4_fname_crypto_alloc_buffer(struct ext4_fname_crypto_ctx *ctx,
u32 ilen, struct ext4_str *crypto_str);
int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
struct dx_hash_info *hinfo,
const struct ext4_str *iname,
struct ext4_str *oname);
int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
struct dx_hash_info *hinfo,
const struct ext4_dir_entry_2 *de,
struct ext4_str *oname);
int ext4_fname_usr_to_disk(struct ext4_fname_crypto_ctx *ctx,
......@@ -2104,11 +2101,12 @@ int ext4_fname_usr_to_disk(struct ext4_fname_crypto_ctx *ctx,
int ext4_fname_usr_to_hash(struct ext4_fname_crypto_ctx *ctx,
const struct qstr *iname,
struct dx_hash_info *hinfo);
int ext4_fname_disk_to_hash(struct ext4_fname_crypto_ctx *ctx,
const struct ext4_dir_entry_2 *de,
struct dx_hash_info *hinfo);
int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx,
u32 namelen);
int ext4_fname_match(struct ext4_fname_crypto_ctx *ctx, struct ext4_str *cstr,
int len, const char * const name,
struct ext4_dir_entry_2 *de);
#ifdef CONFIG_EXT4_FS_ENCRYPTION
void ext4_put_fname_crypto_ctx(struct ext4_fname_crypto_ctx **ctx);
......
......@@ -20,12 +20,20 @@ struct ext4_encryption_policy {
char version;
char contents_encryption_mode;
char filenames_encryption_mode;
char flags;
char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE];
} __attribute__((__packed__));
#define EXT4_ENCRYPTION_CONTEXT_FORMAT_V1 1
#define EXT4_KEY_DERIVATION_NONCE_SIZE 16
#define EXT4_POLICY_FLAGS_PAD_4 0x00
#define EXT4_POLICY_FLAGS_PAD_8 0x01
#define EXT4_POLICY_FLAGS_PAD_16 0x02
#define EXT4_POLICY_FLAGS_PAD_32 0x03
#define EXT4_POLICY_FLAGS_PAD_MASK 0x03
#define EXT4_POLICY_FLAGS_VALID 0x03
/**
* Encryption context for inode
*
......@@ -41,7 +49,7 @@ struct ext4_encryption_context {
char format;
char contents_encryption_mode;
char filenames_encryption_mode;
char reserved;
char flags;
char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE];
char nonce[EXT4_KEY_DERIVATION_NONCE_SIZE];
} __attribute__((__packed__));
......@@ -120,6 +128,7 @@ struct ext4_fname_crypto_ctx {
struct crypto_hash *htfm;
struct page *workpage;
struct ext4_encryption_key key;
unsigned flags : 8;
unsigned has_valid_key : 1;
unsigned ctfm_key_is_ready : 1;
};
......
......@@ -4927,13 +4927,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
if (ret)
return ret;
/*
* currently supporting (pre)allocate mode for extent-based
* files _only_
*/
if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
return -EOPNOTSUPP;
if (mode & FALLOC_FL_COLLAPSE_RANGE)
return ext4_collapse_range(inode, offset, len);
......@@ -4955,6 +4948,14 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
mutex_lock(&inode->i_mutex);
/*
* We only support preallocation for extent-based files only
*/
if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) {
ret = -EOPNOTSUPP;
goto out;
}
if (!(mode & FALLOC_FL_KEEP_SIZE) &&
offset + len > i_size_read(inode)) {
new_size = offset + len;
......
......@@ -703,6 +703,14 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
BUG_ON(end < lblk);
if ((status & EXTENT_STATUS_DELAYED) &&
(status & EXTENT_STATUS_WRITTEN)) {
ext4_warning(inode->i_sb, "Inserting extent [%u/%u] as "
" delayed and written which can potentially "
" cause data loss.\n", lblk, len);
WARN_ON(1);
}
newes.es_lblk = lblk;
newes.es_len = len;
ext4_es_store_pblock_status(&newes, pblk, status);
......
......@@ -531,6 +531,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
status = map->m_flags & EXT4_MAP_UNWRITTEN ?
EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) &&
!(status & EXTENT_STATUS_WRITTEN) &&
ext4_find_delalloc_range(inode, map->m_lblk,
map->m_lblk + map->m_len - 1))
status |= EXTENT_STATUS_DELAYED;
......@@ -635,6 +636,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
status = map->m_flags & EXT4_MAP_UNWRITTEN ?
EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) &&
!(status & EXTENT_STATUS_WRITTEN) &&
ext4_find_delalloc_range(inode, map->m_lblk,
map->m_lblk + map->m_len - 1))
status |= EXTENT_STATUS_DELAYED;
......
......@@ -640,7 +640,7 @@ static struct stats dx_show_leaf(struct inode *dir,
ext4_put_fname_crypto_ctx(&ctx);
ctx = NULL;
}
res = ext4_fname_disk_to_usr(ctx, de,
res = ext4_fname_disk_to_usr(ctx, NULL, de,
&fname_crypto_str);
if (res < 0) {
printk(KERN_WARNING "Error "
......@@ -653,15 +653,8 @@ static struct stats dx_show_leaf(struct inode *dir,
name = fname_crypto_str.name;
len = fname_crypto_str.len;
}
res = ext4_fname_disk_to_hash(ctx, de,
ext4fs_dirhash(de->name, de->name_len,
&h);
if (res < 0) {
printk(KERN_WARNING "Error "
"converting filename "
"from disk to htree"
"\n");
h.hash = 0xDEADBEEF;
}
printk("%*.s:(E)%x.%u ", len, name,
h.hash, (unsigned) ((char *) de
- base));
......@@ -1008,15 +1001,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
/* silently ignore the rest of the block */
break;
}
#ifdef CONFIG_EXT4_FS_ENCRYPTION
err = ext4_fname_disk_to_hash(ctx, de, hinfo);
if (err < 0) {
count = err;
goto errout;
}
#else
ext4fs_dirhash(de->name, de->name_len, hinfo);
#endif
if ((hinfo->hash < start_hash) ||
((hinfo->hash == start_hash) &&
(hinfo->minor_hash < start_minor_hash)))
......@@ -1032,7 +1017,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
&tmp_str);
} else {
/* Directory is encrypted */
err = ext4_fname_disk_to_usr(ctx, de,
err = ext4_fname_disk_to_usr(ctx, hinfo, de,
&fname_crypto_str);
if (err < 0) {
count = err;
......@@ -1193,26 +1178,10 @@ static int dx_make_map(struct inode *dir, struct ext4_dir_entry_2 *de,
int count = 0;
char *base = (char *) de;
struct dx_hash_info h = *hinfo;
#ifdef CONFIG_EXT4_FS_ENCRYPTION
struct ext4_fname_crypto_ctx *ctx = NULL;
int err;
ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN);
if (IS_ERR(ctx))
return PTR_ERR(ctx);
#endif
while ((char *) de < base + blocksize) {
if (de->name_len && de->inode) {
#ifdef CONFIG_EXT4_FS_ENCRYPTION
err = ext4_fname_disk_to_hash(ctx, de, &h);
if (err < 0) {
ext4_put_fname_crypto_ctx(&ctx);
return err;
}
#else
ext4fs_dirhash(de->name, de->name_len, &h);
#endif
map_tail--;
map_tail->hash = h.hash;
map_tail->offs = ((char *) de - base)>>2;
......@@ -1223,9 +1192,6 @@ static int dx_make_map(struct inode *dir, struct ext4_dir_entry_2 *de,
/* XXX: do we need to check rec_len == 0 case? -Chris */
de = ext4_next_entry(de, blocksize);
}
#ifdef CONFIG_EXT4_FS_ENCRYPTION
ext4_put_fname_crypto_ctx(&ctx);
#endif
return count;
}
......@@ -1287,16 +1253,8 @@ static inline int ext4_match(struct ext4_fname_crypto_ctx *ctx,
return 0;
#ifdef CONFIG_EXT4_FS_ENCRYPTION
if (ctx) {
/* Directory is encrypted */
res = ext4_fname_disk_to_usr(ctx, de, fname_crypto_str);
if (res < 0)
return res;
if (len != res)
return 0;
res = memcmp(name, fname_crypto_str->name, len);
return (res == 0) ? 1 : 0;
}
if (ctx)
return ext4_fname_match(ctx, fname_crypto_str, len, name, de);
#endif
if (len != de->name_len)
return 0;
......@@ -1324,16 +1282,6 @@ int search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
if (IS_ERR(ctx))
return -1;
if (ctx != NULL) {
/* Allocate buffer to hold maximum name length */
res = ext4_fname_crypto_alloc_buffer(ctx, EXT4_NAME_LEN,
&fname_crypto_str);
if (res < 0) {
ext4_put_fname_crypto_ctx(&ctx);
return -1;
}
}
de = (struct ext4_dir_entry_2 *)search_buf;
dlimit = search_buf + buf_size;
while ((char *) de < dlimit) {
......@@ -1872,14 +1820,6 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
return res;
}
reclen = EXT4_DIR_REC_LEN(res);
/* Allocate buffer to hold maximum name length */
res = ext4_fname_crypto_alloc_buffer(ctx, EXT4_NAME_LEN,
&fname_crypto_str);
if (res < 0) {
ext4_put_fname_crypto_ctx(&ctx);
return -1;
}
}
de = (struct ext4_dir_entry_2 *)buf;
......
......@@ -1432,12 +1432,15 @@ static int ext4_flex_group_add(struct super_block *sb,
goto exit;
/*
* We will always be modifying at least the superblock and GDT
* block. If we are adding a group past the last current GDT block,
* blocks. If we are adding a group past the last current GDT block,
* we will also modify the inode and the dindirect block. If we
* are adding a group with superblock/GDT backups we will also
* modify each of the reserved GDT dindirect blocks.
*/
credit = flex_gd->count * 4 + reserved_gdb;
credit = 3; /* sb, resize inode, resize inode dindirect */
/* GDT blocks */
credit += 1 + DIV_ROUND_UP(flex_gd->count, EXT4_DESC_PER_BLOCK(sb));
credit += reserved_gdb; /* Reserved GDT dindirect blocks */
handle = ext4_journal_start_sb(sb, EXT4_HT_RESIZE, credit);
if (IS_ERR(handle)) {
err = PTR_ERR(handle);
......
......@@ -74,7 +74,7 @@ static void *ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
goto errout;
}
pstr.name = paddr;
res = _ext4_fname_disk_to_usr(ctx, &cstr, &pstr);
res = _ext4_fname_disk_to_usr(ctx, NULL, &cstr, &pstr);
if (res < 0)
goto errout;
/* Null-terminate the name */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment