1 From 1b53cf9815bb4744958d41f3795d5d5a1d365e2d Mon Sep 17 00:00:00 2001
2 From: Eric Biggers <ebiggers@google.com>
3 Date: Tue, 21 Feb 2017 15:07:11 -0800
4 Subject: fscrypt: remove broken support for detecting keyring key revocation
6 From: Eric Biggers <ebiggers@google.com>
8 commit 1b53cf9815bb4744958d41f3795d5d5a1d365e2d upstream.
10 Filesystem encryption ostensibly supported revoking a keyring key that
11 had been used to "unlock" encrypted files, causing those files to become
12 "locked" again. This was, however, buggy for several reasons, the most
13 severe of which was that when key revocation happened to be detected for
14 an inode, its fscrypt_info was immediately freed, even while other
15 threads could be using it for encryption or decryption concurrently.
16 This could be exploited to crash the kernel or worse.
18 This patch fixes the use-after-free by removing the code which detects
19 the keyring key having been revoked, invalidated, or expired. Instead,
20 an encrypted inode that is "unlocked" now simply remains unlocked until
21 it is evicted from memory. Note that this is no worse than the case for
22 block device-level encryption, e.g. dm-crypt, and it still remains
23 possible for a privileged user to evict unused pages, inodes, and
24 dentries by running 'sync; echo 3 > /proc/sys/vm/drop_caches', or by
25 simply unmounting the filesystem. In fact, one of those actions was
26 already needed anyway for key revocation to work even somewhat sanely.
27 This change is not expected to break any applications.
29 In the future I'd like to implement a real API for fscrypt key
30 revocation that interacts sanely with ongoing filesystem operations ---
31 waiting for existing operations to complete and blocking new operations,
32 and invalidating and sanitizing key material and plaintext from the VFS
33 caches. But this is a hard problem, and for now this bug must be fixed.
35 This bug affected almost all versions of ext4, f2fs, and ubifs
36 encryption, and it was potentially reachable in any kernel configured
37 with encryption support (CONFIG_EXT4_ENCRYPTION=y,
38 CONFIG_EXT4_FS_ENCRYPTION=y, CONFIG_F2FS_FS_ENCRYPTION=y, or
39 CONFIG_UBIFS_FS_ENCRYPTION=y). Note that older kernels did not use the
40 shared fs/crypto/ code, but due to the potential security implications
41 of this bug, it may still be worthwhile to backport this fix to them.
43 Fixes: b7236e21d55f ("ext4 crypto: reorganize how we store keys in the inode")
44 Signed-off-by: Eric Biggers <ebiggers@google.com>
45 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
46 Acked-by: Michael Halcrow <mhalcrow@google.com>
47 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
50 fs/crypto/crypto.c | 10 --------
51 fs/crypto/fname.c | 2 -
52 fs/crypto/fscrypt_private.h | 4 ---
53 fs/crypto/keyinfo.c | 52 +++++++-------------------------------------
54 4 files changed, 11 insertions(+), 57 deletions(-)
56 --- a/fs/crypto/crypto.c
57 +++ b/fs/crypto/crypto.c
58 @@ -394,7 +394,6 @@ EXPORT_SYMBOL(fscrypt_zeroout_range);
59 static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
62 - struct fscrypt_info *ci;
63 int dir_has_key, cached_with_key;
65 if (flags & LOOKUP_RCU)
66 @@ -406,18 +405,11 @@ static int fscrypt_d_revalidate(struct d
70 - ci = d_inode(dir)->i_crypt_info;
71 - if (ci && ci->ci_keyring_key &&
72 - (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
73 - (1 << KEY_FLAG_REVOKED) |
74 - (1 << KEY_FLAG_DEAD))))
77 /* this should eventually be an flag in d_flags */
78 spin_lock(&dentry->d_lock);
79 cached_with_key = dentry->d_flags & DCACHE_ENCRYPTED_WITH_KEY;
80 spin_unlock(&dentry->d_lock);
81 - dir_has_key = (ci != NULL);
82 + dir_has_key = (d_inode(dir)->i_crypt_info != NULL);
86 --- a/fs/crypto/fname.c
87 +++ b/fs/crypto/fname.c
88 @@ -350,7 +350,7 @@ int fscrypt_setup_filename(struct inode
89 fname->disk_name.len = iname->len;
92 - ret = fscrypt_get_crypt_info(dir);
93 + ret = fscrypt_get_encryption_info(dir);
94 if (ret && ret != -EOPNOTSUPP)
97 --- a/fs/crypto/fscrypt_private.h
98 +++ b/fs/crypto/fscrypt_private.h
99 @@ -67,7 +67,6 @@ struct fscrypt_info {
102 struct crypto_skcipher *ci_ctfm;
103 - struct key *ci_keyring_key;
104 u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE];
107 @@ -87,7 +86,4 @@ struct fscrypt_completion_result {
109 int fscrypt_initialize(unsigned int cop_flags);
112 -extern int fscrypt_get_crypt_info(struct inode *);
114 #endif /* _FSCRYPT_PRIVATE_H */
115 --- a/fs/crypto/keyinfo.c
116 +++ b/fs/crypto/keyinfo.c
117 @@ -99,6 +99,7 @@ static int validate_user_key(struct fscr
118 kfree(full_key_descriptor);
119 if (IS_ERR(keyring_key))
120 return PTR_ERR(keyring_key);
121 + down_read(&keyring_key->sem);
123 if (keyring_key->type != &key_type_logon) {
124 printk_once(KERN_WARNING
125 @@ -106,11 +107,9 @@ static int validate_user_key(struct fscr
129 - down_read(&keyring_key->sem);
130 ukp = user_key_payload(keyring_key);
131 if (ukp->datalen != sizeof(struct fscrypt_key)) {
133 - up_read(&keyring_key->sem);
136 master_key = (struct fscrypt_key *)ukp->data;
137 @@ -121,17 +120,11 @@ static int validate_user_key(struct fscr
138 "%s: key size incorrect: %d\n",
139 __func__, master_key->size);
141 - up_read(&keyring_key->sem);
144 res = derive_key_aes(ctx->nonce, master_key->raw, raw_key);
145 - up_read(&keyring_key->sem);
149 - crypt_info->ci_keyring_key = keyring_key;
152 + up_read(&keyring_key->sem);
153 key_put(keyring_key);
156 @@ -173,12 +166,11 @@ static void put_crypt_info(struct fscryp
160 - key_put(ci->ci_keyring_key);
161 crypto_free_skcipher(ci->ci_ctfm);
162 kmem_cache_free(fscrypt_info_cachep, ci);
165 -int fscrypt_get_crypt_info(struct inode *inode)
166 +int fscrypt_get_encryption_info(struct inode *inode)
168 struct fscrypt_info *crypt_info;
169 struct fscrypt_context ctx;
170 @@ -188,21 +180,15 @@ int fscrypt_get_crypt_info(struct inode
174 + if (inode->i_crypt_info)
177 res = fscrypt_initialize(inode->i_sb->s_cop->flags);
181 if (!inode->i_sb->s_cop->get_context)
184 - crypt_info = ACCESS_ONCE(inode->i_crypt_info);
186 - if (!crypt_info->ci_keyring_key ||
187 - key_validate(crypt_info->ci_keyring_key) == 0)
189 - fscrypt_put_encryption_info(inode, crypt_info);
193 res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
195 @@ -230,7 +216,6 @@ retry:
196 crypt_info->ci_data_mode = ctx.contents_encryption_mode;
197 crypt_info->ci_filename_mode = ctx.filenames_encryption_mode;
198 crypt_info->ci_ctfm = NULL;
199 - crypt_info->ci_keyring_key = NULL;
200 memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor,
201 sizeof(crypt_info->ci_master_key));
203 @@ -286,14 +271,8 @@ got_key:
209 - if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) != NULL) {
210 - put_crypt_info(crypt_info);
215 + if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) == NULL)
220 @@ -301,6 +280,7 @@ out:
224 +EXPORT_SYMBOL(fscrypt_get_encryption_info);
226 void fscrypt_put_encryption_info(struct inode *inode, struct fscrypt_info *ci)
228 @@ -318,17 +298,3 @@ void fscrypt_put_encryption_info(struct
231 EXPORT_SYMBOL(fscrypt_put_encryption_info);
233 -int fscrypt_get_encryption_info(struct inode *inode)
235 - struct fscrypt_info *ci = inode->i_crypt_info;
238 - (ci->ci_keyring_key &&
239 - (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
240 - (1 << KEY_FLAG_REVOKED) |
241 - (1 << KEY_FLAG_DEAD)))))
242 - return fscrypt_get_crypt_info(inode);
245 -EXPORT_SYMBOL(fscrypt_get_encryption_info);