Skip to content

Commit e81f334

Browse files
committed
eCryptfs: Do not allocate hash tfm in NORECLAIM context
You cannot allocate crypto tfm objects in NORECLAIM or NOFS contexts. The ecryptfs code currently does exactly that for the MD5 tfm. This patch fixes it by preallocating the MD5 tfm in a safe context. The MD5 tfm is also reentrant so this patch removes the superfluous cs_hash_tfm_mutex. Reported-by: Nicolas Boichat <drinkcat@chromium.org> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent b3ab30a commit e81f334

File tree

4 files changed

+26
-21
lines changed

4 files changed

+26
-21
lines changed

fs/ecryptfs/crypto.c

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -105,19 +105,7 @@ static int ecryptfs_calculate_md5(char *dst,
105105
struct crypto_shash *tfm;
106106
int rc = 0;
107107

108-
mutex_lock(&crypt_stat->cs_hash_tfm_mutex);
109108
tfm = crypt_stat->hash_tfm;
110-
if (!tfm) {
111-
tfm = crypto_alloc_shash(ECRYPTFS_DEFAULT_HASH, 0, 0);
112-
if (IS_ERR(tfm)) {
113-
rc = PTR_ERR(tfm);
114-
ecryptfs_printk(KERN_ERR, "Error attempting to "
115-
"allocate crypto context; rc = [%d]\n",
116-
rc);
117-
goto out;
118-
}
119-
crypt_stat->hash_tfm = tfm;
120-
}
121109
rc = ecryptfs_hash_digest(tfm, src, len, dst);
122110
if (rc) {
123111
printk(KERN_ERR
@@ -126,7 +114,6 @@ static int ecryptfs_calculate_md5(char *dst,
126114
goto out;
127115
}
128116
out:
129-
mutex_unlock(&crypt_stat->cs_hash_tfm_mutex);
130117
return rc;
131118
}
132119

@@ -207,16 +194,29 @@ int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
207194
*
208195
* Initialize the crypt_stat structure.
209196
*/
210-
void
211-
ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat)
197+
int ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat)
212198
{
199+
struct crypto_shash *tfm;
200+
int rc;
201+
202+
tfm = crypto_alloc_shash(ECRYPTFS_DEFAULT_HASH, 0, 0);
203+
if (IS_ERR(tfm)) {
204+
rc = PTR_ERR(tfm);
205+
ecryptfs_printk(KERN_ERR, "Error attempting to "
206+
"allocate crypto context; rc = [%d]\n",
207+
rc);
208+
return rc;
209+
}
210+
213211
memset((void *)crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat));
214212
INIT_LIST_HEAD(&crypt_stat->keysig_list);
215213
mutex_init(&crypt_stat->keysig_list_mutex);
216214
mutex_init(&crypt_stat->cs_mutex);
217215
mutex_init(&crypt_stat->cs_tfm_mutex);
218-
mutex_init(&crypt_stat->cs_hash_tfm_mutex);
216+
crypt_stat->hash_tfm = tfm;
219217
crypt_stat->flags |= ECRYPTFS_STRUCT_INITIALIZED;
218+
219+
return 0;
220220
}
221221

222222
/**

fs/ecryptfs/ecryptfs_kernel.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,6 @@ struct ecryptfs_crypt_stat {
242242
struct list_head keysig_list;
243243
struct mutex keysig_list_mutex;
244244
struct mutex cs_tfm_mutex;
245-
struct mutex cs_hash_tfm_mutex;
246245
struct mutex cs_mutex;
247246
};
248247

@@ -577,7 +576,7 @@ int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg,
577576
int sg_size);
578577
int ecryptfs_compute_root_iv(struct ecryptfs_crypt_stat *crypt_stat);
579578
void ecryptfs_rotate_iv(unsigned char *iv);
580-
void ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat);
579+
int ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat);
581580
void ecryptfs_destroy_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat);
582581
void ecryptfs_destroy_mount_crypt_stat(
583582
struct ecryptfs_mount_crypt_stat *mount_crypt_stat);

fs/ecryptfs/inode.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -898,8 +898,11 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
898898
struct ecryptfs_crypt_stat *crypt_stat;
899899

900900
crypt_stat = &ecryptfs_inode_to_private(d_inode(dentry))->crypt_stat;
901-
if (!(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED))
902-
ecryptfs_init_crypt_stat(crypt_stat);
901+
if (!(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED)) {
902+
rc = ecryptfs_init_crypt_stat(crypt_stat);
903+
if (rc)
904+
return rc;
905+
}
903906
inode = d_inode(dentry);
904907
lower_inode = ecryptfs_inode_to_lower(inode);
905908
lower_dentry = ecryptfs_dentry_to_lower(dentry);

fs/ecryptfs/super.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@ static struct inode *ecryptfs_alloc_inode(struct super_block *sb)
5555
inode_info = kmem_cache_alloc(ecryptfs_inode_info_cache, GFP_KERNEL);
5656
if (unlikely(!inode_info))
5757
goto out;
58-
ecryptfs_init_crypt_stat(&inode_info->crypt_stat);
58+
if (ecryptfs_init_crypt_stat(&inode_info->crypt_stat)) {
59+
kmem_cache_free(ecryptfs_inode_info_cache, inode_info);
60+
goto out;
61+
}
5962
mutex_init(&inode_info->lower_file_mutex);
6063
atomic_set(&inode_info->lower_file_count, 0);
6164
inode_info->lower_file = NULL;

0 commit comments

Comments
 (0)