Author: ion
Date: Sat Jul 22 20:03:12 2006
New Revision: 23226
URL:
http://svn.reactos.org/svn/reactos?rev=23226&view=rev
Log:
- Give winlogon SE_ASSIGNPRIMARYTOKEN_PRIVILEGE because it was lacking it and would fail
under this kernel patch.
- PspAssignPrimaryToken was good enough for actually *assigning* the token, but when
NtSetInfoProcess is called with ProcessPrimaryToken, we want to do a lot more then just
randomly assigning it. Added PspSetPrimaryToken which first verifies if the token being
assigned is a child token and if not, checks for SeAssignPrimaryTokenPrivilege. Also added
a fixme for more code that's needed, to actually re-calculate the process's
granted access towards itself. Also added thread-safety.
Modified:
trunk/reactos/base/system/winlogon/winlogon.c
trunk/reactos/base/system/winlogon/winlogon.h
trunk/reactos/ntoskrnl/include/internal/ps.h
trunk/reactos/ntoskrnl/include/internal/se.h
trunk/reactos/ntoskrnl/ps/query.c
trunk/reactos/ntoskrnl/ps/security.c
trunk/reactos/ntoskrnl/se/token.c
Modified: trunk/reactos/base/system/winlogon/winlogon.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/winlogon/winlo…
==============================================================================
--- trunk/reactos/base/system/winlogon/winlogon.c (original)
+++ trunk/reactos/base/system/winlogon/winlogon.c Sat Jul 22 20:03:12 2006
@@ -534,6 +534,7 @@
LPSTR lpCmdLine,
int nShowCmd)
{
+ BOOLEAN Old;
#if SUPPORT_CONSOLESTART
// WCHAR LoginName[255];
// WCHAR Password[255];
@@ -554,6 +555,9 @@
ExitProcess(0);
return 0;
}
+
+ /* Get privilege */
+ RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &Old);
#if START_LSASS
if (StartProcess(L"StartLsass"))
Modified: trunk/reactos/base/system/winlogon/winlogon.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/winlogon/winlo…
==============================================================================
--- trunk/reactos/base/system/winlogon/winlogon.h (original)
+++ trunk/reactos/base/system/winlogon/winlogon.h Sat Jul 22 20:03:12 2006
@@ -33,6 +33,7 @@
#include <winwlx.h>
#include <rtlfuncs.h>
#include <exfuncs.h>
+#include <setypes.h>
#include <reactos/winlogon.h>
Modified: trunk/reactos/ntoskrnl/include/internal/ps.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ps.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/ps.h Sat Jul 22 20:03:12 2006
@@ -59,10 +59,11 @@
);
NTSTATUS
-STDCALL
-PspAssignPrimaryToken(
- PEPROCESS Process,
- HANDLE TokenHandle
+NTAPI
+PspSetPrimaryToken(
+ IN PEPROCESS Process,
+ IN HANDLE TokenHandle OPTIONAL,
+ IN PTOKEN Token OPTIONAL
);
PETHREAD
Modified: trunk/reactos/ntoskrnl/include/internal/se.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/se.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/se.h Sat Jul 22 20:03:12 2006
@@ -130,6 +130,13 @@
);
NTSTATUS
+NTAPI
+SeIsTokenChild(
+ IN PTOKEN Token,
+ OUT PBOOLEAN IsChild
+);
+
+NTSTATUS
STDCALL
SepCreateImpersonationTokenDacl(
PTOKEN Token,
Modified: trunk/reactos/ntoskrnl/ps/query.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ps/query.c?rev=23…
==============================================================================
--- trunk/reactos/ntoskrnl/ps/query.c (original)
+++ trunk/reactos/ntoskrnl/ps/query.c Sat Jul 22 20:03:12 2006
@@ -581,7 +581,7 @@
if (!NT_SUCCESS(Status)) break;
/* Assign the actual token */
- Status = PspAssignPrimaryToken(Process, TokenHandle);
+ Status = PspSetPrimaryToken(Process, TokenHandle, NULL);
break;
/* Hard error processing */
Modified: trunk/reactos/ntoskrnl/ps/security.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ps/security.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/ps/security.c (original)
+++ trunk/reactos/ntoskrnl/ps/security.c Sat Jul 22 20:03:12 2006
@@ -25,7 +25,7 @@
KeEnterCriticalRegion();
/* Lock the Process */
- //ExAcquirePushLockShared(&Process->ProcessLock);
+ ExAcquirePushLockShared(&Process->ProcessLock);
}
/* FIXME: Turn into Macro */
@@ -34,7 +34,31 @@
PspUnlockProcessSecurityShared(IN PEPROCESS Process)
{
/* Unlock the Process */
- //ExReleasePushLockShared(&Process->ProcessLock);
+ ExReleasePushLockShared(&Process->ProcessLock);
+
+ /* Leave Critical Region */
+ KeLeaveCriticalRegion();
+}
+
+/* FIXME: Turn into Macro */
+VOID
+NTAPI
+PspLockProcessSecurityExclusive(IN PEPROCESS Process)
+{
+ /* Enter a Critical Region */
+ KeEnterCriticalRegion();
+
+ /* Lock the Process */
+ ExAcquirePushLockExclusive(&Process->ProcessLock);
+}
+
+/* FIXME: Turn into Macro */
+VOID
+NTAPI
+PspUnlockProcessSecurityExclusive(IN PEPROCESS Process)
+{
+ /* Unlock the Process */
+ ExReleasePushLockExclusive(&Process->ProcessLock);
/* Leave Critical Region */
KeLeaveCriticalRegion();
@@ -119,25 +143,89 @@
NTSTATUS
NTAPI
PspAssignPrimaryToken(IN PEPROCESS Process,
- IN HANDLE TokenHandle)
-{
- PACCESS_TOKEN Token, OldToken;
+ IN PTOKEN Token)
+{
+ PACCESS_TOKEN OldToken;
NTSTATUS Status;
-
- /* Reference the Token */
- Status = ObReferenceObjectByHandle(TokenHandle,
- TOKEN_ASSIGN_PRIMARY,
- SepTokenObjectType,
- KeGetPreviousMode(),
- (PVOID*)&Token,
- NULL);
- if (!NT_SUCCESS(Status)) return Status;
+ PAGED_CODE();
+
+ /* Lock the process */
+ PspLockProcessSecurityExclusive(Process);
/* Exchange them */
Status = SeExchangePrimaryToken(Process, Token, &OldToken);
- /* Derefernece Tokens and Return */
+ /* Release the lock */
+ PspUnlockProcessSecurityExclusive(Process);
+
+ /* Dereference Tokens and Return */
+ if (NT_SUCCESS(Status)) ObDereferenceObject(OldToken);
ObDereferenceObject(Token);
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+PspSetPrimaryToken(IN PEPROCESS Process,
+ IN HANDLE TokenHandle OPTIONAL,
+ IN PTOKEN Token OPTIONAL)
+{
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ BOOLEAN IsChild;
+ NTSTATUS Status;
+
+ /* Make sure we got a handle */
+ if (TokenHandle)
+ {
+ /* Reference it */
+ Status = ObReferenceObjectByHandle(TokenHandle,
+ TOKEN_ASSIGN_PRIMARY,
+ SepTokenObjectType,
+ PreviousMode,
+ (PVOID*)&Token,
+ NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ }
+
+ /* Check if this is a child */
+ Status = SeIsTokenChild(Token, &IsChild);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed, dereference */
+ if (TokenHandle) ObDereferenceObject(Token);
+ return Status;
+ }
+
+ /* Check if this was an independent token */
+ if (!IsChild)
+ {
+ /* Make sure we have the privilege to assign a new one */
+ if (!SeSinglePrivilegeCheck(SeAssignPrimaryTokenPrivilege,
+ PreviousMode))
+ {
+ /* Failed, dereference */
+ if (TokenHandle) ObDereferenceObject(Token);
+ return STATUS_PRIVILEGE_NOT_HELD;
+ }
+ }
+
+ /* Assign the token */
+ Status = PspAssignPrimaryToken(Process, Token);
+ if (NT_SUCCESS(Status))
+ {
+ /*
+ * The idea here is that we need to completely reverify
+ * if the process still has access to itself under this new
+ * token, by doing an SeAccessCheck with the Primary Token and
+ * the SD of the Process (ObGetObjectSecurity).
+ * In the really twisted case where we lose access to ourselves,
+ * we would set Process->GrantedAccess to 0.
+ */
+ DPRINT1("Process security not complete\n");
+ }
+
+ /* Dereference the token */
+ if (TokenHandle) ObDereferenceObject(Token);
return Status;
}
Modified: trunk/reactos/ntoskrnl/se/token.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/token.c?rev=23…
==============================================================================
--- trunk/reactos/ntoskrnl/se/token.c (original)
+++ trunk/reactos/ntoskrnl/se/token.c Sat Jul 22 20:03:12 2006
@@ -366,6 +366,36 @@
/* Return status */
return Status;
+}
+
+NTSTATUS
+NTAPI
+SeIsTokenChild(IN PTOKEN Token,
+ OUT PBOOLEAN IsChild)
+{
+ PTOKEN ProcessToken;
+ LUID ProcessLuid, CallerLuid;
+
+ /* Assume failure */
+ *IsChild = FALSE;
+
+ /* Reference the process token */
+ ProcessToken = PsReferencePrimaryToken(PsGetCurrentProcess());
+
+ /* Get the ID */
+ ProcessLuid = ProcessToken->TokenId;
+
+ /* Dereference the token */
+ ObFastDereferenceObject(&PsGetCurrentProcess()->Token, ProcessToken);
+
+ /* Get our LUID */
+ CallerLuid = Token->TokenId;
+
+ /* Compare the LUIDs */
+ if (RtlEqualLuid(&CallerLuid, &ProcessLuid)) *IsChild = TRUE;
+
+ /* Return success */
+ return STATUS_SUCCESS;
}
/*