VirtualBox

Ignore:
Timestamp:
Mar 28, 2015 12:19:24 AM (10 years ago)
Author:
vboxsync
Message:

supHardNt: Never call WinVerifyTrust and friends when owning the loader lock, they do an awful lot of loader work (GetProcAddress and sometimes LoadLibrary).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyImage-win.cpp

    r53820 r54997  
    9898typedef BOOL (WINAPI *PFNCERTCLOSESTORE)(HCERTSTORE hCertStore, DWORD dwFlags);
    9999typedef PCCERT_CONTEXT (WINAPI *PFNCERTENUMCERTIFICATESINSTORE)(HCERTSTORE hCertStore, PCCERT_CONTEXT pPrevCertContext);
     100
     101typedef NTSTATUS (WINAPI *PFNBCRYPTOPENALGORTIHMPROVIDER)(BCRYPT_ALG_HANDLE *phAlgo, PCWSTR pwszAlgoId,
     102                                                          PCWSTR pwszImpl, DWORD dwFlags);
    100103#endif
    101104
     
    20512054
    20522055    /*
    2053      * Resolve it.
     2056     * Resolve the imports we need.
    20542057     */
    20552058    HMODULE hWintrust = supR3HardenedWinLoadSystem32Dll("Wintrust.dll");
     
    20752078    RESOLVE_CRYPT_API(CryptCATAdminCalcHashFromFileHandle2,  PFNCRYPTCATADMINCALCHASHFROMFILEHANDLE2, SUP_NT_VER_W80);
    20762079
    2077     /*
    2078      * Call it on ourselves and ntdll to make sure it loads all the providers
    2079      * now, we would otherwise geting into recursive trouble in the
    2080      * NtCreateSection hook.
    2081      */
    20822080# ifdef IN_SUP_HARDENED_R3
     2081    /*
     2082     * Load bcrypt.dll and instantiate a few hashing and signing providers to
     2083     * make sure the providers are cached for later us.  Avoid recursion issues.
     2084     */
     2085    HMODULE hBCrypt = supR3HardenedWinLoadSystem32Dll("bcrypt.dll");
     2086    if (hBCrypt)
     2087    {
     2088        PFNBCRYPTOPENALGORTIHMPROVIDER pfnOpenAlgoProvider;
     2089        pfnOpenAlgoProvider = (PFNBCRYPTOPENALGORTIHMPROVIDER)GetProcAddress(hBCrypt, "BCryptOpenAlgorithmProvider");
     2090        if (pfnOpenAlgoProvider)
     2091        {
     2092            SUP_DPRINTF(("bcrypt.dll loaded at %p, BCryptOpenAlgorithmProvider at %p, preloading providers:\n",
     2093                         hBCrypt, pfnOpenAlgoProvider));
     2094#  define PRELOAD_ALGO_PROVIDER(a_Name) \
     2095                do { \
     2096                    BCRYPT_ALG_HANDLE hAlgo = NULL; \
     2097                    NTSTATUS rcNt = pfnOpenAlgoProvider(&hAlgo, a_Name, NULL, 0); \
     2098                    SUP_DPRINTF(("%sBCryptOpenAlgorithmProvider(,'%ls',0,0) -> %#x (hAlgo=%p)\n", \
     2099                                 NT_SUCCESS(rcNt) ? "    " : "warning: ", a_Name, rcNt, hAlgo)); \
     2100                } while (0)
     2101            PRELOAD_ALGO_PROVIDER(BCRYPT_MD2_ALGORITHM);
     2102            PRELOAD_ALGO_PROVIDER(BCRYPT_MD4_ALGORITHM);
     2103            PRELOAD_ALGO_PROVIDER(BCRYPT_MD5_ALGORITHM);
     2104            PRELOAD_ALGO_PROVIDER(BCRYPT_SHA1_ALGORITHM);
     2105            PRELOAD_ALGO_PROVIDER(BCRYPT_SHA256_ALGORITHM);
     2106            PRELOAD_ALGO_PROVIDER(BCRYPT_SHA512_ALGORITHM);
     2107            PRELOAD_ALGO_PROVIDER(BCRYPT_RSA_ALGORITHM);
     2108            PRELOAD_ALGO_PROVIDER(BCRYPT_DSA_ALGORITHM);
     2109#  undef PRELOAD_ALGO_PROVIDER
     2110        }
     2111        else
     2112            SUP_DPRINTF(("Warning! Failed to find BCryptOpenAlgorithmProvider in bcrypt.dll\n"));
     2113    }
     2114    else
     2115        SUP_DPRINTF(("Warning! Failed to load bcrypt.dll\n"));
     2116
     2117    /*
     2118     * Call the verification API on ourselves and ntdll to make sure it works
     2119     * and loads more stuff it needs, preventing any recursive fun we'd run
     2120     * into after we set g_pfnWinVerifyTrust.
     2121     */
    20832122    RTERRINFOSTATIC ErrInfoStatic;
    20842123    RTErrInfoInitStatic(&ErrInfoStatic);
     
    25822621    if (g_pfnWinVerifyTrust != NULL)
    25832622    {
    2584         /* Check for recursion. */
    2585         bool fNoRecursion;
    2586         if (g_iTlsWinVerifyTrustRecursion != UINT32_MAX)
     2623        uint32_t const idCurrentThread = RTNtCurrentThreadId();
     2624
     2625        /* Check if loader lock owner. */
     2626        struct _RTL_CRITICAL_SECTION volatile *pLoaderLock = NtCurrentPeb()->LoaderLock;
     2627        bool fOwnsLoaderLock = pLoaderLock
     2628                            && pLoaderLock->OwningThread == (HANDLE)(uintptr_t)idCurrentThread
     2629                            && pLoaderLock->LockCount >= 0;
     2630        if (!fOwnsLoaderLock)
    25872631        {
    2588             fNoRecursion = TlsGetValue(g_iTlsWinVerifyTrustRecursion) == 0;
    2589             if (fNoRecursion)
    2590                 TlsSetValue(g_iTlsWinVerifyTrustRecursion, (void *)1);
    2591         }
    2592         else
    2593         {
    2594             uint32_t const idCurrentThread = RTNtCurrentThreadId();
    2595             fNoRecursion = ASMAtomicCmpXchgU32(&g_idActiveThread, idCurrentThread, UINT32_MAX);
    2596         }
    2597         if (fNoRecursion)
    2598         {
    2599             /* We can call WinVerifyTrust. */
    2600             if (pfWinVerifyTrust)
    2601                 *pfWinVerifyTrust = true;
    2602 
    2603             if (rc != VERR_LDRVI_NOT_SIGNED)
     2632            /* Check for recursion. */
     2633            bool fNoRecursion;
     2634            if (g_iTlsWinVerifyTrustRecursion != UINT32_MAX)
    26042635            {
    2605                 if (rc == VINF_LDRVI_NOT_SIGNED)
     2636                fNoRecursion = TlsGetValue(g_iTlsWinVerifyTrustRecursion) == 0;
     2637                if (fNoRecursion)
     2638                    TlsSetValue(g_iTlsWinVerifyTrustRecursion, (void *)1);
     2639            }
     2640            else
     2641                fNoRecursion = ASMAtomicCmpXchgU32(&g_idActiveThread, idCurrentThread, UINT32_MAX);
     2642
     2643            if (fNoRecursion && !fOwnsLoaderLock)
     2644            {
     2645                /* We can call WinVerifyTrust. */
     2646                if (pfWinVerifyTrust)
     2647                    *pfWinVerifyTrust = true;
     2648
     2649                if (rc != VERR_LDRVI_NOT_SIGNED)
    26062650                {
    2607                     if (fFlags & SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION)
     2651                    if (rc == VINF_LDRVI_NOT_SIGNED)
    26082652                    {
    2609                         int rc2 = supR3HardNtViCallWinVerifyTrustCatFile(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust);
    2610                         SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile -> %d (org %d)\n", rc2, rc));
    2611                         rc = rc2;
     2653                        if (fFlags & SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION)
     2654                        {
     2655                            int rc2 = supR3HardNtViCallWinVerifyTrustCatFile(hFile, pwszName, fFlags, pErrInfo,
     2656                                                                             g_pfnWinVerifyTrust);
     2657                            SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile -> %d (org %d)\n", rc2, rc));
     2658                            rc = rc2;
     2659                        }
     2660                        else
     2661                        {
     2662                            AssertFailed();
     2663                            rc = VERR_LDRVI_NOT_SIGNED;
     2664                        }
     2665                    }
     2666                    else if (RT_SUCCESS(rc))
     2667                    {
     2668                        HRESULT hrcWinVerifyTrust;
     2669                        rc = supR3HardNtViCallWinVerifyTrust(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust,
     2670                                                             &hrcWinVerifyTrust);
     2671
     2672                        /* DLLs signed with special roots, like "Microsoft Digital Media Authority 2005",
     2673                           may fail here because the root cert is not in the normal certificate stores
     2674                           (if any).  Our verification code has the basics of these certificates included
     2675                           and can verify them, which is why we end up here instead of in the
     2676                           VINF_LDRVI_NOT_SIGNED case above.  Current workaround is to do as above.
     2677                           (Intel graphics driver DLLs, like igdusc64.dll. */
     2678                        if (   RT_FAILURE(rc)
     2679                            && hrcWinVerifyTrust == CERT_E_CHAINING
     2680                            && (fFlags & SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION))
     2681                        {
     2682                            rc = supR3HardNtViCallWinVerifyTrustCatFile(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust);
     2683                            SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile -> %d (was CERT_E_CHAINING)\n", rc));
     2684                        }
    26122685                    }
    26132686                    else
    26142687                    {
    2615                         AssertFailed();
    2616                         rc = VERR_LDRVI_NOT_SIGNED;
     2688                        int rc2 = supR3HardNtViCallWinVerifyTrust(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust, NULL);
     2689                        AssertMsg(RT_FAILURE_NP(rc2),
     2690                                  ("rc=%Rrc, rc2=%Rrc %s", rc, rc2, pErrInfo ? pErrInfo->pszMsg : "<no-err-info>"));
    26172691                    }
    26182692                }
    2619                 else if (RT_SUCCESS(rc))
    2620                 {
    2621                     HRESULT hrcWinVerifyTrust;
    2622                     rc = supR3HardNtViCallWinVerifyTrust(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust,
    2623                                                          &hrcWinVerifyTrust);
    2624 
    2625                     /* DLLs signed with special roots, like "Microsoft Digital Media Authority 2005",
    2626                        may fail here because the root cert is not in the normal certificate stores
    2627                        (if any).  Our verification code has the basics of these certificates included
    2628                        and can verify them, which is why we end up here instead of in the
    2629                        VINF_LDRVI_NOT_SIGNED case above.  Current workaround is to do as above.
    2630                        (Intel graphics driver DLLs, like igdusc64.dll. */
    2631                     if (   RT_FAILURE(rc)
    2632                         && hrcWinVerifyTrust == CERT_E_CHAINING
    2633                         && (fFlags & SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION))
    2634                     {
    2635                         rc = supR3HardNtViCallWinVerifyTrustCatFile(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust);
    2636                         SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile -> %d (was CERT_E_CHAINING)\n", rc));
    2637                     }
    2638                 }
     2693
     2694                /* Unwind recursion. */
     2695                if (g_iTlsWinVerifyTrustRecursion != UINT32_MAX)
     2696                    TlsSetValue(g_iTlsWinVerifyTrustRecursion, (void *)0);
    26392697                else
    2640                 {
    2641                     int rc2 = supR3HardNtViCallWinVerifyTrust(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust, NULL);
    2642                     AssertMsg(RT_FAILURE_NP(rc2),
    2643                               ("rc=%Rrc, rc2=%Rrc %s", rc, rc2, pErrInfo ? pErrInfo->pszMsg : "<no-err-info>"));
    2644                 }
     2698                    ASMAtomicWriteU32(&g_idActiveThread, UINT32_MAX);
    26452699            }
    2646 
    2647             /* Unwind recursion. */
    2648             if (g_iTlsWinVerifyTrustRecursion != UINT32_MAX)
    2649                 TlsSetValue(g_iTlsWinVerifyTrustRecursion, (void *)0);
     2700            /*
     2701             * No can do.
     2702             */
    26502703            else
    2651                 ASMAtomicWriteU32(&g_idActiveThread, UINT32_MAX);
     2704                SUP_DPRINTF(("Detected WinVerifyTrust recursion: rc=%Rrc '%ls'.\n", rc, pwszName));
    26522705        }
    26532706        else
    2654             SUP_DPRINTF(("Detected WinVerifyTrust recursion: rc=%Rrc '%ls'.\n", rc, pwszName));
     2707            SUP_DPRINTF(("Detected loader lock ownership: rc=%Rrc '%ls'.\n", rc, pwszName));
    26552708    }
    26562709    return rc;
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