diff options
author | VMware, Inc <> | 2013-09-17 20:32:18 -0700 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2013-09-22 22:19:59 -0700 |
commit | 81536c78e78200c58825b65cb5d188704b70c15f (patch) | |
tree | 1a529d6db4bc0f631fed2ddaa85038da77aaa2b2 | |
parent | a4f7f191d0cb1d260f1b13e2545340109be4631d (diff) |
HGFS: Fix a Linux client memory corruption
When doing partial page writes the Linux HGFS client would trash the
initial part of the page leading up to the start of the write and also
trash the remaining part of the page after the written segment of the
page.
This trashing of the initial part of the page was incorrect and
overwrites earlier partial page writes to that page. This was also
incorrect as the arguments for the offsets into the page were
miscalculated.
Signed-off-by: Dmitry Torokhov <dtor@vmware.com>
-rw-r--r-- | open-vm-tools/modules/linux/vmhgfs/page.c | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/open-vm-tools/modules/linux/vmhgfs/page.c b/open-vm-tools/modules/linux/vmhgfs/page.c index 4aec4883..5b682326 100644 --- a/open-vm-tools/modules/linux/vmhgfs/page.c +++ b/open-vm-tools/modules/linux/vmhgfs/page.c @@ -472,6 +472,7 @@ HgfsDoWrite(HgfsHandle handle, // IN: Handle for this file replyStatus = HgfsReplyStatus(req); result = HgfsStatusConvertToLinux(replyStatus); + LOG(4, (KERN_WARNING "VMware hgfs: HgfsDoWrite: res %u\n", result)); switch (result) { case 0: if (opUsed == HGFS_OP_WRITE_V3 || opUsed == HGFS_OP_WRITE_FAST_V4) { @@ -598,6 +599,8 @@ HgfsDoReadpage(HgfsHandle handle, // IN: Handle to use for reading */ if (remainingCount) { char *buffer = kmap(page) + pageTo; + LOG(6, (KERN_DEBUG "VMware hgfs: %s: zeroing last %Zu bytes\n", + __func__, remainingCount)); memset(buffer - remainingCount, 0, remainingCount); kunmap(page); } @@ -815,6 +818,8 @@ HgfsWritepage(struct page *page, // IN: Page to write from */ currentFileSize = compat_i_size_read(inode); lastPageIndex = currentFileSize >> PAGE_CACHE_SHIFT; + LOG(4, (KERN_WARNING "VMware hgfs: %s: file size lpi %lu pi %lu\n", + __func__, lastPageIndex, page->index)); if (page->index > lastPageIndex) { goto exit; } else if (page->index == lastPageIndex) { @@ -902,9 +907,6 @@ HgfsDoWriteBegin(struct page *page, // IN: Page to be written ((pageFrom == 0) && (offset + pageTo) >= currentFileSize)) { void *kaddr = compat_kmap_atomic(page); - if (pageFrom) { - memset(kaddr, 0, pageFrom); - } if (pageTo < PAGE_CACHE_SIZE) { memset(kaddr + pageTo, 0, PAGE_CACHE_SIZE - pageTo); } @@ -977,8 +979,8 @@ HgfsWriteBegin(struct file *file, // IN: File to be written void **clientData) // OUT: Opaque to pass to write_end, unused { pgoff_t index = pos >> PAGE_CACHE_SHIFT; - unsigned pageFrom = pos & (PAGE_CACHE_SHIFT - 1); - unsigned pageTo = pos + len; + unsigned pageFrom = pos & (PAGE_CACHE_SIZE - 1); + unsigned pageTo = pageFrom + len; struct page *page; LOG(6, (KERN_WARNING "VMware hgfs: %s: (%s/%s(%ld), %u@%lld)\n", |