Exemple #1
0
/**
 * @copydoc RTNetIPv6PseudoChecksumBits
 */
DECLINLINE(uint32_t) rtNetIPv6PseudoChecksumBits(PCRTNETADDRIPV6 pSrcAddr, PCRTNETADDRIPV6 pDstAddr,
                                                 uint8_t bProtocol, uint32_t cbPkt)
{
    uint32_t u32Sum = pSrcAddr->au16[0]
                    + pSrcAddr->au16[1]
                    + pSrcAddr->au16[2]
                    + pSrcAddr->au16[3]
                    + pSrcAddr->au16[4]
                    + pSrcAddr->au16[5]
                    + pSrcAddr->au16[6]
                    + pSrcAddr->au16[7]
                    + pDstAddr->au16[0]
                    + pDstAddr->au16[1]
                    + pDstAddr->au16[2]
                    + pDstAddr->au16[3]
                    + pDstAddr->au16[4]
                    + pDstAddr->au16[5]
                    + pDstAddr->au16[6]
                    + pDstAddr->au16[7]
                    + RT_H2BE_U16(RT_HIWORD(cbPkt))
                    + RT_H2BE_U16(RT_LOWORD(cbPkt))
                    + 0
                    + RT_H2BE_U16(RT_MAKE_U16(bProtocol, 0));
    return u32Sum;
}
Exemple #2
0
RTDECL(uint16_t) ASMByteSwapU16(uint16_t u16)
{
    return RT_MAKE_U16(RT_HIBYTE(u16), RT_LOBYTE(u16));
}
Exemple #3
0
/* Used by PutEventMultiTouch and PutEventMultiTouchString. */
HRESULT Mouse::putEventMultiTouch(LONG aCount,
                                  LONG64 *paContacts,
                                  ULONG aScanTime)
{
    if (aCount >= 256)
    {
         return E_INVALIDARG;
    }

    DisplayMouseInterface *pDisplay = mParent->getDisplayMouseInterface();
    ComAssertRet(pDisplay, E_FAIL);

    HRESULT rc = S_OK;

    uint64_t* pau64Contacts = NULL;
    uint8_t cContacts = 0;

    /* Deliver 0 contacts too, touch device may use this to reset the state. */
    if (aCount > 0)
    {
        /* Create a copy with converted coords. */
        pau64Contacts = (uint64_t *)RTMemTmpAlloc(aCount * sizeof(uint64_t));
        if (pau64Contacts)
        {
            int32_t x1, y1, x2, y2;
            /* Takes the display lock */
            pDisplay->getFramebufferDimensions(&x1, &y1, &x2, &y2);

            LONG i;
            for (i = 0; i < aCount; i++)
            {
                uint32_t u32Lo = RT_LO_U32(paContacts[i]);
                uint32_t u32Hi = RT_HI_U32(paContacts[i]);
                int32_t x = (int16_t)u32Lo;
                int32_t y = (int16_t)(u32Lo >> 16);
                uint8_t contactId =  RT_BYTE1(u32Hi);
                bool fInContact   = (RT_BYTE2(u32Hi) & 0x1) != 0;
                bool fInRange     = (RT_BYTE2(u32Hi) & 0x2) != 0;

                LogRel3(("%s: [%d] %d,%d id %d, inContact %d, inRange %d\n",
                         __FUNCTION__, i, x, y, contactId, fInContact, fInRange));

                /* Framebuffer dimensions are 0,0 width, height, that is x2,y2 are exclusive,
                 * while coords are inclusive.
                 */
                int32_t xAdj = x1 < x2 ?   ((x - 1 - x1) * VMMDEV_MOUSE_RANGE)
                                         / (x2 - x1) : 0;
                int32_t yAdj = y1 < y2 ?   ((y - 1 - y1) * VMMDEV_MOUSE_RANGE)
                                         / (y2 - y1) : 0;

                bool fValid = (   xAdj >= VMMDEV_MOUSE_RANGE_MIN
                               && xAdj <= VMMDEV_MOUSE_RANGE_MAX
                               && yAdj >= VMMDEV_MOUSE_RANGE_MIN
                               && yAdj <= VMMDEV_MOUSE_RANGE_MAX);

                if (fValid)
                {
                    uint8_t fu8 =   (fInContact? 0x01: 0x00)
                                  | (fInRange?   0x02: 0x00);
                    pau64Contacts[cContacts] = RT_MAKE_U64_FROM_U16((uint16_t)xAdj,
                                                                    (uint16_t)yAdj,
                                                                    RT_MAKE_U16(contactId, fu8),
                                                                    0);
                    cContacts++;
                }
            }
        }
        else
        {
/* Used by PutEventMultiTouch and PutEventMultiTouchString. */
HRESULT Mouse::putEventMultiTouch(LONG aCount,
                                  LONG64 *paContacts,
                                  ULONG aScanTime)
{
    if (aCount >= 256)
    {
         return E_INVALIDARG;
    }

    DisplayMouseInterface *pDisplay = mParent->getDisplayMouseInterface();
    ComAssertRet(pDisplay, E_FAIL);

    /* Touch events are mapped to the primary monitor, because the emulated USB
     * touchscreen device is associated with one (normally the primary) screen in the guest.
     */
    ULONG uScreenId = 0;

    ULONG cWidth  = 0;
    ULONG cHeight = 0;
    LONG  xOrigin = 0;
    LONG  yOrigin = 0;
    HRESULT rc = pDisplay->getScreenResolution(uScreenId, &cWidth, &cHeight, NULL, &xOrigin, &yOrigin);
    ComAssertComRCRetRC(rc);

    uint64_t* pau64Contacts = NULL;
    uint8_t cContacts = 0;

    /* Deliver 0 contacts too, touch device may use this to reset the state. */
    if (aCount > 0)
    {
        /* Create a copy with converted coords. */
        pau64Contacts = (uint64_t *)RTMemTmpAlloc(aCount * sizeof(uint64_t));
        if (pau64Contacts)
        {
            int32_t x1 = xOrigin;
            int32_t y1 = yOrigin;
            int32_t x2 = x1 + cWidth;
            int32_t y2 = y1 + cHeight;

            LogRel3(("%s: screen [%d] %d,%d %d,%d\n",
                     __FUNCTION__, uScreenId, x1, y1, x2, y2));

            LONG i;
            for (i = 0; i < aCount; i++)
            {
                uint32_t u32Lo = RT_LO_U32(paContacts[i]);
                uint32_t u32Hi = RT_HI_U32(paContacts[i]);
                int32_t x = (int16_t)u32Lo;
                int32_t y = (int16_t)(u32Lo >> 16);
                uint8_t contactId =  RT_BYTE1(u32Hi);
                bool fInContact   = (RT_BYTE2(u32Hi) & 0x1) != 0;
                bool fInRange     = (RT_BYTE2(u32Hi) & 0x2) != 0;

                LogRel3(("%s: [%d] %d,%d id %d, inContact %d, inRange %d\n",
                         __FUNCTION__, i, x, y, contactId, fInContact, fInRange));

                /* x1,y1 are inclusive and x2,y2 are exclusive,
                 * while x,y start from 1 and are inclusive.
                 */
                if (x <= x1 || x > x2 || y <= y1 || y > y2)
                {
                    /* Out of range. Skip the contact. */
                    continue;
                }

                int32_t xAdj = x1 < x2? ((x - 1 - x1) * VMMDEV_MOUSE_RANGE) / (x2 - x1) : 0;
                int32_t yAdj = y1 < y2? ((y - 1 - y1) * VMMDEV_MOUSE_RANGE) / (y2 - y1) : 0;

                bool fValid = (   xAdj >= VMMDEV_MOUSE_RANGE_MIN
                               && xAdj <= VMMDEV_MOUSE_RANGE_MAX
                               && yAdj >= VMMDEV_MOUSE_RANGE_MIN
                               && yAdj <= VMMDEV_MOUSE_RANGE_MAX);

                if (fValid)
                {
                    uint8_t fu8 =   (fInContact? 0x01: 0x00)
                                  | (fInRange?   0x02: 0x00);
                    pau64Contacts[cContacts] = RT_MAKE_U64_FROM_U16((uint16_t)xAdj,
                                                                    (uint16_t)yAdj,
                                                                    RT_MAKE_U16(contactId, fu8),
                                                                    0);
                    cContacts++;
                }
            }
        }
        else
        {
/**
 * Initalizes the triple fault / boot hack.
 *
 * Always call vmmR0TripleFaultHackTerm to clean up, even when this call fails.
 *
 * @returns VBox status code.
 */
int vmmR0TripleFaultHackInit(void)
{
    /*
     * Map the first page.
     */
    int rc = RTR0MemObjEnterPhys(&g_hMemPage0, 0, PAGE_SIZE, RTMEM_CACHE_POLICY_DONT_CARE);
    AssertRCReturn(rc, rc);
    rc = RTR0MemObjMapKernel(&g_hMapPage0, g_hMemPage0, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
    AssertRCReturn(rc, rc);
    g_pbPage0 = (uint8_t *)RTR0MemObjAddress(g_hMapPage0);
    LogRel(("0040:0067 = %04x:%04x\n", RT_MAKE_U16(g_pbPage0[0x467+2],  g_pbPage0[0x467+3]),  RT_MAKE_U16(g_pbPage0[0x467+0],  g_pbPage0[0x467+1]) ));

    /*
     * Allocate some "low core" memory.  If that fails, just grab some memory.
     */
    //rc = RTR0MemObjAllocPhys(&g_hMemLowCore, PAGE_SIZE, _1M - 1);
    //__debugbreak();
    rc = RTR0MemObjEnterPhys(&g_hMemLowCore, 0x7000, PAGE_SIZE, RTMEM_CACHE_POLICY_DONT_CARE);
    AssertRCReturn(rc, rc);
    rc = RTR0MemObjMapKernel(&g_hMapLowCore, g_hMemLowCore, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
    AssertRCReturn(rc, rc);
    g_pbLowCore = (uint8_t *)RTR0MemObjAddress(g_hMapLowCore);
    g_HCPhysLowCore = RTR0MemObjGetPagePhysAddr(g_hMapLowCore, 0);
    LogRel(("Low core at %RHp mapped at %p\n", g_HCPhysLowCore, g_pbLowCore));

    /*
     * Save memory we'll be overwriting.
     */
    g_pvSavedLowCore = RTMemAlloc(PAGE_SIZE);
    AssertReturn(g_pvSavedLowCore, VERR_NO_MEMORY);
    memcpy(g_pvSavedLowCore, g_pbLowCore, PAGE_SIZE);

    g_u32SavedVector = RT_MAKE_U32_FROM_U8(g_pbPage0[0x467], g_pbPage0[0x467+1], g_pbPage0[0x467+2], g_pbPage0[0x467+3]);
    g_u16SavedCadIndicator = RT_MAKE_U16(g_pbPage0[0x472], g_pbPage0[0x472+1]);

    /*
     * Install the code.
     */
    size_t cbCode = (uintptr_t)&vmmR0TripleFaultHackEnd - (uintptr_t)&vmmR0TripleFaultHackStart;
    AssertLogRelReturn(cbCode <= PAGE_SIZE, VERR_OUT_OF_RANGE);
    memcpy(g_pbLowCore, &vmmR0TripleFaultHackStart, cbCode);

    g_pbPage0[0x467+0] = 0x00;
    g_pbPage0[0x467+1] = 0x70;
    g_pbPage0[0x467+2] = 0x00;
    g_pbPage0[0x467+3] = 0x00;

    g_pbPage0[0x472+0] = 0x34;
    g_pbPage0[0x472+1] = 0x12;

    /*
     * Configure the status port and cmos shutdown command.
     */
    uint32_t fSaved = ASMIntDisableFlags();

    ASMOutU8(0x70, 0x0f);
    ASMOutU8(0x71, 0x0a);

    ASMOutU8(0x70, 0x05);
    ASMInU8(0x71);

    ASMReloadCR3();
    ASMWriteBackAndInvalidateCaches();

    ASMSetFlags(fSaved);

#if 1 /* For testing & debugging. */
    vmmR0TripleFaultHackTripleFault();
#endif

    return VINF_SUCCESS;
}
static void supR3HardenedDirectSyscall(PSUPHNTIMPDLL pDll, PCSUPHNTIMPFUNC pImport, PCSUPHNTIMPSYSCALL pSyscall,
                                       PSUPHNTLDRCACHEENTRY pLdrEntry, uint8_t *pbBits, bool fReportErrors)
{
    /*
     * Skip non-syscall entries.
     */
    if (!pSyscall->puApiNo)
        return;

    /*
     * Locate the virgin bits.
     */
    RTLDRADDR uValue;
    int rc = RTLdrGetSymbolEx(pLdrEntry->hLdrMod, pbBits, (uintptr_t)pDll->pbImageBase, UINT32_MAX, pImport->pszName, &uValue);
    if (RT_FAILURE(rc))
    {
        SUPHNTIMP_ERROR(fReportErrors, 16, "supR3HardenedDirectSyscall", kSupInitOp_Misc, rc,
                        "%s: RTLdrGetSymbolEx failed on %s: %Rrc", pDll->pszName, pImport->pszName, rc);
        return;
    }
    uintptr_t offSymbol = (uintptr_t)uValue - (uintptr_t)pDll->pbImageBase;
    uint8_t const *pbFunction = &pbBits[offSymbol];

    /*
     * Parse the code and extract the API call number.
     */
#ifdef RT_ARCH_AMD64
    /* Pattern #1: XP64/W2K3-64 thru Windows 8.1
       0:000> u ntdll!NtCreateSection
       ntdll!NtCreateSection:
       00000000`779f1750 4c8bd1          mov     r10,rcx
       00000000`779f1753 b847000000      mov     eax,47h
       00000000`779f1758 0f05            syscall
       00000000`779f175a c3              ret
       00000000`779f175b 0f1f440000      nop     dword ptr [rax+rax] */
    if (   pbFunction[ 0] == 0x4c /* mov r10, rcx */
        && pbFunction[ 1] == 0x8b
        && pbFunction[ 2] == 0xd1
        && pbFunction[ 3] == 0xb8 /* mov eax, 0000yyzzh */
        //&& pbFunction[ 4] == 0xZZ
        //&& pbFunction[ 5] == 0xYY
        && pbFunction[ 6] == 0x00
        && pbFunction[ 7] == 0x00
        && pbFunction[ 8] == 0x0f /* syscall */
        && pbFunction[ 9] == 0x05
        && pbFunction[10] == 0xc3 /* ret */ )
    {
        *pSyscall->puApiNo = RT_MAKE_U16(pbFunction[4], pbFunction[5]);
        *pImport->ppfnImport = pSyscall->pfnType1;
        return;
    }
#else
    /* Pattern #1: XP thru Windows 7
            kd> u ntdll!NtCreateSection
            ntdll!NtCreateSection:
            7c90d160 b832000000      mov     eax,32h
            7c90d165 ba0003fe7f      mov     edx,offset SharedUserData!SystemCallStub (7ffe0300)
            7c90d16a ff12            call    dword ptr [edx]
            7c90d16c c21c00          ret     1Ch
            7c90d16f 90              nop
       The variable bit is the value loaded into eax: XP=32h, W2K3=34h, Vista=4bh, W7=54h

       Pattern #2: Windows 8.1
            0:000:x86> u ntdll_6a0f0000!NtCreateSection
            ntdll_6a0f0000!NtCreateSection:
            6a15eabc b854010000      mov     eax,154h
            6a15eac1 e803000000      call    ntdll_6a0f0000!NtCreateSection+0xd (6a15eac9)
            6a15eac6 c21c00          ret     1Ch
            6a15eac9 8bd4            mov     edx,esp
            6a15eacb 0f34            sysenter
            6a15eacd c3              ret
       The variable bit is the value loaded into eax: W81=154h
       Note! One nice thing here is that we can share code pattern #1.  */

    if (   pbFunction[ 0] == 0xb8 /* mov eax, 0000yyzzh*/
        //&& pbFunction[ 1] <= 0xZZ
        //&& pbFunction[ 2] <= 0xYY
        && pbFunction[ 3] == 0x00
        && pbFunction[ 4] == 0x00)
    {
        *pSyscall->puApiNo = RT_MAKE_U16(pbFunction[1], pbFunction[2]);
        if (   pbFunction[5] == 0xba /* mov edx, offset SharedUserData!SystemCallStub */
            && pbFunction[ 6] == 0x00
            && pbFunction[ 7] == 0x03
            && pbFunction[ 8] == 0xfe
            && pbFunction[ 9] == 0x7f
            && pbFunction[10] == 0xff /* call [edx] */
            && pbFunction[11] == 0x12
            && (   (   pbFunction[12] == 0xc2 /* ret 1ch */
                    && pbFunction[13] == pSyscall->cbParams
                    && pbFunction[14] == 0x00)
                || (   pbFunction[12] == 0xc3 /* ret */
                    && pSyscall->cbParams == 0)
                )
           )
        {
            *pImport->ppfnImport = pSyscall->pfnType1;
            return;
        }

        if (   pbFunction[ 5] == 0xe8 /* call [$+3] */
            && RT_ABS(*(int32_t *)&pbFunction[6]) < 0x10
            && (   (   pbFunction[10] == 0xc2 /* ret 1ch */
                    && pbFunction[11] == pSyscall->cbParams
                    && pbFunction[12] == 0x00)
                || (   pbFunction[10] == 0xc3 /* ret */
                    && pSyscall->cbParams == 0)
               )
           )
        {
            *pImport->ppfnImport = pSyscall->pfnType2;
            return;
        }
    }
#endif

    /*
     * Failed to parse it.
     */
    volatile uint8_t abCopy[16];
    memcpy((void *)&abCopy[0], pbFunction, sizeof(abCopy));
    SUPHNTIMP_ERROR(fReportErrors, 17, "supR3HardenedWinInitImports", kSupInitOp_Misc, rc,
                    "%ls: supHardNtLdrCacheOpen failed: '%s': %.16Rhxs",
                    pDll->pwszName, pImport->pszName, &abCopy[0]);
}
RTDECL(int) RTZipGzipDecompressIoStream(RTVFSIOSTREAM hVfsIosIn, uint32_t fFlags, PRTVFSIOSTREAM phVfsIosOut)
{
    AssertPtrReturn(hVfsIosIn, VERR_INVALID_HANDLE);
    AssertReturn(!(fFlags & ~RTZIPGZIPDECOMP_F_ALLOW_ZLIB_HDR), VERR_INVALID_PARAMETER);
    AssertPtrReturn(phVfsIosOut, VERR_INVALID_POINTER);

    uint32_t cRefs = RTVfsIoStrmRetain(hVfsIosIn);
    AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);

    /*
     * Create the decompression I/O stream.
     */
    RTVFSIOSTREAM    hVfsIos;
    PRTZIPGZIPSTREAM pThis;
    int rc = RTVfsNewIoStream(&g_rtZipGzipOps, sizeof(RTZIPGZIPSTREAM), RTFILE_O_READ, NIL_RTVFS, NIL_RTVFSLOCK,
                              &hVfsIos, (void **)&pThis);
    if (RT_SUCCESS(rc))
    {
        pThis->hVfsIos      = hVfsIosIn;
        pThis->offStream    = 0;
        pThis->fDecompress  = true;
        pThis->SgSeg.pvSeg  = &pThis->abBuffer[0];
        pThis->SgSeg.cbSeg  = sizeof(pThis->abBuffer);
        RTSgBufInit(&pThis->SgBuf, &pThis->SgSeg, 1);

        memset(&pThis->Zlib, 0, sizeof(pThis->Zlib));
        pThis->Zlib.opaque  = pThis;
        rc = inflateInit2(&pThis->Zlib, MAX_WBITS | RT_BIT(5) /* autodetect gzip header */);
        if (rc >= 0)
        {
            /*
             * Read the gzip header from the input stream to check that it's
             * a gzip stream as specified by the user.
             *
             * Note! Since we've told zlib to check for the gzip header, we
             *       prebuffer what we read in the input buffer so it can
             *       be handed on to zlib later on.
             */
            rc = RTVfsIoStrmRead(pThis->hVfsIos, pThis->abBuffer, sizeof(RTZIPGZIPHDR), true /*fBlocking*/, NULL /*pcbRead*/);
            if (RT_SUCCESS(rc))
            {
                /* Validate the header and make a copy of it. */
                PCRTZIPGZIPHDR pHdr = (PCRTZIPGZIPHDR)pThis->abBuffer;
                if (   pHdr->bId1 == RTZIPGZIPHDR_ID1
                    && pHdr->bId2 == RTZIPGZIPHDR_ID2
                    && !(pHdr->fFlags & ~RTZIPGZIPHDR_FLG_VALID_MASK))
                {
                    if (pHdr->bCompressionMethod == RTZIPGZIPHDR_CM_DEFLATE)
                        rc = VINF_SUCCESS;
                    else
                        rc = VERR_ZIP_UNSUPPORTED_METHOD;
                }
                else if (   (fFlags & RTZIPGZIPDECOMP_F_ALLOW_ZLIB_HDR)
                         && (RT_MAKE_U16(pHdr->bId2, pHdr->bId1) % 31) == 0
                         && (pHdr->bId1 & 0xf) == RTZIPGZIPHDR_CM_DEFLATE )
                {
                    pHdr = NULL;
                    rc = VINF_SUCCESS;
                }
                else
                    rc = VERR_ZIP_BAD_HEADER;
                if (RT_SUCCESS(rc))
                {
                    pThis->Zlib.avail_in = sizeof(RTZIPGZIPHDR);
                    pThis->Zlib.next_in  = &pThis->abBuffer[0];
                    if (pHdr)
                    {
                        pThis->Hdr = *pHdr;
                        /* Parse on if there are names or comments. */
                        if (pHdr->fFlags & (RTZIPGZIPHDR_FLG_NAME | RTZIPGZIPHDR_FLG_COMMENT))
                        {
                            /** @todo Can implement this when someone needs the
                             *        name or comment for something useful. */
                        }
                    }
                    if (RT_SUCCESS(rc))
                    {
                        *phVfsIosOut = hVfsIos;
                        return VINF_SUCCESS;
                    }
                }
            }
        }
        else
            rc = rtZipGzipConvertErrFromZlib(pThis, rc); /** @todo cleaning up in this situation is going to go wrong. */
        RTVfsIoStrmRelease(hVfsIos);
    }
    else
        RTVfsIoStrmRelease(hVfsIosIn);
    return rc;
}