summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVMware, Inc <>2013-09-17 20:32:18 -0700
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2013-09-22 22:19:59 -0700
commit81536c78e78200c58825b65cb5d188704b70c15f (patch)
tree1a529d6db4bc0f631fed2ddaa85038da77aaa2b2
parenta4f7f191d0cb1d260f1b13e2545340109be4631d (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.c12
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",