[NTOS/MM] Recognize AMD64 image in PeFmtCreateSection failure case
[reactos.git] / ntoskrnl / mm / section.c
index 5c95439..a8d2945 100644 (file)
@@ -197,7 +197,7 @@ NTSTATUS NTAPI PeFmtCreateSection(IN CONST VOID * FileHeader,
     ULONG cbHeadersSize = 0;
     ULONG nSectionAlignment;
     ULONG nFileAlignment;
-    ULONG_PTR ImageBase;
+    ULONG_PTR ImageBase = 0;
     const IMAGE_DOS_HEADER * pidhDosHeader;
     const IMAGE_NT_HEADERS32 * pinhNtHeader;
     const IMAGE_OPTIONAL_HEADER32 * piohOptHeader;
@@ -364,6 +364,10 @@ l_ReadHeaderFromFile:
 #endif // _WIN64
         break;
 
+#ifndef _WIN64
+    case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
+        nStatus = STATUS_INVALID_IMAGE_WIN_64;
+#endif
     default:
         DIE(("Unrecognized optional header, Magic is %X\n", piohOptHeader->Magic));
     }
@@ -684,7 +688,7 @@ l_ReadHeaderFromFile:
     pssSegments[0].Length.QuadPart = nPrevVirtualEndOfSegment;
     pssSegments[0].RawLength.QuadPart = nFileSizeOfHeaders;
     pssSegments[0].Image.VirtualAddress = 0;
-    pssSegments[0].Image.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA;
+    pssSegments[0].Image.Characteristics = 0;
     pssSegments[0].WriteCopy = TRUE;
 
     /* skip the headers segment */
@@ -1040,23 +1044,21 @@ BOOLEAN MiIsPageFromCache(PMEMORY_AREA MemoryArea,
 
 NTSTATUS
 NTAPI
-MiCopyFromUserPage(PFN_NUMBER DestPage, PFN_NUMBER SrcPage)
+MiCopyFromUserPage(PFN_NUMBER DestPage, const VOID *SrcAddress)
 {
     PEPROCESS Process;
-    KIRQL Irql, Irql2;
-    PVOID DestAddress, SrcAddress;
+    KIRQL Irql;
+    PVOID DestAddress;
 
     Process = PsGetCurrentProcess();
     DestAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql);
-    SrcAddress = MiMapPageInHyperSpace(Process, SrcPage, &Irql2);
-    if (DestAddress == NULL || SrcAddress == NULL)
+    if (DestAddress == NULL)
     {
         return(STATUS_NO_MEMORY);
     }
     ASSERT((ULONG_PTR)DestAddress % PAGE_SIZE == 0);
     ASSERT((ULONG_PTR)SrcAddress % PAGE_SIZE == 0);
     RtlCopyMemory(DestAddress, SrcAddress, PAGE_SIZE);
-    MiUnmapPageInHyperSpace(Process, SrcAddress, Irql2);
     MiUnmapPageInHyperSpace(Process, DestAddress, Irql);
     return(STATUS_SUCCESS);
 }
@@ -1277,6 +1279,87 @@ MiReadPage(PMEMORY_AREA MemoryArea,
 }
 #endif
 
+static VOID
+MmAlterViewAttributes(PMMSUPPORT AddressSpace,
+                      PVOID BaseAddress,
+                      SIZE_T RegionSize,
+                      ULONG OldType,
+                      ULONG OldProtect,
+                      ULONG NewType,
+                      ULONG NewProtect)
+{
+    PMEMORY_AREA MemoryArea;
+    PMM_SECTION_SEGMENT Segment;
+    BOOLEAN DoCOW = FALSE;
+    ULONG i;
+    PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
+
+    MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress);
+    ASSERT(MemoryArea != NULL);
+    Segment = MemoryArea->Data.SectionData.Segment;
+    MmLockSectionSegment(Segment);
+
+    if ((Segment->WriteCopy) &&
+            (NewProtect == PAGE_READWRITE || NewProtect == PAGE_EXECUTE_READWRITE))
+    {
+        DoCOW = TRUE;
+    }
+
+    if (OldProtect != NewProtect)
+    {
+        for (i = 0; i < PAGE_ROUND_UP(RegionSize) / PAGE_SIZE; i++)
+        {
+            SWAPENTRY SwapEntry;
+            PVOID Address = (char*)BaseAddress + (i * PAGE_SIZE);
+            ULONG Protect = NewProtect;
+
+            /* Wait for a wait entry to disappear */
+            do
+            {
+                MmGetPageFileMapping(Process, Address, &SwapEntry);
+                if (SwapEntry != MM_WAIT_ENTRY)
+                    break;
+                MiWaitForPageEvent(Process, Address);
+            }
+            while (TRUE);
+
+            /*
+             * If we doing COW for this segment then check if the page is
+             * already private.
+             */
+            if (DoCOW && MmIsPagePresent(Process, Address))
+            {
+                LARGE_INTEGER Offset;
+                ULONG_PTR Entry;
+                PFN_NUMBER Page;
+
+                Offset.QuadPart = (ULONG_PTR)Address - MA_GetStartingAddress(MemoryArea)
+                                  + MemoryArea->Data.SectionData.ViewOffset.QuadPart;
+                Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
+                /*
+                 * An MM_WAIT_ENTRY is ok in this case...  It'll just count as
+                 * IS_SWAP_FROM_SSE and we'll do the right thing.
+                 */
+                Page = MmGetPfnForProcess(Process, Address);
+
+                Protect = PAGE_READONLY;
+                if (IS_SWAP_FROM_SSE(Entry) || PFN_FROM_SSE(Entry) != Page)
+                {
+                    Protect = NewProtect;
+                }
+            }
+
+            if (MmIsPagePresent(Process, Address) || MmIsDisabledPage(Process, Address))
+            {
+                MmSetPageProtect(Process, Address,
+                                 Protect);
+            }
+        }
+    }
+
+    MmUnlockSectionSegment(Segment);
+}
+
 NTSTATUS
 NTAPI
 MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
@@ -1331,6 +1414,29 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
                           &MemoryArea->Data.SectionData.RegionListHead,
                           Address, NULL);
     ASSERT(Region != NULL);
+
+    /* Check for a NOACCESS mapping */
+    if (Region->Protect & PAGE_NOACCESS)
+    {
+        return STATUS_ACCESS_VIOLATION;
+    }
+
+    if (Region->Protect & PAGE_GUARD)
+    {
+        /* Remove it */
+        Status = MmAlterRegion(AddressSpace, (PVOID)MA_GetStartingAddress(MemoryArea),
+                &MemoryArea->Data.SectionData.RegionListHead,
+                Address, PAGE_SIZE, Region->Type, Region->Protect & ~PAGE_GUARD,
+                MmAlterViewAttributes);
+
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("Removing PAGE_GUARD protection failed : 0x%08x.\n", Status);
+        }
+
+        return STATUS_GUARD_PAGE_VIOLATION;
+    }
+
     /*
      * Lock the segment
      */
@@ -1367,7 +1473,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
     HasSwapEntry = MmIsPageSwapEntry(Process, Address);
 
     /* See if we should use a private page */
-    if ((HasSwapEntry) || (Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA))
+    if (HasSwapEntry)
     {
         SWAPENTRY DummyEntry;
 
@@ -1781,7 +1887,7 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
     /*
      * Copy the old page
      */
-    MiCopyFromUserPage(NewPage, OldPage);
+    NT_VERIFY(NT_SUCCESS(MiCopyFromUserPage(NewPage, PAddress)));
 
     /*
      * Unshare the old page.
@@ -1958,9 +2064,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
      */
     MmUnlockSectionSegment(Context.Segment);
     Context.WasDirty = FALSE;
-    if (Context.Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
-            IS_SWAP_FROM_SSE(Entry) ||
-            PFN_FROM_SSE(Entry) != Page)
+    if (IS_SWAP_FROM_SSE(Entry) || PFN_FROM_SSE(Entry) != Page)
     {
         Context.Private = TRUE;
     }
@@ -2348,9 +2452,7 @@ MmWritePageSectionView(PMMSUPPORT AddressSpace,
     /*
      * Check for a private (COWed) page.
      */
-    if (Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
-            IS_SWAP_FROM_SSE(Entry) ||
-            PFN_FROM_SSE(Entry) != Page)
+    if (IS_SWAP_FROM_SSE(Entry) || PFN_FROM_SSE(Entry) != Page)
     {
         Private = TRUE;
     }
@@ -2419,89 +2521,6 @@ MmWritePageSectionView(PMMSUPPORT AddressSpace,
     return(STATUS_SUCCESS);
 }
 
-static VOID
-MmAlterViewAttributes(PMMSUPPORT AddressSpace,
-                      PVOID BaseAddress,
-                      SIZE_T RegionSize,
-                      ULONG OldType,
-                      ULONG OldProtect,
-                      ULONG NewType,
-                      ULONG NewProtect)
-{
-    PMEMORY_AREA MemoryArea;
-    PMM_SECTION_SEGMENT Segment;
-    BOOLEAN DoCOW = FALSE;
-    ULONG i;
-    PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
-
-    MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress);
-    ASSERT(MemoryArea != NULL);
-    Segment = MemoryArea->Data.SectionData.Segment;
-    MmLockSectionSegment(Segment);
-
-    if ((Segment->WriteCopy) &&
-            (NewProtect == PAGE_READWRITE || NewProtect == PAGE_EXECUTE_READWRITE))
-    {
-        DoCOW = TRUE;
-    }
-
-    if (OldProtect != NewProtect)
-    {
-        for (i = 0; i < PAGE_ROUND_UP(RegionSize) / PAGE_SIZE; i++)
-        {
-            SWAPENTRY SwapEntry;
-            PVOID Address = (char*)BaseAddress + (i * PAGE_SIZE);
-            ULONG Protect = NewProtect;
-
-            /* Wait for a wait entry to disappear */
-            do
-            {
-                MmGetPageFileMapping(Process, Address, &SwapEntry);
-                if (SwapEntry != MM_WAIT_ENTRY)
-                    break;
-                MiWaitForPageEvent(Process, Address);
-            }
-            while (TRUE);
-
-            /*
-             * If we doing COW for this segment then check if the page is
-             * already private.
-             */
-            if (DoCOW && MmIsPagePresent(Process, Address))
-            {
-                LARGE_INTEGER Offset;
-                ULONG_PTR Entry;
-                PFN_NUMBER Page;
-
-                Offset.QuadPart = (ULONG_PTR)Address - MA_GetStartingAddress(MemoryArea)
-                                  + MemoryArea->Data.SectionData.ViewOffset.QuadPart;
-                Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
-                /*
-                 * An MM_WAIT_ENTRY is ok in this case...  It'll just count as
-                 * IS_SWAP_FROM_SSE and we'll do the right thing.
-                 */
-                Page = MmGetPfnForProcess(Process, Address);
-
-                Protect = PAGE_READONLY;
-                if (Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
-                        IS_SWAP_FROM_SSE(Entry) ||
-                        PFN_FROM_SSE(Entry) != Page)
-                {
-                    Protect = NewProtect;
-                }
-            }
-
-            if (MmIsPagePresent(Process, Address) || MmIsDisabledPage(Process, Address))
-            {
-                MmSetPageProtect(Process, Address,
-                                 Protect);
-            }
-        }
-    }
-
-    MmUnlockSectionSegment(Segment);
-}
-
 NTSTATUS
 NTAPI
 MmProtectSectionView(PMMSUPPORT AddressSpace,
@@ -3724,7 +3743,7 @@ MmCreateImageSection(PROS_SECTION_OBJECT *SectionObject,
         return STATUS_INVALID_FILE_FOR_SECTION;
 
 #ifndef NEWCC
-    if (FileObject->SectionObjectPointer->SharedCacheMap == NULL)
+    if (!CcIsFileCached(FileObject))
     {
         DPRINT1("Denying section creation due to missing cache initialization\n");
         return STATUS_INVALID_FILE_FOR_SECTION;
@@ -3758,17 +3777,7 @@ MmCreateImageSection(PROS_SECTION_OBJECT *SectionObject,
     Section->SectionPageProtection = SectionPageProtection;
     Section->AllocationAttributes = AllocationAttributes;
 
-#ifndef NEWCC
-    /*
-     * Initialized caching for this file object if previously caching
-     * was initialized for the same on disk file
-     */
-    Status = CcTryToInitializeFileCache(FileObject);
-#else
-    Status = STATUS_SUCCESS;
-#endif
-
-    if (!NT_SUCCESS(Status) || FileObject->SectionObjectPointer->ImageSectionObject == NULL)
+    if (FileObject->SectionObjectPointer->ImageSectionObject == NULL)
     {
         NTSTATUS StatusExeFmt;