1 ext4 crypto: enable encryption feature flag
3 Also add the test dummy encryption mode flag so we can more easily
4 test the encryption patches using xfstests.
6 Change-Id: I63a7f5b969738eed81b2f12715cfff161a988d84
7 Signed-off-by: Michael Halcrow <mhalcrow@google.com>
8 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
10 fs/ext4/crypto_key.c | 27 +++++++++++++++------------
11 fs/ext4/crypto_policy.c | 18 +++++++++++++++---
12 fs/ext4/ext4.h | 17 +++++++++++++----
13 fs/ext4/ialloc.c | 3 ++-
14 fs/ext4/namei.c | 9 ++++++---
15 fs/ext4/super.c | 29 ++++++++++++++++++++++++++++-
16 6 files changed, 79 insertions(+), 24 deletions(-)
18 diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c
19 index 572bd97..c8392af 100644
20 --- a/fs/ext4/crypto_key.c
21 +++ b/fs/ext4/crypto_key.c
22 @@ -98,6 +98,7 @@ int ext4_generate_encryption_key(struct inode *inode)
23 struct ext4_encryption_key *master_key;
24 struct ext4_encryption_context ctx;
25 struct user_key_payload *ukp;
26 + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
27 int res = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
28 EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
30 @@ -109,6 +110,20 @@ int ext4_generate_encryption_key(struct inode *inode)
34 + if (S_ISREG(inode->i_mode))
35 + crypt_key->mode = ctx.contents_encryption_mode;
36 + else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
37 + crypt_key->mode = ctx.filenames_encryption_mode;
39 + printk(KERN_ERR "ext4 crypto: Unsupported inode type.\n");
42 + crypt_key->size = ext4_encryption_key_size(crypt_key->mode);
43 + BUG_ON(!crypt_key->size);
44 + if (DUMMY_ENCRYPTION_ENABLED(sbi)) {
45 + memset(crypt_key->raw, 0x42, EXT4_AES_256_XTS_KEY_SIZE);
48 memcpy(full_key_descriptor, EXT4_KEY_DESC_PREFIX,
49 EXT4_KEY_DESC_PREFIX_SIZE);
50 sprintf(full_key_descriptor + EXT4_KEY_DESC_PREFIX_SIZE,
51 @@ -129,21 +144,9 @@ int ext4_generate_encryption_key(struct inode *inode)
54 master_key = (struct ext4_encryption_key *)ukp->data;
56 - if (S_ISREG(inode->i_mode))
57 - crypt_key->mode = ctx.contents_encryption_mode;
58 - else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
59 - crypt_key->mode = ctx.filenames_encryption_mode;
61 - printk(KERN_ERR "ext4 crypto: Unsupported inode type.\n");
64 - crypt_key->size = ext4_encryption_key_size(crypt_key->mode);
65 - BUG_ON(!crypt_key->size);
66 BUILD_BUG_ON(EXT4_AES_128_ECB_KEY_SIZE !=
67 EXT4_KEY_DERIVATION_NONCE_SIZE);
68 BUG_ON(master_key->size != EXT4_AES_256_XTS_KEY_SIZE);
69 - BUG_ON(crypt_key->size < EXT4_AES_256_CBC_KEY_SIZE);
70 res = ext4_derive_key_aes(ctx.nonce, master_key->raw, crypt_key->raw);
73 diff --git a/fs/ext4/crypto_policy.c b/fs/ext4/crypto_policy.c
74 index 5b4fbb3..89024ec 100644
75 --- a/fs/ext4/crypto_policy.c
76 +++ b/fs/ext4/crypto_policy.c
77 @@ -158,13 +158,25 @@ int ext4_inherit_context(struct inode *parent, struct inode *child)
78 EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
81 - if (res != sizeof(ctx))
84 + if (res != sizeof(ctx)) {
85 + if (DUMMY_ENCRYPTION_ENABLED(EXT4_SB(parent->i_sb))) {
86 + ctx.format = EXT4_ENCRYPTION_CONTEXT_FORMAT_V1;
87 + ctx.contents_encryption_mode =
88 + EXT4_ENCRYPTION_MODE_AES_256_XTS;
89 + ctx.filenames_encryption_mode =
90 + EXT4_ENCRYPTION_MODE_AES_256_CTS;
91 + memset(ctx.master_key_descriptor, 0x42,
92 + EXT4_KEY_DESCRIPTOR_SIZE);
98 get_random_bytes(ctx.nonce, EXT4_KEY_DERIVATION_NONCE_SIZE);
99 res = ext4_xattr_set(child, EXT4_XATTR_INDEX_ENCRYPTION,
100 EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx,
104 ext4_set_inode_flag(child, EXT4_INODE_ENCRYPT);
106 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
107 index 7ae0454..c4e2a2e 100644
110 @@ -1189,8 +1189,16 @@ struct ext4_super_block {
112 * run-time mount flags
114 -#define EXT4_MF_MNTDIR_SAMPLED 0x0001
115 -#define EXT4_MF_FS_ABORTED 0x0002 /* Fatal error detected */
116 +#define EXT4_MF_MNTDIR_SAMPLED 0x0001
117 +#define EXT4_MF_FS_ABORTED 0x0002 /* Fatal error detected */
118 +#define EXT4_MF_TEST_DUMMY_ENCRYPTION 0x0004
120 +#ifdef CONFIG_EXT4_FS_ENCRYPTION
121 +#define DUMMY_ENCRYPTION_ENABLED(sbi) (unlikely((sbi)->s_mount_flags & \
122 + EXT4_MF_TEST_DUMMY_ENCRYPTION))
124 +#define DUMMY_ENCRYPTION_ENABLED(sbi) (0)
127 /* Number of quota types we support */
128 #define EXT4_MAXQUOTAS 2
129 @@ -1601,8 +1609,9 @@ static inline int ext4_encrypted_inode(struct inode *inode)
130 EXT4_FEATURE_INCOMPAT_EXTENTS| \
131 EXT4_FEATURE_INCOMPAT_64BIT| \
132 EXT4_FEATURE_INCOMPAT_FLEX_BG| \
133 - EXT4_FEATURE_INCOMPAT_MMP | \
134 - EXT4_FEATURE_INCOMPAT_INLINE_DATA)
135 + EXT4_FEATURE_INCOMPAT_MMP | \
136 + EXT4_FEATURE_INCOMPAT_INLINE_DATA | \
137 + EXT4_FEATURE_INCOMPAT_ENCRYPT)
138 #define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \
139 EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
140 EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \
141 diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
142 index 8f37c9e..12571b4 100644
143 --- a/fs/ext4/ialloc.c
144 +++ b/fs/ext4/ialloc.c
145 @@ -999,7 +999,8 @@ got:
147 /* If the directory encrypted, then we should encrypt the inode. */
148 if ((S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode)) &&
149 - ext4_encrypted_inode(dir))
150 + (ext4_encrypted_inode(dir) ||
151 + DUMMY_ENCRYPTION_ENABLED(sbi)))
152 ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
154 ext4_set_inode_flags(inode);
155 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
156 index 09b2f89..07e2ad1 100644
157 --- a/fs/ext4/namei.c
158 +++ b/fs/ext4/namei.c
159 @@ -2577,7 +2577,8 @@ retry:
160 if (!err && IS_DIRSYNC(dir))
161 ext4_handle_sync(handle);
162 #ifdef CONFIG_EXT4_FS_ENCRYPTION
163 - if (!err && ext4_encrypted_inode(dir)) {
164 + if (!err && (ext4_encrypted_inode(dir) ||
165 + DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb)))) {
166 err = ext4_inherit_context(dir, inode);
168 ext4_unlink(dir, dentry);
169 @@ -2782,7 +2783,8 @@ out_clear_inode:
171 ext4_handle_sync(handle);
172 #ifdef CONFIG_EXT4_FS_ENCRYPTION
173 - if (ext4_encrypted_inode(dir)) {
174 + if (ext4_encrypted_inode(dir) ||
175 + DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb))) {
176 err = ext4_inherit_context(dir, inode);
178 ext4_unlink(dir, dentry);
179 @@ -3187,7 +3189,8 @@ static int ext4_symlink(struct inode *dir,
180 disk_link.len = len + 1;
181 disk_link.name = (char *) symname;
183 - encryption_required = ext4_encrypted_inode(dir);
184 + encryption_required = (ext4_encrypted_inode(dir) ||
185 + DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb)));
186 if (encryption_required)
187 disk_link.len = encrypted_symlink_data_len(len) + 1;
188 if (disk_link.len > dir->i_sb->s_blocksize)
189 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
190 index 1a44e74..31a8574 100644
191 --- a/fs/ext4/super.c
192 +++ b/fs/ext4/super.c
193 @@ -1136,7 +1136,7 @@ enum {
194 Opt_commit, Opt_min_batch_time, Opt_max_batch_time, Opt_journal_dev,
195 Opt_journal_path, Opt_journal_checksum, Opt_journal_async_commit,
196 Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
197 - Opt_data_err_abort, Opt_data_err_ignore,
198 + Opt_data_err_abort, Opt_data_err_ignore, Opt_test_dummy_encryption,
199 Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
200 Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
201 Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err,
202 @@ -1223,6 +1223,7 @@ static const match_table_t tokens = {
203 {Opt_init_itable, "init_itable"},
204 {Opt_noinit_itable, "noinit_itable"},
205 {Opt_max_dir_size_kb, "max_dir_size_kb=%u"},
206 + {Opt_test_dummy_encryption, "test_dummy_encryption"},
207 {Opt_removed, "check=none"}, /* mount option from ext2/3 */
208 {Opt_removed, "nocheck"}, /* mount option from ext2/3 */
209 {Opt_removed, "reservation"}, /* mount option from ext2/3 */
210 @@ -1423,6 +1424,7 @@ static const struct mount_opts {
211 {Opt_jqfmt_vfsv0, QFMT_VFS_V0, MOPT_QFMT},
212 {Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT},
213 {Opt_max_dir_size_kb, 0, MOPT_GTE0},
214 + {Opt_test_dummy_encryption, 0, MOPT_GTE0},
218 @@ -1593,6 +1595,15 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
221 IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, arg);
222 + } else if (token == Opt_test_dummy_encryption) {
223 +#ifdef CONFIG_EXT4_FS_ENCRYPTION
224 + sbi->s_mount_flags |= EXT4_MF_TEST_DUMMY_ENCRYPTION;
225 + ext4_msg(sb, KERN_WARNING,
226 + "Test dummy encryption mode enabled");
228 + ext4_msg(sb, KERN_WARNING,
229 + "Test dummy encryption mount option ignored");
231 } else if (m->flags & MOPT_DATAJ) {
234 @@ -2685,11 +2696,13 @@ static struct attribute *ext4_attrs[] = {
235 EXT4_INFO_ATTR(lazy_itable_init);
236 EXT4_INFO_ATTR(batched_discard);
237 EXT4_INFO_ATTR(meta_bg_resize);
238 +EXT4_INFO_ATTR(encryption);
240 static struct attribute *ext4_feat_attrs[] = {
241 ATTR_LIST(lazy_itable_init),
242 ATTR_LIST(batched_discard),
243 ATTR_LIST(meta_bg_resize),
244 + ATTR_LIST(encryption),
248 @@ -3673,6 +3686,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
252 + if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT) &&
253 + es->s_encryption_level) {
254 + ext4_msg(sb, KERN_ERR, "Unsupported encryption level %d",
255 + es->s_encryption_level);
259 if (sb->s_blocksize != blocksize) {
260 /* Validate the filesystem blocksize */
261 if (!sb_set_blocksize(sb, blocksize)) {
262 @@ -4036,6 +4056,13 @@ no_journal:
266 + if (unlikely(sbi->s_mount_flags & EXT4_MF_TEST_DUMMY_ENCRYPTION) &&
267 + !(sb->s_flags & MS_RDONLY) &&
268 + !EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT)) {
269 + EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT);
270 + ext4_commit_super(sb, 1);
274 * Get the # of file system overhead blocks from the
275 * superblock if present.