提交 87b811c3 编写于 作者: E Eric Sandeen 提交者: Linus Torvalds

ecryptfs: fix memory corruption when storing crypto info in xattrs

When ecryptfs allocates space to write crypto headers into, before copying
it out to file headers or to xattrs, it looks at the value of
crypt_stat->num_header_bytes_at_front to determine how much space it
needs.  This is also used as the file offset to the actual encrypted data,
so for xattr-stored crypto info, the value was zero.

So, we kzalloc'd 0 bytes, and then ran off to write to that memory.
(Which returned as ZERO_SIZE_PTR, so we explode quickly).

The right answer is to always allocate a page to write into; the current
code won't ever write more than that (this is enforced by the
(PAGE_CACHE_SIZE - offset) length in the call to
ecryptfs_generate_key_packet_set).  To be explicit about this, we now send
in a "max" parameter, rather than magically using PAGE_CACHE_SIZE there.

Also, since the pointer we pass down the callchain eventually gets the
virt_to_page() treatment, we should be using a alloc_page variant, not
kzalloc (see also 7fcba054)
Signed-off-by: NEric Sandeen <sandeen@redhat.com>
Acked-by: NMichael Halcrow <mhalcrow@us.ibm.com>
Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
上级 ce05fcc3
...@@ -1251,6 +1251,7 @@ struct kmem_cache *ecryptfs_header_cache_2; ...@@ -1251,6 +1251,7 @@ struct kmem_cache *ecryptfs_header_cache_2;
/** /**
* ecryptfs_write_headers_virt * ecryptfs_write_headers_virt
* @page_virt: The virtual address to write the headers to * @page_virt: The virtual address to write the headers to
* @max: The size of memory allocated at page_virt
* @size: Set to the number of bytes written by this function * @size: Set to the number of bytes written by this function
* @crypt_stat: The cryptographic context * @crypt_stat: The cryptographic context
* @ecryptfs_dentry: The eCryptfs dentry * @ecryptfs_dentry: The eCryptfs dentry
...@@ -1278,7 +1279,8 @@ struct kmem_cache *ecryptfs_header_cache_2; ...@@ -1278,7 +1279,8 @@ struct kmem_cache *ecryptfs_header_cache_2;
* *
* Returns zero on success * Returns zero on success
*/ */
static int ecryptfs_write_headers_virt(char *page_virt, size_t *size, static int ecryptfs_write_headers_virt(char *page_virt, size_t max,
size_t *size,
struct ecryptfs_crypt_stat *crypt_stat, struct ecryptfs_crypt_stat *crypt_stat,
struct dentry *ecryptfs_dentry) struct dentry *ecryptfs_dentry)
{ {
...@@ -1296,7 +1298,7 @@ static int ecryptfs_write_headers_virt(char *page_virt, size_t *size, ...@@ -1296,7 +1298,7 @@ static int ecryptfs_write_headers_virt(char *page_virt, size_t *size,
offset += written; offset += written;
rc = ecryptfs_generate_key_packet_set((page_virt + offset), crypt_stat, rc = ecryptfs_generate_key_packet_set((page_virt + offset), crypt_stat,
ecryptfs_dentry, &written, ecryptfs_dentry, &written,
PAGE_CACHE_SIZE - offset); max - offset);
if (rc) if (rc)
ecryptfs_printk(KERN_WARNING, "Error generating key packet " ecryptfs_printk(KERN_WARNING, "Error generating key packet "
"set; rc = [%d]\n", rc); "set; rc = [%d]\n", rc);
...@@ -1368,14 +1370,14 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry) ...@@ -1368,14 +1370,14 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry)
goto out; goto out;
} }
/* Released in this function */ /* Released in this function */
virt = kzalloc(crypt_stat->num_header_bytes_at_front, GFP_KERNEL); virt = (char *)get_zeroed_page(GFP_KERNEL);
if (!virt) { if (!virt) {
printk(KERN_ERR "%s: Out of memory\n", __func__); printk(KERN_ERR "%s: Out of memory\n", __func__);
rc = -ENOMEM; rc = -ENOMEM;
goto out; goto out;
} }
rc = ecryptfs_write_headers_virt(virt, &size, crypt_stat, rc = ecryptfs_write_headers_virt(virt, PAGE_CACHE_SIZE, &size,
ecryptfs_dentry); crypt_stat, ecryptfs_dentry);
if (unlikely(rc)) { if (unlikely(rc)) {
printk(KERN_ERR "%s: Error whilst writing headers; rc = [%d]\n", printk(KERN_ERR "%s: Error whilst writing headers; rc = [%d]\n",
__func__, rc); __func__, rc);
...@@ -1393,8 +1395,7 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry) ...@@ -1393,8 +1395,7 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry)
goto out_free; goto out_free;
} }
out_free: out_free:
memset(virt, 0, crypt_stat->num_header_bytes_at_front); free_page((unsigned long)virt);
kfree(virt);
out: out:
return rc; return rc;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册