summaryrefslogtreecommitdiff
path: root/fs/f2fs/crypto_key.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/f2fs/crypto_key.c')
-rw-r--r--fs/f2fs/crypto_key.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/fs/f2fs/crypto_key.c b/fs/f2fs/crypto_key.c
index 18595d7a0efc..5de2d866a25c 100644
--- a/fs/f2fs/crypto_key.c
+++ b/fs/f2fs/crypto_key.c
@@ -92,6 +92,7 @@ static void f2fs_free_crypt_info(struct f2fs_crypt_info *ci)
if (!ci)
return;
+ key_put(ci->ci_keyring_key);
crypto_free_ablkcipher(ci->ci_ctfm);
kmem_cache_free(f2fs_crypt_info_cachep, ci);
}
@@ -112,7 +113,7 @@ void f2fs_free_encryption_info(struct inode *inode, struct f2fs_crypt_info *ci)
f2fs_free_crypt_info(ci);
}
-int f2fs_get_encryption_info(struct inode *inode)
+int _f2fs_get_encryption_info(struct inode *inode)
{
struct f2fs_inode_info *fi = F2FS_I(inode);
struct f2fs_crypt_info *crypt_info;
@@ -128,12 +129,18 @@ int f2fs_get_encryption_info(struct inode *inode)
char mode;
int res;
- if (fi->i_crypt_info)
- return 0;
-
res = f2fs_crypto_initialize();
if (res)
return res;
+retry:
+ crypt_info = ACCESS_ONCE(fi->i_crypt_info);
+ if (crypt_info) {
+ if (!crypt_info->ci_keyring_key ||
+ key_validate(crypt_info->ci_keyring_key) == 0)
+ return 0;
+ f2fs_free_encryption_info(inode, crypt_info);
+ goto retry;
+ }
res = f2fs_getxattr(inode, F2FS_XATTR_INDEX_ENCRYPTION,
F2FS_XATTR_NAME_ENCRYPTION_CONTEXT,
@@ -152,6 +159,7 @@ int f2fs_get_encryption_info(struct inode *inode)
crypt_info->ci_data_mode = ctx.contents_encryption_mode;
crypt_info->ci_filename_mode = ctx.filenames_encryption_mode;
crypt_info->ci_ctfm = NULL;
+ crypt_info->ci_keyring_key = NULL;
memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor,
sizeof(crypt_info->ci_master_key));
if (S_ISREG(inode->i_mode))
@@ -189,6 +197,7 @@ int f2fs_get_encryption_info(struct inode *inode)
keyring_key = NULL;
goto out;
}
+ crypt_info->ci_keyring_key = keyring_key;
BUG_ON(keyring_key->type != &key_type_logon);
ukp = user_key_payload(keyring_key);
if (ukp->datalen != sizeof(struct f2fs_encryption_key)) {
@@ -221,12 +230,17 @@ int f2fs_get_encryption_info(struct inode *inode)
if (res)
goto out;
- if (cmpxchg(&fi->i_crypt_info, NULL, crypt_info) == NULL)
- crypt_info = NULL;
+ memzero_explicit(raw_key, sizeof(raw_key));
+ if (cmpxchg(&fi->i_crypt_info, NULL, crypt_info) != NULL) {
+ f2fs_free_crypt_info(crypt_info);
+ goto retry;
+ }
+ return 0;
+
out:
if (res == -ENOKEY && !S_ISREG(inode->i_mode))
res = 0;
- key_put(keyring_key);
+
f2fs_free_crypt_info(crypt_info);
memzero_explicit(raw_key, sizeof(raw_key));
return res;