VirtualBox

Changeset 41090 in vbox


Ignore:
Timestamp:
Apr 27, 2012 11:26:51 PM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
77678
Message:

memobj-r0drv-darwin.cpp: Attempt at fixing the vm_protect/fExecute problem.

File:
1 edited

Legend:

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

    r41077 r41090  
    6767
    6868/**
    69  * HACK ALERT!
    70  *
    71  * Touch the pages to force the kernel to create  the page
    72  * table entries. This is necessary since the kernel gets
    73  * upset if we take a page fault when preemption is disabled
    74  * and/or we own a simple lock. It has no problems with us
    75  * disabling interrupts when taking the traps, weird stuff.
     69 * Touch the pages to force the kernel to create or write-enable the page table
     70 * entries.
     71 *
     72 * This is necessary since the kernel gets upset if we take a page fault when
     73 * preemption is disabled and/or we own a simple lock (same thing).  It has no
     74 * problems with us disabling interrupts when taking the traps, weird stuff.
     75 *
     76 * (This is basically a way of invoking vm_fault on a range of pages.)
    7677 *
    7778 * @param  pv           Pointer to the first page.
     
    8485    {
    8586        ASMAtomicCmpXchgU32(pu32, 0xdeadbeef, 0xdeadbeef);
     87        if (cb <= PAGE_SIZE)
     88            break;
     89        cb -= PAGE_SIZE;
     90        pu32 += PAGE_SIZE / sizeof(uint32_t);
     91    }
     92}
     93
     94
     95/**
     96 * Read (sniff) every page in the range to make sure there are some page tables
     97 * entries backing it.
     98 *
     99 * This is just to be sure vm_protect didn't remove stuff without re-adding it
     100 * if someone should try write-protect something.
     101 *
     102 * @param  pv           Pointer to the first page.
     103 * @param  cb           The number of bytes.
     104 */
     105static void rtR0MemObjDarwinSniffPages(void const *pv, size_t cb)
     106{
     107    uint32_t volatile  *pu32 = (uint32_t volatile *)pv;
     108    uint32_t volatile   u32Counter = 0;
     109    for (;;)
     110    {
     111        u32Counter += *pu32;
     112
    86113        if (cb <= PAGE_SIZE)
    87114            break;
     
    508535                    }
    509536
    510 #if 0 /* Experimental code. */
     537#if 1 /* Experimental code. */
    511538                    if (fExecutable)
    512539                    {
     
    514541# ifdef RT_STRICT
    515542                        /* check that the memory is actually mapped. */
    516                         //addr64_t Addr = pMemDesc->getPhysicalSegment64(0, NULL);
    517                         //printf("rtR0MemObjNativeAllocWorker: pv=%p %8llx %8llx\n", pv, rtR0MemObjDarwinGetPTE(pv), Addr);
    518543                        RTTHREADPREEMPTSTATE State = RTTHREADPREEMPTSTATE_INITIALIZER;
    519544                        RTThreadPreemptDisable(&State);
     
    858883                        rtR0MemObjDarwinTouchPages(pv, cbSub);
    859884                        /** @todo First, the memory should've been mapped by now, and second, it
    860                          *        should have the wired attribute in the PTE (bit 9). Neither is
     885                         *        should have the wired attribute in the PTE (bit 9). Neither
    861886                         *        seems to be the case. The disabled locking code doesn't make any
    862887                         *        difference, which is extremely odd, and breaks
     
    967992        return VERR_NOT_SUPPORTED;
    968993
    969     /* Convert the protection. */
     994    /*
     995     * Convert the protection.
     996     */
    970997    vm_prot_t fMachProt;
    971998    switch (fProt)
     
    9831010            fMachProt = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
    9841011            break;
     1012        case RTMEM_PROT_WRITE:
     1013            fMachProt = VM_PROT_WRITE | VM_PROT_READ;                   /* never write-only */
     1014            break;
    9851015        case RTMEM_PROT_WRITE | RTMEM_PROT_EXEC:
    986             fMachProt = VM_PROT_WRITE | VM_PROT_EXECUTE;
     1016            fMachProt = VM_PROT_WRITE | VM_PROT_EXECUTE | VM_PROT_READ; /* never write-only or execute-only */
    9871017            break;
    9881018        case RTMEM_PROT_EXEC:
    989             fMachProt = VM_PROT_EXECUTE;
     1019            fMachProt = VM_PROT_EXECUTE | VM_PROT_READ;                 /* never execute-only */
    9901020            break;
    9911021        default:
     
    9931023    }
    9941024
    995     /* do the job. */
     1025    /*
     1026     * Do the job.
     1027     */
    9961028    vm_offset_t Start = (uintptr_t)pMem->pv + offSub;
    9971029    kern_return_t krc = vm_protect(pVmMap,
     
    10021034    if (krc != KERN_SUCCESS)
    10031035        return RTErrConvertFromDarwinKern(krc);
     1036
     1037    /*
     1038     * Touch the pages if they should be writable afterwards and accessible
     1039     * from code which should never fault. vm_protect() may leave pages
     1040     * temporarily write protected, possibly due to pmap no-upgrade rules?
     1041     *
     1042     * This is the same trick (or HACK ALERT if you like) as applied in
     1043     * rtR0MemObjNativeMapKernel.
     1044     */
     1045    if (   pMem->enmType != RTR0MEMOBJTYPE_MAPPING
     1046        || pMem->u.Mapping.R0Process == NIL_RTR0PROCESS)
     1047    {
     1048        if (fProt & RTMEM_PROT_WRITE)
     1049            rtR0MemObjDarwinTouchPages((void *)Start, cbSub);
     1050        /*
     1051         * Sniff (read) read-only pages too, just to be sure.
     1052         */
     1053        else if (fProt & (RTMEM_PROT_READ | RTMEM_PROT_EXEC))
     1054            rtR0MemObjDarwinSniffPages((void const *)Start, cbSub);
     1055    }
     1056
    10041057    return VINF_SUCCESS;
    10051058}
Note: See TracChangeset for help on using the changeset viewer.

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