mirror of
https://github.com/reactos/reactos.git
synced 2024-07-01 10:20:03 +00:00
[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:
parent
4f1b5e8e7b
commit
b3b73888b1
|
@ -496,6 +496,12 @@ MmIsSessionAddress(
|
||||||
IN PVOID Address
|
IN PVOID Address
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
MmGetSessionId(
|
||||||
|
IN PEPROCESS Process
|
||||||
|
);
|
||||||
|
|
||||||
/* marea.c *******************************************************************/
|
/* marea.c *******************************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -1114,8 +1114,7 @@ ULONG
|
||||||
NTAPI
|
NTAPI
|
||||||
PsGetCurrentProcessSessionId(VOID)
|
PsGetCurrentProcessSessionId(VOID)
|
||||||
{
|
{
|
||||||
// FIXME: this is broken!
|
return MmGetSessionId(PsGetCurrentProcess());
|
||||||
return PtrToUlong(PsGetCurrentProcess()->Session);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue