Commit eb95e7ff authored by Michael Halcrow's avatar Michael Halcrow Committed by Linus Torvalds

[PATCH] eCryptfs: Reduce stack usage in ecryptfs_generate_key_packet_set()

eCryptfs is gobbling a lot of stack in ecryptfs_generate_key_packet_set()
because it allocates a temporary memory-hungry ecryptfs_key_record struct.
This patch introduces a new kmem_cache for that struct and converts
ecryptfs_generate_key_packet_set() to use it.
Signed-off-by: default avatarMichael Halcrow <mhalcrow@us.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 29dbb3fc
...@@ -467,6 +467,7 @@ extern struct kmem_cache *ecryptfs_header_cache_1; ...@@ -467,6 +467,7 @@ extern struct kmem_cache *ecryptfs_header_cache_1;
extern struct kmem_cache *ecryptfs_header_cache_2; extern struct kmem_cache *ecryptfs_header_cache_2;
extern struct kmem_cache *ecryptfs_xattr_cache; extern struct kmem_cache *ecryptfs_xattr_cache;
extern struct kmem_cache *ecryptfs_lower_page_cache; extern struct kmem_cache *ecryptfs_lower_page_cache;
extern struct kmem_cache *ecryptfs_key_record_cache;
int ecryptfs_interpose(struct dentry *hidden_dentry, int ecryptfs_interpose(struct dentry *hidden_dentry,
struct dentry *this_dentry, struct super_block *sb, struct dentry *this_dentry, struct super_block *sb,
......
...@@ -1638,6 +1638,8 @@ out: ...@@ -1638,6 +1638,8 @@ out:
return rc; return rc;
} }
struct kmem_cache *ecryptfs_key_record_cache;
/** /**
* ecryptfs_generate_key_packet_set * ecryptfs_generate_key_packet_set
* @dest: Virtual address from which to write the key record set * @dest: Virtual address from which to write the key record set
...@@ -1664,50 +1666,55 @@ ecryptfs_generate_key_packet_set(char *dest_base, ...@@ -1664,50 +1666,55 @@ ecryptfs_generate_key_packet_set(char *dest_base,
&ecryptfs_superblock_to_private( &ecryptfs_superblock_to_private(
ecryptfs_dentry->d_sb)->mount_crypt_stat; ecryptfs_dentry->d_sb)->mount_crypt_stat;
size_t written; size_t written;
struct ecryptfs_key_record key_rec; struct ecryptfs_key_record *key_rec;
int rc = 0; int rc = 0;
(*len) = 0; (*len) = 0;
key_rec = kmem_cache_alloc(ecryptfs_key_record_cache, GFP_KERNEL);
if (!key_rec) {
rc = -ENOMEM;
goto out;
}
if (mount_crypt_stat->global_auth_tok) { if (mount_crypt_stat->global_auth_tok) {
auth_tok = mount_crypt_stat->global_auth_tok; auth_tok = mount_crypt_stat->global_auth_tok;
if (auth_tok->token_type == ECRYPTFS_PASSWORD) { if (auth_tok->token_type == ECRYPTFS_PASSWORD) {
rc = write_tag_3_packet((dest_base + (*len)), rc = write_tag_3_packet((dest_base + (*len)),
max, auth_tok, max, auth_tok,
crypt_stat, &key_rec, crypt_stat, key_rec,
&written); &written);
if (rc) { if (rc) {
ecryptfs_printk(KERN_WARNING, "Error " ecryptfs_printk(KERN_WARNING, "Error "
"writing tag 3 packet\n"); "writing tag 3 packet\n");
goto out; goto out_free;
} }
(*len) += written; (*len) += written;
/* Write auth tok signature packet */ /* Write auth tok signature packet */
rc = write_tag_11_packet( rc = write_tag_11_packet(
(dest_base + (*len)), (dest_base + (*len)),
(max - (*len)), (max - (*len)),
key_rec.sig, ECRYPTFS_SIG_SIZE, &written); key_rec->sig, ECRYPTFS_SIG_SIZE, &written);
if (rc) { if (rc) {
ecryptfs_printk(KERN_ERR, "Error writing " ecryptfs_printk(KERN_ERR, "Error writing "
"auth tok signature packet\n"); "auth tok signature packet\n");
goto out; goto out_free;
} }
(*len) += written; (*len) += written;
} else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) { } else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) {
rc = write_tag_1_packet(dest_base + (*len), rc = write_tag_1_packet(dest_base + (*len),
max, auth_tok, max, auth_tok,
crypt_stat,mount_crypt_stat, crypt_stat,mount_crypt_stat,
&key_rec, &written); key_rec, &written);
if (rc) { if (rc) {
ecryptfs_printk(KERN_WARNING, "Error " ecryptfs_printk(KERN_WARNING, "Error "
"writing tag 1 packet\n"); "writing tag 1 packet\n");
goto out; goto out_free;
} }
(*len) += written; (*len) += written;
} else { } else {
ecryptfs_printk(KERN_WARNING, "Unsupported " ecryptfs_printk(KERN_WARNING, "Unsupported "
"authentication token type\n"); "authentication token type\n");
rc = -EINVAL; rc = -EINVAL;
goto out; goto out_free;
} }
} else } else
BUG(); BUG();
...@@ -1717,6 +1724,9 @@ ecryptfs_generate_key_packet_set(char *dest_base, ...@@ -1717,6 +1724,9 @@ ecryptfs_generate_key_packet_set(char *dest_base,
ecryptfs_printk(KERN_ERR, "Error writing boundary byte\n"); ecryptfs_printk(KERN_ERR, "Error writing boundary byte\n");
rc = -EIO; rc = -EIO;
} }
out_free:
kmem_cache_free(ecryptfs_key_record_cache, key_rec);
out: out:
if (rc) if (rc)
(*len) = 0; (*len) = 0;
......
...@@ -651,6 +651,11 @@ static struct ecryptfs_cache_info { ...@@ -651,6 +651,11 @@ static struct ecryptfs_cache_info {
.name = "ecryptfs_lower_page_cache", .name = "ecryptfs_lower_page_cache",
.size = PAGE_CACHE_SIZE, .size = PAGE_CACHE_SIZE,
}, },
{
.cache = &ecryptfs_key_record_cache,
.name = "ecryptfs_key_record_cache",
.size = sizeof(struct ecryptfs_key_record),
},
}; };
static void ecryptfs_free_kmem_caches(void) static void ecryptfs_free_kmem_caches(void)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment