Clean up whitespace and fixed a bug in the context inheritance error path
[ext4-patch-queue.git] / enable-encryption-feature
blob14a4eed2a14d22c78255bf9128b04f99a922bfb5
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 Signed-off-by: Michael Halcrow <mhalcrow@google.com>
7 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
8 ---
9  fs/ext4/crypto_key.c    | 27 +++++++++++++++------------
10  fs/ext4/crypto_policy.c | 18 +++++++++++++++---
11  fs/ext4/ext4.h          | 17 +++++++++++++----
12  fs/ext4/ialloc.c        |  3 ++-
13  fs/ext4/namei.c         |  9 ++++++---
14  fs/ext4/super.c         | 29 ++++++++++++++++++++++++++++-
15  6 files changed, 79 insertions(+), 24 deletions(-)
17 diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c
18 index 572bd97..c8392af 100644
19 --- a/fs/ext4/crypto_key.c
20 +++ b/fs/ext4/crypto_key.c
21 @@ -98,6 +98,7 @@ int ext4_generate_encryption_key(struct inode *inode)
22         struct ext4_encryption_key *master_key;
23         struct ext4_encryption_context ctx;
24         struct user_key_payload *ukp;
25 +       struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
26         int res = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
27                                  EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
28                                  &ctx, sizeof(ctx));
29 @@ -109,6 +110,20 @@ int ext4_generate_encryption_key(struct inode *inode)
30         }
31         res = 0;
33 +       if (S_ISREG(inode->i_mode))
34 +               crypt_key->mode = ctx.contents_encryption_mode;
35 +       else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
36 +               crypt_key->mode = ctx.filenames_encryption_mode;
37 +       else {
38 +               printk(KERN_ERR "ext4 crypto: Unsupported inode type.\n");
39 +               BUG();
40 +       }
41 +       crypt_key->size = ext4_encryption_key_size(crypt_key->mode);
42 +       BUG_ON(!crypt_key->size);
43 +       if (DUMMY_ENCRYPTION_ENABLED(sbi)) {
44 +               memset(crypt_key->raw, 0x42, EXT4_AES_256_XTS_KEY_SIZE);
45 +               goto out;
46 +       }
47         memcpy(full_key_descriptor, EXT4_KEY_DESC_PREFIX,
48                EXT4_KEY_DESC_PREFIX_SIZE);
49         sprintf(full_key_descriptor + EXT4_KEY_DESC_PREFIX_SIZE,
50 @@ -129,21 +144,9 @@ int ext4_generate_encryption_key(struct inode *inode)
51                 goto out;
52         }
53         master_key = (struct ext4_encryption_key *)ukp->data;
55 -       if (S_ISREG(inode->i_mode))
56 -               crypt_key->mode = ctx.contents_encryption_mode;
57 -       else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
58 -               crypt_key->mode = ctx.filenames_encryption_mode;
59 -       else {
60 -               printk(KERN_ERR "ext4 crypto: Unsupported inode type.\n");
61 -               BUG();
62 -       }
63 -       crypt_key->size = ext4_encryption_key_size(crypt_key->mode);
64 -       BUG_ON(!crypt_key->size);
65         BUILD_BUG_ON(EXT4_AES_128_ECB_KEY_SIZE !=
66                      EXT4_KEY_DERIVATION_NONCE_SIZE);
67         BUG_ON(master_key->size != EXT4_AES_256_XTS_KEY_SIZE);
68 -       BUG_ON(crypt_key->size < EXT4_AES_256_CBC_KEY_SIZE);
69         res = ext4_derive_key_aes(ctx.nonce, master_key->raw, crypt_key->raw);
70  out:
71         if (keyring_key)
72 diff --git a/fs/ext4/crypto_policy.c b/fs/ext4/crypto_policy.c
73 index 749ed6e..30eaf9e 100644
74 --- a/fs/ext4/crypto_policy.c
75 +++ b/fs/ext4/crypto_policy.c
76 @@ -169,13 +169,25 @@ int ext4_inherit_context(struct inode *parent, struct inode *child)
77                                  EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
78                                  &ctx, sizeof(ctx));
80 -       if (res != sizeof(ctx))
81 -               return -ENOENT;
83 +       if (res != sizeof(ctx)) {
84 +               if (DUMMY_ENCRYPTION_ENABLED(EXT4_SB(parent->i_sb))) {
85 +                       ctx.format = EXT4_ENCRYPTION_CONTEXT_FORMAT_V1;
86 +                       ctx.contents_encryption_mode =
87 +                               EXT4_ENCRYPTION_MODE_AES_256_XTS;
88 +                       ctx.filenames_encryption_mode =
89 +                               EXT4_ENCRYPTION_MODE_AES_256_CTS;
90 +                       memset(ctx.master_key_descriptor, 0x42,
91 +                              EXT4_KEY_DESCRIPTOR_SIZE);
92 +                       res = 0;
93 +               } else {
94 +                       goto out;
95 +               }
96 +       }
97         get_random_bytes(ctx.nonce, EXT4_KEY_DERIVATION_NONCE_SIZE);
98         res = ext4_xattr_set(child, EXT4_XATTR_INDEX_ENCRYPTION,
99                              EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx,
100                              sizeof(ctx), 0);
101 +out:
102         if (!res)
103                 ext4_set_inode_flag(child, EXT4_INODE_ENCRYPT);
104         return res;
105 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
106 index c79db59..68eaa2d 100644
107 --- a/fs/ext4/ext4.h
108 +++ b/fs/ext4/ext4.h
109 @@ -1189,8 +1189,16 @@ struct ext4_super_block {
110  /*
111   * run-time mount flags
112   */
113 -#define EXT4_MF_MNTDIR_SAMPLED 0x0001
114 -#define EXT4_MF_FS_ABORTED     0x0002  /* Fatal error detected */
115 +#define EXT4_MF_MNTDIR_SAMPLED         0x0001
116 +#define EXT4_MF_FS_ABORTED             0x0002  /* Fatal error detected */
117 +#define EXT4_MF_TEST_DUMMY_ENCRYPTION  0x0004
119 +#ifdef CONFIG_EXT4_FS_ENCRYPTION
120 +#define DUMMY_ENCRYPTION_ENABLED(sbi) (unlikely((sbi)->s_mount_flags & \
121 +                                               EXT4_MF_TEST_DUMMY_ENCRYPTION))
122 +#else
123 +#define DUMMY_ENCRYPTION_ENABLED(sbi) (0)
124 +#endif
126  /* Number of quota types we support */
127  #define EXT4_MAXQUOTAS 2
128 @@ -1601,8 +1609,9 @@ static inline int ext4_encrypted_inode(struct inode *inode)
129                                          EXT4_FEATURE_INCOMPAT_EXTENTS| \
130                                          EXT4_FEATURE_INCOMPAT_64BIT| \
131                                          EXT4_FEATURE_INCOMPAT_FLEX_BG| \
132 -                                        EXT4_FEATURE_INCOMPAT_MMP |    \
133 -                                        EXT4_FEATURE_INCOMPAT_INLINE_DATA)
134 +                                        EXT4_FEATURE_INCOMPAT_MMP | \
135 +                                        EXT4_FEATURE_INCOMPAT_INLINE_DATA | \
136 +                                        EXT4_FEATURE_INCOMPAT_ENCRYPT)
137  #define EXT4_FEATURE_RO_COMPAT_SUPP    (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \
138                                          EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
139                                          EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \
140 diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
141 index 8f37c9e..12571b4 100644
142 --- a/fs/ext4/ialloc.c
143 +++ b/fs/ext4/ialloc.c
144 @@ -999,7 +999,8 @@ got:
146         /* If the directory encrypted, then we should encrypt the inode. */
147         if ((S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode)) &&
148 -           ext4_encrypted_inode(dir))
149 +           (ext4_encrypted_inode(dir) ||
150 +            DUMMY_ENCRYPTION_ENABLED(sbi)))
151                 ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
153         ext4_set_inode_flags(inode);
154 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
155 index 10496eb..e6bb4e2 100644
156 --- a/fs/ext4/namei.c
157 +++ b/fs/ext4/namei.c
158 @@ -2578,7 +2578,8 @@ retry:
159                 ext4_set_aops(inode);
160                 err = 0;
161  #ifdef CONFIG_EXT4_FS_ENCRYPTION
162 -               if (!err && ext4_encrypted_inode(dir)) {
163 +               if (!err && (ext4_encrypted_inode(dir) ||
164 +                            DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb)))) {
165                         err = ext4_inherit_context(dir, inode);
166                         if (err) {
167                                 clear_nlink(inode);
168 @@ -2770,7 +2771,8 @@ retry:
169         if (err)
170                 goto out_clear_inode;
171  #ifdef CONFIG_EXT4_FS_ENCRYPTION
172 -       if (ext4_encrypted_inode(dir)) {
173 +       if (ext4_encrypted_inode(dir) ||
174 +           DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb))) {
175                 err = ext4_inherit_context(dir, inode);
176                 if (err)
177                         goto out_clear_inode;
178 @@ -3195,7 +3197,8 @@ static int ext4_symlink(struct inode *dir,
179         disk_link.len = len + 1;
180         disk_link.name = (char *) symname;
182 -       encryption_required = ext4_encrypted_inode(dir);
183 +       encryption_required = (ext4_encrypted_inode(dir) ||
184 +                              DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb)));
185         if (encryption_required)
186                 disk_link.len = encrypted_symlink_data_len(len) + 1;
187         if (disk_link.len > dir->i_sb->s_blocksize)
188 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
189 index 1a44e74..31a8574 100644
190 --- a/fs/ext4/super.c
191 +++ b/fs/ext4/super.c
192 @@ -1136,7 +1136,7 @@ enum {
193         Opt_commit, Opt_min_batch_time, Opt_max_batch_time, Opt_journal_dev,
194         Opt_journal_path, Opt_journal_checksum, Opt_journal_async_commit,
195         Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
196 -       Opt_data_err_abort, Opt_data_err_ignore,
197 +       Opt_data_err_abort, Opt_data_err_ignore, Opt_test_dummy_encryption,
198         Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
199         Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
200         Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err,
201 @@ -1223,6 +1223,7 @@ static const match_table_t tokens = {
202         {Opt_init_itable, "init_itable"},
203         {Opt_noinit_itable, "noinit_itable"},
204         {Opt_max_dir_size_kb, "max_dir_size_kb=%u"},
205 +       {Opt_test_dummy_encryption, "test_dummy_encryption"},
206         {Opt_removed, "check=none"},    /* mount option from ext2/3 */
207         {Opt_removed, "nocheck"},       /* mount option from ext2/3 */
208         {Opt_removed, "reservation"},   /* mount option from ext2/3 */
209 @@ -1423,6 +1424,7 @@ static const struct mount_opts {
210         {Opt_jqfmt_vfsv0, QFMT_VFS_V0, MOPT_QFMT},
211         {Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT},
212         {Opt_max_dir_size_kb, 0, MOPT_GTE0},
213 +       {Opt_test_dummy_encryption, 0, MOPT_GTE0},
214         {Opt_err, 0, 0}
215  };
217 @@ -1593,6 +1595,15 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
218                 }
219                 *journal_ioprio =
220                         IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, arg);
221 +       } else if (token == Opt_test_dummy_encryption) {
222 +#ifdef CONFIG_EXT4_FS_ENCRYPTION
223 +               sbi->s_mount_flags |= EXT4_MF_TEST_DUMMY_ENCRYPTION;
224 +               ext4_msg(sb, KERN_WARNING,
225 +                        "Test dummy encryption mode enabled");
226 +#else
227 +               ext4_msg(sb, KERN_WARNING,
228 +                        "Test dummy encryption mount option ignored");
229 +#endif
230         } else if (m->flags & MOPT_DATAJ) {
231                 if (is_remount) {
232                         if (!sbi->s_journal)
233 @@ -2685,11 +2696,13 @@ static struct attribute *ext4_attrs[] = {
234  EXT4_INFO_ATTR(lazy_itable_init);
235  EXT4_INFO_ATTR(batched_discard);
236  EXT4_INFO_ATTR(meta_bg_resize);
237 +EXT4_INFO_ATTR(encryption);
239  static struct attribute *ext4_feat_attrs[] = {
240         ATTR_LIST(lazy_itable_init),
241         ATTR_LIST(batched_discard),
242         ATTR_LIST(meta_bg_resize),
243 +       ATTR_LIST(encryption),
244         NULL,
245  };
247 @@ -3673,6 +3686,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
248                 goto failed_mount;
249         }
251 +       if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT) &&
252 +           es->s_encryption_level) {
253 +               ext4_msg(sb, KERN_ERR, "Unsupported encryption level %d",
254 +                        es->s_encryption_level);
255 +               goto failed_mount;
256 +       }
258         if (sb->s_blocksize != blocksize) {
259                 /* Validate the filesystem blocksize */
260                 if (!sb_set_blocksize(sb, blocksize)) {
261 @@ -4036,6 +4056,13 @@ no_journal:
262                 }
263         }
265 +       if (unlikely(sbi->s_mount_flags & EXT4_MF_TEST_DUMMY_ENCRYPTION) &&
266 +           !(sb->s_flags & MS_RDONLY) &&
267 +           !EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT)) {
268 +               EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT);
269 +               ext4_commit_super(sb, 1);
270 +       }
272         /*
273          * Get the # of file system overhead blocks from the
274          * superblock if present.