]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.10.7/fscrypt-remove-broken-support-for-detecting-keyring-key-revocation.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.10.7 / fscrypt-remove-broken-support-for-detecting-keyring-key-revocation.patch
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
5
6 From: Eric Biggers <ebiggers@google.com>
7
8 commit 1b53cf9815bb4744958d41f3795d5d5a1d365e2d upstream.
9
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.
17
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.
28
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.
34
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.
42
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>
48
49 ---
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(-)
55
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)
60 {
61 struct dentry *dir;
62 - struct fscrypt_info *ci;
63 int dir_has_key, cached_with_key;
64
65 if (flags & LOOKUP_RCU)
66 @@ -406,18 +405,11 @@ static int fscrypt_d_revalidate(struct d
67 return 0;
68 }
69
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))))
75 - ci = NULL;
76 -
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);
83 dput(dir);
84
85 /*
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;
90 return 0;
91 }
92 - ret = fscrypt_get_crypt_info(dir);
93 + ret = fscrypt_get_encryption_info(dir);
94 if (ret && ret != -EOPNOTSUPP)
95 return ret;
96
97 --- a/fs/crypto/fscrypt_private.h
98 +++ b/fs/crypto/fscrypt_private.h
99 @@ -67,7 +67,6 @@ struct fscrypt_info {
100 u8 ci_filename_mode;
101 u8 ci_flags;
102 struct crypto_skcipher *ci_ctfm;
103 - struct key *ci_keyring_key;
104 u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE];
105 };
106
107 @@ -87,7 +86,4 @@ struct fscrypt_completion_result {
108 /* crypto.c */
109 int fscrypt_initialize(unsigned int cop_flags);
110
111 -/* keyinfo.c */
112 -extern int fscrypt_get_crypt_info(struct inode *);
113 -
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);
122
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
126 res = -ENOKEY;
127 goto out;
128 }
129 - down_read(&keyring_key->sem);
130 ukp = user_key_payload(keyring_key);
131 if (ukp->datalen != sizeof(struct fscrypt_key)) {
132 res = -EINVAL;
133 - up_read(&keyring_key->sem);
134 goto out;
135 }
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);
140 res = -ENOKEY;
141 - up_read(&keyring_key->sem);
142 goto out;
143 }
144 res = derive_key_aes(ctx->nonce, master_key->raw, raw_key);
145 - up_read(&keyring_key->sem);
146 - if (res)
147 - goto out;
148 -
149 - crypt_info->ci_keyring_key = keyring_key;
150 - return 0;
151 out:
152 + up_read(&keyring_key->sem);
153 key_put(keyring_key);
154 return res;
155 }
156 @@ -173,12 +166,11 @@ static void put_crypt_info(struct fscryp
157 if (!ci)
158 return;
159
160 - key_put(ci->ci_keyring_key);
161 crypto_free_skcipher(ci->ci_ctfm);
162 kmem_cache_free(fscrypt_info_cachep, ci);
163 }
164
165 -int fscrypt_get_crypt_info(struct inode *inode)
166 +int fscrypt_get_encryption_info(struct inode *inode)
167 {
168 struct fscrypt_info *crypt_info;
169 struct fscrypt_context ctx;
170 @@ -188,21 +180,15 @@ int fscrypt_get_crypt_info(struct inode
171 u8 *raw_key = NULL;
172 int res;
173
174 + if (inode->i_crypt_info)
175 + return 0;
176 +
177 res = fscrypt_initialize(inode->i_sb->s_cop->flags);
178 if (res)
179 return res;
180
181 if (!inode->i_sb->s_cop->get_context)
182 return -EOPNOTSUPP;
183 -retry:
184 - crypt_info = ACCESS_ONCE(inode->i_crypt_info);
185 - if (crypt_info) {
186 - if (!crypt_info->ci_keyring_key ||
187 - key_validate(crypt_info->ci_keyring_key) == 0)
188 - return 0;
189 - fscrypt_put_encryption_info(inode, crypt_info);
190 - goto retry;
191 - }
192
193 res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
194 if (res < 0) {
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));
202
203 @@ -286,14 +271,8 @@ got_key:
204 if (res)
205 goto out;
206
207 - kzfree(raw_key);
208 - raw_key = NULL;
209 - if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) != NULL) {
210 - put_crypt_info(crypt_info);
211 - goto retry;
212 - }
213 - return 0;
214 -
215 + if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) == NULL)
216 + crypt_info = NULL;
217 out:
218 if (res == -ENOKEY)
219 res = 0;
220 @@ -301,6 +280,7 @@ out:
221 kzfree(raw_key);
222 return res;
223 }
224 +EXPORT_SYMBOL(fscrypt_get_encryption_info);
225
226 void fscrypt_put_encryption_info(struct inode *inode, struct fscrypt_info *ci)
227 {
228 @@ -318,17 +298,3 @@ void fscrypt_put_encryption_info(struct
229 put_crypt_info(ci);
230 }
231 EXPORT_SYMBOL(fscrypt_put_encryption_info);
232 -
233 -int fscrypt_get_encryption_info(struct inode *inode)
234 -{
235 - struct fscrypt_info *ci = inode->i_crypt_info;
236 -
237 - if (!ci ||
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);
243 - return 0;
244 -}
245 -EXPORT_SYMBOL(fscrypt_get_encryption_info);