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;
6060UCHAR SeAuditingState [POLICY_AUDIT_EVENT_TYPE_COUNT ];
6161
6262KGUARDED_MUTEX SepRmDbLock ;
63- PSEP_LOGON_SESSION_REFERENCES SepLogonSessions = NULL ;
6463PSEP_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
512525SepRmCreateLogonSession (
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
590610SepRmDeleteLogonSession (
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