VirtualBox

Changeset 2938 in kBuild


Ignore:
Timestamp:
Sep 19, 2016 4:50:47 PM (8 years ago)
Author:
bird
Message:

kWorker: TlsAlloc and FlsAlloc must only be intercepted for EXE images, otherwise we'll end up freeing in-use indexes when doing the late sandbox cleanup. Also seems we need to roll our own RtlUnwind for x86 for the same reason as we need to do our exception dispatching (our modules are not in the module table / inverse function table / whatever, and the handlers are considered invalid). RtlUnwind is used for error handling in cl.exe.

Location:
trunk/src/kWorker
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kWorker/Makefile.kmk

    r2934 r2938  
    4949kWorker_LDFLAGS.win = \
    5050        /BASE:0x10000 /DYNAMICBASE:NO /FIXED
     51#kWorker_LDFLAGS.win.x86 = \
     52#       /SAFESEH:NO - doesn't help anyone.
    5153
    5254
  • trunk/src/kWorker/kWorker.c

    r2936 r2938  
    8787#define WITH_LOG_FILE
    8888
     89/** @def WITH_HISTORY
     90 * Keep history of the last jobs.  For debugging.  */
     91#define WITH_HISTORY
     92
     93
    8994#ifndef NDEBUG
    9095# define KW_LOG_ENABLED
    9196#endif
    92 
    9397
    9498/** @def KW_LOG
     
    844848
    845849
     850#ifdef WITH_HISTORY
     851/** The job history. */
     852static char     *g_apszHistory[32];
     853/** Index of the next history entry. */
     854static unsigned  g_iHistoryNext = 0;
     855#endif
     856
     857
    846858/*********************************************************************************************************************************
    847859*   Internal Functions                                                                                                           *
     
    853865static void kwSandboxConsoleWriteA(PKWSANDBOX pSandbox, PKWOUTPUTSTREAMBUF pLineBuf, const char *pchBuffer, KU32 cchToWrite);
    854866#endif
     867
    855868
    856869
     
    42964309                        || kHlpStrICompAscii(g_aSandboxGetProcReplacements[i].pszModule, &pMod->pszPath[pMod->offFilename]) == 0)
    42974310                    {
    4298                         if (   pMod->fExe
    4299                             || !g_aSandboxGetProcReplacements[i].fOnlyExe)
     4311                        if (   !g_aSandboxGetProcReplacements[i].fOnlyExe
     4312                            || (KUPTR)_ReturnAddress() - (KUPTR)g_Sandbox.pTool->u.Sandboxed.pExe->hOurMod
     4313                               < g_Sandbox.pTool->u.Sandboxed.pExe->cbImage)
    43004314                        {
    43014315                            uValue = g_aSandboxGetProcReplacements[i].pfnReplacement;
     
    75557569/*
    75567570 *
     7571 * Structured exception handling.
     7572 * Structured exception handling.
     7573 * Structured exception handling.
     7574 *
     7575 */
     7576#if defined(KBUILD_OS_WINDOWS) && defined(KBUILD_ARCH_X86)
     7577
     7578# define EH_NONCONTINUABLE      KU32_C(0x00000001)
     7579# define EH_UNWINDING           KU32_C(0x00000002)
     7580# define EH_EXIT_UNWIND         KU32_C(0x00000004)
     7581# define EH_STACK_INVALID       KU32_C(0x00000008)
     7582# define EH_NESTED_CALL         KU32_C(0x00000010)
     7583
     7584typedef KU32 (__cdecl * volatile PFNXCPTHANDLER)(PEXCEPTION_RECORD, struct _EXCEPTION_REGISTRATION_RECORD*, PCONTEXT,
     7585                                                 struct _EXCEPTION_REGISTRATION_RECORD * volatile *);
     7586typedef struct _EXCEPTION_REGISTRATION_RECORD
     7587{
     7588    struct _EXCEPTION_REGISTRATION_RECORD * volatile    pPrevRegRec;
     7589    PFNXCPTHANDLER                                      pfnXcptHandler;
     7590};
     7591
     7592
     7593/**
     7594 * Calls @a pfnHandler.
     7595 */
     7596static KU32 kwSandboxXcptCallHandler(PEXCEPTION_RECORD pXcptRec, struct _EXCEPTION_REGISTRATION_RECORD *pRegRec,
     7597                                     PCONTEXT pXcptCtx, struct _EXCEPTION_REGISTRATION_RECORD * volatile * ppRegRec,
     7598                                     PFNXCPTHANDLER pfnHandler)
     7599{
     7600# if 1
     7601    /* This is a more robust version that isn't subject to calling
     7602       convension cleanup disputes and such. */
     7603    KU32 uSavedEdi;
     7604    KU32 uSavedEsi;
     7605    KU32 uSavedEbx;
     7606    KU32 rcHandler;
     7607
     7608    __asm
     7609    {
     7610        mov     [uSavedEdi], edi
     7611        mov     [uSavedEsi], esi
     7612        mov     [uSavedEbx], ebx
     7613        mov     esi, esp
     7614        mov     edi, esp
     7615        mov     edi, [pXcptRec]
     7616        mov     edx, [pRegRec]
     7617        mov     eax, [pXcptCtx]
     7618        mov     ebx, [ppRegRec]
     7619        mov     ecx, [pfnHandler]
     7620        sub     esp, 16
     7621        and     esp, 0fffffff0h
     7622        mov     [esp     ], edi
     7623        mov     [esp +  4], edx
     7624        mov     [esp +  8], eax
     7625        mov     [esp + 12], ebx
     7626        mov     edi, esi
     7627        call    ecx
     7628        mov     esp, esi
     7629        cmp     esp, edi
     7630        je      stack_ok
     7631        int     3
     7632    stack_ok:
     7633        mov     edi, [uSavedEdi]
     7634        mov     esi, [uSavedEsi]
     7635        mov     ebx, [uSavedEbx]
     7636        mov     [rcHandler], eax
     7637    }
     7638    return rcHandler;
     7639# else
     7640    return pfnHandler(pXcptRec, pRegRec, pXctpCtx, ppRegRec);
     7641# endif
     7642}
     7643
     7644
     7645/**
     7646 * Vectored exception handler that emulates x86 chained exception handler.
     7647 *
     7648 * This is necessary because the RtlIsValidHandler check fails for self loaded
     7649 * code and prevents cl.exe from working.  (On AMD64 we can register function
     7650 * tables, but on X86 cooking your own handling seems to be the only viabke
     7651 * alternative.)
     7652 *
     7653 * @returns EXCEPTION_CONTINUE_SEARCH or EXCEPTION_CONTINUE_EXECUTION.
     7654 * @param   pXcptPtrs           The exception details.
     7655 */
     7656static LONG CALLBACK kwSandboxVecXcptEmulateChained(PEXCEPTION_POINTERS pXcptPtrs)
     7657{
     7658    PNT_TIB pTib = (PNT_TIB)NtCurrentTeb();
     7659    KW_LOG(("kwSandboxVecXcptEmulateChained: %#x\n", pXcptPtrs->ExceptionRecord->ExceptionCode));
     7660    if (g_Sandbox.fRunning)
     7661    {
     7662        HANDLE const                                      hCurProc = GetCurrentProcess();
     7663        PEXCEPTION_RECORD                                 pXcptRec = pXcptPtrs->ExceptionRecord;
     7664        PCONTEXT                                          pXcptCtx = pXcptPtrs->ContextRecord;
     7665        struct _EXCEPTION_REGISTRATION_RECORD *           pRegRec  = pTib->ExceptionList;
     7666        while (((KUPTR)pRegRec & (sizeof(void *) - 3)) == 0 && pRegRec != NULL)
     7667        {
     7668            /* Read the exception record in a safe manner. */
     7669            struct _EXCEPTION_REGISTRATION_RECORD   RegRec;
     7670            DWORD                                   cbActuallyRead = 0;
     7671            if (   ReadProcessMemory(hCurProc, pRegRec, &RegRec, sizeof(RegRec), &cbActuallyRead)
     7672                && cbActuallyRead == sizeof(RegRec))
     7673            {
     7674                struct _EXCEPTION_REGISTRATION_RECORD * volatile    pDispRegRec = NULL;
     7675                KU32                                                rcHandler;
     7676                KW_LOG(("kwSandboxVecXcptEmulateChained: calling %p, pRegRec=%p, pPrevRegRec=%p\n",
     7677                        RegRec.pfnXcptHandler, pRegRec, RegRec.pPrevRegRec));
     7678                rcHandler = kwSandboxXcptCallHandler(pXcptRec, pRegRec, pXcptCtx, &pDispRegRec, RegRec.pfnXcptHandler);
     7679                KW_LOG(("kwSandboxVecXcptEmulateChained: rcHandler=%#x pDispRegRec=%p\n", rcHandler, pDispRegRec));
     7680                if (rcHandler == ExceptionContinueExecution)
     7681                {
     7682                    kHlpAssert(!(pXcptPtrs->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE));
     7683                    KW_LOG(("kwSandboxVecXcptEmulateChained: returning EXCEPTION_CONTINUE_EXECUTION!\n"));
     7684                    return EXCEPTION_CONTINUE_EXECUTION;
     7685                }
     7686
     7687                if (rcHandler == ExceptionContinueSearch)
     7688                    kHlpAssert(!(pXcptPtrs->ExceptionRecord->ExceptionFlags & 8 /*EXCEPTION_STACK_INVALID*/));
     7689                else if (rcHandler == ExceptionNestedException)
     7690                    kHlpAssertMsgFailed(("Nested exceptions.\n"));
     7691                else
     7692                    kHlpAssertMsgFailed(("Invalid return %#x (%d).\n", rcHandler, rcHandler));
     7693            }
     7694            else
     7695            {
     7696                KW_LOG(("kwSandboxVecXcptEmulateChained: Bad xcpt chain entry at %p! Stopping search.\n", pRegRec));
     7697                break;
     7698            }
     7699
     7700            /*
     7701             * Next.
     7702             */
     7703            pRegRec = RegRec.pPrevRegRec;
     7704        }
     7705    }
     7706    return EXCEPTION_CONTINUE_SEARCH;
     7707}
     7708
     7709
     7710/** NtDll,Kernel32 - RtlUnwind */
     7711static VOID WINAPI kwSandbox_ntdll_RtlUnwind(struct _EXCEPTION_REGISTRATION_RECORD *pStopXcptRec, PVOID pvTargetIp,
     7712                                             PEXCEPTION_RECORD pXcptRec, PVOID pvReturnValue)
     7713{
     7714    PNT_TIB pTib = (PNT_TIB)NtCurrentTeb();
     7715    KW_LOG(("kwSandbox_ntdll_RtlUnwind: pStopXcptRec=%p pvTargetIp=%p pXctpRec=%p pvReturnValue=%p%s\n",
     7716            pStopXcptRec, pvTargetIp, pXcptRec, pvReturnValue, g_Sandbox.fRunning ? "" : " [sandbox not running]"));
     7717    if (g_Sandbox.fRunning)
     7718    {
     7719        HANDLE const                                      hCurProc = GetCurrentProcess();
     7720        PCONTEXT                                          pXcptCtx = NULL;
     7721        struct _EXCEPTION_REGISTRATION_RECORD *           pRegRec  = pTib->ExceptionList;
     7722
     7723        /*
     7724         * Update / create an exception record.
     7725         */
     7726        if (pXcptRec)
     7727            pXcptRec->ExceptionFlags |= EH_UNWINDING;
     7728        else
     7729        {
     7730            pXcptRec = (PEXCEPTION_RECORD)alloca(sizeof(*pXcptRec));
     7731            kHlpMemSet(pXcptRec, 0, sizeof(*pXcptRec));
     7732            pXcptRec->ExceptionCode  = STATUS_UNWIND;
     7733            pXcptRec->ExceptionFlags = EH_UNWINDING;
     7734        }
     7735        if (!pStopXcptRec)
     7736            pXcptRec->ExceptionFlags |= EH_EXIT_UNWIND;
     7737
     7738        /*
     7739         * Walk the chain till we find pStopXctpRec.
     7740         */
     7741        while (   ((KUPTR)pRegRec & (sizeof(void *) - 3)) == 0
     7742               && pRegRec != NULL
     7743               && pRegRec != pStopXcptRec)
     7744        {
     7745            /* Read the exception record in a safe manner. */
     7746            struct _EXCEPTION_REGISTRATION_RECORD   RegRec;
     7747            DWORD                                   cbActuallyRead = 0;
     7748            if (   ReadProcessMemory(hCurProc, pRegRec, &RegRec, sizeof(RegRec), &cbActuallyRead)
     7749                && cbActuallyRead == sizeof(RegRec))
     7750            {
     7751                struct _EXCEPTION_REGISTRATION_RECORD * volatile    pDispRegRec = NULL;
     7752                KU32                                                rcHandler;
     7753                KW_LOG(("kwSandbox_ntdll_RtlUnwind: calling %p, pRegRec=%p, pPrevRegRec=%p\n",
     7754                        RegRec.pfnXcptHandler, pRegRec, RegRec.pPrevRegRec));
     7755                rcHandler = kwSandboxXcptCallHandler(pXcptRec, pRegRec, pXcptCtx, &pDispRegRec, RegRec.pfnXcptHandler);
     7756                KW_LOG(("kwSandbox_ntdll_RtlUnwind: rcHandler=%#x pDispRegRec=%p\n", rcHandler, pDispRegRec));
     7757
     7758                if (rcHandler == ExceptionContinueSearch)
     7759                    kHlpAssert(!(pXcptRec->ExceptionFlags & 8 /*EXCEPTION_STACK_INVALID*/));
     7760                else if (rcHandler == ExceptionCollidedUnwind)
     7761                    kHlpAssertMsgFailed(("Implement collided unwind!\n"));
     7762                else
     7763                    kHlpAssertMsgFailed(("Invalid return %#x (%d).\n", rcHandler, rcHandler));
     7764            }
     7765            else
     7766            {
     7767                KW_LOG(("kwSandbox_ntdll_RtlUnwind: Bad xcpt chain entry at %p! Stopping search.\n", pRegRec));
     7768                break;
     7769            }
     7770
     7771            /*
     7772             * Pop next.
     7773             */
     7774            pTib->ExceptionList = RegRec.pPrevRegRec;
     7775            pRegRec = RegRec.pPrevRegRec;
     7776        }
     7777        return;
     7778    }
     7779
     7780    RtlUnwind(pStopXcptRec, pvTargetIp, pXcptRec, pvReturnValue);
     7781}
     7782
     7783#endif /* WINDOWS + X86 */
     7784
     7785
     7786/*
     7787 *
    75577788 * Misc function only intercepted while debugging.
    75587789 * Misc function only intercepted while debugging.
     
    76557886    { TUPLE("HeapDestroy"),                 NULL,       (KUPTR)kwSandbox_Kernel32_HeapDestroy,      K_TRUE /*fOnlyExe*/ },
    76567887
    7657     { TUPLE("FlsAlloc"),                    NULL,       (KUPTR)kwSandbox_Kernel32_FlsAlloc },
    7658     { TUPLE("FlsFree"),                     NULL,       (KUPTR)kwSandbox_Kernel32_FlsFree },
    7659     { TUPLE("TlsAlloc"),                    NULL,       (KUPTR)kwSandbox_Kernel32_TlsAlloc },
    7660     { TUPLE("TlsFree"),                     NULL,       (KUPTR)kwSandbox_Kernel32_TlsFree },
     7888    { TUPLE("FlsAlloc"),                    NULL,       (KUPTR)kwSandbox_Kernel32_FlsAlloc,         K_TRUE /*fOnlyExe*/ },
     7889    { TUPLE("FlsFree"),                     NULL,       (KUPTR)kwSandbox_Kernel32_FlsFree,          K_TRUE /*fOnlyExe*/ },
     7890    { TUPLE("TlsAlloc"),                    NULL,       (KUPTR)kwSandbox_Kernel32_TlsAlloc,         K_TRUE /*fOnlyExe*/ },
     7891    { TUPLE("TlsFree"),                     NULL,       (KUPTR)kwSandbox_Kernel32_TlsFree,          K_TRUE /*fOnlyExe*/ },
    76617892
    76627893    { TUPLE("SetConsoleCtrlHandler"),       NULL,       (KUPTR)kwSandbox_Kernel32_SetConsoleCtrlHandler },
     7894
     7895#if defined(KBUILD_OS_WINDOWS) && defined(KBUILD_ARCH_X86)
     7896    { TUPLE("RtlUnwind"),                   NULL,       (KUPTR)kwSandbox_ntdll_RtlUnwind },
     7897#endif
     7898
    76637899
    76647900#ifdef WITH_HASH_MD5_CACHE
     
    77858021    { TUPLE("RtlPcToFileHeader"),           NULL,       (KUPTR)kwSandbox_ntdll_RtlPcToFileHeader },
    77868022
     8023#if defined(KBUILD_OS_WINDOWS) && defined(KBUILD_ARCH_X86)
     8024    { TUPLE("RtlUnwind"),                   NULL,       (KUPTR)kwSandbox_ntdll_RtlUnwind },
     8025#endif
    77878026
    77888027    /*
     
    78138052     * Kernel32.dll and friends.
    78148053     */
    7815     { TUPLE("FlsAlloc"),                    NULL,       (KUPTR)kwSandbox_Kernel32_FlsAlloc },
    7816     { TUPLE("FlsFree"),                     NULL,       (KUPTR)kwSandbox_Kernel32_FlsFree },
    7817     { TUPLE("TlsAlloc"),                    NULL,       (KUPTR)kwSandbox_Kernel32_TlsAlloc },
    7818     { TUPLE("TlsFree"),                     NULL,       (KUPTR)kwSandbox_Kernel32_TlsFree },
     8054    { TUPLE("FlsAlloc"),                    NULL,       (KUPTR)kwSandbox_Kernel32_FlsAlloc, K_TRUE /*fOnlyExe*/ },
     8055    { TUPLE("FlsFree"),                     NULL,       (KUPTR)kwSandbox_Kernel32_FlsFree,  K_TRUE /*fOnlyExe*/ },
     8056    { TUPLE("TlsAlloc"),                    NULL,       (KUPTR)kwSandbox_Kernel32_TlsAlloc, K_TRUE /*fOnlyExe*/ },
     8057    { TUPLE("TlsFree"),                     NULL,       (KUPTR)kwSandbox_Kernel32_TlsFree,  K_TRUE /*fOnlyExe*/ },
    78198058};
    78208059/** Number of entries in g_aSandboxGetProcReplacements. */
     
    78958134#endif
    78968135}
    7897 
    7898 
    7899 #if defined(KBUILD_OS_WINDOWS) && defined(KBUILD_ARCH_X86)
    7900 typedef struct _EXCEPTION_REGISTRATION_RECORD
    7901 {
    7902     struct _EXCEPTION_REGISTRATION_RECORD * volatile PrevStructure;
    7903     KU32 (__cdecl * volatile ExceptionHandler)(PEXCEPTION_RECORD, struct _EXCEPTION_REGISTRATION_RECORD*, PCONTEXT,
    7904                                                struct _EXCEPTION_REGISTRATION_RECORD * volatile *);
    7905 };
    7906 
    7907 /**
    7908  * Vectored exception handler that emulates x86 chained exception handler.
    7909  *
    7910  * This is necessary because the RtlIsValidHandler check fails for self loaded
    7911  * code and prevents cl.exe from working.  (On AMD64 we can register function
    7912  * tables, but on X86 cooking your own handling seems to be the only viabke
    7913  * alternative.)
    7914  *
    7915  * @returns EXCEPTION_CONTINUE_SEARCH or EXCEPTION_CONTINUE_EXECUTION.
    7916  * @param   pXcptPtrs           The exception details.
    7917  */
    7918 static LONG CALLBACK kwSandboxVecXcptEmulateChained(PEXCEPTION_POINTERS pXcptPtrs)
    7919 {
    7920     PNT_TIB pTib = (PNT_TIB)NtCurrentTeb();
    7921     KW_LOG(("kwSandboxVecXcptEmulateChained: %#x\n", pXcptPtrs->ExceptionRecord->ExceptionCode));
    7922     if (g_Sandbox.fRunning)
    7923     {
    7924         PEXCEPTION_RECORD                                 pXcptRec = pXcptPtrs->ExceptionRecord;
    7925         PCONTEXT                                          pXcptCtx = pXcptPtrs->ContextRecord;
    7926         struct _EXCEPTION_REGISTRATION_RECORD * volatile *ppRegRec = &pTib->ExceptionList;
    7927         struct _EXCEPTION_REGISTRATION_RECORD *           pRegRec  = *ppRegRec;
    7928         while (((KUPTR)pRegRec & (sizeof(void *) - 3)) == 0 && pRegRec != NULL)
    7929         {
    7930 #if 1
    7931             /* This is a more robust version that isn't subject to calling
    7932                convension cleanup disputes and such. */
    7933             KU32 uSavedEdi;
    7934             KU32 uSavedEsi;
    7935             KU32 uSavedEbx;
    7936             KU32 rcHandler;
    7937             __asm
    7938             {
    7939                 mov     [uSavedEdi], edi
    7940                 mov     [uSavedEsi], esi
    7941                 mov     [uSavedEbx], ebx
    7942                 mov     esi, esp
    7943                 mov     edi, esp
    7944                 mov     ecx, [pXcptRec]
    7945                 mov     edx, [pRegRec]
    7946                 mov     eax, [pXcptCtx]
    7947                 mov     ebx, [ppRegRec]
    7948                 sub     esp, 16
    7949                 and     esp, 0fffffff0h
    7950                 mov     [esp     ], ecx
    7951                 mov     [esp +  4], edx
    7952                 mov     [esp +  8], eax
    7953                 mov     [esp + 12], ebx
    7954                 call    dword ptr [edx + 4]
    7955                 mov     esp, esi
    7956                 cmp     esp, edi
    7957                 je      stack_ok
    7958                 int     3
    7959             stack_ok:
    7960                 mov     edi, [uSavedEdi]
    7961                 mov     esi, [uSavedEsi]
    7962                 mov     ebx, [uSavedEbx]
    7963                 mov     [rcHandler], eax
    7964             }
    7965 #else
    7966             KU32 rcHandler = pRegRec->ExceptionHandler(pXcptPtrs->ExceptionRecord, pRegRec, pXcptPtrs->ContextRecord, ppRegRec);
    7967 #endif
    7968             if (rcHandler == ExceptionContinueExecution)
    7969             {
    7970                 kHlpAssert(!(pXcptPtrs->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE));
    7971                 return EXCEPTION_CONTINUE_EXECUTION;
    7972             }
    7973             if (rcHandler == ExceptionContinueSearch)
    7974                 kHlpAssert(!(pXcptPtrs->ExceptionRecord->ExceptionFlags & 8 /*EXCEPTION_STACK_INVALID*/));
    7975             else if (rcHandler == ExceptionNestedException)
    7976                 kHlpAssertMsgFailed(("Nested exceptions.\n"));
    7977             else
    7978                 kHlpAssertMsgFailed(("Invalid return %#x (%d).\n", rcHandler, rcHandler));
    7979 
    7980             /*
    7981              * Next.
    7982              */
    7983             ppRegRec = &pRegRec->PrevStructure;
    7984             pRegRec = pRegRec->PrevStructure;
    7985         }
    7986     }
    7987     return EXCEPTION_CONTINUE_SEARCH;
    7988 }
    7989 #endif /* WINDOWS + X86 */
    79908136
    79918137
     
    81988344        return kwErrPrintfRc(KERR_NO_MEMORY, "Error setting up environment variables: kwSandboxGrowEnv failed\n");
    81998345
     8346
    82008347    /*
    82018348     * Invalidate the volatile parts of cache (kBuild output directory,
     
    82038350     */
    82048351    kFsCacheInvalidateCustomBoth(g_pFsCache);
     8352
     8353#ifdef WITH_HISTORY
     8354    /*
     8355     * Record command line in debug history.
     8356     */
     8357    kHlpFree(g_apszHistory[g_iHistoryNext]);
     8358    g_apszHistory[g_iHistoryNext] = kHlpStrDup(pSandbox->pszCmdLine);
     8359    g_iHistoryNext = (g_iHistoryNext + 1) % K_ELEMENTS(g_apszHistory);
     8360#endif
     8361
    82058362    return 0;
    82068363}
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette