Skip to content

Data Race in Session Cache #133

@alpe

Description

@alpe

It occurs between the background cleanup goroutine and main request threads and results in a fatal runtime panic, causing a Denial of Service.

  • Steps To Reproduce:

Copy test into pkg/session/race_test.go and run from the project root: go test -v -race -run TestRaceCondition ./pkg/session

package session

import (
	"testing"
	"time"
)

func TestRaceCondition(t *testing.T) {
	// The init function in token.go already creates the global 'sessions' cache.
	// We will use it directly.

	done := make(chan bool)

	// Goroutine 1: Continuously writes to the map (acquires Lock)
	go func() {
		for {
			select {
			case <-done:
				return
			default:
				GenerateToken("test-role", 3600)
				time.Sleep(1 * time.Millisecond)
			}
		}
	}()

	// Goroutine 2: Continuously reads/iterates the map (NO Lock used in clean())
	// The clean() method in cache.go:61 iterates c.TokenMap without locking.
	go func() {
		for {
			select {
			case <-done:
				return
			default:
				// specific to the implementation of weep/pkg/session
				// where sessions is unexported but accessible in package tests
				sessions.clean()
				time.Sleep(1 * time.Millisecond)
			}
		}
	}()

	// Run for a short duration to trigger the race
	time.Sleep(2 * time.Second)
	close(done)
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions