VirtualBox

Changeset 58268 in vbox for trunk/src


Ignore:
Timestamp:
Oct 15, 2015 6:18:17 PM (9 years ago)
Author:
vboxsync
Message:

r0drv/nt: Some rtR0MemObjNativeProtect sketches.

File:
1 edited

Legend:

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

    r57358 r58268  
    7777    PMDL                apMdls[1];
    7878} RTR0MEMOBJNT, *PRTR0MEMOBJNT;
     79
     80
     81/*********************************************************************************************************************************
     82*   Global Variables                                                                                                             *
     83*********************************************************************************************************************************/
     84/** Pointer to the MmProtectMdlSystemAddress kernel function if it's available.
     85 * This API was introduced in XP. */
     86static decltype(MmProtectMdlSystemAddress) *g_pfnMmProtectMdlSystemAddress = NULL;
     87/** Set if we've resolved the dynamic APIs. */
     88static bool volatile g_fResolvedDynamicApis = false;
     89static ULONG g_uMajorVersion = 5;
     90static ULONG g_uMinorVersion = 1;
     91
     92
     93static void rtR0MemObjNtResolveDynamicApis(void)
     94{
     95    ULONG uBuildNumber  = 0;
     96    PsGetVersion(&g_uMajorVersion, &g_uMinorVersion, &uBuildNumber, NULL);
     97
     98#ifndef IPRT_TARGET_NT4 /* MmGetSystemRoutineAddress was introduced in w2k. */
     99
     100    UNICODE_STRING RoutineName;
     101    RtlInitUnicodeString(&RoutineName, L"MmProtectMdlSystemAddress");
     102    g_pfnMmProtectMdlSystemAddress = (decltype(MmProtectMdlSystemAddress) *)MmGetSystemRoutineAddress(&RoutineName);
     103
     104#endif
     105    ASMCompilerBarrier();
     106    g_fResolvedDynamicApis = true;
     107}
    79108
    80109
     
    820849DECLHIDDEN(int) rtR0MemObjNativeProtect(PRTR0MEMOBJINTERNAL pMem, size_t offSub, size_t cbSub, uint32_t fProt)
    821850{
    822     NOREF(pMem);
    823     NOREF(offSub);
    824     NOREF(cbSub);
    825     NOREF(fProt);
     851    PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)pMem;
     852    if (!g_fResolvedDynamicApis)
     853        rtR0MemObjNtResolveDynamicApis();
     854
     855    /*
     856     * Seems there are some issues with this MmProtectMdlSystemAddress API, so
     857     * this code isn't currently enabled until we've tested it with the verifier.
     858     */
     859#if 0
     860    /*
     861     * The API we've got requires a kernel mapping.
     862     */
     863    if (   pMemNt->cMdls
     864        && g_pfnMmProtectMdlSystemAddress
     865        && (g_uMajorVersion > 6 || (g_uMajorVersion == 6 && g_uMinorVersion >= 1)) /* Windows 7 and later. */
     866        && pMemNt->Core.pv != NULL
     867        && (   pMemNt->Core.enmType == RTR0MEMOBJTYPE_PAGE
     868            || pMemNt->Core.enmType == RTR0MEMOBJTYPE_LOW
     869            || pMemNt->Core.enmType == RTR0MEMOBJTYPE_CONT
     870            || (   pMemNt->Core.enmType             == RTR0MEMOBJTYPE_LOCK
     871                && pMemNt->Core.u.Lock.R0Process    == NIL_RTPROCESS)
     872            || (   pMemNt->Core.enmType             == RTR0MEMOBJTYPE_MAPPING
     873                && pMemNt->Core.u.Mapping.R0Process == NIL_RTPROCESS) ) )
     874    {
     875        /* Convert the protection. */
     876        LOCK_OPERATION enmLockOp;
     877        ULONG fAccess;
     878        switch (fProt)
     879        {
     880            case RTMEM_PROT_NONE:
     881                fAccess = PAGE_NOACCESS;
     882                enmLockOp = IoReadAccess;
     883                break;
     884            case RTMEM_PROT_READ:
     885                fAccess = PAGE_READONLY;
     886                enmLockOp = IoReadAccess;
     887                break;
     888            case RTMEM_PROT_WRITE:
     889            case RTMEM_PROT_WRITE | RTMEM_PROT_READ:
     890                fAccess = PAGE_READWRITE;
     891                enmLockOp = IoModifyAccess;
     892                break;
     893            case RTMEM_PROT_EXEC:
     894                fAccess = PAGE_EXECUTE;
     895                enmLockOp = IoReadAccess;
     896                break;
     897            case RTMEM_PROT_EXEC | RTMEM_PROT_READ:
     898                fAccess = PAGE_EXECUTE_READ;
     899                enmLockOp = IoReadAccess;
     900                break;
     901            case RTMEM_PROT_EXEC | RTMEM_PROT_WRITE:
     902            case RTMEM_PROT_EXEC | RTMEM_PROT_WRITE | RTMEM_PROT_READ:
     903                fAccess = PAGE_EXECUTE_READWRITE;
     904                enmLockOp = IoModifyAccess;
     905                break;
     906            default:
     907                AssertFailedReturn(VERR_INVALID_FLAGS);
     908        }
     909
     910        NTSTATUS rcNt = STATUS_SUCCESS;
     911# if 0 /** @todo test this against the verifier. */
     912        if (offSub == 0 && pMemNt->Core.cb == cbSub)
     913        {
     914            uint32_t iMdl = pMemNt->cMdls;
     915            while (iMdl-- > 0)
     916            {
     917                rcNt = g_pfnMmProtectMdlSystemAddress(pMemNt->apMdls[i], fAccess);
     918                if (!NT_SUCCESS(rcNt))
     919                    break;
     920            }
     921        }
     922        else
     923# endif
     924        {
     925            /*
     926             * We ASSUME the following here:
     927             *   - MmProtectMdlSystemAddress can deal with nonpaged pool memory
     928             *   - MmProtectMdlSystemAddress doesn't actually store anything in the MDL we pass it.
     929             *   - We are not required to call MmProtectMdlSystemAddress with PAGE_READWRITE for the
     930             *     exact same ranges prior to freeing them.
     931             *
     932             * So, we lock the pages temporarily, call the API and unlock them.
     933             */
     934            uint8_t *pbCur = (uint8_t *)pMemNt->Core.pv + offSub;
     935            while (cbSub > 0 && NT_SUCCESS(rcNt))
     936            {
     937                size_t cbCur = cbSub;
     938                if (cbCur > MAX_LOCK_MEM_SIZE)
     939                    cbCur = MAX_LOCK_MEM_SIZE;
     940                PMDL pMdl = IoAllocateMdl(pbCur, (ULONG)cbCur, FALSE, FALSE, NULL);
     941                if (pMdl)
     942                {
     943                    __try
     944                    {
     945                        MmProbeAndLockPages(pMdl, KernelMode, enmLockOp);
     946                    }
     947                    __except(EXCEPTION_EXECUTE_HANDLER)
     948                    {
     949                        rcNt = GetExceptionCode();
     950                    }
     951                    if (NT_SUCCESS(rcNt))
     952                    {
     953                        rcNt = g_pfnMmProtectMdlSystemAddress(pMdl, fAccess);
     954                        MmUnlockPages(pMdl);
     955                    }
     956                    IoFreeMdl(pMdl);
     957                }
     958                else
     959                    rcNt = STATUS_NO_MEMORY;
     960                pbCur += cbCur;
     961                cbSub -= cbCur;
     962            }
     963        }
     964
     965        if (NT_SUCCESS(rcNt))
     966            return VINF_SUCCESS;
     967        return RTErrConvertFromNtStatus(rcNt);
     968    }
     969#endif
     970
    826971    return VERR_NOT_SUPPORTED;
    827972}
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