From 03247983bbc97716c4ff1c13a43f39f6ca0d837d Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Tue, 30 Apr 2019 03:31:16 +0000 Subject: [PATCH 1/3] Possibly fix race condition in rate limiting --- contrib/smash | 26 ++++++++++++++++++++++++++ src/instance.go | 25 +++++++++++++++++++------ src/maintenance.go | 11 ++++++++++- 3 files changed, 55 insertions(+), 7 deletions(-) create mode 100755 contrib/smash diff --git a/contrib/smash b/contrib/smash new file mode 100755 index 0000000..9a743c0 --- /dev/null +++ b/contrib/smash @@ -0,0 +1,26 @@ +#! /bin/sh + +BASEURL=http://localhost:8080 + +case "$1" in + a) + URL=$BASEURL/answer + ;; + b) + URL=$BASEURL/puzzles.json + ;; + *) + echo "Usage: $0 a|b" 1>&2 + exit 1 + ;; +esac + +while true; do + curl \ + -X POST \ + -F "cat=base" \ + -F "points=1" \ + -F "id=test" \ + -F "answer=moo" \ + $URL +done diff --git a/src/instance.go b/src/instance.go index 968e70a..1d3a26f 100644 --- a/src/instance.go +++ b/src/instance.go @@ -11,6 +11,7 @@ import ( "os" "path" "strings" + "sync" "time" ) @@ -21,12 +22,13 @@ type Instance struct { ThemeDir string AttemptInterval time.Duration - categories map[string]*Mothball - update chan bool - jPuzzleList []byte - jPointsLog []byte - nextAttempt map[string]time.Time - mux *http.ServeMux + categories map[string]*Mothball + update chan bool + jPuzzleList []byte + jPointsLog []byte + nextAttempt map[string]time.Time + nextAttemptMutex *sync.RWMutex + mux *http.ServeMux } func (ctx *Instance) Initialize() error { @@ -42,6 +44,7 @@ func (ctx *Instance) Initialize() error { ctx.categories = map[string]*Mothball{} ctx.update = make(chan bool, 10) ctx.nextAttempt = map[string]time.Time{} + ctx.nextAttemptMutex = new(sync.RWMutex) ctx.mux = http.NewServeMux() ctx.BindHandlers() @@ -129,8 +132,15 @@ func (ctx *Instance) ThemePath(parts ...string) string { func (ctx *Instance) TooFast(teamId string) bool { now := time.Now() + + ctx.nextAttemptMutex.RLock() next, _ := ctx.nextAttempt[teamId] + ctx.nextAttemptMutex.RUnlock() + + ctx.nextAttemptMutex.Lock() ctx.nextAttempt[teamId] = now.Add(ctx.AttemptInterval) + ctx.nextAttemptMutex.Unlock() + return now.Before(next) } @@ -212,7 +222,10 @@ func (ctx *Instance) OpenCategoryFile(category string, parts ...string) (io.Read } func (ctx *Instance) ValidTeamId(teamId string) bool { + ctx.nextAttemptMutex.RLock() _, ok := ctx.nextAttempt[teamId] + ctx.nextAttemptMutex.RUnlock() + return ok } diff --git a/src/maintenance.go b/src/maintenance.go index 3152c28..abd51e0 100644 --- a/src/maintenance.go +++ b/src/maintenance.go @@ -186,19 +186,28 @@ func (ctx *Instance) readTeams() { now := time.Now() added := 0 for k, _ := range newList { - if _, ok := ctx.nextAttempt[k]; !ok { + ctx.nextAttemptMutex.RLock() + _, ok := ctx.nextAttempt[k] + ctx.nextAttemptMutex.RUnlock() + + if !ok { + ctx.nextAttemptMutex.Lock() ctx.nextAttempt[k] = now + ctx.nextAttemptMutex.Unlock() + added += 1 } } // For any removed team IDs, remove them removed := 0 + ctx.nextAttemptMutex.Lock() // XXX: This could be less of a cludgel for k, _ := range ctx.nextAttempt { if _, ok := newList[k]; !ok { delete(ctx.nextAttempt, k) } } + ctx.nextAttemptMutex.Unlock() if (added > 0) || (removed > 0) { log.Printf("Team IDs updated: %d added, %d removed", added, removed) From cf79c8ec5ab22cc501bac92734d7fd9aed717ecb Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Tue, 30 Apr 2019 03:49:59 +0000 Subject: [PATCH 2/3] Modify smash script to trigger the bug --- contrib/smash | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/contrib/smash b/contrib/smash index 9a743c0..0e958f0 100755 --- a/contrib/smash +++ b/contrib/smash @@ -1,26 +1,16 @@ #! /bin/sh -BASEURL=http://localhost:8080 +## Run two of these to trigger the race condition from -case "$1" in - a) - URL=$BASEURL/answer - ;; - b) - URL=$BASEURL/puzzles.json - ;; - *) - echo "Usage: $0 a|b" 1>&2 - exit 1 - ;; -esac +BASEURL=http://localhost:8080 +URL=$BASEURL/answer while true; do curl \ -X POST \ - -F "cat=base" \ - -F "points=1" \ + -F "cat=byobf" \ + -F "points=10" \ -F "id=test" \ - -F "answer=moo" \ + -F "answer=6" \ $URL done From 0198d242574b4bee48b3eeb14b9be63d89a64975 Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Tue, 30 Apr 2019 03:50:31 +0000 Subject: [PATCH 3/3] Bump version --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index a3ec5a4..eb39e53 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.2 +3.3