Skip to content

Commit 0dafdc5

Browse files
committed
[NTOS:SE] Adapt the logon session database into a hash table
Right now nt!SepLogonSessions in ROS is a mere pointer list of _SEP_LOGON_SESSION_REFERENCES structures. !logonsession command of WinDBG expects it to be a hash table, composed as an array of lists though. Consequently this command doesn't work if you debug ROS, it simply causes the debugger to spam the logger with garbage into an infinite loop. So in order to fix this, we gotta make this database construct behave as what WinDBG would strictly expect. CORE-20344
1 parent c7e1c79 commit 0dafdc5

1 file changed

Lines changed: 44 additions & 18 deletions

File tree

‎ntoskrnl/se/srm.c‎

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* PURPOSE: Security Reference Monitor Server
55
* COPYRIGHT: Copyright Timo Kreuzer <timo.kreuzer@reactos.org>
66
* Copyright Pierre Schweitzer <pierre@reactos.org>
7-
* Copyright 2021 George Bișoc <george.bisoc@reactos.org>
7+
* Copyright 2021-2026 George Bișoc <george.bisoc@reactos.org>
88
*/
99

1010
/* INCLUDES *******************************************************************/
@@ -60,9 +60,20 @@ ULONG SepAdtMaxListLength = 0x3000;
6060
UCHAR SeAuditingState[POLICY_AUDIT_EVENT_TYPE_COUNT];
6161

6262
KGUARDED_MUTEX SepRmDbLock;
63-
PSEP_LOGON_SESSION_REFERENCES SepLogonSessions = NULL;
6463
PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION SepLogonNotifications = NULL;
6564

65+
/*
66+
* The logon session database is a hash table comprised of 16 hash buckets.
67+
* Each bucket is a single-list of SEP_LOGON_SESSION_REFERENCES structures,
68+
* that is simply indexed by a session logon ID modulo the number of buckets.
69+
*
70+
* !logonsession command extension from WinDBG strictly expects nt!SepLogonSessions
71+
* symbol to follow this mechanism.
72+
*/
73+
#define MAX_LOGON_SESSION_LISTS_IN_ARRAY 16
74+
static PSEP_LOGON_SESSION_REFERENCES _SepLogonSessions[MAX_LOGON_SESSION_LISTS_IN_ARRAY] = {NULL};
75+
PSEP_LOGON_SESSION_REFERENCES* const SepLogonSessions = _SepLogonSessions;
76+
6677
/* PRIVATE FUNCTIONS **********************************************************/
6778

6879
/**
@@ -377,7 +388,8 @@ SepRmInsertLogonSessionIntoToken(
377388
/* Acquire the database lock */
378389
KeAcquireGuardedMutex(&SepRmDbLock);
379390

380-
for (LogonSession = SepLogonSessions;
391+
/* Retrieve the hash bucket and loop over it */
392+
for (LogonSession = SepLogonSessions[Token->AuthenticationId.LowPart % MAX_LOGON_SESSION_LISTS_IN_ARRAY];
381393
LogonSession != NULL;
382394
LogonSession = LogonSession->Next)
383395
{
@@ -458,7 +470,8 @@ SepRmRemoveLogonSessionFromToken(
458470
/* Acquire the database lock */
459471
KeAcquireGuardedMutex(&SepRmDbLock);
460472

461-
for (LogonSession = SepLogonSessions;
473+
/* Retrieve the hash bucket and loop over it */
474+
for (LogonSession = SepLogonSessions[Token->AuthenticationId.LowPart % MAX_LOGON_SESSION_LISTS_IN_ARRAY];
462475
LogonSession != NULL;
463476
LogonSession = LogonSession->Next)
464477
{
@@ -512,7 +525,7 @@ NTSTATUS
512525
SepRmCreateLogonSession(
513526
_In_ PLUID LogonLuid)
514527
{
515-
PSEP_LOGON_SESSION_REFERENCES CurrentSession, NewSession;
528+
PSEP_LOGON_SESSION_REFERENCES *LogonSession, CurrentSession, NewSession;
516529
NTSTATUS Status;
517530
PAGED_CODE();
518531

@@ -538,8 +551,15 @@ SepRmCreateLogonSession(
538551
/* Acquire the database lock */
539552
KeAcquireGuardedMutex(&SepRmDbLock);
540553

554+
/*
555+
* Cache the previous session from the hash bucket, the newly created
556+
* session will keep hold of the previous session and the hash bucket
557+
* gets a new assigned session.
558+
*/
559+
LogonSession = &SepLogonSessions[LogonLuid->LowPart % MAX_LOGON_SESSION_LISTS_IN_ARRAY];
560+
541561
/* Loop all existing sessions */
542-
for (CurrentSession = SepLogonSessions;
562+
for (CurrentSession = *LogonSession;
543563
CurrentSession != NULL;
544564
CurrentSession = CurrentSession->Next)
545565
{
@@ -552,8 +572,8 @@ SepRmCreateLogonSession(
552572
}
553573

554574
/* Insert the new session */
555-
NewSession->Next = SepLogonSessions;
556-
SepLogonSessions = NewSession;
575+
NewSession->Next = *LogonSession;
576+
*LogonSession = NewSession;
557577

558578
Status = STATUS_SUCCESS;
559579

@@ -590,7 +610,7 @@ NTSTATUS
590610
SepRmDeleteLogonSession(
591611
_In_ PLUID LogonLuid)
592612
{
593-
PSEP_LOGON_SESSION_REFERENCES SessionToDelete;
613+
PSEP_LOGON_SESSION_REFERENCES SessionToDelete, *LogonSession;
594614
NTSTATUS Status;
595615
PAGED_CODE();
596616

@@ -600,8 +620,11 @@ SepRmDeleteLogonSession(
600620
/* Acquire the database lock */
601621
KeAcquireGuardedMutex(&SepRmDbLock);
602622

623+
/* Retrieve the hash bucket, the database will have this session pulled away down below */
624+
LogonSession = &SepLogonSessions[LogonLuid->LowPart % MAX_LOGON_SESSION_LISTS_IN_ARRAY];
625+
603626
/* Loop over the existing logon sessions */
604-
for (SessionToDelete = SepLogonSessions;
627+
for (SessionToDelete = *LogonSession;
605628
SessionToDelete != NULL;
606629
SessionToDelete = SessionToDelete->Next)
607630
{
@@ -667,6 +690,9 @@ SepRmDeleteLogonSession(
667690
ObfDereferenceDeviceMap(SessionToDelete->pDeviceMap);
668691
}
669692

693+
/* Unlink the session from the bucket list */
694+
*LogonSession = SessionToDelete->Next;
695+
670696
/* If we're here then we've deleted the logon session successfully */
671697
DPRINT("SepRmDeleteLogonSession(): Logon session deleted with success!\n");
672698
Status = STATUS_SUCCESS;
@@ -705,8 +731,8 @@ SepRmReferenceLogonSession(
705731
/* Acquire the database lock */
706732
KeAcquireGuardedMutex(&SepRmDbLock);
707733

708-
/* Loop all existing sessions */
709-
for (CurrentSession = SepLogonSessions;
734+
/* Retrieve the hash bucket and loop over it */
735+
for (CurrentSession = SepLogonSessions[LogonLuid->LowPart % MAX_LOGON_SESSION_LISTS_IN_ARRAY];
710736
CurrentSession != NULL;
711737
CurrentSession = CurrentSession->Next)
712738
{
@@ -1018,8 +1044,8 @@ SepRmDereferenceLogonSession(
10181044
/* Acquire the database lock */
10191045
KeAcquireGuardedMutex(&SepRmDbLock);
10201046

1021-
/* Loop all existing sessions */
1022-
for (CurrentSession = SepLogonSessions;
1047+
/* Retrieve the hash bucket and walk over it */
1048+
for (CurrentSession = SepLogonSessions[LogonLuid->LowPart % MAX_LOGON_SESSION_LISTS_IN_ARRAY];
10231049
CurrentSession != NULL;
10241050
CurrentSession = CurrentSession->Next)
10251051
{
@@ -1367,8 +1393,8 @@ SeGetLogonIdDeviceMap(
13671393
/* Acquire the database lock */
13681394
KeAcquireGuardedMutex(&SepRmDbLock);
13691395

1370-
/* Loop all existing sessions */
1371-
for (CurrentSession = SepLogonSessions;
1396+
/* Retrieve the hash bucket and loop over it */
1397+
for (CurrentSession = SepLogonSessions[LogonId->LowPart % MAX_LOGON_SESSION_LISTS_IN_ARRAY];
13721398
CurrentSession != NULL;
13731399
CurrentSession = CurrentSession->Next)
13741400
{
@@ -1519,8 +1545,8 @@ SeMarkLogonSessionForTerminationNotification(
15191545
/* Acquire the database lock */
15201546
KeAcquireGuardedMutex(&SepRmDbLock);
15211547

1522-
/* Loop over the existing logon sessions */
1523-
for (SessionToMark = SepLogonSessions;
1548+
/* Retrieve the hash bucket and loop over it */
1549+
for (SessionToMark = SepLogonSessions[LogonId->LowPart % MAX_LOGON_SESSION_LISTS_IN_ARRAY];
15241550
SessionToMark != NULL;
15251551
SessionToMark = SessionToMark->Next)
15261552
{

0 commit comments

Comments
 (0)