VirtualBox

Changeset 53035 in vbox


Ignore:
Timestamp:
Oct 11, 2014 2:50:10 AM (10 years ago)
Author:
vboxsync
Message:

supHardNtViRdrRead: Cleanup and deal with async i/o in ring-3 just to be on the safe side.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/err.h

    r53017 r53035  
    25302530 * got potentially fatally buggy anti-virus software installed.) */
    25312531#define VERR_SUP_VP_REPLACE_VIRTUAL_MEMORY_FAILED   (-5673)
     2532/** Error getting the file mode. */
     2533#define VERR_SUP_VP_FILE_MODE_ERROR                 (-5674)
     2534/** Error creating an event semaphore for used with asynchronous reads. */
     2535#define VERR_SUP_VP_CREATE_READ_EVT_SEM_FAILED      (-5675)
    25322536
    25332537/** @} */
  • trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerify-win.h

    r53022 r53035  
    9393    /** The core reader structure. */
    9494    RTLDRREADER Core;
    95     /** The file handle . */
     95    /** The file handle. */
    9696    HANDLE      hFile;
     97    /** Handle to event sempahore in case we're force to deal with asynchronous
     98     * I/O. */
     99    HANDLE      hEvent;
    97100    /** Current file offset. */
    98101    RTFOFF      off;
  • trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyImage-win.cpp

    r53034 r53035  
    211211    PSUPHNTVIRDR pNtViRdr = (PSUPHNTVIRDR)pReader;
    212212    Assert(pNtViRdr->Core.uMagic == RTLDRREADER_MAGIC);
    213 
     213    NTSTATUS rcNt;
     214
     215    /* Check for type overflow (paranoia). */
    214216    if ((ULONG)cb != cb)
    215217        return VERR_OUT_OF_RANGE;
    216218
    217 
    218     /*
    219      * For some reason I'm getting occational read error in an XP VM with
    220      * STATUS_FAILED_DRIVER_ENTRY.  Redoing the call again works in the
    221      * debugger, so try do that automatically.
    222      */
    223     for (uint32_t iTry = 0;; iTry++)
    224     {
    225         LARGE_INTEGER offNt;
    226         offNt.QuadPart = off;
    227 
    228         IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
    229         NTSTATUS rcNt = NtReadFile(pNtViRdr->hFile,
    230                                    NULL /*hEvent*/,
    231                                    NULL /*ApcRoutine*/,
    232                                    NULL /*ApcContext*/,
    233                                    &Ios,
    234                                    pvBuf,
    235                                    (ULONG)cb,
    236                                    &offNt,
    237                                    NULL);
    238         if (NT_SUCCESS(rcNt))
    239             rcNt = Ios.Status;
    240         if (NT_SUCCESS(rcNt))
     219#ifdef IN_RING3
     220    /* Make sure the event semaphore is reset (normally we don't use one). */
     221    if (pNtViRdr->hEvent)
     222    {
     223        rcNt = NtClearEvent(pNtViRdr->hEvent);
     224        if (!NT_SUCCESS(rcNt))
     225            return RTErrConvertFromNtStatus(rcNt);
     226    }
     227#endif
     228
     229    /* Perform the read. */
     230    LARGE_INTEGER offNt;
     231    offNt.QuadPart = off;
     232
     233    IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
     234    rcNt = NtReadFile(pNtViRdr->hFile,
     235                      pNtViRdr->hEvent,
     236                      NULL /*ApcRoutine*/,
     237                      NULL /*ApcContext*/,
     238                      &Ios,
     239                      pvBuf,
     240                      (ULONG)cb,
     241                      &offNt,
     242                      NULL);
     243
     244#ifdef IN_RING0
     245    /* In ring-0 the handles shall be synchronized and not alertable. */
     246    AssertMsg(rcNt == STATUS_SUCCESS || !NT_SUCCESS(rcNt), ("%#x\n", rcNt));
     247#else
     248    /* In ring-3 we like our handles synchronized and non-alertable, but we
     249       sometimes have to take what we can get.  So, deal with pending I/O as
     250       best we can. */
     251    if (rcNt == STATUS_PENDING)
     252        rcNt = NtWaitForSingleObject(pNtViRdr->hEvent ? pNtViRdr->hEvent : pNtViRdr->hFile, FALSE /*Alertable*/, NULL);
     253#endif
     254    if (NT_SUCCESS(rcNt))
     255        rcNt = Ios.Status;
     256    if (NT_SUCCESS(rcNt))
     257    {
     258        /* We require the caller to not read beyond the end of the file since
     259           we don't have any way to communicate that we've read less that
     260           requested. */
     261        if (Ios.Information == cb)
    241262        {
    242             if (Ios.Information == cb)
    243             {
    244                 pNtViRdr->off = off + cb;
    245                 return VINF_SUCCESS;
    246             }
     263            pNtViRdr->off = off + cb; /* (just for show) */
     264            return VINF_SUCCESS;
     265        }
    247266#ifdef IN_RING3
    248             supR3HardenedError(VERR_READ_ERROR, false,
    249                                "supHardNtViRdrRead: Only got %#zx bytes when requesting %#zx bytes at %#llx in '%s'.\n",
    250                                Ios.Information, off, cb, pNtViRdr->szFilename);
     267        supR3HardenedError(VERR_READ_ERROR, false,
     268                           "supHardNtViRdrRead: Only got %#zx bytes when requesting %#zx bytes at %#llx in '%s'.\n",
     269                           Ios.Information, off, cb, pNtViRdr->szFilename);
    251270#endif
    252             pNtViRdr->off = -1;
    253             return VERR_READ_ERROR;
    254         }
    255 
    256 /** @todo This nonsense is probably due to missing FILE_SYNCHRONOUS_IO_NONALERT
    257  *        flags in early code stage.  Should clean this up, but leave code
    258  *        for handling STATUS_PENDING as we don't know what callers of
    259  *        NtCreateSection might've been passing to their NtCreateFile calls.
    260  *        In ring-0, this code is mostly pointless, I think. */
    261         /*
    262          * Delay a little before we retry?
    263          */
    264 #ifdef IN_RING3
    265         if (iTry == 0)
    266             NtYieldExecution();
    267         else if (iTry >= 1)
    268         {
    269             LARGE_INTEGER Time;
    270             Time.QuadPart = -1000000 / 100; /* 1ms in 100ns units, relative time. */
    271             NtDelayExecution(TRUE, &Time);
    272         }
    273 #endif
    274         /*
    275          * Before we give up, we'll try split up the request in case the
    276          * kernel is low on memory or similar.  For simplicity reasons, we do
    277          * this in a recursion fashion.
    278          */
    279         if (iTry >= 2)
    280         {
    281             if (cb >= _8K)
    282             {
    283                 size_t const cbBlock = RT_ALIGN_Z(cb / 4, 512);
    284                 while (cb > 0)
    285                 {
    286                     size_t cbThisRead = RT_MIN(cb, cbBlock);
    287                     int rc = supHardNtViRdrRead(&pNtViRdr->Core, pvBuf, cbThisRead, off);
    288                     if (RT_FAILURE(rc))
    289                         return rc;
    290                     off  += cbThisRead;
    291                     cb   -= cbThisRead;
    292                     pvBuf = (uint8_t *)pvBuf + cbThisRead;
    293                 }
    294                 return VINF_SUCCESS;
    295             }
    296 
    297 #ifdef IN_RING3
    298             supR3HardenedError(VERR_READ_ERROR, false, "supHardNtViRdrRead: Error %#x reading %#zx bytes at %#llx in '%s'.\n",
    299                                rcNt, off, cb, pNtViRdr->szFilename);
    300 #endif
    301             pNtViRdr->off = -1;
    302             return VERR_READ_ERROR;
    303         }
    304     }
     271    }
     272    pNtViRdr->off = -1;
     273    return VERR_READ_ERROR;
    305274}
    306275
     
    354323    pNtViRdr->Core.uMagic = ~RTLDRREADER_MAGIC;
    355324    pNtViRdr->hFile = NULL;
    356 
     325#ifdef IN_RING3
     326    if (pNtViRdr->hEvent)
     327    {
     328        NtClose(pNtViRdr->hEvent);
     329        pNtViRdr->hEvent = NULL;
     330    }
     331#endif
    357332    RTMemFree(pNtViRdr);
    358333    return VINF_SUCCESS;
     
    381356
    382357    /*
     358     * Figure the file mode so we can see whether we'll be needing an event
     359     * semaphore for waiting on reads.  This may happen in very unlikely
     360     * NtCreateSection scenarios.
     361     */
     362#if defined(IN_RING3) || defined(VBOX_STRICT)
     363    Ios.Status = STATUS_UNSUCCESSFUL;
     364    ULONG fMode;
     365    rcNt = NtQueryInformationFile(hFile, &Ios, &fMode, sizeof(fMode), FileModeInformation);
     366    if (!NT_SUCCESS(rcNt) || !NT_SUCCESS(Ios.Status))
     367        return VERR_SUP_VP_FILE_MODE_ERROR;
     368#endif
     369
     370    HANDLE hEvent = NULL;
     371#ifdef IN_RING3
     372    if (!(fMode & (FILE_SYNCHRONOUS_IO_NONALERT | FILE_SYNCHRONOUS_IO_ALERT)))
     373    {
     374        rcNt = NtCreateEvent(&hEvent, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE);
     375        if (!NT_SUCCESS(rcNt))
     376            return VERR_SUP_VP_CREATE_READ_EVT_SEM_FAILED;
     377    }
     378#else
     379    Assert(fMode & FILE_SYNCHRONOUS_IO_NONALERT);
     380#endif
     381
     382    /*
    383383     * Calc the file name length and allocate memory for the reader instance.
    384384     */
     
    390390    PSUPHNTVIRDR pNtViRdr = (PSUPHNTVIRDR)RTMemAllocZ(sizeof(*pNtViRdr) + cchFilename);
    391391    if (!pNtViRdr)
     392    {
     393#ifdef IN_RING3
     394        if (hEvent != NULL)
     395            NtClose(hEvent);
     396#endif
    392397        return VERR_NO_MEMORY;
     398    }
    393399
    394400    /*
     
    413419    pNtViRdr->Core.pfnDestroy = supHardNtViRdrDestroy;
    414420    pNtViRdr->hFile           = hFile;
     421    pNtViRdr->hEvent          = hEvent;
    415422    pNtViRdr->off             = 0;
    416423    pNtViRdr->cbFile          = StdInfo.EndOfFile.QuadPart;
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