[NTOSKRNL]: Implement last bits of session space support (minus session pool). Processes now have a ->Session pointer! Implement and enable MmSessionId in a bunch of places.

[NTOSKRNL]: Set MiSessionSpaceWs address and use where needed.
[NTOSKRNL]: Initialize the session working set, and add support to MiLockWorkingSet and MiUnlockWorkingSet for session WS.
[NTOSKRNL]: Implement MiSessionAddProcess and MiSessionRemoveProcess which does the work required for this.
[NTOSKRNL]: Fix IoGetIrpRequestorProcess.
In my private branch, MmMapViewInSessionSpace is working fine for the user and GDI heaps. Will enable after TestBot tests.

svn path=/trunk/; revision=57011
This commit is contained in:
Alex Ionescu 2012-08-01 07:54:37 +00:00
parent 4f1b5e8e7b
commit b3b73888b1
10 changed files with 462 additions and 46 deletions

View file

@ -496,6 +496,12 @@ MmIsSessionAddress(
IN PVOID Address IN PVOID Address
); );
ULONG
NTAPI
MmGetSessionId(
IN PEPROCESS Process
);
/* marea.c *******************************************************************/ /* marea.c *******************************************************************/
NTSTATUS NTSTATUS

View file

@ -1615,7 +1615,14 @@ IoGetRequestorProcess(IN PIRP Irp)
/* Return the requestor process */ /* Return the requestor process */
if (Irp->Tail.Overlay.Thread) if (Irp->Tail.Overlay.Thread)
{ {
return Irp->Tail.Overlay.Thread->ThreadsProcess; if (Irp->ApcEnvironment == OriginalApcEnvironment)
{
return Irp->Tail.Overlay.Thread->ThreadsProcess;
}
else if (Irp->ApcEnvironment == AttachedApcEnvironment)
{
return (PEPROCESS)Irp->Tail.Overlay.Thread->Tcb.ApcState.Process;
}
} }
return NULL; return NULL;
@ -1631,10 +1638,8 @@ IoGetRequestorProcessId(IN PIRP Irp)
PEPROCESS Process; PEPROCESS Process;
/* Return the requestor process' id */ /* Return the requestor process' id */
if ((Process = IoGetRequestorProcess(Irp))) Process = IoGetRequestorProcess(Irp);
{ if (Process) return PtrToUlong(Process->UniqueProcessId);
return PtrToUlong(Process->UniqueProcessId);
}
return 0; return 0;
} }
@ -1650,10 +1655,10 @@ IoGetRequestorSessionId(IN PIRP Irp,
PEPROCESS Process; PEPROCESS Process;
/* Return the session */ /* Return the session */
if ((Process = IoGetRequestorProcess(Irp))) if (Irp->Tail.Overlay.Thread)
{ {
// FIXME: broken Process = Irp->Tail.Overlay.Thread->ThreadsProcess;
*pSessionId = PtrToUlong(Process->Session); *pSessionId = MmGetSessionId(Process);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }

View file

@ -110,6 +110,7 @@ MiInitializeSessionSpaceLayout()
MiSessionImagePteStart = MiAddressToPte(MiSessionImageStart); MiSessionImagePteStart = MiAddressToPte(MiSessionImageStart);
MiSessionImagePteEnd = MiAddressToPte(MiSessionImageEnd); MiSessionImagePteEnd = MiAddressToPte(MiSessionImageEnd);
MiSessionBasePte = MiAddressToPte(MmSessionBase); MiSessionBasePte = MiAddressToPte(MmSessionBase);
MiSessionSpaceWs = (PVOID)((ULONG_PTR)MiSessionViewStart + MmSessionViewSize);
MiSessionLastPte = MiAddressToPte(MiSessionSpaceEnd); MiSessionLastPte = MiAddressToPte(MiSessionSpaceEnd);
/* Initialize session space */ /* Initialize session space */

View file

@ -687,6 +687,7 @@ extern PVOID MiSystemViewStart;
extern PVOID MiSessionPoolEnd; // 0xBE000000 extern PVOID MiSessionPoolEnd; // 0xBE000000
extern PVOID MiSessionPoolStart; // 0xBD000000 extern PVOID MiSessionPoolStart; // 0xBD000000
extern PVOID MiSessionViewStart; // 0xBE000000 extern PVOID MiSessionViewStart; // 0xBE000000
extern PVOID MiSessionSpaceWs;
extern ULONG MmMaximumDeadKernelStacks; extern ULONG MmMaximumDeadKernelStacks;
extern SLIST_HEADER MmDeadStackSListHead; extern SLIST_HEADER MmDeadStackSListHead;
extern MM_AVL_TABLE MmSectionBasedRoot; extern MM_AVL_TABLE MmSectionBasedRoot;
@ -1059,9 +1060,10 @@ MiLockWorkingSet(IN PETHREAD Thread,
} }
else if (WorkingSet->Flags.SessionSpace) else if (WorkingSet->Flags.SessionSpace)
{ {
/* We don't implement this yet */ /* Own the session working set */
UNIMPLEMENTED; ASSERT((Thread->OwnsSessionWorkingSetExclusive == FALSE) &&
while (TRUE); (Thread->OwnsSessionWorkingSetShared == FALSE));
Thread->OwnsSessionWorkingSetExclusive = TRUE;
} }
else else
{ {
@ -1093,9 +1095,10 @@ MiUnlockWorkingSet(IN PETHREAD Thread,
} }
else if (WorkingSet->Flags.SessionSpace) else if (WorkingSet->Flags.SessionSpace)
{ {
/* We don't implement this yet */ /* Release the session working set */
UNIMPLEMENTED; ASSERT((Thread->OwnsSessionWorkingSetExclusive == TRUE) ||
while (TRUE); (Thread->OwnsSessionWorkingSetShared == TRUE));
Thread->OwnsSessionWorkingSetExclusive = 0;
} }
else else
{ {
@ -1610,6 +1613,24 @@ MiInitializeSystemSpaceMap(
IN PMMSESSION InputSession OPTIONAL IN PMMSESSION InputSession OPTIONAL
); );
VOID
NTAPI
MiSessionRemoveProcess(
VOID
);
VOID
NTAPI
MiReleaseProcessReferenceToSessionDataPage(
IN PMM_SESSION_SPACE SessionGlobal
);
VOID
NTAPI
MiSessionAddProcess(
IN PEPROCESS NewProcess
);
NTSTATUS NTSTATUS
NTAPI NTAPI
MiSessionCommitPageTables( MiSessionCommitPageTables(

View file

@ -128,6 +128,7 @@ PFN_NUMBER MmSizeOfPagedPoolInPages = MI_MIN_INIT_PAGED_POOLSIZE / PAGE_SIZE;
PVOID MiSessionSpaceEnd; // 0xC0000000 PVOID MiSessionSpaceEnd; // 0xC0000000
PVOID MiSessionImageEnd; // 0xC0000000 PVOID MiSessionImageEnd; // 0xC0000000
PVOID MiSessionImageStart; // 0xBF800000 PVOID MiSessionImageStart; // 0xBF800000
PVOID MiSessionSpaceWs;
PVOID MiSessionViewStart; // 0xBE000000 PVOID MiSessionViewStart; // 0xBE000000
PVOID MiSessionPoolEnd; // 0xBE000000 PVOID MiSessionPoolEnd; // 0xBE000000
PVOID MiSessionPoolStart; // 0xBD000000 PVOID MiSessionPoolStart; // 0xBD000000

View file

@ -153,9 +153,79 @@ NTSTATUS
FASTCALL FASTCALL
MiCheckPdeForSessionSpace(IN PVOID Address) MiCheckPdeForSessionSpace(IN PVOID Address)
{ {
/* Code not yet tested */ MMPTE TempPde;
ASSERT(FALSE); PMMPTE PointerPde;
return STATUS_NOT_IMPLEMENTED; PVOID SessionPageTable;
ULONG Index;
/* Is this a session PTE? */
if (MI_IS_SESSION_PTE(Address))
{
/* Make sure the PDE for session space is valid */
PointerPde = MiAddressToPde(MmSessionSpace);
if (!PointerPde->u.Hard.Valid)
{
/* This means there's no valid session, bail out */
DbgPrint("MiCheckPdeForSessionSpace: No current session for PTE %p\n",
Address);
DbgBreakPoint();
return STATUS_ACCESS_VIOLATION;
}
/* Now get the session-specific page table for this address */
SessionPageTable = MiPteToAddress(Address);
PointerPde = MiPteToAddress(Address);
if (PointerPde->u.Hard.Valid) return STATUS_WAIT_1;
/* It's not valid, so find it in the page table array */
Index = ((ULONG_PTR)SessionPageTable - (ULONG_PTR)MmSessionBase) >> 22;
TempPde.u.Long = MmSessionSpace->PageTables[Index].u.Long;
if (TempPde.u.Hard.Valid)
{
/* The copy is valid, so swap it in */
InterlockedExchange((PLONG)PointerPde, TempPde.u.Long);
return STATUS_WAIT_1;
}
/* We don't seem to have allocated a page table for this address yet? */
DbgPrint("MiCheckPdeForSessionSpace: No Session PDE for PTE %p, %p\n",
PointerPde->u.Long, SessionPageTable);
DbgBreakPoint();
return STATUS_ACCESS_VIOLATION;
}
/* Is the address also a session address? If not, we're done */
if (!MI_IS_SESSION_ADDRESS(Address)) return STATUS_SUCCESS;
/* It is, so again get the PDE for session space */
PointerPde = MiAddressToPde(MmSessionSpace);
if (!PointerPde->u.Hard.Valid)
{
/* This means there's no valid session, bail out */
DbgPrint("MiCheckPdeForSessionSpace: No current session for VA %p\n",
Address);
DbgBreakPoint();
return STATUS_ACCESS_VIOLATION;
}
/* Now get the PDE for the address itself */
PointerPde = MiAddressToPde(Address);
if (!PointerPde->u.Hard.Valid)
{
/* Do the swap, we should be good to go */
Index = ((ULONG_PTR)Address - (ULONG_PTR)MmSessionBase) >> 22;
PointerPde->u.Long = MmSessionSpace->PageTables[Index].u.Long;
if (PointerPde->u.Hard.Valid) return STATUS_WAIT_1;
/* We had not allocated a page table for this session address yet, fail! */
DbgPrint("MiCheckPdeForSessionSpace: No Session PDE for VA %p, %p\n",
PointerPde->u.Long, Address);
DbgBreakPoint();
return STATUS_ACCESS_VIOLATION;
}
/* It's valid, so there's nothing to do */
return STATUS_SUCCESS;
} }
NTSTATUS NTSTATUS
@ -305,16 +375,14 @@ MiResolveDemandZeroFault(IN PVOID Address,
/* Check if we need a zero page */ /* Check if we need a zero page */
NeedZero = (OldIrql != MM_NOIRQL); NeedZero = (OldIrql != MM_NOIRQL);
#if 0
/* Session-backed image views must be zeroed */ /* Session-backed image views must be zeroed */
if ((Process == HYDRA_PROCESS) && if ((Process == HYDRA_PROCESS) &&
((MI_IS_SESSION_IMAGE_ADDRESS(Address)) || ((MI_IS_SESSION_IMAGE_ADDRESS(Address)) ||
((Address >= (PVOID)MiSessionViewStart) && ((Address >= MiSessionViewStart) && (Address < MiSessionSpaceWs))))
(Address < (PVOID)MiSessionSpaceWs))))
{ {
NeedZero = TRUE; NeedZero = TRUE;
} }
#endif
/* Hardcode unknown color */ /* Hardcode unknown color */
Color = 0xFFFFFFFF; Color = 0xFFFFFFFF;
} }
@ -1200,18 +1268,22 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
else
{
/* Not yet handled */
ASSERT(FALSE);
}
} }
/* Check if this was a session PTE that needs to remap the session PDE */ /* Check if this was a session PTE that needs to remap the session PDE */
if (MI_IS_SESSION_PTE(Address)) if (MI_IS_SESSION_PTE(Address))
{ {
/* Not yet handled */ /* Do the remapping */
ASSERT(FALSE); Status = MiCheckPdeForSessionSpace(Address);
if (!NT_SUCCESS(Status))
{
/* It failed, this address is invalid */
KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
(ULONG_PTR)Address,
StoreInstruction,
(ULONG_PTR)TrapInformation,
6);
}
} }
/* Check for a fault on the page table or hyperspace */ /* Check for a fault on the page table or hyperspace */
@ -1249,8 +1321,17 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
} }
else else
{ {
/* Not yet handled */ /* Use the session process and working set */
ASSERT(FALSE); CurrentProcess = HYDRA_PROCESS;
WorkingSet = &MmSessionSpace->GlobalVirtualAddress->Vm;
/* Make sure we don't have a recursive working set lock */
if ((CurrentThread->OwnsSessionWorkingSetExclusive) ||
(CurrentThread->OwnsSessionWorkingSetShared))
{
/* Fail */
return STATUS_IN_PAGE_ERROR | 0x10000000;
}
} }
/* Acquire the working set lock */ /* Acquire the working set lock */
@ -1282,8 +1363,28 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
} }
} }
/* Case not yet handled */ /* Check for read-only write in session space */
ASSERT(!IsSessionAddress); if ((IsSessionAddress) &&
(StoreInstruction) &&
!(TempPte.u.Hard.Write))
{
/* Sanity check */
ASSERT(MI_IS_SESSION_IMAGE_ADDRESS(Address));
/* Was this COW? */
if (TempPte.u.Hard.CopyOnWrite == 0)
{
/* Then this is not allowed */
KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
(ULONG_PTR)Address,
(ULONG_PTR)TempPte.u.Long,
(ULONG_PTR)TrapInformation,
13);
}
/* Otherwise, handle COW */
ASSERT(FALSE);
}
/* Release the working set */ /* Release the working set */
MiUnlockWorkingSet(CurrentThread, WorkingSet); MiUnlockWorkingSet(CurrentThread, WorkingSet);
@ -1315,8 +1416,16 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
/* Get the prototype PTE! */ /* Get the prototype PTE! */
ProtoPte = MiProtoPteToPte(&TempPte); ProtoPte = MiProtoPteToPte(&TempPte);
/* Case not yet handled */ /* Do we need to locate the prototype PTE in session space? */
ASSERT(!IsSessionAddress); if ((IsSessionAddress) &&
(TempPte.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED))
{
/* Yep, go find it as well as the VAD for it */
ProtoPte = MiCheckVirtualAddress(Address,
&ProtectionCode,
&Vad);
ASSERT(ProtoPte != NULL);
}
} }
else else
{ {

View file

@ -577,9 +577,7 @@ MmGetSessionLocaleId(VOID)
// //
// Get the Locale ID // Get the Locale ID
// //
#if ROS_HAS_SESSIONS
return ((PMM_SESSION_SPACE)Process->Session)->LocaleId; return ((PMM_SESSION_SPACE)Process->Session)->LocaleId;
#endif
} }
} }
@ -698,7 +696,7 @@ MmCreatePeb(IN PEPROCESS Process,
// //
// Session ID // Session ID
// //
if (Process->Session) Peb->SessionId = 0; // MmGetSessionId(Process); MmGetSessionId(Process);
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
@ -1317,6 +1315,9 @@ MmCreateProcessAddressSpace(IN ULONG MinWs,
/* Let go of the system PTE */ /* Let go of the system PTE */
MiReleaseSystemPtes(PointerPte, 1, SystemPteSpace); MiReleaseSystemPtes(PointerPte, 1, SystemPteSpace);
/* Add the process to the session */
MiSessionAddProcess(Process);
return TRUE; return TRUE;
} }
#endif #endif
@ -1332,6 +1333,9 @@ MmCleanProcessAddressSpace(IN PEPROCESS Process)
/* Only support this */ /* Only support this */
ASSERT(Process->AddressSpaceInitialized == 2); ASSERT(Process->AddressSpaceInitialized == 2);
/* Remove from the session */
MiSessionRemoveProcess();
/* Lock the process address space from changes */ /* Lock the process address space from changes */
MmLockAddressSpace(&Process->Vm); MmLockAddressSpace(&Process->Vm);
@ -1383,6 +1387,7 @@ MmCleanProcessAddressSpace(IN PEPROCESS Process)
/* Free the VAD memory */ /* Free the VAD memory */
ExFreePool(Vad); ExFreePool(Vad);
} }
/* Delete the shared user data section */ /* Delete the shared user data section */
MiDeleteVirtualAddresses(USER_SHARED_DATA, USER_SHARED_DATA, NULL); MiDeleteVirtualAddresses(USER_SHARED_DATA, USER_SHARED_DATA, NULL);
@ -1447,8 +1452,8 @@ MmDeleteProcessAddressSpace2(IN PEPROCESS Process)
/* Release the PFN lock */ /* Release the PFN lock */
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
/* No support for sessions yet */ /* Drop a reference on the session */
ASSERT(Process->Session == 0); if (Process->Session) MiReleaseProcessReferenceToSessionDataPage(Process->Session);
/* Clear out the PDE pages */ /* Clear out the PDE pages */
Process->Pcb.DirectoryTableBase[0] = 0; Process->Pcb.DirectoryTableBase[0] = 0;
@ -1528,6 +1533,257 @@ MiSessionLeader(IN PEPROCESS Process)
KeReleaseQueuedSpinLock(LockQueueExpansionLock, OldIrql); KeReleaseQueuedSpinLock(LockQueueExpansionLock, OldIrql);
} }
ULONG
NTAPI
MmGetSessionId(IN PEPROCESS Process)
{
PMM_SESSION_SPACE SessionGlobal;
/* The session leader is always session zero */
if (Process->Vm.Flags.SessionLeader == 1) return 0;
/* Otherwise, get the session global, and read the session ID from it */
SessionGlobal = (PMM_SESSION_SPACE)Process->Session;
if (!SessionGlobal) return 0;
return SessionGlobal->SessionId;
}
VOID
NTAPI
MiReleaseProcessReferenceToSessionDataPage(IN PMM_SESSION_SPACE SessionGlobal)
{
ULONG i, SessionId;
PMMPTE PointerPte;
PFN_NUMBER PageFrameIndex[MI_SESSION_DATA_PAGES_MAXIMUM];
PMMPFN Pfn1;
KIRQL OldIrql;
/* Is there more than just this reference? If so, bail out */
if (InterlockedDecrement(&SessionGlobal->ProcessReferenceToSession)) return;
/* Get the session ID */
SessionId = SessionGlobal->SessionId;
DPRINT1("Last process in sessino %d going down!!!\n", SessionId);
/* Free the session page tables */
ExFreePool(SessionGlobal->PageTables);
ASSERT(!MI_IS_PHYSICAL_ADDRESS(SessionGlobal));
/* Capture the data page PFNs */
PointerPte = MiAddressToPte(SessionGlobal);
for (i = 0; i < MiSessionDataPages; i++)
{
PageFrameIndex[i] = PFN_FROM_PTE(PointerPte + i);
}
/* Release them */
MiReleaseSystemPtes(PointerPte, MiSessionDataPages, SystemPteSpace);
/* Mark them as deleted */
for (i = 0; i < MiSessionDataPages; i++)
{
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex[i]);
MI_SET_PFN_DELETED(Pfn1);
}
/* Loop every data page and drop a reference count */
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
for (i = 0; i < MiSessionDataPages; i++)
{
/* Sanity check that the page is correct, then decrement it */
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex[i]);
ASSERT(Pfn1->u2.ShareCount == 1);
ASSERT(Pfn1->u3.e2.ReferenceCount == 1);
MiDecrementShareCount(Pfn1, PageFrameIndex[i]);
}
/* Done playing with pages, release the lock */
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
/* Decrement the number of data pages */
InterlockedDecrement(&MmSessionDataPages);
/* Free this session ID from the session bitmap */
KeAcquireGuardedMutex(&MiSessionIdMutex);
ASSERT(RtlCheckBit(MiSessionIdBitmap, SessionId));
RtlClearBit(MiSessionIdBitmap, SessionId);
KeReleaseGuardedMutex(&MiSessionIdMutex);
}
VOID
NTAPI
MiSessionRemoveProcess(VOID)
{
PEPROCESS CurrentProcess = PsGetCurrentProcess();
/* If the process isn't already in a session, or if it's the leader... */
if (!(CurrentProcess->Flags & PSF_PROCESS_IN_SESSION_BIT) ||
(CurrentProcess->Vm.Flags.SessionLeader))
{
/* Then there's nothing to do */
return;
}
/* Sanity check */
ASSERT(MmIsAddressValid(MmSessionSpace) == TRUE);
/* Remove the process from the list ,and dereference the session */
RemoveEntryList(&CurrentProcess->SessionProcessLinks);
//MiDereferenceSession();
}
VOID
NTAPI
MiSessionAddProcess(IN PEPROCESS NewProcess)
{
PMM_SESSION_SPACE SessionGlobal;
/* The current process must already be in a session */
if (!(PsGetCurrentProcess()->Flags & PSF_PROCESS_IN_SESSION_BIT)) return;
/* Sanity check */
ASSERT(MmIsAddressValid(MmSessionSpace) == TRUE);
/* Get the global session */
SessionGlobal = MmSessionSpace->GlobalVirtualAddress;
/* Increment counters */
InterlockedIncrement((PLONG)&SessionGlobal->ReferenceCount);
InterlockedIncrement(&SessionGlobal->ResidentProcessCount);
InterlockedIncrement(&SessionGlobal->ProcessReferenceToSession);
/* Set the session pointer */
ASSERT(NewProcess->Session == NULL);
NewProcess->Session = SessionGlobal;
/* Insert it into the process list */
InsertTailList(&SessionGlobal->ProcessList, &NewProcess->SessionProcessLinks);
/* Set the flag */
PspSetProcessFlag(NewProcess, PSF_PROCESS_IN_SESSION_BIT);
}
NTSTATUS
NTAPI
MiSessionInitializeWorkingSetList(VOID)
{
KIRQL OldIrql;
PMMPTE PointerPte, PointerPde;
MMPTE TempPte;
ULONG Color, Index;
PFN_NUMBER PageFrameIndex;
PMM_SESSION_SPACE SessionGlobal;
BOOLEAN AllocatedPageTable;
PMMWSL WorkingSetList;
/* Get pointers to session global and the session working set list */
SessionGlobal = MmSessionSpace->GlobalVirtualAddress;
WorkingSetList = (PMMWSL)MiSessionSpaceWs;
/* Fill out the two pointers */
MmSessionSpace->Vm.VmWorkingSetList = WorkingSetList;
MmSessionSpace->Wsle = (PMMWSLE)WorkingSetList->UsedPageTableEntries;
/* Get the PDE for the working set, and check if it's already allocated */
PointerPde = MiAddressToPde(WorkingSetList);
if (PointerPde->u.Hard.Valid == 1)
{
/* Nope, we'll have to do it */
ASSERT(PointerPde->u.Hard.Global == 0);
AllocatedPageTable = FALSE;
}
else
{
/* Yep, that makes our job easier */
AllocatedPageTable = TRUE;
}
/* Get the PTE for the working set */
PointerPte = MiAddressToPte(WorkingSetList);
/* Initialize the working set lock, and lock the PFN database */
ExInitializePushLock(&SessionGlobal->Vm.WorkingSetMutex);
//MmLockPageableSectionByHandle(ExPageLockHandle);
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
/* Check if we need a page table */
if (AllocatedPageTable == TRUE)
{
/* Get a zeroed colored zero page */
Color = MI_GET_NEXT_COLOR();
PageFrameIndex = MiRemoveZeroPageSafe(Color);
if (!PageFrameIndex)
{
/* No zero pages, grab a free one */
PageFrameIndex = MiRemoveAnyPage(Color);
/* Zero it outside the PFN lock */
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
MiZeroPhysicalPage(PageFrameIndex);
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
}
/* Write a valid PDE for it */
TempPte.u.Long = ValidKernelPdeLocal.u.Long;
TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
MI_WRITE_VALID_PTE(PointerPde, TempPte);
/* Add this into the list */
Index = ((ULONG_PTR)WorkingSetList - (ULONG_PTR)MmSessionBase) >> 22;
MmSessionSpace->PageTables[Index] = TempPte;
/* Initialize the page directory page, and now zero the working set list itself */
MiInitializePfnForOtherProcess(PageFrameIndex,
PointerPde,
MmSessionSpace->SessionPageDirectoryIndex);
KeZeroPages(PointerPte, PAGE_SIZE);
}
/* Get a zeroed colored zero page */
Color = MI_GET_NEXT_COLOR();
PageFrameIndex = MiRemoveZeroPageSafe(Color);
if (!PageFrameIndex)
{
/* No zero pages, grab a free one */
PageFrameIndex = MiRemoveAnyPage(Color);
/* Zero it outside the PFN lock */
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
MiZeroPhysicalPage(PageFrameIndex);
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
}
/* Write a valid PTE for it */
TempPte.u.Long = ValidKernelPteLocal.u.Long;
TempPte.u.Hard.Dirty = TRUE;
TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
/* Initialize the working set list page */
MiInitializePfnAndMakePteValid(PageFrameIndex, PointerPte, TempPte);
/* Now we can release the PFN database lock */
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
/* Fill out the working set structure */
MmSessionSpace->Vm.Flags.SessionSpace = 1;
MmSessionSpace->Vm.MinimumWorkingSetSize = 20;
MmSessionSpace->Vm.MaximumWorkingSetSize = 384;
WorkingSetList->LastEntry = 20;
WorkingSetList->HashTable = NULL;
WorkingSetList->HashTableSize = 0;
WorkingSetList->Wsle = MmSessionSpace->Wsle;
/* FIXME: Handle list insertions */
ASSERT(SessionGlobal->WsListEntry.Flink == NULL);
ASSERT(SessionGlobal->WsListEntry.Blink == NULL);
ASSERT(SessionGlobal->Vm.WorkingSetExpansionLinks.Flink == NULL);
ASSERT(SessionGlobal->Vm.WorkingSetExpansionLinks.Blink == NULL);
/* All done, return */
//MmUnlockPageableImageSection(ExPageLockHandle);
return STATUS_SUCCESS;
}
NTSTATUS NTSTATUS
NTAPI NTAPI
MiSessionCreateInternal(OUT PULONG SessionId) MiSessionCreateInternal(OUT PULONG SessionId)
@ -1770,12 +2026,31 @@ MmSessionCreate(OUT PULONG SessionId)
MiSessionLeader(Process); MiSessionLeader(Process);
} }
/* FIXME: Actually create a session */ /* Create the session */
KeEnterCriticalRegion(); KeEnterCriticalRegion();
Status = MiSessionCreateInternal(SessionId); Status = MiSessionCreateInternal(SessionId);
if (!NT_SUCCESS(Status))
{
KeLeaveCriticalRegion();
return Status;
}
/* Set up the session working set */
Status = MiSessionInitializeWorkingSetList();
if (!NT_SUCCESS(Status))
{
/* Fail */
//MiDereferenceSession();
ASSERT(FALSE);
KeLeaveCriticalRegion();
return Status;
}
/* All done */
KeLeaveCriticalRegion(); KeLeaveCriticalRegion();
/* Set and assert the flags, and return */ /* Set and assert the flags, and return */
MmSessionSpace->u.Flags.Initialized = 1;
PspSetProcessFlag(Process, PSF_PROCESS_IN_SESSION_BIT); PspSetProcessFlag(Process, PSF_PROCESS_IN_SESSION_BIT);
ASSERT(MiSessionLeaderExists == 1); ASSERT(MiSessionLeaderExists == 1);
return Status; return Status;

View file

@ -827,7 +827,7 @@ MiSessionCommitPageTables(IN PVOID StartVa,
/* Get the start and end PDE, then loop each one */ /* Get the start and end PDE, then loop each one */
StartPde = MiAddressToPde(StartVa); StartPde = MiAddressToPde(StartVa);
EndPde = MiAddressToPde((PVOID)((ULONG_PTR)EndVa - 1)); EndPde = MiAddressToPde((PVOID)((ULONG_PTR)EndVa - 1));
Index = (ULONG_PTR)StartVa >> 22; Index = ((ULONG_PTR)StartVa - (ULONG_PTR)MmSessionBase) >> 22;
while (StartPde <= EndPde) while (StartPde <= EndPde)
{ {
/* If we don't already have a page table for it, increment count */ /* If we don't already have a page table for it, increment count */
@ -843,7 +843,7 @@ MiSessionCommitPageTables(IN PVOID StartVa,
/* Reset the start PDE and index */ /* Reset the start PDE and index */
StartPde = MiAddressToPde(StartVa); StartPde = MiAddressToPde(StartVa);
Index = (ULONG_PTR)StartVa >> 22; Index = ((ULONG_PTR)StartVa - (ULONG_PTR)MmSessionBase) >> 22;
/* Loop each PDE while holding the working set lock */ /* Loop each PDE while holding the working set lock */
// MiLockWorkingSet(PsGetCurrentThread(), // MiLockWorkingSet(PsGetCurrentThread(),
@ -2330,7 +2330,6 @@ MmMapViewInSessionSpace(IN PVOID Section,
/* Use the system space API, but with the session view instead */ /* Use the system space API, but with the session view instead */
ASSERT(MmIsAddressValid(MmSessionSpace) == TRUE); ASSERT(MmIsAddressValid(MmSessionSpace) == TRUE);
ASSERT(FALSE);
return MiMapViewInSystemSpace(Section, return MiMapViewInSystemSpace(Section,
&MmSessionSpace->Session, &MmSessionSpace->Session,
MappedBase, MappedBase,

View file

@ -1114,8 +1114,7 @@ ULONG
NTAPI NTAPI
PsGetCurrentProcessSessionId(VOID) PsGetCurrentProcessSessionId(VOID)
{ {
// FIXME: this is broken! return MmGetSessionId(PsGetCurrentProcess());
return PtrToUlong(PsGetCurrentProcess()->Session);
} }
/* /*

View file

@ -86,7 +86,7 @@ PspInitializeProcessSecurity(IN PEPROCESS Process,
Status = SeSubProcessToken(ParentToken, Status = SeSubProcessToken(ParentToken,
&NewToken, &NewToken,
TRUE, TRUE,
0);//MmGetSessionId(Process)); MmGetSessionId(Process));
/* Dereference the Parent */ /* Dereference the Parent */
ObFastDereferenceObject(&Parent->Token, ParentToken); ObFastDereferenceObject(&Parent->Token, ParentToken);