VirtualBox

Ignore:
Timestamp:
Aug 27, 2020 1:42:38 PM (4 years ago)
Author:
vboxsync
Message:

Runtime/dbgkrnlinfo-r0drv-nt.cpp: Split up rtR0DbgKrnlNtInit() and make it reallocate the module information to the maximum and search again for a module symbol when not being found on the first try, fixes VERR_NEM_MISSING_KERNEL_API_2 when using Hyper-V on systems with a lot of loaded kernel modules, bugref:9044 comment 66 until 68

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r0drv/nt/dbgkrnlinfo-r0drv-nt.cpp

    r82968 r85905  
    365365
    366366/**
     367 * Searches the given module information from the kernel for the NT kernel module, the
     368 * HAL module, and optionally one more module.
     369 *
     370 * If the NT kernel or HAL modules have already been found, they'll be skipped.
     371 *
     372 * @returns IPRT status code.
     373 * @retval  VERR_LDR_GENERAL_FAILURE if we failed to parse the NT kernel or HAL.
     374 * @retval  VERR_BAD_EXE_FORMAT if we failed to parse @a pModInfo.
     375 * @retval  VERR_MODULE_NOT_FOUND if @a pModInfo wasn't found.
     376 *
     377 * @param   pInfo               Pointer to the module information.
     378 * @param   cModules            Number of valid module entries in the module information pointer.
     379 * @param   pModInfo            Custom module to search for.  Optional.
     380 */
     381static int rtR0DbgKrnlNtSearchForModuleWorker(PRTL_PROCESS_MODULES pInfo, uint32_t cModules, PRTDBGNTKRNLMODINFO pModInfo)
     382{
     383    AssertPtrReturn(pInfo, VERR_INVALID_PARAMETER);
     384    AssertReturn(cModules >= 2, VERR_INVALID_PARAMETER);
     385
     386    /*
     387     * Search the info.  The information is ordered with the kernel bits first,
     388     * we expect aleast two modules to be returned to us (kernel + hal)!
     389     */
     390    int rc = VINF_SUCCESS;
     391#if ARCH_BITS == 32
     392    uintptr_t const uMinKernelAddr = _2G; /** @todo resolve MmSystemRangeStart */
     393#else
     394    uintptr_t const uMinKernelAddr = (uintptr_t)MM_SYSTEM_RANGE_START;
     395#endif
     396
     397    for (uint32_t iModule = 0; iModule < cModules; iModule++)
     398        RTR0DBG_NT_DEBUG_LOG(("rtR0DbgKrnlNtInit: [%u]= %p LB %#x %s\n", iModule, pInfo->Modules[iModule].ImageBase,
     399                              pInfo->Modules[iModule].ImageSize, pInfo->Modules[iModule].FullPathName));
     400
     401    /*
     402     * First time around we serch for the NT kernel and HAL.  We'll look for NT
     403     * kerneland HAL in the first 16 entries, and if not found, use the first
     404     * and second entry respectively.
     405     */
     406    if (   !g_NtOsKrnlInfo.pbImageBase
     407        && !g_HalInfo.pbImageBase)
     408    {
     409        /* Find them. */
     410        RTR0DBG_NT_DEBUG_LOG(("rtR0DbgKrnlNtInit: Looking for kernel and hal...\n"));
     411        uint32_t const cMaxModules = RT_MIN(cModules, 16);
     412        uint32_t       idxNtOsKrnl = UINT32_MAX;
     413        uint32_t       idxHal      = UINT32_MAX;
     414        for (uint32_t iModule = 0; iModule < cMaxModules; iModule++)
     415        {
     416            RTL_PROCESS_MODULE_INFORMATION const * const pModule = &pInfo->Modules[iModule];
     417            if (   (uintptr_t)pModule->ImageBase >= uMinKernelAddr
     418                && (uintptr_t)pModule->ImageSize >= _4K)
     419            {
     420                const char *pszName = (const char *)&pModule->FullPathName[pModule->OffsetToFileName];
     421                if (   idxNtOsKrnl == UINT32_MAX
     422                    && RTStrICmpAscii(pszName, g_NtOsKrnlInfo.szName) == 0)
     423                {
     424                    idxNtOsKrnl = iModule;
     425                    if (idxHal != UINT32_MAX)
     426                        break;
     427                }
     428                else if (   idxHal == UINT32_MAX
     429                         && RTStrICmpAscii(pszName, g_HalInfo.szName) == 0)
     430                {
     431                    idxHal = iModule;
     432                    if (idxHal != UINT32_MAX)
     433                        break;
     434                }
     435            }
     436        }
     437        RTR0DBG_NT_DEBUG_LOG(("rtR0DbgKrnlNtInit: idxNtOsKrnl=%#x idxHal=%#x\n", idxNtOsKrnl, idxHal));
     438        if (idxNtOsKrnl == UINT32_MAX)
     439        {
     440            idxNtOsKrnl = 0;
     441            RTR0DBG_NT_ERROR_LOG(("rtR0DbgKrnlNtInit: 'ntoskrnl.exe' not found, picking '%s' instead\n",
     442                                  pInfo->Modules[idxNtOsKrnl].FullPathName));
     443        }
     444        if (idxHal == UINT32_MAX)
     445        {
     446            idxHal = 1;
     447            RTR0DBG_NT_ERROR_LOG(("rtR0DbgKrnlNtInit: 'hal.dll' not found, picking '%s' instead\n",
     448                                  pInfo->Modules[idxHal].FullPathName));
     449        }
     450
     451        /* Parse them. */
     452        //RTR0DBG_NT_DEBUG_LOG(("rtR0DbgKrnlNtInit: Parsing NT kernel...\n"));
     453        __try
     454        {
     455            g_NtOsKrnlInfo.fOkay = rtR0DbgKrnlNtParseModule(&g_NtOsKrnlInfo,
     456                                                            (uint8_t const *)pInfo->Modules[idxNtOsKrnl].ImageBase,
     457                                                            pInfo->Modules[idxNtOsKrnl].ImageSize);
     458        }
     459        __except(EXCEPTION_EXECUTE_HANDLER)
     460        {
     461            g_NtOsKrnlInfo.fOkay = false;
     462            RTR0DBG_NT_ERROR_LOG(("rtR0DbgKrnlNtInit: Exception in rtR0DbgKrnlNtParseModule parsing ntoskrnl.exe...\n"));
     463        }
     464
     465        //RTR0DBG_NT_DEBUG_LOG(("rtR0DbgKrnlNtInit: Parsing HAL...\n"));
     466        __try
     467        {
     468            g_HalInfo.fOkay = rtR0DbgKrnlNtParseModule(&g_HalInfo, (uint8_t const *)pInfo->Modules[idxHal].ImageBase,
     469                                                       pInfo->Modules[idxHal].ImageSize);
     470        }
     471        __except(EXCEPTION_EXECUTE_HANDLER)
     472        {
     473            g_HalInfo.fOkay = false;
     474            RTR0DBG_NT_ERROR_LOG(("rtR0DbgKrnlNtInit: Exception in rtR0DbgKrnlNtParseModule parsing hal.dll...\n"));
     475        }
     476        if (!g_NtOsKrnlInfo.fOkay || !g_HalInfo.fOkay)
     477            rc = VERR_LDR_GENERAL_FAILURE;
     478
     479        /*
     480         * Resolve symbols we may need in the NT kernel (provided it parsed successfully)
     481         */
     482        if (g_NtOsKrnlInfo.fOkay)
     483        {
     484            if (!g_pfnMmGetSystemRoutineAddress)
     485            {
     486                //RTR0DBG_NT_DEBUG_LOG(("rtR0DbgKrnlNtInit: Looking up 'MmGetSystemRoutineAddress'...\n"));
     487                rtR0DbgKrnlInfoLookupSymbol(&g_NtOsKrnlInfo, "MmGetSystemRoutineAddress", 0,
     488                                            (void **)&g_pfnMmGetSystemRoutineAddress);
     489            }
     490        }
     491    }
     492
     493    /*
     494     * If we're still good, search for the given module (optional).
     495     */
     496    if (RT_SUCCESS(rc) && pModInfo)
     497    {
     498        RTR0DBG_NT_DEBUG_LOG(("rtR0DbgKrnlNtInit: Locating module '%s'...\n", pModInfo->szName));
     499        rc = VERR_MODULE_NOT_FOUND;
     500        for (uint32_t iModule = 0; iModule < cModules; iModule++)
     501        {
     502            RTL_PROCESS_MODULE_INFORMATION const * const pModule = &pInfo->Modules[iModule];
     503            if (   (uintptr_t)pModule->ImageBase >= uMinKernelAddr
     504                && (uintptr_t)pModule->ImageSize >= _4K)
     505            {
     506                const char *pszName = (const char *)&pModule->FullPathName[pModule->OffsetToFileName];
     507                if (   pModInfo->pbImageBase == NULL
     508                    && RTStrICmpAscii(pszName, pModInfo->szName) == 0)
     509                {
     510                    /*
     511                     * Found the module, try parse it.
     512                     */
     513                    __try
     514                    {
     515                        pModInfo->fOkay = rtR0DbgKrnlNtParseModule(pModInfo, (uint8_t const *)pModule->ImageBase,
     516                                                                   pModule->ImageSize);
     517                        rc = VINF_SUCCESS;
     518                    }
     519                    __except(EXCEPTION_EXECUTE_HANDLER)
     520                    {
     521                        pModInfo->fOkay = false;
     522                        rc = VERR_BAD_EXE_FORMAT;
     523                    }
     524                    break;
     525                }
     526            }
     527        }
     528    }
     529
     530    return rc;
     531}
     532
     533
     534/**
     535 * Queries the given maximum amount of modules and returns a pointer to the
     536 * allocation holding the modules.
     537 *
     538 * @returns IPRT status code.
     539 * @param   ppInfo              Where to store the pointer to the module information structure on success.
     540 *                              Free with RTMemFree() when done.
     541 * @param   cModulesMax         Maximum number of modules to return.
     542 * @param   pcModules           Where to store the amount of modules returned upon success,
     543 *                              can be lower than the requested maximum.
     544 */
     545static int rtR0DbgKrnlNtQueryModules(PRTL_PROCESS_MODULES *ppInfo, uint32_t cModulesMax, uint32_t *pcModules)
     546{
     547    *ppInfo = NULL;
     548    *pcModules = 0;
     549
     550    ULONG                   cbInfo   = RT_UOFFSETOF_DYN(RTL_PROCESS_MODULES, Modules[cModulesMax]);
     551    PRTL_PROCESS_MODULES    pInfo    = (PRTL_PROCESS_MODULES)RTMemAllocZ(cbInfo);
     552    if (!pInfo)
     553    {
     554        cModulesMax = cModulesMax / 4;
     555        cbInfo      = RT_UOFFSETOF_DYN(RTL_PROCESS_MODULES, Modules[cModulesMax]);
     556        pInfo       = (PRTL_PROCESS_MODULES)RTMemAllocZ(cbInfo);
     557        if (!pInfo)
     558        {
     559            RTR0DBG_NT_ERROR_LOG(("rtR0DbgKrnlNtQueryModules: Out of memory!\n"));
     560            return VERR_NO_MEMORY;
     561        }
     562    }
     563
     564    int      rc;
     565    ULONG    cbActual = 0;
     566    NTSTATUS rcNt = ZwQuerySystemInformation(SystemModuleInformation, pInfo, cbInfo, &cbActual);
     567    RTR0DBG_NT_DEBUG_LOG(("rtR0DbgKrnlNtQueryModules: ZwQuerySystemInformation returned %#x and NumberOfModules=%#x\n",
     568                          rcNt, pInfo->NumberOfModules));
     569    if (   NT_SUCCESS(rcNt)
     570        || rcNt == STATUS_INFO_LENGTH_MISMATCH)
     571    {
     572        *ppInfo    = pInfo;
     573        *pcModules = RT_MIN(cModulesMax, pInfo->NumberOfModules);
     574        rc = VINF_SUCCESS;
     575    }
     576    else
     577    {
     578        RTMemFree(pInfo);
     579        RTR0DBG_NT_ERROR_LOG(("rtR0DbgKrnlNtQueryModules: ZwQuerySystemInformation failed: %#x\n", rcNt));
     580        rc = RTErrConvertFromNtStatus(rcNt);
     581    }
     582
     583    return rc;
     584}
     585
     586
     587/**
    367588 * Searches the module information from the kernel for the NT kernel module, the
    368589 * HAL module, and optionally one more module.
     
    398619     *       the syscall ourselves, if we cared.
    399620     */
    400     uint32_t                cModules = pModInfo ? 110 /*32KB*/ : 27 /*8KB*/;
    401     ULONG                   cbInfo   = RT_UOFFSETOF_DYN(RTL_PROCESS_MODULES, Modules[cModules]);
    402     PRTL_PROCESS_MODULES    pInfo    = (PRTL_PROCESS_MODULES)RTMemAllocZ(cbInfo);
    403     if (!pInfo)
    404     {
    405         cModules = cModules / 4;
    406         cbInfo   = RT_UOFFSETOF_DYN(RTL_PROCESS_MODULES, Modules[cModules]);
    407         pInfo    = (PRTL_PROCESS_MODULES)RTMemAllocZ(cbInfo);
    408         if (!pInfo)
    409         {
    410             RTR0DBG_NT_ERROR_LOG(("rtR0DbgKrnlNtInit: Out of memory!\n"));
    411             return VERR_NO_MEMORY;
    412         }
    413     }
    414 
    415     int      rc;
    416     ULONG    cbActual = 0;
    417     NTSTATUS rcNt = ZwQuerySystemInformation(SystemModuleInformation, pInfo, cbInfo, &cbActual);
    418     RTR0DBG_NT_DEBUG_LOG(("rtR0DbgKrnlNtInit: ZwQuerySystemInformation returned %#x and NumberOfModules=%#x\n",
    419                           rcNt, pInfo->NumberOfModules));
    420     if (   NT_SUCCESS(rcNt)
    421         || rcNt == STATUS_INFO_LENGTH_MISMATCH)
    422         rc = VINF_SUCCESS;
    423     else
    424     {
    425         RTR0DBG_NT_ERROR_LOG(("rtR0DbgKrnlNtInit: ZwQuerySystemInformation failed: %#x\n", rcNt));
    426         rc = RTErrConvertFromNtStatus(rcNt);
    427     }
     621    uint32_t             cModules = 0;
     622    PRTL_PROCESS_MODULES pInfo    = NULL;
     623    int rc = rtR0DbgKrnlNtQueryModules(&pInfo, pModInfo ? 110 /*32KB*/ : 27 /*8KB*/, &cModules);
    428624    if (RT_SUCCESS(rc))
    429625    {
    430         /*
    431          * Search the info.  The information is ordered with the kernel bits first,
    432          * we expect aleast two modules to be returned to us (kernel + hal)!
    433          */
    434 #if ARCH_BITS == 32
    435         uintptr_t const uMinKernelAddr = _2G; /** @todo resolve MmSystemRangeStart */
    436 #else
    437         uintptr_t const uMinKernelAddr = (uintptr_t)MM_SYSTEM_RANGE_START;
    438 #endif
    439         if (pInfo->NumberOfModules < cModules)
    440             cModules = pInfo->NumberOfModules;
    441         if (cModules < 2)
    442         {
     626        if (cModules >= 2)
     627        {
     628            rc = rtR0DbgKrnlNtSearchForModuleWorker(pInfo, cModules, pModInfo);
     629            if (   rc == VERR_MODULE_NOT_FOUND
     630                && pInfo->NumberOfModules > cModules
     631                && pModInfo)
     632            {
     633                /* Module not found in the first round, reallocate array to maximum size and rerun. */
     634                cModules = pInfo->NumberOfModules;
     635
     636                RTMemFree(pInfo);
     637                pInfo = NULL;
     638
     639                rc = rtR0DbgKrnlNtQueryModules(&pInfo, cModules, &cModules);
     640                if (RT_SUCCESS(rc))
     641                {
     642                    rc = rtR0DbgKrnlNtSearchForModuleWorker(pInfo, cModules, pModInfo);
     643                    RTMemFree(pInfo);
     644                }
     645            }
     646        }
     647        else
     648        {
     649            RTMemFree(pInfo);
    443650            RTR0DBG_NT_ERROR_LOG(("rtR0DbgKrnlNtInit: Error! Only %u module(s) returned!\n", cModules));
    444651            rc = VERR_BUFFER_UNDERFLOW;
    445652        }
    446         for (uint32_t iModule = 0; iModule < cModules; iModule++)
    447             RTR0DBG_NT_DEBUG_LOG(("rtR0DbgKrnlNtInit: [%u]= %p LB %#x %s\n", iModule, pInfo->Modules[iModule].ImageBase,
    448                                   pInfo->Modules[iModule].ImageSize, pInfo->Modules[iModule].FullPathName));
    449 
    450         /*
    451          * First time around we serch for the NT kernel and HAL.  We'll look for NT
    452          * kerneland HAL in the first 16 entries, and if not found, use the first
    453          * and second entry respectively.
    454          */
    455         if (   RT_SUCCESS(rc)
    456             && !g_NtOsKrnlInfo.pbImageBase
    457             && !g_HalInfo.pbImageBase)
    458         {
    459             /* Find them. */
    460             RTR0DBG_NT_DEBUG_LOG(("rtR0DbgKrnlNtInit: Looking for kernel and hal...\n"));
    461             uint32_t const cMaxModules = RT_MIN(cModules, 16);
    462             uint32_t       idxNtOsKrnl = UINT32_MAX;
    463             uint32_t       idxHal      = UINT32_MAX;
    464             for (uint32_t iModule = 0; iModule < cMaxModules; iModule++)
    465             {
    466                 RTL_PROCESS_MODULE_INFORMATION const * const pModule = &pInfo->Modules[iModule];
    467                 if (   (uintptr_t)pModule->ImageBase >= uMinKernelAddr
    468                     && (uintptr_t)pModule->ImageSize >= _4K)
    469                 {
    470                     const char *pszName = (const char *)&pModule->FullPathName[pModule->OffsetToFileName];
    471                     if (   idxNtOsKrnl == UINT32_MAX
    472                         && RTStrICmpAscii(pszName, g_NtOsKrnlInfo.szName) == 0)
    473                     {
    474                         idxNtOsKrnl = iModule;
    475                         if (idxHal != UINT32_MAX)
    476                             break;
    477                     }
    478                     else if (   idxHal == UINT32_MAX
    479                              && RTStrICmpAscii(pszName, g_HalInfo.szName) == 0)
    480                     {
    481                         idxHal = iModule;
    482                         if (idxHal != UINT32_MAX)
    483                             break;
    484                     }
    485                 }
    486             }
    487             RTR0DBG_NT_DEBUG_LOG(("rtR0DbgKrnlNtInit: idxNtOsKrnl=%#x idxHal=%#x\n", idxNtOsKrnl, idxHal));
    488             if (idxNtOsKrnl == UINT32_MAX)
    489             {
    490                 idxNtOsKrnl = 0;
    491                 RTR0DBG_NT_ERROR_LOG(("rtR0DbgKrnlNtInit: 'ntoskrnl.exe' not found, picking '%s' instead\n",
    492                                       pInfo->Modules[idxNtOsKrnl].FullPathName));
    493             }
    494             if (idxHal == UINT32_MAX)
    495             {
    496                 idxHal = 1;
    497                 RTR0DBG_NT_ERROR_LOG(("rtR0DbgKrnlNtInit: 'hal.dll' not found, picking '%s' instead\n",
    498                                       pInfo->Modules[idxHal].FullPathName));
    499             }
    500 
    501             /* Parse them. */
    502             //RTR0DBG_NT_DEBUG_LOG(("rtR0DbgKrnlNtInit: Parsing NT kernel...\n"));
    503             __try
    504             {
    505                 g_NtOsKrnlInfo.fOkay = rtR0DbgKrnlNtParseModule(&g_NtOsKrnlInfo,
    506                                                                 (uint8_t const *)pInfo->Modules[idxNtOsKrnl].ImageBase,
    507                                                                 pInfo->Modules[idxNtOsKrnl].ImageSize);
    508             }
    509             __except(EXCEPTION_EXECUTE_HANDLER)
    510             {
    511                 g_NtOsKrnlInfo.fOkay = false;
    512                 RTR0DBG_NT_ERROR_LOG(("rtR0DbgKrnlNtInit: Exception in rtR0DbgKrnlNtParseModule parsing ntoskrnl.exe...\n"));
    513             }
    514 
    515             //RTR0DBG_NT_DEBUG_LOG(("rtR0DbgKrnlNtInit: Parsing HAL...\n"));
    516             __try
    517             {
    518                 g_HalInfo.fOkay = rtR0DbgKrnlNtParseModule(&g_HalInfo, (uint8_t const *)pInfo->Modules[idxHal].ImageBase,
    519                                                            pInfo->Modules[idxHal].ImageSize);
    520             }
    521             __except(EXCEPTION_EXECUTE_HANDLER)
    522             {
    523                 g_HalInfo.fOkay = false;
    524                 RTR0DBG_NT_ERROR_LOG(("rtR0DbgKrnlNtInit: Exception in rtR0DbgKrnlNtParseModule parsing hal.dll...\n"));
    525             }
    526             if (!g_NtOsKrnlInfo.fOkay || !g_HalInfo.fOkay)
    527                 rc = VERR_LDR_GENERAL_FAILURE;
    528 
    529             /*
    530              * Resolve symbols we may need in the NT kernel (provided it parsed successfully)
    531              */
    532             if (g_NtOsKrnlInfo.fOkay)
    533             {
    534                 if (!g_pfnMmGetSystemRoutineAddress)
    535                 {
    536                     //RTR0DBG_NT_DEBUG_LOG(("rtR0DbgKrnlNtInit: Looking up 'MmGetSystemRoutineAddress'...\n"));
    537                     rtR0DbgKrnlInfoLookupSymbol(&g_NtOsKrnlInfo, "MmGetSystemRoutineAddress", 0,
    538                                                 (void **)&g_pfnMmGetSystemRoutineAddress);
    539                 }
    540             }
    541         }
    542 
    543         /*
    544          * If we're still good, search for the given module (optional).
    545          */
    546         if (RT_SUCCESS(rc) && pModInfo)
    547         {
    548             RTR0DBG_NT_DEBUG_LOG(("rtR0DbgKrnlNtInit: Locating module '%s'...\n", pModInfo->szName));
    549             rc = VERR_MODULE_NOT_FOUND;
    550             for (uint32_t iModule = 0; iModule < cModules; iModule++)
    551             {
    552                 RTL_PROCESS_MODULE_INFORMATION const * const pModule = &pInfo->Modules[iModule];
    553                 if (   (uintptr_t)pModule->ImageBase >= uMinKernelAddr
    554                     && (uintptr_t)pModule->ImageSize >= _4K)
    555                 {
    556                     const char *pszName = (const char *)&pModule->FullPathName[pModule->OffsetToFileName];
    557                     if (   pModInfo->pbImageBase == NULL
    558                         && RTStrICmpAscii(pszName, pModInfo->szName) == 0)
    559                     {
    560                         /*
    561                          * Found the module, try parse it.
    562                          */
    563                         __try
    564                         {
    565                             pModInfo->fOkay = rtR0DbgKrnlNtParseModule(pModInfo, (uint8_t const *)pModule->ImageBase,
    566                                                                        pModule->ImageSize);
    567                             rc = VINF_SUCCESS;
    568                         }
    569                         __except(EXCEPTION_EXECUTE_HANDLER)
    570                         {
    571                             pModInfo->fOkay = false;
    572                             rc = VERR_BAD_EXE_FORMAT;
    573                         }
    574                         break;
    575                     }
    576                 }
    577             }
    578         }
    579653    }
    580654
    581655    RTR0DBG_NT_DEBUG_LOG(("rtR0DbgKrnlNtInit: returns %d\n", rc));
    582     RTMemFree(pInfo);
    583656    return rc;
    584657}
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