mirror of
https://github.com/reactos/reactos.git
synced 2024-06-26 07:51:52 +00:00
- Implement Fast Referencing and fix EX_FAST_REF definition.
- Implement ObReferenceEx and ObDereferenceEx. - Split off ObpDeferObjectCompletion. A new win2003/vista API requires direct acess to being able to defer deletes. - Fix some bugs in Process Token management and make it all properly use Fast Referencing. - When duplicating a token in a new process, don't de-reference it before it's even created, and also insert it. - Change ExpChangeRundown macro to fix warnings in msvc. svn path=/trunk/; revision=23013
This commit is contained in:
parent
f8aab41375
commit
d2e356eda6
|
@ -361,8 +361,8 @@ typedef struct _EX_FAST_REF
|
|||
union
|
||||
{
|
||||
PVOID Object;
|
||||
ULONG RefCnt:3;
|
||||
ULONG Value;
|
||||
ULONG_PTR RefCnt:3;
|
||||
ULONG_PTR Value;
|
||||
};
|
||||
} EX_FAST_REF, *PEX_FAST_REF;
|
||||
|
||||
|
|
|
@ -267,7 +267,7 @@ static __inline _SEH_FILTER(_SEH_ExSystemExceptionFilter)
|
|||
#define ExpChangeRundown(x, y, z) InterlockedCompareExchange64((PLONGLONG)x, y, z)
|
||||
#define ExpSetRundown(x, y) InterlockedExchange64((PLONGLONG)x, y)
|
||||
#else
|
||||
#define ExpChangeRundown(x, y, z) InterlockedCompareExchange((PLONG)x, y, z)
|
||||
#define ExpChangeRundown(x, y, z) InterlockedCompareExchange((PLONG)x, PtrToLong(y), PtrToLong(z))
|
||||
#define ExpSetRundown(x, y) InterlockedExchange((PLONG)x, y)
|
||||
#endif
|
||||
|
||||
|
|
|
@ -120,6 +120,15 @@ VOID
|
|||
NTAPI
|
||||
SeDeassignPrimaryToken(struct _EPROCESS *Process);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SeSubProcessToken(
|
||||
IN PTOKEN Parent,
|
||||
OUT PTOKEN *Token,
|
||||
IN BOOLEAN InUse,
|
||||
IN ULONG SessionId
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
SepCreateImpersonationTokenDacl(
|
||||
|
|
|
@ -17,37 +17,183 @@
|
|||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ObpDeferObjectDeletion(IN PVOID Object)
|
||||
{
|
||||
POBJECT_HEADER Header = OBJECT_TO_OBJECT_HEADER(Object);
|
||||
|
||||
/* Add us to the list */
|
||||
do
|
||||
{
|
||||
Header->NextToFree = ObpReaperList;
|
||||
} while (InterlockedCompareExchangePointer(&ObpReaperList,
|
||||
Header,
|
||||
Header->NextToFree) !=
|
||||
Header->NextToFree);
|
||||
|
||||
/* Queue the work item */
|
||||
ExQueueWorkItem(&ObpReaperWorkItem, DelayedWorkQueue);
|
||||
}
|
||||
|
||||
LONG
|
||||
FASTCALL
|
||||
ObReferenceObjectEx(IN PVOID Object,
|
||||
IN ULONG Count)
|
||||
{
|
||||
/* Increment the reference count and return the count now */
|
||||
return InterlockedExchangeAdd(&OBJECT_TO_OBJECT_HEADER(Object)->
|
||||
PointerCount,
|
||||
Count);
|
||||
}
|
||||
|
||||
LONG
|
||||
FASTCALL
|
||||
ObDereferenceObjectEx(IN PVOID Object,
|
||||
IN ULONG Count)
|
||||
{
|
||||
POBJECT_HEADER Header;
|
||||
ULONG NewCount;
|
||||
|
||||
/* Extract the object header */
|
||||
Header = OBJECT_TO_OBJECT_HEADER(Object);
|
||||
|
||||
/* Check whether the object can now be deleted. */
|
||||
NewCount = InterlockedExchangeAdd(&Header->PointerCount, -Count);
|
||||
if (!Count)
|
||||
{
|
||||
/* Add us to the deferred deletion list */
|
||||
ObpDeferObjectDeletion(Object);
|
||||
}
|
||||
|
||||
/* Return the current count */
|
||||
return NewCount;
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
ObInitializeFastReference(IN PEX_FAST_REF FastRef,
|
||||
PVOID Object)
|
||||
IN PVOID Object OPTIONAL)
|
||||
{
|
||||
/* FIXME: Fast Referencing is Unimplemented */
|
||||
FastRef->Object = Object;
|
||||
/* Check if we were given an object and reference it 7 times */
|
||||
if (Object) ObReferenceObjectEx(Object, MAX_FAST_REFS);
|
||||
|
||||
/* Sanity check */
|
||||
ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
|
||||
|
||||
/* Check if the caller gave us an object */
|
||||
if (Object)
|
||||
{
|
||||
/* He did, so write the biased pointer */
|
||||
FastRef->Object = (PVOID)((ULONG_PTR)Object | MAX_FAST_REFS);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, clear the current object */
|
||||
FastRef->Object = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
PVOID
|
||||
FASTCALL
|
||||
ObFastReferenceObjectLocked(IN PEX_FAST_REF FastRef)
|
||||
{
|
||||
PVOID Object;
|
||||
|
||||
/* Get the object and reference it slowly */
|
||||
Object = (PVOID)((ULONG_PTR)FastRef->Object & MAX_FAST_REFS);
|
||||
if (Object) ObReferenceObject(Object);
|
||||
return Object;
|
||||
}
|
||||
|
||||
PVOID
|
||||
FASTCALL
|
||||
ObFastReferenceObject(IN PEX_FAST_REF FastRef)
|
||||
{
|
||||
/* FIXME: Fast Referencing is Unimplemented */
|
||||
ULONG_PTR Value, NewValue;
|
||||
ULONG_PTR Count;
|
||||
PVOID Object;
|
||||
|
||||
/* Do a normal Reference */
|
||||
ObReferenceObject(FastRef->Object);
|
||||
/* Start reference loop */
|
||||
for (;;)
|
||||
{
|
||||
/* Get the current count */
|
||||
Value = FastRef->Value;
|
||||
if (!Value & MAX_FAST_REFS) break;
|
||||
|
||||
/* Increase the reference count */
|
||||
NewValue = Value - 1;
|
||||
if (ExpChangeRundown(FastRef, NewValue, Value) == Value) break;
|
||||
}
|
||||
|
||||
/* Get the object and count */
|
||||
Object = (PVOID)(Value &~ MAX_FAST_REFS);
|
||||
Count = Value & MAX_FAST_REFS;
|
||||
DPRINT("Ref: %p\n", Object);
|
||||
|
||||
/* Check if the reference count is over 1 */
|
||||
if (Count > 1) return Object;
|
||||
|
||||
/* Check if the reference count has reached 0 */
|
||||
if (!Count) return NULL;
|
||||
|
||||
/* Otherwise, reference the object 7 times */
|
||||
ObReferenceObjectEx(Object, MAX_FAST_REFS);
|
||||
ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* Check if the current count is too high */
|
||||
Value = FastRef->Value;
|
||||
if (((FastRef->RefCnt + MAX_FAST_REFS) > MAX_FAST_REFS) ||
|
||||
((PVOID)((ULONG_PTR)FastRef->Object &~ MAX_FAST_REFS) != Object))
|
||||
{
|
||||
/* Completely dereference the object */
|
||||
ObDereferenceObjectEx(Object, MAX_FAST_REFS);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Increase the reference count */
|
||||
NewValue = Value + MAX_FAST_REFS;
|
||||
if (ExpChangeRundown(FastRef, NewValue, Value) == Value) break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the Object */
|
||||
return FastRef->Object;
|
||||
return Object;
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
ObFastDereferenceObject(IN PEX_FAST_REF FastRef,
|
||||
PVOID Object)
|
||||
IN PVOID Object)
|
||||
{
|
||||
/* FIXME: Fast Referencing is Unimplemented */
|
||||
ULONG_PTR Value, NewValue;
|
||||
|
||||
/* Do a normal Dereference */
|
||||
ObDereferenceObject(FastRef->Object);
|
||||
/* Sanity checks */
|
||||
DPRINT("DeRef: %p\n", Object);
|
||||
ASSERT(Object);
|
||||
ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
|
||||
|
||||
/* Start dereference loop */
|
||||
for (;;)
|
||||
{
|
||||
/* Get the current count */
|
||||
Value = FastRef->Value;
|
||||
if ((Value ^ (ULONG_PTR)Object) < MAX_FAST_REFS)
|
||||
{
|
||||
/* Decrease the reference count */
|
||||
NewValue = Value + 1;
|
||||
if (ExpChangeRundown(FastRef, NewValue, Value) == Value) return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Do a normal Dereference */
|
||||
ObDereferenceObject(Object);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PVOID
|
||||
|
@ -55,15 +201,38 @@ FASTCALL
|
|||
ObFastReplaceObject(IN PEX_FAST_REF FastRef,
|
||||
PVOID Object)
|
||||
{
|
||||
PVOID OldObject = FastRef->Object;
|
||||
ULONG_PTR NewValue;
|
||||
EX_FAST_REF OldRef;
|
||||
PVOID OldObject;
|
||||
|
||||
/* FIXME: Fast Referencing is Unimplemented */
|
||||
FastRef->Object = Object;
|
||||
/* Check if we were given an object and reference it 7 times */
|
||||
if (Object) ObReferenceObjectEx(Object, MAX_FAST_REFS);
|
||||
|
||||
/* Do a normal Dereference */
|
||||
ObDereferenceObject(OldObject);
|
||||
/* Sanity check */
|
||||
ASSERT(!(((ULONG_PTR)Object) & MAX_FAST_REFS));
|
||||
|
||||
/* Return old Object*/
|
||||
/* Check if the caller gave us an object */
|
||||
if (Object)
|
||||
{
|
||||
/* He did, so bias the pointer */
|
||||
NewValue = (ULONG_PTR)Object | MAX_FAST_REFS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No object, we're clearing */
|
||||
NewValue = 0;
|
||||
}
|
||||
|
||||
/* Switch objects */
|
||||
OldRef.Value = InterlockedExchange(&FastRef->Value, NewValue);
|
||||
OldObject = (PVOID)((ULONG_PTR)OldRef.Object &~ MAX_FAST_REFS);
|
||||
if ((OldObject) && (OldRef.RefCnt))
|
||||
{
|
||||
/* Dereference the old object */
|
||||
ObDereferenceObjectEx(OldObject, OldRef.RefCnt);
|
||||
}
|
||||
|
||||
/* Return the old object */
|
||||
return OldObject;
|
||||
}
|
||||
|
||||
|
@ -112,17 +281,8 @@ ObfDereferenceObject(IN PVOID Object)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Add us to the list */
|
||||
do
|
||||
{
|
||||
Header->NextToFree = ObpReaperList;
|
||||
} while (InterlockedCompareExchangePointer(&ObpReaperList,
|
||||
Header,
|
||||
Header->NextToFree) !=
|
||||
Header->NextToFree);
|
||||
|
||||
/* Queue the work item */
|
||||
ExQueueWorkItem(&ObpReaperWorkItem, DelayedWorkQueue);
|
||||
/* Add us to the deferred deletion list */
|
||||
ObpDeferObjectDeletion(Object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -196,6 +196,7 @@ PsInitProcessManagment(VOID)
|
|||
InitializeListHead(&PsIdleProcess->Pcb.ThreadListHead);
|
||||
InitializeListHead(&PsIdleProcess->ThreadListHead);
|
||||
InitializeListHead(&PsIdleProcess->ActiveProcessLinks);
|
||||
ObInitializeFastReference(&PsIdleProcess->Token, NULL);
|
||||
KeInitializeDispatcherHeader(&PsIdleProcess->Pcb.Header,
|
||||
ProcessObject,
|
||||
sizeof(EPROCESS) / sizeof(LONG),
|
||||
|
@ -278,8 +279,7 @@ PsInitProcessManagment(VOID)
|
|||
/* No parent, this is the Initial System Process. Assign Boot Token */
|
||||
BootToken = SepCreateSystemProcessToken();
|
||||
BootToken->TokenInUse = TRUE;
|
||||
PsInitialSystemProcess->Token.Object = BootToken; /* FIXME */
|
||||
ObReferenceObject(BootToken);
|
||||
ObInitializeFastReference(&PsInitialSystemProcess->Token, BootToken);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ PsReferencePrimaryToken(PEPROCESS Process)
|
|||
PspLockProcessSecurityShared(Process);
|
||||
|
||||
/* Do a Locked Fast Reference */
|
||||
//Token = ObFastReferenceObjectLocked(&Process->Token);
|
||||
Token = ObFastReferenceObjectLocked(&Process->Token);
|
||||
|
||||
/* Unlock the Process */
|
||||
PspUnlockProcessSecurityShared(Process);
|
||||
|
@ -222,47 +222,25 @@ PspInitializeProcessSecurity(PEPROCESS Process,
|
|||
PEPROCESS Parent OPTIONAL)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PTOKEN NewToken, ParentToken;
|
||||
|
||||
/* If we have a parent, then duplicate the Token */
|
||||
if (Parent) {
|
||||
|
||||
PTOKEN pNewToken;
|
||||
PTOKEN pParentToken;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
|
||||
if (Parent)
|
||||
{
|
||||
/* Get the Parent Token */
|
||||
pParentToken = PsReferencePrimaryToken(Parent);
|
||||
ParentToken = PsReferencePrimaryToken(Parent);
|
||||
|
||||
/* Initialize the Object Attributes */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
/* Duplicate it */
|
||||
Status = SeSubProcessToken(ParentToken, &NewToken, TRUE, 0);
|
||||
|
||||
/* Duplicate the Token */
|
||||
Status = SepDuplicateToken(pParentToken,
|
||||
&ObjectAttributes,
|
||||
FALSE,
|
||||
TokenPrimary,
|
||||
pParentToken->ImpersonationLevel,
|
||||
KernelMode,
|
||||
&pNewToken);
|
||||
|
||||
if(!NT_SUCCESS(Status)) {
|
||||
|
||||
DPRINT1("Failed to Duplicate Token\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Dereference the Token */
|
||||
ObFastDereferenceObject(&Parent->Token, pParentToken);
|
||||
/* Dereference the Parent */
|
||||
ObFastDereferenceObject(&Parent->Token, ParentToken);
|
||||
|
||||
/* Set the new Token */
|
||||
ObInitializeFastReference(&Process->Token, pNewToken);
|
||||
|
||||
} else {
|
||||
|
||||
ObInitializeFastReference(&Process->Token, NewToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef SCHED_REWRITE
|
||||
PTOKEN BootToken;
|
||||
|
||||
|
@ -449,7 +427,7 @@ PsReferenceEffectiveToken(PETHREAD Thread,
|
|||
PspLockProcessSecurityShared(Process);
|
||||
|
||||
/* Do a Locked Fast Reference */
|
||||
//Token = ObFastReferenceObjectLocked(&Process->Token);
|
||||
Token = ObFastReferenceObjectLocked(&Process->Token);
|
||||
|
||||
/* Unlock the Process */
|
||||
PspUnlockProcessSecurityShared(Process);
|
||||
|
|
|
@ -10,10 +10,9 @@
|
|||
/*
|
||||
* Alex FIXMEs:
|
||||
* - CRITICAL: NtCurrentTeb returns KPCR.
|
||||
* - CRITICAL: Verify rundown APIs (ex/rundown.c) and use them where necessary.
|
||||
* - MAJOR: Implement Pushlocks and use them as process lock.
|
||||
* - MAJOR: Use Process Rundown
|
||||
* - MAJOR: Use Process Pushlock Locks
|
||||
* - MAJOR: Implement Safe Referencing (See PsGetNextProcess/Thread).
|
||||
* - MAJOR: Implement Fast Referencing (mostly for tokens).
|
||||
* - MAJOR: Use Guarded Mutex instead of Fast Mutex for Active Process Locks.
|
||||
* - Generate process cookie for user-more thread.
|
||||
* - Add security calls where necessary.
|
||||
|
|
|
@ -485,7 +485,7 @@ SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
|
|||
|
||||
if (SubjectContext->PrimaryToken != NULL)
|
||||
{
|
||||
ObDereferenceObject(SubjectContext->PrimaryToken);
|
||||
ObFastDereferenceObject(&PsGetCurrentProcess()->Token, SubjectContext->PrimaryToken);
|
||||
}
|
||||
|
||||
if (SubjectContext->ClientToken != NULL)
|
||||
|
|
|
@ -321,10 +321,53 @@ SepDuplicateToken(PTOKEN Token,
|
|||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
ObDereferenceObject(AccessToken);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SeSubProcessToken(IN PTOKEN ParentToken,
|
||||
OUT PTOKEN *Token,
|
||||
IN BOOLEAN InUse,
|
||||
IN ULONG SessionId)
|
||||
{
|
||||
PTOKEN NewToken;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Initialize the attributes and duplicate it */
|
||||
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
|
||||
Status = SepDuplicateToken(ParentToken,
|
||||
&ObjectAttributes,
|
||||
FALSE,
|
||||
TokenPrimary,
|
||||
ParentToken->ImpersonationLevel,
|
||||
KernelMode,
|
||||
&NewToken);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Insert it */
|
||||
Status = ObInsertObject(NewToken,
|
||||
NULL,
|
||||
0,
|
||||
1,
|
||||
NULL,
|
||||
NULL);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Set the session ID */
|
||||
NewToken->SessionId = SessionId;
|
||||
NewToken->TokenInUse = InUse;
|
||||
|
||||
/* Return the token */
|
||||
*Token = NewToken;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
|
@ -2472,6 +2515,7 @@ NtOpenThreadTokenEx(IN HANDLE ThreadHandle,
|
|||
|
||||
PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
|
||||
Status = SepCreateImpersonationTokenDacl(Token, PrimaryToken, &Dacl);
|
||||
KEBUGCHECK(0);
|
||||
ObfDereferenceObject(PrimaryToken);
|
||||
ObfDereferenceObject(Thread);
|
||||
if (!NT_SUCCESS(Status))
|
||||
|
|
Loading…
Reference in a new issue