]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
vmmemctl: fix a double free on linux balloon driver
authorVMware, Inc <>
Mon, 15 Oct 2012 04:54:23 +0000 (21:54 -0700)
committerDmitry Torokhov <dtor@vmware.com>
Fri, 19 Oct 2012 18:32:41 +0000 (11:32 -0700)
On unload when using the unbatched commands, b->pageHandle would
be free two times. The first one when releasing all the pages of
the balloon, and the second time when releasing the batch
structures. This was causing OOPS and sometimes panic when rmmod
the driver.

The fix is to set b->pageHandle to PAGE_HANDLE_INVALID when it's
added to the chunks or when the page is released.

Signed-off-by: Dmitry Torokhov <dtor@vmware.com>
open-vm-tools/modules/shared/vmmemctl/vmballoon.c

index 1289fd64b6f4b4ee471c37191c48d122c3f8188c..cb62a8c2c442ff320488f8a780e77cc9dfdd81b5 100644 (file)
@@ -1000,7 +1000,8 @@ BalloonLock(Balloon *b,       // IN
    chunk = BalloonGetChunk(b);
    if (chunk == NULL) {
       OS_ReservedPageFree(b->pageHandle);
-      return BALLOON_PAGE_ALLOC_FAILURE;
+      status = BALLOON_PAGE_ALLOC_FAILURE;
+      goto out;
    }
 
    /* inform monitor via backdoor */
@@ -1012,17 +1013,18 @@ BalloonLock(Balloon *b,       // IN
       if (status == BALLOON_ERROR_RESET ||
           status == BALLOON_ERROR_PPN_NOTNEEDED) {
          OS_ReservedPageFree(b->pageHandle);
-         return status;
+         goto out;
       }
 
       /* place on list of non-balloonable pages, retry allocation */
       status = BalloonErrorPageStore(b, b->pageHandle);
       if (status != BALLOON_SUCCESS) {
          OS_ReservedPageFree(b->pageHandle);
-         return status;
+         goto out;
       }
 
-      return old_status;
+      status = old_status;
+      goto out;
    }
 
    /* track allocated page */
@@ -1031,6 +1033,8 @@ BalloonLock(Balloon *b,       // IN
    /* update balloon size */
    b->nPages++;
 
+out:
+   b->pageHandle = PAGE_HANDLE_INVALID;
    return status;
 }
 
@@ -1071,6 +1075,7 @@ BalloonUnlock(Balloon *b,     // IN
    b->nPages--;
 
 out:
+   b->pageHandle = PAGE_HANDLE_INVALID;
    if (b->fallbackChunk != NULL) {
       BalloonChunk_Destroy(b->fallbackChunk);
       b->fallbackChunk = NULL;
@@ -1099,6 +1104,7 @@ BalloonAddPage(Balloon *b,            // IN
                uint16 idx,            // IN
                PageHandle page)       // IN
 {
+   ASSERT(b->pageHandle == PAGE_HANDLE_INVALID);
    b->pageHandle = page;
 }
 
@@ -1252,6 +1258,8 @@ Balloon_Init(BalloonGuest guestType)
    /* initialize reset flag */
    b->resetFlag = TRUE;
 
+   b->hypervisorCapabilities = 0;
+
    b->pageHandle = PAGE_HANDLE_INVALID;
    b->batchPageMapping = MAPPING_INVALID;
    b->batchPage = NULL;