Esempio n. 1
0
/**
 * Check if this page needs to be analysed by CSAM.
 *
 * This function should only be called for supervisor pages and
 * only when CSAM is enabled. Leaving these selection criteria
 * to the caller simplifies the interface (PTE passing).
 *
 * Note that the page has not yet been synced, so the TLB trick
 * (which wasn't ever active anyway) cannot be applied.
 *
 * @returns true if the page should be marked not present because
 *          CSAM want need to scan it.
 * @returns false if the page was already scanned.
 * @param   pVM         Pointer to the VM.
 * @param   GCPtr       GC pointer of page
 */
VMM_INT_DECL(bool) CSAMDoesPageNeedScanning(PVM pVM, RTRCUINTPTR GCPtr)
{
    if(!CSAMIsEnabled(pVM))
        return false;

    if(CSAMIsPageScanned(pVM, (RTRCPTR)GCPtr))
    {
        /* Already checked! */
        STAM_COUNTER_ADD(&CTXSUFF(pVM->csam.s.StatNrKnownPages), 1);
        return false;
    }
    STAM_COUNTER_ADD(&CTXSUFF(pVM->csam.s.StatNrPageNP), 1);
    return true;
}
Esempio n. 2
0
/**
 * Check if this page needs to be analysed by CSAM
 *
 * @returns VBox status code
 * @param   pVM         Pointer to the VM.
 * @param   pvFault     Fault address
 */
VMM_INT_DECL(int) CSAMExecFault(PVM pVM, RTRCPTR pvFault)
{
    if(!CSAMIsEnabled(pVM))
        return VINF_SUCCESS;

    LogFlow(("CSAMGCExecFault: for page %08X scanned=%d\n", pvFault, CSAMIsPageScanned(pVM, pvFault)));

    if(CSAMIsPageScanned(pVM, pvFault))
    {
        // Already checked!
        STAM_COUNTER_ADD(&pVM->csam.s.StatNrKnownPagesGC, 1);
        return VINF_SUCCESS;
    }

    STAM_COUNTER_ADD(&pVM->csam.s.StatNrTraps, 1);
    VMCPU_FF_SET(VMMGetCpu0(pVM), VMCPU_FF_CSAM_SCAN_PAGE);
    return VINF_CSAM_PENDING_ACTION;
}
/**
 * Receive thread loop.
 *
 * @returns 0 on success.
 * @param   ThreadSelf  Thread handle to this thread.
 * @param   pvUser      User argument.
 */
static DECLCALLBACK(int) drvCharReceiveLoop(RTTHREAD ThreadSelf, void *pvUser)
{
    PDRVCHAR    pThis = (PDRVCHAR)pvUser;
    char        abBuffer[256];
    char       *pbRemaining = abBuffer;
    size_t      cbRemaining = 0;
    int         rc;

    while (!pThis->fShutdown)
    {
        if (!cbRemaining)
        {
            /* Get block of data from stream driver. */
            if (pThis->pDrvStream)
            {
                pbRemaining = abBuffer;
                cbRemaining = sizeof(abBuffer);
                rc = pThis->pDrvStream->pfnRead(pThis->pDrvStream, abBuffer, &cbRemaining);
                if (RT_FAILURE(rc))
                {
                    LogFlow(("Read failed with %Rrc\n", rc));
                    break;
                }
            }
            else
                RTThreadSleep(100);
        }
        else
        {
            /* Send data to guest. */
            size_t cbProcessed = cbRemaining;
            rc = pThis->pDrvCharPort->pfnNotifyRead(pThis->pDrvCharPort, pbRemaining, &cbProcessed);
            if (RT_SUCCESS(rc))
            {
                Assert(cbProcessed);
                pbRemaining += cbProcessed;
                cbRemaining -= cbProcessed;
                STAM_COUNTER_ADD(&pThis->StatBytesRead, cbProcessed);
            }
            else if (rc == VERR_TIMEOUT)
            {
                /* Normal case, just means that the guest didn't accept a new
                 * character before the timeout elapsed. Just retry. */
                rc = VINF_SUCCESS;
            }
            else
            {
                LogFlow(("NotifyRead failed with %Rrc\n", rc));
                break;
            }
        }
    }

    return VINF_SUCCESS;
}
/*
 * Read from so's socket into sb_snd, updating all relevant sbuf fields
 * NOTE: This will only be called if it is select()ed for reading, so
 * a read() of 0 (or less) means it's disconnected
 */
int
soread(PNATState pData, struct socket *so)
{
    int n, nn, lss, total;
    struct sbuf *sb = &so->so_snd;
    u_int len = sb->sb_datalen - sb->sb_cc;
    struct iovec iov[2];
    int mss = so->so_tcpcb->t_maxseg;
    int sockerr;

    STAM_PROFILE_START(&pData->StatIOread, a);
    STAM_COUNTER_RESET(&pData->StatIORead_in_1);
    STAM_COUNTER_RESET(&pData->StatIORead_in_2);

    QSOCKET_LOCK(tcb);
    SOCKET_LOCK(so);
    QSOCKET_UNLOCK(tcb);

    LogFlow(("soread: so = %R[natsock]\n", so));
    Log2(("%s: so = %R[natsock] so->so_snd = %R[sbuf]\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__, so, sb));

    /*
     * No need to check if there's enough room to read.
     * soread wouldn't have been called if there weren't
     */

    len = sb->sb_datalen - sb->sb_cc;

    iov[0].iov_base = sb->sb_wptr;
    iov[1].iov_base = 0;
    iov[1].iov_len  = 0;
    if (sb->sb_wptr < sb->sb_rptr)
    {
        iov[0].iov_len = sb->sb_rptr - sb->sb_wptr;
        /* Should never succeed, but... */
        if (iov[0].iov_len > len)
            iov[0].iov_len = len;
        if (iov[0].iov_len > mss)
            iov[0].iov_len -= iov[0].iov_len%mss;
        n = 1;
    }
    else
    {
        iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr;
        /* Should never succeed, but... */
        if (iov[0].iov_len > len)
            iov[0].iov_len = len;
        len -= iov[0].iov_len;
        if (len)
        {
            iov[1].iov_base = sb->sb_data;
            iov[1].iov_len = sb->sb_rptr - sb->sb_data;
            if (iov[1].iov_len > len)
                iov[1].iov_len = len;
            total = iov[0].iov_len + iov[1].iov_len;
            if (total > mss)
            {
                lss = total % mss;
                if (iov[1].iov_len > lss)
                {
                    iov[1].iov_len -= lss;
                    n = 2;
                }
                else
                {
                    lss -= iov[1].iov_len;
                    iov[0].iov_len -= lss;
                    n = 1;
                }
            }
            else
                n = 2;
        }
        else
        {
            if (iov[0].iov_len > mss)
                iov[0].iov_len -= iov[0].iov_len%mss;
            n = 1;
        }
    }

#ifdef HAVE_READV
    nn = readv(so->s, (struct iovec *)iov, n);
#else
    nn = recv(so->s, iov[0].iov_base, iov[0].iov_len, (so->so_tcpcb->t_force? MSG_OOB:0));
#endif
    if (nn < 0)
        sockerr = errno; /* save it, as it may be clobbered by logging */
    else
        sockerr = 0;

    Log2(("%s: read(1) nn = %d bytes\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__, nn));
    Log2(("%s: so = %R[natsock] so->so_snd = %R[sbuf]\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__, so, sb));
    if (nn <= 0)
    {
#ifdef RT_OS_WINDOWS
        /*
         * Windows reports ESHUTDOWN after SHUT_RD (SD_RECEIVE)
         * instead of just returning EOF indication.
         */
        if (nn < 0 && sockerr == ESHUTDOWN)
        {
            nn = 0;
            sockerr = 0;
        }
#endif

        if (nn == 0) /* XXX: should this be inside #if defined(RT_OS_WINDOWS)? */
        {
            /*
             * Special case for WSAEnumNetworkEvents: If we receive 0 bytes that
             * _could_ mean that the connection is closed. But we will receive an
             * FD_CLOSE event later if the connection was _really_ closed. With
             * www.youtube.com I see this very often. Closing the socket too early
             * would be dangerous.
             */
            int status;
            unsigned long pending = 0;
            status = ioctlsocket(so->s, FIONREAD, &pending);
            if (status < 0)
                Log(("NAT:%s: error in WSAIoctl: %d\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__, errno));
            if (pending != 0)
            {
                SOCKET_UNLOCK(so);
                STAM_PROFILE_STOP(&pData->StatIOread, a);
                return 0;
            }
        }

        if (   nn < 0
            && soIgnorableErrorCode(sockerr))
        {
            SOCKET_UNLOCK(so);
            STAM_PROFILE_STOP(&pData->StatIOread, a);
            return 0;
        }
        else
        {
            int fUninitializedTemplate = 0;
            int shuterr;

            fUninitializedTemplate = RT_BOOL((   sototcpcb(so)
                                              && (  sototcpcb(so)->t_template.ti_src.s_addr == INADDR_ANY
                                                 || sototcpcb(so)->t_template.ti_dst.s_addr == INADDR_ANY)));
            /* nn == 0 means peer has performed an orderly shutdown */
            Log2(("%s: disconnected, nn = %d, errno = %d (%s)\n",
                  RT_GCC_EXTENSION __PRETTY_FUNCTION__, nn, sockerr, strerror(sockerr)));

            shuterr = sofcantrcvmore(so);
            if (!sockerr && !shuterr && !fUninitializedTemplate)
                tcp_sockclosed(pData, sototcpcb(so));
            else
            {
                LogRel2(("NAT: sockerr %d, shuterr %d - %R[natsock]\n", sockerr, shuterr, so));
                tcp_drop(pData, sototcpcb(so), sockerr);
            }
            SOCKET_UNLOCK(so);
            STAM_PROFILE_STOP(&pData->StatIOread, a);
            return -1;
        }
    }
    STAM_STATS(
        if (n == 1)
        {
            STAM_COUNTER_INC(&pData->StatIORead_in_1);
            STAM_COUNTER_ADD(&pData->StatIORead_in_1_bytes, nn);
        }
        else
        {
            STAM_COUNTER_INC(&pData->StatIORead_in_2);
            STAM_COUNTER_ADD(&pData->StatIORead_in_2_1st_bytes, nn);
        }
    );