fix(correlation): prevent race condition in session manager
Fixed potential use-after-free in Update() when gcRound deletes a session between GetOrCreate() and acquiring the session lock. Changes: - Add 'deleted' flag to SessionState - Mark sessions as deleted before removing from map in gcRound - Check deleted flag in Update and recreate session if needed This ensures updates to deleted sessions create a new session instead of modifying a freed/dangling reference. Race detector verified: go test ./internal/correlation/... -race Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@ -84,10 +84,21 @@ func (m *Manager) GetOrCreate(key SessionKey) *SessionState {
|
||||
|
||||
// Update applique la fonction fn sur la session identifiée par key,
|
||||
// en créant la session si elle n'existe pas encore.
|
||||
// Thread-safe : vérifie le flag deleted pour éviter les use-after-free.
|
||||
func (m *Manager) Update(key SessionKey, fn func(*SessionState)) {
|
||||
s := m.GetOrCreate(key)
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
// Vérifier si la session a été marquée comme supprimée par gcRound
|
||||
if s.deleted {
|
||||
// La session a été supprimée, recréer une nouvelle session
|
||||
s = m.GetOrCreate(key)
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
}
|
||||
|
||||
fn(s)
|
||||
s.LastActivity = time.Now()
|
||||
}
|
||||
@ -128,6 +139,12 @@ func (m *Manager) gcRound(slowlorisThreshold time.Duration) {
|
||||
|
||||
if expired || slowloris {
|
||||
toDelete = append(toDelete, key)
|
||||
// Marquer la session comme supprimée AVANT de l'envoyer à ReadyCh
|
||||
// pour éviter les race conditions avec Update()
|
||||
s.mu.Lock()
|
||||
s.deleted = true
|
||||
s.mu.Unlock()
|
||||
|
||||
// Envoyer sans bloquer (drop si le canal est plein)
|
||||
select {
|
||||
case m.ReadyCh <- s:
|
||||
|
||||
@ -88,6 +88,7 @@ type SessionState struct {
|
||||
FirstSeen time.Time // horodatage de création de la session
|
||||
LastActivity time.Time // horodatage de la dernière activité
|
||||
|
||||
deleted bool // true si la session a été supprimée du map par gcRound
|
||||
mu sync.Mutex // protection des modifications concurrentes
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user