Ejemplo n.º 1
0
/*
 * Map a range of virtual memory.  Note that the size asked for here
 * is literally what the upper level has asked for.  We need to do
 * any rounding, etc. here.  If mapping fails return 0, otherwise
 * return the address of the base of the mapped memory.
 */
void *
sysMapMem(size_t requestedSize, size_t *mappedSize)
{
    void *mappedAddr;

    *mappedSize = roundUpToGrain(requestedSize);
#ifdef USE_MALLOC
    mappedAddr = (void *) sysMalloc(*mappedSize); /* Returns 0 on failure */
#ifdef __linux__
     if (mappedAddr) {
       memset(mappedAddr, 0, *mappedSize);
       mappedAddr = (void *) roundUpToGrain(mappedAddr);
     }
#endif
#else
    mappedAddr = mapChunk(*mappedSize);           /* Returns 0 on failure */
#endif /* USE_MALLOC */
    if (mappedAddr) {
        Log3(2, "sysMapMem: 0x%x bytes at 0x%x (request: 0x%x bytes)\n",
             *mappedSize, mappedAddr, requestedSize);
    } else {
        Log1(2, "sysMapMem failed: (request: 0x%x bytes)\n", requestedSize);
    }
    return mappedAddr;
}
Ejemplo n.º 2
0
/*
 * Return the address of the base of the newly committed memory, or 0
 * if committing failed.
 */
void *
sysCommitMem(void *requestedAddr, size_t requestedSize, size_t *committedSize)
{
    void *committedAddr;
    char *ret;

    *committedSize = roundUpToGrain(requestedSize);
    committedAddr = (void *) roundDownToGrain((long) requestedAddr);
#ifdef USE_MALLOC
#ifdef __linux__
    ret = committedAddr;
#else
    ret = requestedAddr;
#endif
#else
    ret = mapChunkReserve(committedAddr, *committedSize);
#endif
    if (ret) {
        committedAddr = ret;
        Log4(2,
    "sysCommitMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n",
             *committedSize, committedAddr, requestedSize, requestedAddr);
    } else {
        committedAddr = 0;
        Log2(2, "sysCommitMem failed: (request: 0x%x bytes at 0x%x)\n",
             requestedSize, requestedAddr);
    }

    return committedAddr;
}
Ejemplo n.º 3
0
/*
 * Unmap a range of virtual memory.  Note that the size asked for here
 * is literally what the upper level has asked for.  We need to do any
 * rounding, etc. here.  If unmapping fails return 0, otherwise return
 * the address of the base of the unmapped memory.
 */
void *
sysUnmapMem(void *requestedAddr, size_t requestedSize, size_t *unmappedSize)
{
    void *unmappedAddr;
    int ret;

    *unmappedSize = roundUpToGrain(requestedSize);
#ifdef USE_MALLOC
    sysFree(requestedAddr);
    ret = 1;
#else
    ret = unmapChunk(requestedAddr, *unmappedSize);
#endif /* USE_MALLOC */
    if (ret) {
        unmappedAddr = requestedAddr;
        Log4(2,
             "sysUnmapMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n",
             *unmappedSize, unmappedAddr, requestedSize, requestedAddr);
    } else {
        unmappedAddr = 0;
        Log2(2, "sysUnmapMem failed: (request: 0x%x bytes at 0x%x)\n",
             requestedSize, requestedAddr);
    }
    return unmappedAddr;
}
Ejemplo n.º 4
0
/* Purpose: Relinquishes a range of memory which was previously reserved using
            CVMmemMap().  The memory range may be a subset of the range
	    returned by CVMmemMap().  The range to relinquish is specified by
	    addr as the starting address of the range, and requestedSize as the
	    size of the range in units of bytes.
   Returns: The starting address of the unmmapped range is returned.
            The actual size of the unmapped range is set in *unmappedSize
	    in units of bytes.
	    Else, if failed to unmap, NULL is returned and *unmappedSize is
	    set to 0.
   Note: memory sizes must be in increments of the page size as returned
         by CVMmemPageSize() in units of bytes.
*/
void *CVMmemUnmap(void *requestedAddr, size_t requestedSize,
		  size_t *unmappedSize)
{
    void *unmappedAddr = NULL;
    CVMBool success = CVM_FALSE;

    CVMassert(requestedAddr != NULL);
    CVMassert(requestedSize == roundUpToGrain(requestedSize));

    if (requestedSize != 0) {
	success = VirtualFree(requestedAddr, 0, MEM_RELEASE);
    }
    if (success) {
	unmappedAddr = requestedAddr;
	*unmappedSize = requestedSize;
    } else {
	*unmappedSize = 0;
    }

#ifdef DEBUG_MMAP
    if (success) {
        CVMconsolePrintf(
	    "CVMmemUnmap: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n",
            *unmappedSize, unmappedAddr, requestedSize, requestedAddr);
    } else {
	CVMconsolePrintf("CVMmemUnmap failed: Error %d, (request: 0x%x bytes at 0x%x)\n",
                         GetLastError(), requestedSize, requestedAddr);
    }
#endif
    return unmappedAddr;
}
Ejemplo n.º 5
0
/* Purpose: Decommits a range of memory which was previously committed using
            CVMmemCommit().  The memory range may be a subset of the range
	    returned by CVMmemCommit().  The range to decommit is specified by
            addr as the starting address of the range, and requestedSize as the
	    size of the range in units of bytes.
   Returns: The starting address of the decommitted range is returned.
            The actual size of the decommitted range is set in *decommittedSize
	    in units of bytes.
	    Else, if failed to decommit, NULL is returned and *decommittedSize
	    is set to 0.
   Note: memory sizes must be in increments of the page size as returned
         by CVMmemPageSize() in units of bytes.
	 Committed memory must be uncommitted using CVMmemDecommit() before it
	 is unmmapped with CVMmemUnmap().  If this order is not adhered to,
	 then the state of the committed memory will be undefined.
*/
void *CVMmemDecommit(void *requestedAddr, size_t requestedSize,
		     size_t *decommittedSize)
{
    void *decommittedAddr = NULL;
    CVMBool success = CVM_FALSE;

    CVMassert(requestedSize == roundDownToGrain(requestedSize));
    CVMassert(requestedAddr == (void *)roundUpToGrain((CVMAddr)requestedAddr));

    if (requestedSize != 0) {
        success = VirtualFree(requestedAddr, requestedSize, MEM_DECOMMIT);
#ifdef WINCE
        if (!success && ((DWORD)requestedAddr + requestedSize) >=
            ROUND_UP_32MB(requestedAddr)) {
            /* crossing 32MB boundary, need to break up the decommit */
            size_t origSize = requestedSize;
            void *newAddr = requestedAddr;

            while(((DWORD)newAddr + origSize) >= ROUND_UP_32MB(newAddr)) {
                size_t newSize = ROUND_UP_32MB(newAddr) - (DWORD)newAddr;
                success = VirtualFree(newAddr, newSize, MEM_DECOMMIT);
                if (!success) {
                    break;
                }
                newAddr = (void*)((DWORD)newAddr + newSize);
                origSize -= newSize;
            }

            if (success && origSize > 0) {
                /* Some residual pages to decommit */
                success = VirtualFree(newAddr, origSize, MEM_DECOMMIT);
            }
        }
#endif
    }
    if (success) {
	decommittedAddr = requestedAddr;
	*decommittedSize = requestedSize;
    } else {
	*decommittedSize = 0;
    }

#ifdef DEBUG_MMAP
    if (success) {
	CVMconsolePrintf(
            "CVMmemDecommit: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n",
            *decommittedSize, decommittedAddr, requestedSize, requestedAddr);
    } else {
	CVMconsolePrintf(
	    "CVMmemDecommit failed: (request: 0x%x bytes at 0x%x)\n",
	    requestedSize, requestedAddr);
    }
#endif

    return decommittedAddr;
}
Ejemplo n.º 6
0
/* Purpose: Reserves a memory address range of the requested size for later use.
   Returns: The starting address of the reserved memory range if successful.
            The actual size of the reserved memory range will be set in
	    *mappedSize in units of bytes.
            Else if failed to map, NULL is returned and *mappedSize is set
	    to 0.
   Note: memory sizes must be in increments of the page size as returned
         by CVMmemPageSize() in units of bytes.
*/
void *CVMmemMap(size_t requestedSize, size_t *mappedSize)
{
    void *mappedAddr = NULL;

    CVMassert(requestedSize == roundUpToGrain(requestedSize));
    if (requestedSize != 0) {
	DWORD protectAttr;

	/* For WinCE 5.0 and earlier, calling VirtualAlloc() with PAGE_READONLY
	   will ensure that the virtual address range is reserved from within
	   the 32M process space.  This range is protected from reads and
	   writes by other non-trusted processes.  On WinCE systems where all
	   processes are trusted, other processes can still read and write into
	   our process via WinCE system calls.

	   If instead of PAGE_READONLY, we use PAGE_NOACCESS together with
	   MEM_RESERVE and we request a size greater than 2M, than the address
	   range will be reserved from shared memory.  Note that shared memory
	   can be read and written to by other processes as long as they know
	   the address.  This could open the heap data to security
	   vulnerabilities, and expose the VM to attacks more easily.

	   Note that PAGE_READONLY doesn't actually mean that the page is
	   read only later, nor does PAGE_NOACCESS means that the page is
	   in accessible.  Before the pages are used, they will be committed
	   in CVMmemCommit() using VirtualAlloc(... PAGE_READWRITE).  Hence,
	   we'll have read write access to the committed heap pages.

	   Relevant MSDN references:
	   http://msdn2.microsoft.com/EN-US/library/aa454885.aspx#effective_memory_storage_power_mgmt_wm5_topic2
	   http://msdn2.microsoft.com/en-us/library/aa908768.aspx 
	*/

	protectAttr = PAGE_READONLY;
#ifdef WINCE
	if (CVMglobals.target.useLargeMemoryArea) {
	    protectAttr = PAGE_NOACCESS;
	}
#endif
	/* Returns NULL on failure */
	mappedAddr = VirtualAlloc(0, requestedSize, MEM_RESERVE, protectAttr);
    }
    *mappedSize = (mappedAddr != NULL) ? requestedSize : 0;

#ifdef DEBUG_MMAP
    if (mappedAddr != NULL) {
	CVMconsolePrintf(
	    "CVMmemMap: 0x%x bytes at 0x%x (request: 0x%x bytes)\n",
	    *mappedSize, mappedAddr, requestedSize);
    } else {
	CVMconsolePrintf("CVMmemMap failed: Error %d, (request: 0x%x bytes)\n",
			 GetLastError(), requestedSize);
    }
#endif
    return mappedAddr;
}
Ejemplo n.º 7
0
/*
 * Return the address of the base of the newly decommitted memory, or 0
 * if decommitting failed.
 */
void *
sysDecommitMem(void *requestedAddr, size_t requestedSize,
               size_t *decommittedSize)
{
    void *decommittedAddr;
    char *ret;

    *decommittedSize = roundDownToGrain(requestedSize);
    decommittedAddr = (void *) roundUpToGrain((long) requestedAddr);
#ifdef USE_MALLOC
    ret = 0;
#else
    ret = mapChunkNoreserve(decommittedAddr, *decommittedSize);
#endif
    Log4(2,
         "sysDecommitMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n",
         *decommittedSize, decommittedAddr, requestedSize, requestedAddr);

    return ret;
}
Ejemplo n.º 8
0
/* Purpose: Commits a range of memory which was previously reserved using
            CVMmemMap().  The memory range may be a subset of the range
	    returned by CVMmemMap().  The range to commit is specified by
            addr as the starting address of the range, and requestedSize as the
	    size of the range in units of bytes.
   Returns: The starting address of the committed range is returned.
            The actual size of the committed range is set in *committedSize
	    in units of bytes.
	    Else, if failed to commit, NULL is returned and *committedSize is
	    set to 0.
   Note: memory sizes must be in increments of the page size as returned
         by CVMmemPageSize() in units of bytes.
	 Committed memory must be uncommitted using CVMmemDecommit() before it
	 is unmmapped with CVMmemUnmap().  If this order is not adhered to,
	 then the state of the committed memory will be undefined.
*/
void *CVMmemCommit(void *requestedAddr, size_t requestedSize,
		   size_t *committedSize)
{
    void *committedAddr = NULL;
    MEMORY_BASIC_INFORMATION mb;

    CVMassert(requestedSize == roundUpToGrain(requestedSize));
    CVMassert(requestedAddr ==
	      (void *)roundDownToGrain((CVMAddr)requestedAddr));

    if (requestedSize != 0) {
        committedAddr = VirtualAlloc(requestedAddr, requestedSize, MEM_COMMIT,
                                     PAGE_READWRITE);
#ifdef WINCE
        if (committedAddr == NULL && ((DWORD)requestedAddr + requestedSize) >=
            ROUND_UP_32MB(requestedAddr)) {
            /* hitting/crossing 32MB boundary, need to break up the commit */
            size_t origSize = requestedSize;
            void *newAddr = requestedAddr;
            size_t pageSize = CVMmemPageSize();

            while(((DWORD)newAddr + origSize) >= ROUND_UP_32MB(newAddr)) {
                size_t newSize = ROUND_UP_32MB(newAddr) - (DWORD)newAddr;
                if (newSize >= pageSize * 2) {
                    /* Sometimes, for whatever reason, if you
                     * allocate right up to the 32MB boundary it returns
                     * INVALID PARAMETER error. So, back off a page 
                     */
                    newSize -= pageSize;
                }
                committedAddr = VirtualAlloc(newAddr, newSize, MEM_COMMIT,
                                             PAGE_READWRITE);
                if (committedAddr == NULL) {
                    break;
                }
                newAddr = (void*)((DWORD)newAddr + newSize);
                origSize -= newSize;
            }

#if _WIN32_WCE < 600
            while(committedAddr != NULL && origSize > 0) {
                /* Some residual pages to commit */
                /* WinCE < 6.0 fails on commits that are too big, where too big
                 * is some unknown value I can't seem to pin down. So just do
                 * it a page at a time.
                 */
                committedAddr = VirtualAlloc(newAddr, pageSize, MEM_COMMIT,
                                             PAGE_READWRITE);
                origSize -= pageSize;
                newAddr = (void *)((DWORD)newAddr + pageSize);
            }
#else
            if (committedAddr != NULL) {
                committedAddr = VirtualAlloc(newAddr, origSize, MEM_COMMIT,
                                             PAGE_READWRITE);
            }
#endif
            if (committedAddr != NULL) {
                committedAddr = requestedAddr;
            }
        }
#endif
    }
    *committedSize = (committedAddr != NULL) ?
	(CVMassert(committedAddr == requestedAddr), requestedSize) : 0;

#ifdef WINCE
    if (committedAddr == NULL) {
        /* Must have had an error committing, attempt to decommit anything we
         * committed
         */
        size_t decommittedSize;
        CVMmemDecommit(requestedAddr, requestedSize, &decommittedSize);
    }
#endif
#ifdef DEBUG_MMAP
    if (committedAddr != NULL) {
	CVMconsolePrintf(
	    "CVMmemCommit: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n",
	    *committedSize, committedAddr, requestedSize, requestedAddr);
    } else {
	CVMconsolePrintf(
	    "CVMmemCommit failed: Error %d, (request: 0x%x bytes at 0x%x)\n",
	    GetLastError(), requestedSize, requestedAddr);
        CVMconsolePrintf("CVMmemCommit: State:\n");
        VirtualQuery(requestedAddr, &mb, sizeof(mb));
        CVMconsolePrintf("  Base: 0x%x\n  AllocBase: 0x%x\n  AllocProtect: 0x%x\n  Size: 0x%x\n  State: 0x%x\n  Protect: 0x%x\n  Type: 0x%x\n",
                         (int)mb.BaseAddress, mb.AllocationBase,
                         mb.AllocationProtect, mb.RegionSize, mb.State,
                         mb.Protect, mb.Type);
    }
#endif

    return committedAddr;
}