Skip to content

Commit

Permalink
ext4 crypto: enable encryption feature flag
Browse files Browse the repository at this point in the history
Also add the test dummy encryption mode flag so we can more easily
test the encryption patches using xfstests.

Signed-off-by: Michael Halcrow <mhalcrow@google.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
  • Loading branch information
Theodore Ts'o committed Apr 16, 2015
1 parent f348c25 commit 6ddb244
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 24 deletions.
27 changes: 15 additions & 12 deletions fs/ext4/crypto_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ int ext4_generate_encryption_key(struct inode *inode)
struct ext4_encryption_key *master_key;
struct ext4_encryption_context ctx;
struct user_key_payload *ukp;
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
int res = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
&ctx, sizeof(ctx));
Expand All @@ -109,6 +110,20 @@ int ext4_generate_encryption_key(struct inode *inode)
}
res = 0;

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))
crypt_key->mode = ctx.filenames_encryption_mode;
else {
printk(KERN_ERR "ext4 crypto: Unsupported inode type.\n");
BUG();
}
crypt_key->size = ext4_encryption_key_size(crypt_key->mode);
BUG_ON(!crypt_key->size);
if (DUMMY_ENCRYPTION_ENABLED(sbi)) {
memset(crypt_key->raw, 0x42, EXT4_AES_256_XTS_KEY_SIZE);
goto out;
}
memcpy(full_key_descriptor, EXT4_KEY_DESC_PREFIX,
EXT4_KEY_DESC_PREFIX_SIZE);
sprintf(full_key_descriptor + EXT4_KEY_DESC_PREFIX_SIZE,
Expand All @@ -129,21 +144,9 @@ int ext4_generate_encryption_key(struct inode *inode)
goto out;
}
master_key = (struct ext4_encryption_key *)ukp->data;

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))
crypt_key->mode = ctx.filenames_encryption_mode;
else {
printk(KERN_ERR "ext4 crypto: Unsupported inode type.\n");
BUG();
}
crypt_key->size = ext4_encryption_key_size(crypt_key->mode);
BUG_ON(!crypt_key->size);
BUILD_BUG_ON(EXT4_AES_128_ECB_KEY_SIZE !=
EXT4_KEY_DERIVATION_NONCE_SIZE);
BUG_ON(master_key->size != EXT4_AES_256_XTS_KEY_SIZE);
BUG_ON(crypt_key->size < EXT4_AES_256_CBC_KEY_SIZE);
res = ext4_derive_key_aes(ctx.nonce, master_key->raw, crypt_key->raw);
out:
if (keyring_key)
Expand Down
18 changes: 15 additions & 3 deletions fs/ext4/crypto_policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,25 @@ int ext4_inherit_context(struct inode *parent, struct inode *child)
EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
&ctx, sizeof(ctx));

if (res != sizeof(ctx))
return -ENOENT;

if (res != sizeof(ctx)) {
if (DUMMY_ENCRYPTION_ENABLED(EXT4_SB(parent->i_sb))) {
ctx.format = EXT4_ENCRYPTION_CONTEXT_FORMAT_V1;
ctx.contents_encryption_mode =
EXT4_ENCRYPTION_MODE_AES_256_XTS;
ctx.filenames_encryption_mode =
EXT4_ENCRYPTION_MODE_AES_256_CTS;
memset(ctx.master_key_descriptor, 0x42,
EXT4_KEY_DESCRIPTOR_SIZE);
res = 0;
} else {
goto out;
}
}
get_random_bytes(ctx.nonce, EXT4_KEY_DERIVATION_NONCE_SIZE);
res = ext4_xattr_set(child, EXT4_XATTR_INDEX_ENCRYPTION,
EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx,
sizeof(ctx), 0);
out:
if (!res)
ext4_set_inode_flag(child, EXT4_INODE_ENCRYPT);
return res;
Expand Down
17 changes: 13 additions & 4 deletions fs/ext4/ext4.h
Original file line number Diff line number Diff line change
Expand Up @@ -1200,8 +1200,16 @@ struct ext4_super_block {
/*
* run-time mount flags
*/
#define EXT4_MF_MNTDIR_SAMPLED 0x0001
#define EXT4_MF_FS_ABORTED 0x0002 /* Fatal error detected */
#define EXT4_MF_MNTDIR_SAMPLED 0x0001
#define EXT4_MF_FS_ABORTED 0x0002 /* Fatal error detected */
#define EXT4_MF_TEST_DUMMY_ENCRYPTION 0x0004

#ifdef CONFIG_EXT4_FS_ENCRYPTION
#define DUMMY_ENCRYPTION_ENABLED(sbi) (unlikely((sbi)->s_mount_flags & \
EXT4_MF_TEST_DUMMY_ENCRYPTION))
#else
#define DUMMY_ENCRYPTION_ENABLED(sbi) (0)
#endif

/* Number of quota types we support */
#define EXT4_MAXQUOTAS 2
Expand Down Expand Up @@ -1613,8 +1621,9 @@ static inline int ext4_encrypted_inode(struct inode *inode)
EXT4_FEATURE_INCOMPAT_EXTENTS| \
EXT4_FEATURE_INCOMPAT_64BIT| \
EXT4_FEATURE_INCOMPAT_FLEX_BG| \
EXT4_FEATURE_INCOMPAT_MMP | \
EXT4_FEATURE_INCOMPAT_INLINE_DATA)
EXT4_FEATURE_INCOMPAT_MMP | \
EXT4_FEATURE_INCOMPAT_INLINE_DATA | \
EXT4_FEATURE_INCOMPAT_ENCRYPT)
#define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \
EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \
Expand Down
3 changes: 2 additions & 1 deletion fs/ext4/ialloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -998,7 +998,8 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,

/* If the directory encrypted, then we should encrypt the inode. */
if ((S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode)) &&
ext4_encrypted_inode(dir))
(ext4_encrypted_inode(dir) ||
DUMMY_ENCRYPTION_ENABLED(sbi)))
ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);

ext4_set_inode_flags(inode);
Expand Down
9 changes: 6 additions & 3 deletions fs/ext4/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -2582,7 +2582,8 @@ static int ext4_create(struct inode *dir, struct dentry *dentry, umode_t mode,
ext4_set_aops(inode);
err = 0;
#ifdef CONFIG_EXT4_FS_ENCRYPTION
if (!err && ext4_encrypted_inode(dir)) {
if (!err && (ext4_encrypted_inode(dir) ||
DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb)))) {
err = ext4_inherit_context(dir, inode);
if (err) {
clear_nlink(inode);
Expand Down Expand Up @@ -2777,7 +2778,8 @@ static int ext4_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
if (err)
goto out_clear_inode;
#ifdef CONFIG_EXT4_FS_ENCRYPTION
if (ext4_encrypted_inode(dir)) {
if (ext4_encrypted_inode(dir) ||
DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb))) {
err = ext4_inherit_context(dir, inode);
if (err)
goto out_clear_inode;
Expand Down Expand Up @@ -3202,7 +3204,8 @@ static int ext4_symlink(struct inode *dir,
disk_link.len = len + 1;
disk_link.name = (char *) symname;

encryption_required = ext4_encrypted_inode(dir);
encryption_required = (ext4_encrypted_inode(dir) ||
DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb)));
if (encryption_required)
disk_link.len = encrypted_symlink_data_len(len) + 1;
if (disk_link.len > dir->i_sb->s_blocksize)
Expand Down
29 changes: 28 additions & 1 deletion fs/ext4/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1106,7 +1106,7 @@ enum {
Opt_commit, Opt_min_batch_time, Opt_max_batch_time, Opt_journal_dev,
Opt_journal_path, Opt_journal_checksum, Opt_journal_async_commit,
Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
Opt_data_err_abort, Opt_data_err_ignore,
Opt_data_err_abort, Opt_data_err_ignore, Opt_test_dummy_encryption,
Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err,
Expand Down Expand Up @@ -1197,6 +1197,7 @@ static const match_table_t tokens = {
{Opt_init_itable, "init_itable"},
{Opt_noinit_itable, "noinit_itable"},
{Opt_max_dir_size_kb, "max_dir_size_kb=%u"},
{Opt_test_dummy_encryption, "test_dummy_encryption"},
{Opt_removed, "check=none"}, /* mount option from ext2/3 */
{Opt_removed, "nocheck"}, /* mount option from ext2/3 */
{Opt_removed, "reservation"}, /* mount option from ext2/3 */
Expand Down Expand Up @@ -1398,6 +1399,7 @@ static const struct mount_opts {
{Opt_jqfmt_vfsv0, QFMT_VFS_V0, MOPT_QFMT},
{Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT},
{Opt_max_dir_size_kb, 0, MOPT_GTE0},
{Opt_test_dummy_encryption, 0, MOPT_GTE0},
{Opt_err, 0, 0}
};

Expand Down Expand Up @@ -1574,6 +1576,15 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
}
*journal_ioprio =
IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, arg);
} else if (token == Opt_test_dummy_encryption) {
#ifdef CONFIG_EXT4_FS_ENCRYPTION
sbi->s_mount_flags |= EXT4_MF_TEST_DUMMY_ENCRYPTION;
ext4_msg(sb, KERN_WARNING,
"Test dummy encryption mode enabled");
#else
ext4_msg(sb, KERN_WARNING,
"Test dummy encryption mount option ignored");
#endif
} else if (m->flags & MOPT_DATAJ) {
if (is_remount) {
if (!sbi->s_journal)
Expand Down Expand Up @@ -2671,11 +2682,13 @@ static struct attribute *ext4_attrs[] = {
EXT4_INFO_ATTR(lazy_itable_init);
EXT4_INFO_ATTR(batched_discard);
EXT4_INFO_ATTR(meta_bg_resize);
EXT4_INFO_ATTR(encryption);

static struct attribute *ext4_feat_attrs[] = {
ATTR_LIST(lazy_itable_init),
ATTR_LIST(batched_discard),
ATTR_LIST(meta_bg_resize),
ATTR_LIST(encryption),
NULL,
};

Expand Down Expand Up @@ -3683,6 +3696,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
}
}

if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT) &&
es->s_encryption_level) {
ext4_msg(sb, KERN_ERR, "Unsupported encryption level %d",
es->s_encryption_level);
goto failed_mount;
}

if (sb->s_blocksize != blocksize) {
/* Validate the filesystem blocksize */
if (!sb_set_blocksize(sb, blocksize)) {
Expand Down Expand Up @@ -4045,6 +4065,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
}
}

if (unlikely(sbi->s_mount_flags & EXT4_MF_TEST_DUMMY_ENCRYPTION) &&
!(sb->s_flags & MS_RDONLY) &&
!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT)) {
EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT);
ext4_commit_super(sb, 1);
}

/*
* Get the # of file system overhead blocks from the
* superblock if present.
Expand Down

0 comments on commit 6ddb244

Please sign in to comment.