diff options
Diffstat (limited to 'fs/crypto')
-rw-r--r-- | fs/crypto/crypto.c | 10 | ||||
-rw-r--r-- | fs/crypto/fname.c | 2 | ||||
-rw-r--r-- | fs/crypto/fscrypt_private.h | 4 | ||||
-rw-r--r-- | fs/crypto/keyinfo.c | 52 |
4 files changed, 11 insertions, 57 deletions
diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 02a7a9286449..6d6eca394d4d 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c | |||
@@ -327,7 +327,6 @@ EXPORT_SYMBOL(fscrypt_decrypt_page); | |||
327 | static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags) | 327 | static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags) |
328 | { | 328 | { |
329 | struct dentry *dir; | 329 | struct dentry *dir; |
330 | struct fscrypt_info *ci; | ||
331 | int dir_has_key, cached_with_key; | 330 | int dir_has_key, cached_with_key; |
332 | 331 | ||
333 | if (flags & LOOKUP_RCU) | 332 | if (flags & LOOKUP_RCU) |
@@ -339,18 +338,11 @@ static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags) | |||
339 | return 0; | 338 | return 0; |
340 | } | 339 | } |
341 | 340 | ||
342 | ci = d_inode(dir)->i_crypt_info; | ||
343 | if (ci && ci->ci_keyring_key && | ||
344 | (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) | | ||
345 | (1 << KEY_FLAG_REVOKED) | | ||
346 | (1 << KEY_FLAG_DEAD)))) | ||
347 | ci = NULL; | ||
348 | |||
349 | /* this should eventually be an flag in d_flags */ | 341 | /* this should eventually be an flag in d_flags */ |
350 | spin_lock(&dentry->d_lock); | 342 | spin_lock(&dentry->d_lock); |
351 | cached_with_key = dentry->d_flags & DCACHE_ENCRYPTED_WITH_KEY; | 343 | cached_with_key = dentry->d_flags & DCACHE_ENCRYPTED_WITH_KEY; |
352 | spin_unlock(&dentry->d_lock); | 344 | spin_unlock(&dentry->d_lock); |
353 | dir_has_key = (ci != NULL); | 345 | dir_has_key = (d_inode(dir)->i_crypt_info != NULL); |
354 | dput(dir); | 346 | dput(dir); |
355 | 347 | ||
356 | /* | 348 | /* |
diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index 13052b85c393..37b49894c762 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c | |||
@@ -350,7 +350,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, | |||
350 | fname->disk_name.len = iname->len; | 350 | fname->disk_name.len = iname->len; |
351 | return 0; | 351 | return 0; |
352 | } | 352 | } |
353 | ret = fscrypt_get_crypt_info(dir); | 353 | ret = fscrypt_get_encryption_info(dir); |
354 | if (ret && ret != -EOPNOTSUPP) | 354 | if (ret && ret != -EOPNOTSUPP) |
355 | return ret; | 355 | return ret; |
356 | 356 | ||
diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index fdbb8af32eaf..e39696e64494 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h | |||
@@ -67,7 +67,6 @@ struct fscrypt_info { | |||
67 | u8 ci_filename_mode; | 67 | u8 ci_filename_mode; |
68 | u8 ci_flags; | 68 | u8 ci_flags; |
69 | struct crypto_skcipher *ci_ctfm; | 69 | struct crypto_skcipher *ci_ctfm; |
70 | struct key *ci_keyring_key; | ||
71 | u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE]; | 70 | u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE]; |
72 | }; | 71 | }; |
73 | 72 | ||
@@ -101,7 +100,4 @@ extern int fscrypt_do_page_crypto(const struct inode *inode, | |||
101 | extern struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx, | 100 | extern struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx, |
102 | gfp_t gfp_flags); | 101 | gfp_t gfp_flags); |
103 | 102 | ||
104 | /* keyinfo.c */ | ||
105 | extern int fscrypt_get_crypt_info(struct inode *); | ||
106 | |||
107 | #endif /* _FSCRYPT_PRIVATE_H */ | 103 | #endif /* _FSCRYPT_PRIVATE_H */ |
diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index 02eb6b9e4438..cb3e82abf034 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c | |||
@@ -95,6 +95,7 @@ static int validate_user_key(struct fscrypt_info *crypt_info, | |||
95 | kfree(description); | 95 | kfree(description); |
96 | if (IS_ERR(keyring_key)) | 96 | if (IS_ERR(keyring_key)) |
97 | return PTR_ERR(keyring_key); | 97 | return PTR_ERR(keyring_key); |
98 | down_read(&keyring_key->sem); | ||
98 | 99 | ||
99 | if (keyring_key->type != &key_type_logon) { | 100 | if (keyring_key->type != &key_type_logon) { |
100 | printk_once(KERN_WARNING | 101 | printk_once(KERN_WARNING |
@@ -102,11 +103,9 @@ static int validate_user_key(struct fscrypt_info *crypt_info, | |||
102 | res = -ENOKEY; | 103 | res = -ENOKEY; |
103 | goto out; | 104 | goto out; |
104 | } | 105 | } |
105 | down_read(&keyring_key->sem); | ||
106 | ukp = user_key_payload(keyring_key); | 106 | ukp = user_key_payload(keyring_key); |
107 | if (ukp->datalen != sizeof(struct fscrypt_key)) { | 107 | if (ukp->datalen != sizeof(struct fscrypt_key)) { |
108 | res = -EINVAL; | 108 | res = -EINVAL; |
109 | up_read(&keyring_key->sem); | ||
110 | goto out; | 109 | goto out; |
111 | } | 110 | } |
112 | master_key = (struct fscrypt_key *)ukp->data; | 111 | master_key = (struct fscrypt_key *)ukp->data; |
@@ -117,17 +116,11 @@ static int validate_user_key(struct fscrypt_info *crypt_info, | |||
117 | "%s: key size incorrect: %d\n", | 116 | "%s: key size incorrect: %d\n", |
118 | __func__, master_key->size); | 117 | __func__, master_key->size); |
119 | res = -ENOKEY; | 118 | res = -ENOKEY; |
120 | up_read(&keyring_key->sem); | ||
121 | goto out; | 119 | goto out; |
122 | } | 120 | } |
123 | res = derive_key_aes(ctx->nonce, master_key->raw, raw_key); | 121 | res = derive_key_aes(ctx->nonce, master_key->raw, raw_key); |
124 | up_read(&keyring_key->sem); | ||
125 | if (res) | ||
126 | goto out; | ||
127 | |||
128 | crypt_info->ci_keyring_key = keyring_key; | ||
129 | return 0; | ||
130 | out: | 122 | out: |
123 | up_read(&keyring_key->sem); | ||
131 | key_put(keyring_key); | 124 | key_put(keyring_key); |
132 | return res; | 125 | return res; |
133 | } | 126 | } |
@@ -169,12 +162,11 @@ static void put_crypt_info(struct fscrypt_info *ci) | |||
169 | if (!ci) | 162 | if (!ci) |
170 | return; | 163 | return; |
171 | 164 | ||
172 | key_put(ci->ci_keyring_key); | ||
173 | crypto_free_skcipher(ci->ci_ctfm); | 165 | crypto_free_skcipher(ci->ci_ctfm); |
174 | kmem_cache_free(fscrypt_info_cachep, ci); | 166 | kmem_cache_free(fscrypt_info_cachep, ci); |
175 | } | 167 | } |
176 | 168 | ||
177 | int fscrypt_get_crypt_info(struct inode *inode) | 169 | int fscrypt_get_encryption_info(struct inode *inode) |
178 | { | 170 | { |
179 | struct fscrypt_info *crypt_info; | 171 | struct fscrypt_info *crypt_info; |
180 | struct fscrypt_context ctx; | 172 | struct fscrypt_context ctx; |
@@ -184,21 +176,15 @@ int fscrypt_get_crypt_info(struct inode *inode) | |||
184 | u8 *raw_key = NULL; | 176 | u8 *raw_key = NULL; |
185 | int res; | 177 | int res; |
186 | 178 | ||
179 | if (inode->i_crypt_info) | ||
180 | return 0; | ||
181 | |||
187 | res = fscrypt_initialize(inode->i_sb->s_cop->flags); | 182 | res = fscrypt_initialize(inode->i_sb->s_cop->flags); |
188 | if (res) | 183 | if (res) |
189 | return res; | 184 | return res; |
190 | 185 | ||
191 | if (!inode->i_sb->s_cop->get_context) | 186 | if (!inode->i_sb->s_cop->get_context) |
192 | return -EOPNOTSUPP; | 187 | return -EOPNOTSUPP; |
193 | retry: | ||
194 | crypt_info = ACCESS_ONCE(inode->i_crypt_info); | ||
195 | if (crypt_info) { | ||
196 | if (!crypt_info->ci_keyring_key || | ||
197 | key_validate(crypt_info->ci_keyring_key) == 0) | ||
198 | return 0; | ||
199 | fscrypt_put_encryption_info(inode, crypt_info); | ||
200 | goto retry; | ||
201 | } | ||
202 | 188 | ||
203 | res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); | 189 | res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); |
204 | if (res < 0) { | 190 | if (res < 0) { |
@@ -229,7 +215,6 @@ retry: | |||
229 | crypt_info->ci_data_mode = ctx.contents_encryption_mode; | 215 | crypt_info->ci_data_mode = ctx.contents_encryption_mode; |
230 | crypt_info->ci_filename_mode = ctx.filenames_encryption_mode; | 216 | crypt_info->ci_filename_mode = ctx.filenames_encryption_mode; |
231 | crypt_info->ci_ctfm = NULL; | 217 | crypt_info->ci_ctfm = NULL; |
232 | crypt_info->ci_keyring_key = NULL; | ||
233 | memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor, | 218 | memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor, |
234 | sizeof(crypt_info->ci_master_key)); | 219 | sizeof(crypt_info->ci_master_key)); |
235 | 220 | ||
@@ -273,14 +258,8 @@ retry: | |||
273 | if (res) | 258 | if (res) |
274 | goto out; | 259 | goto out; |
275 | 260 | ||
276 | kzfree(raw_key); | 261 | if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) == NULL) |
277 | raw_key = NULL; | 262 | crypt_info = NULL; |
278 | if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) != NULL) { | ||
279 | put_crypt_info(crypt_info); | ||
280 | goto retry; | ||
281 | } | ||
282 | return 0; | ||
283 | |||
284 | out: | 263 | out: |
285 | if (res == -ENOKEY) | 264 | if (res == -ENOKEY) |
286 | res = 0; | 265 | res = 0; |
@@ -288,6 +267,7 @@ out: | |||
288 | kzfree(raw_key); | 267 | kzfree(raw_key); |
289 | return res; | 268 | return res; |
290 | } | 269 | } |
270 | EXPORT_SYMBOL(fscrypt_get_encryption_info); | ||
291 | 271 | ||
292 | void fscrypt_put_encryption_info(struct inode *inode, struct fscrypt_info *ci) | 272 | void fscrypt_put_encryption_info(struct inode *inode, struct fscrypt_info *ci) |
293 | { | 273 | { |
@@ -305,17 +285,3 @@ void fscrypt_put_encryption_info(struct inode *inode, struct fscrypt_info *ci) | |||
305 | put_crypt_info(ci); | 285 | put_crypt_info(ci); |
306 | } | 286 | } |
307 | EXPORT_SYMBOL(fscrypt_put_encryption_info); | 287 | EXPORT_SYMBOL(fscrypt_put_encryption_info); |
308 | |||
309 | int fscrypt_get_encryption_info(struct inode *inode) | ||
310 | { | ||
311 | struct fscrypt_info *ci = inode->i_crypt_info; | ||
312 | |||
313 | if (!ci || | ||
314 | (ci->ci_keyring_key && | ||
315 | (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) | | ||
316 | (1 << KEY_FLAG_REVOKED) | | ||
317 | (1 << KEY_FLAG_DEAD))))) | ||
318 | return fscrypt_get_crypt_info(inode); | ||
319 | return 0; | ||
320 | } | ||
321 | EXPORT_SYMBOL(fscrypt_get_encryption_info); | ||