xref: /reactos/ntoskrnl/mm/ARM3/drvmgmt.c (revision 6afbc8f4)
1 /*
2  * PROJECT:         ReactOS Kernel
3  * LICENSE:         BSD - See COPYING.ARM in the top level directory
4  * FILE:            ntoskrnl/mm/ARM3/drvmgmt.c
5  * PURPOSE:         ARM Memory Manager Driver Management
6  * PROGRAMMERS:     ReactOS Portable Systems Group
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 #line 15 "ARM³::DRVMGMT"
16 #define MODULE_INVOLVED_IN_ARM3
17 #include "../ARM3/miarm.h"
18 
19 /* GLOBALS *******************************************************************/
20 
21 MM_DRIVER_VERIFIER_DATA MmVerifierData;
22 LIST_ENTRY MiVerifierDriverAddedThunkListHead;
23 ULONG MiActiveVerifierThunks;
24 
25 /* PRIVATE FUNCTIONS *********************************************************/
26 
27 PLDR_DATA_TABLE_ENTRY
28 NTAPI
29 MiLookupDataTableEntry(IN PVOID Address)
30 {
31     PLDR_DATA_TABLE_ENTRY LdrEntry, FoundEntry = NULL;
32     PLIST_ENTRY NextEntry;
33     PAGED_CODE();
34 
35     //
36     // Loop entries
37     //
38     NextEntry = PsLoadedModuleList.Flink;
39     do
40     {
41         //
42         // Get the loader entry
43         //
44         LdrEntry =  CONTAINING_RECORD(NextEntry,
45                                       LDR_DATA_TABLE_ENTRY,
46                                       InLoadOrderLinks);
47 
48         //
49         // Check if the address matches
50         //
51         if ((Address >= LdrEntry->DllBase) &&
52             (Address < (PVOID)((ULONG_PTR)LdrEntry->DllBase +
53                                LdrEntry->SizeOfImage)))
54         {
55             //
56             // Found a match
57             //
58             FoundEntry = LdrEntry;
59             break;
60         }
61 
62         //
63         // Move on
64         //
65         NextEntry = NextEntry->Flink;
66     } while(NextEntry != &PsLoadedModuleList);
67 
68     //
69     // Return the entry
70     //
71     return FoundEntry;
72 }
73 
74 /* PUBLIC FUNCTIONS ***********************************************************/
75 
76 /*
77  * @unimplemented
78  */
79 VOID
80 NTAPI
81 MmUnlockPageableImageSection(IN PVOID ImageSectionHandle)
82 {
83     UNIMPLEMENTED;
84 }
85 
86 /*
87  * @unimplemented
88  */
89 VOID
90 NTAPI
91 MmLockPageableSectionByHandle(IN PVOID ImageSectionHandle)
92 {
93     UNIMPLEMENTED;
94 }
95 
96 /*
97  * @unimplemented
98  */
99 PVOID
100 NTAPI
101 MmLockPageableDataSection(IN PVOID AddressWithinSection)
102 {
103     //
104     // We should just find the section and call MmLockPageableSectionByHandle
105     //
106     UNIMPLEMENTED;
107     return AddressWithinSection;
108 }
109 
110 /*
111  * @unimplemented
112  */
113 PVOID
114 NTAPI
115 MmPageEntireDriver(IN PVOID AddressWithinSection)
116 {
117     //PMMPTE StartPte, EndPte;
118     PLDR_DATA_TABLE_ENTRY LdrEntry;
119     PAGED_CODE();
120 
121     //
122     // Get the loader entry
123     //
124     LdrEntry = MiLookupDataTableEntry(AddressWithinSection);
125     if (!LdrEntry) return NULL;
126 
127     //
128     // Check if paging of kernel mode is disabled or if the driver is mapped as
129     // an image
130     //
131     if ((MmDisablePagingExecutive & 0x1) || (LdrEntry->SectionPointer))
132     {
133         //
134         // Don't do anything, just return the base address
135         //
136         return LdrEntry->DllBase;
137     }
138 
139     //
140     // Wait for active DPCs to finish before we page out the driver
141     //
142     KeFlushQueuedDpcs();
143 
144     //
145     // Get the PTE range for the whole driver image
146     //
147     //StartPte = MiGetPteAddress(LdrEntry->DllBase);
148     //EndPte = MiGetPteAddress(LdrEntry->DllBase +
149     //                         LdrEntry->SizeOfImage);
150 
151     //
152     // Enable paging for the PTE range
153     //
154     //MiSetPagingOfDriver(StartPte, EndPte);
155 
156     //
157     // Return the base address
158     //
159     return LdrEntry->DllBase;
160 }
161 
162 /*
163  * @unimplemented
164  */
165 VOID
166 NTAPI
167 MmResetDriverPaging(IN PVOID AddressWithinSection)
168 {
169     UNIMPLEMENTED;
170 }
171 
172 /*
173  * @unimplemented
174  */
175 ULONG
176 NTAPI
177 MmTrimAllSystemPageableMemory(IN ULONG PurgeTransitionList)
178 {
179 	UNIMPLEMENTED;
180 	return 0;
181 }
182 
183 /*
184  * @implemented
185  */
186 NTSTATUS
187 NTAPI
188 MmAddVerifierThunks(IN PVOID ThunkBuffer,
189                     IN ULONG ThunkBufferSize)
190 {
191     PDRIVER_VERIFIER_THUNK_PAIRS ThunkTable;
192     ULONG ThunkCount;
193     PDRIVER_SPECIFIED_VERIFIER_THUNKS DriverThunks;
194     PLDR_DATA_TABLE_ENTRY LdrEntry;
195     PVOID ModuleBase, ModuleEnd;
196     ULONG i;
197     NTSTATUS Status = STATUS_SUCCESS;
198     PAGED_CODE();
199 
200     //
201     // Make sure the driver verifier is initialized
202     //
203     if (!MiVerifierDriverAddedThunkListHead.Flink) return STATUS_NOT_SUPPORTED;
204 
205     //
206     // Get the thunk pairs and count them
207     //
208     ThunkCount = ThunkBufferSize / sizeof(DRIVER_VERIFIER_THUNK_PAIRS);
209     if (!ThunkCount) return STATUS_INVALID_PARAMETER_1;
210 
211     //
212     // Now allocate our own thunk table
213     //
214     DriverThunks = ExAllocatePoolWithTag(PagedPool,
215                                          sizeof(*DriverThunks) +
216                                          ThunkCount *
217                                          sizeof(DRIVER_VERIFIER_THUNK_PAIRS),
218                                          'tVmM');
219     if (!DriverThunks) return STATUS_INSUFFICIENT_RESOURCES;
220 
221     //
222     // Now copy the driver-fed part
223     //
224     ThunkTable = (PDRIVER_VERIFIER_THUNK_PAIRS)(DriverThunks + 1);
225     RtlCopyMemory(ThunkTable,
226                   ThunkBuffer,
227                   ThunkCount * sizeof(DRIVER_VERIFIER_THUNK_PAIRS));
228 
229     //
230     // Acquire the system load lock
231     //
232     KeEnterCriticalRegion();
233     KeWaitForSingleObject(&MmSystemLoadLock,
234                           WrVirtualMemory,
235                           KernelMode,
236                           FALSE,
237                           NULL);
238 
239     //
240     // Get the loader entry
241     //
242     LdrEntry = MiLookupDataTableEntry(ThunkTable->PristineRoutine);
243     if (!LdrEntry)
244     {
245         //
246         // Fail
247         //
248         Status = STATUS_INVALID_PARAMETER_2;
249         goto Cleanup;
250     }
251 
252     //
253     // Get driver base and end
254     //
255     ModuleBase = LdrEntry->DllBase;
256     ModuleEnd = (PVOID)((ULONG_PTR)LdrEntry->DllBase + LdrEntry->SizeOfImage);
257 
258     //
259     // Don't allow hooking the kernel or HAL
260     //
261     if (ModuleBase < (PVOID)(KSEG0_BASE + MmBootImageSize))
262     {
263         //
264         // Fail
265         //
266         Status = STATUS_INVALID_PARAMETER_2;
267         goto Cleanup;
268     }
269 
270     //
271     // Loop all the thunks
272     //
273     for (i = 0; i < ThunkCount; i++)
274     {
275         //
276         // Make sure it's in the driver
277         //
278         if (((ULONG_PTR)ThunkTable->PristineRoutine < (ULONG_PTR)ModuleBase) ||
279             ((ULONG_PTR)ThunkTable->PristineRoutine >= (ULONG_PTR)ModuleEnd))
280         {
281             //
282             // Nope, fail
283             //
284             Status = STATUS_INVALID_PARAMETER_2;
285             goto Cleanup;
286         }
287     }
288 
289     //
290     // Otherwise, add this entry
291     //
292     DriverThunks->DataTableEntry = LdrEntry;
293     DriverThunks->NumberOfThunks = ThunkCount;
294     MiActiveVerifierThunks++;
295     InsertTailList(&MiVerifierDriverAddedThunkListHead,
296                    &DriverThunks->ListEntry);
297     DriverThunks = NULL;
298 
299 Cleanup:
300     //
301     // Release the lock
302     //
303     KeReleaseMutant(&MmSystemLoadLock, 1, FALSE, FALSE);
304     KeLeaveCriticalRegion();
305 
306     //
307     // Free the table if we failed and return status
308     //
309     if (DriverThunks) ExFreePool(DriverThunks);
310     return Status;
311 }
312 
313 /*
314  * @implemented
315  */
316 LOGICAL
317 NTAPI
318 MmIsDriverVerifying(IN PDRIVER_OBJECT DriverObject)
319 {
320     PLDR_DATA_TABLE_ENTRY LdrEntry;
321 
322     //
323     // Get the loader entry
324     //
325     LdrEntry = (PLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection;
326     if (!LdrEntry) return FALSE;
327 
328     //
329     // Check if we're verifying or not
330     //
331     return (LdrEntry->Flags & LDRP_IMAGE_VERIFYING) ? TRUE: FALSE;
332 }
333 
334 /*
335  * @implemented
336  */
337 NTSTATUS
338 NTAPI
339 MmIsVerifierEnabled(OUT PULONG VerifierFlags)
340 {
341     //
342     // Check if we've actually added anything to the list
343     //
344     if (MiVerifierDriverAddedThunkListHead.Flink)
345     {
346         //
347         // We have, read the verifier level
348         //
349         *VerifierFlags = MmVerifierData.Level;
350         return STATUS_SUCCESS;
351     }
352 
353     //
354     // Otherwise, we're disabled
355     //
356     *VerifierFlags = 0;
357     return STATUS_NOT_SUPPORTED;
358 }
359 
360 /* EOF */
361