Example #1
0
DECLHIDDEN(int) rtR0MemObjNativeFree(RTR0MEMOBJ pMem)
{
    PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)pMem;
    int rc;

    switch (pMemOs2->Core.enmType)
    {
        case RTR0MEMOBJTYPE_PHYS_NC:
            AssertMsgFailed(("RTR0MEMOBJTYPE_PHYS_NC\n"));
            return VERR_INTERNAL_ERROR;
            break;

        case RTR0MEMOBJTYPE_PHYS:
            if (!pMemOs2->Core.pv)
                break;

        case RTR0MEMOBJTYPE_MAPPING:
            if (pMemOs2->Core.u.Mapping.R0Process == NIL_RTR0PROCESS)
                break;

            /* fall thru */
        case RTR0MEMOBJTYPE_PAGE:
        case RTR0MEMOBJTYPE_LOW:
        case RTR0MEMOBJTYPE_CONT:
            rc = KernVMFree(pMemOs2->Core.pv);
            AssertMsg(!rc, ("rc=%d type=%d pv=%p cb=%#zx\n", rc, pMemOs2->Core.enmType, pMemOs2->Core.pv, pMemOs2->Core.cb));
            break;

        case RTR0MEMOBJTYPE_LOCK:
            rc = KernVMUnlock(&pMemOs2->Lock);
            AssertMsg(!rc, ("rc=%d\n", rc));
            break;

        case RTR0MEMOBJTYPE_RES_VIRT:
        default:
            AssertMsgFailed(("enmType=%d\n", pMemOs2->Core.enmType));
            return VERR_INTERNAL_ERROR;
    }

    return VINF_SUCCESS;
}
DECLASM(int) VBoxDrvIOCtl(uint16_t sfn, uint8_t iCat, uint8_t iFunction, void *pvParm, void *pvData, uint16_t *pcbParm, uint16_t *pcbData)
{
    /*
     * Find the session.
     */
    const RTPROCESS     Process = RTProcSelf();
    const unsigned      iHash = SESSION_HASH(sfn);
    PSUPDRVSESSION      pSession;

    RTSpinlockAcquire(g_Spinlock);
    pSession = g_apSessionHashTab[iHash];
    if (pSession && pSession->Process != Process)
    {
        do pSession = pSession->pNextHash;
        while (     pSession
               &&   (   pSession->sfn != sfn
                     || pSession->Process != Process));

        if (RT_LIKELY(pSession))
            supdrvSessionRetain(pSession);
    }
    RTSpinlockReleaseNoInts(g_Spinlock);
    if (!pSession)
    {
        OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process));
        return VERR_INVALID_PARAMETER;
    }

    /*
     * Verify the category and dispatch the IOCtl.
     */
    if (RT_LIKELY(iCat == SUP_CTL_CATEGORY))
    {
        Log(("VBoxDrvIOCtl: pSession=%p iFunction=%#x pvParm=%p pvData=%p *pcbParm=%d *pcbData=%d\n", pSession, iFunction, pvParm, pvData, *pcbParm, *pcbData));
        Assert(pvParm);
        Assert(!pvData);

        /*
         * Lock the header.
         */
        PSUPREQHDR pHdr = (PSUPREQHDR)pvParm;
        AssertReturn(*pcbParm == sizeof(*pHdr), VERR_INVALID_PARAMETER);
        KernVMLock_t Lock;
        int rc = KernVMLock(VMDHL_WRITE, pHdr, *pcbParm, &Lock, (KernPageList_t *)-1, NULL);
        AssertMsgReturn(!rc, ("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pHdr, *pcbParm, &Lock, rc), VERR_LOCK_FAILED);

        /*
         * Validate the header.
         */
        if (RT_LIKELY((pHdr->fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) == SUPREQHDR_FLAGS_MAGIC))
        {
            uint32_t cbReq = RT_MAX(pHdr->cbIn, pHdr->cbOut);
            if (RT_LIKELY(    pHdr->cbIn >= sizeof(*pHdr)
                          &&  pHdr->cbOut >= sizeof(*pHdr)
                          &&  cbReq <= _1M*16))
            {
                /*
                 * Lock the rest of the buffer if necessary.
                 */
                if (((uintptr_t)pHdr & PAGE_OFFSET_MASK) + cbReq > PAGE_SIZE)
                {
                    rc = KernVMUnlock(&Lock);
                    AssertMsgReturn(!rc, ("KernVMUnlock(Lock) -> %#x\n", rc), VERR_LOCK_FAILED);

                    rc = KernVMLock(VMDHL_WRITE, pHdr, cbReq, &Lock, (KernPageList_t *)-1, NULL);
                    AssertMsgReturn(!rc, ("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pHdr, cbReq, &Lock, rc), VERR_LOCK_FAILED);
                }

                /*
                 * Process the IOCtl.
                 */
                rc = supdrvIOCtl(iFunction, &g_DevExt, pSession, pHdr);
            }
            else
            {
                OSDBGPRINT(("VBoxDrvIOCtl: max(%#x,%#x); iCmd=%#x\n", pHdr->cbIn, pHdr->cbOut, iFunction));
                rc = VERR_INVALID_PARAMETER;
            }
        }
        else
        {
            OSDBGPRINT(("VBoxDrvIOCtl: bad magic fFlags=%#x; iCmd=%#x\n", pHdr->fFlags, iFunction));
            rc = VERR_INVALID_PARAMETER;
        }

        /*
         * Unlock and return.
         */
        int rc2 = KernVMUnlock(&Lock);
        AssertMsg(!rc2, ("rc2=%d\n", rc2)); NOREF(rc2);s
    }