[PATCH-v2 20/20] ext4 crypto: enable encryption feature flag

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Also add the test dummy encryption mode flag so we can more easily
test the encryption patches using xfstests.

Change-Id: I63a7f5b969738eed81b2f12715cfff161a988d84
Signed-off-by: Michael Halcrow <mhalcrow@xxxxxxxxxx>
Signed-off-by: Theodore Ts'o <tytso@xxxxxxx>
---
 fs/ext4/crypto_key.c    | 27 +++++++++++++++------------
 fs/ext4/crypto_policy.c | 18 +++++++++++++++---
 fs/ext4/ext4.h          | 17 +++++++++++++----
 fs/ext4/ialloc.c        |  3 ++-
 fs/ext4/namei.c         |  9 ++++++---
 fs/ext4/super.c         | 29 ++++++++++++++++++++++++++++-
 6 files changed, 79 insertions(+), 24 deletions(-)

diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c
index 572bd97..c8392af 100644
--- a/fs/ext4/crypto_key.c
+++ b/fs/ext4/crypto_key.c
@@ -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));
@@ -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,
@@ -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)
diff --git a/fs/ext4/crypto_policy.c b/fs/ext4/crypto_policy.c
index 5b4fbb3..89024ec 100644
--- a/fs/ext4/crypto_policy.c
+++ b/fs/ext4/crypto_policy.c
@@ -158,13 +158,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;
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 7ae0454..c4e2a2e 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1189,8 +1189,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
@@ -1601,8 +1609,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| \
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 8f37c9e..12571b4 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -999,7 +999,8 @@ got:
 
 	/* 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);
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index b67c216..49159df 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -2577,7 +2577,8 @@ retry:
 		if (!err && IS_DIRSYNC(dir))
 			ext4_handle_sync(handle);
 #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)
 				ext4_unlink(dir, dentry);
@@ -2782,7 +2783,8 @@ out_clear_inode:
 	if (IS_DIRSYNC(dir))
 		ext4_handle_sync(handle);
 #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)
 			ext4_unlink(dir, dentry);
@@ -3187,7 +3189,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)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 1a44e74..31a8574 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1136,7 +1136,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,
@@ -1223,6 +1223,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 */
@@ -1423,6 +1424,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}
 };
 
@@ -1593,6 +1595,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)
@@ -2685,11 +2696,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,
 };
 
@@ -3673,6 +3686,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 		goto failed_mount;
 	}
 
+	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)) {
@@ -4036,6 +4056,13 @@ no_journal:
 		}
 	}
 
+	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.
-- 
2.3.0

--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Reiser Filesystem Development]     [Ceph FS]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite National Park]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]     [Linux Media]

  Powered by Linux