diff options
Diffstat (limited to 'fs/f2fs/crypto_key.c')
| -rw-r--r-- | fs/f2fs/crypto_key.c | 28 |
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; |
