Skip to content

Commit 98a1f03

Browse files
nateberkopecevanphx
andcommitted
Merge pull request from GHSA-7xx3-m584-x994
could monopolize a thread. Previously, this could make a DoS attack more severe. Co-authored-by: Evan Phoenix <evan@phx.io>
1 parent d20242b commit 98a1f03

File tree

2 files changed

+22
-1
lines changed

2 files changed

+22
-1
lines changed

lib/puma/const.rb

+7
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,13 @@ module Const
118118
# sending data back
119119
WRITE_TIMEOUT = 10
120120

121+
# How many requests to attempt inline before sending a client back to
122+
# the reactor to be subject to normal ordering. The idea here is that
123+
# we amortize the cost of going back to the reactor for a well behaved
124+
# but very "greedy" client across 10 requests. This prevents a not
125+
# well behaved client from monopolizing the thread forever.
126+
MAX_FAST_INLINE = 10
127+
121128
# The original URI requested by the client.
122129
REQUEST_URI= 'REQUEST_URI'.freeze
123130
REQUEST_PATH = 'REQUEST_PATH'.freeze

lib/puma/server.rb

+15-1
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,8 @@ def process_client(client, buffer)
466466
clean_thread_locals = @options[:clean_thread_locals]
467467
close_socket = true
468468

469+
requests = 0
470+
469471
while true
470472
case handle_request(client, buffer)
471473
when false
@@ -479,7 +481,19 @@ def process_client(client, buffer)
479481

480482
ThreadPool.clean_thread_locals if clean_thread_locals
481483

482-
unless client.reset(@status == :run)
484+
requests += 1
485+
486+
check_for_more_data = @status == :run
487+
488+
if requests >= MAX_FAST_INLINE
489+
# This will mean that reset will only try to use the data it already
490+
# has buffered and won't try to read more data. What this means is that
491+
# every client, independent of their request speed, gets treated like a slow
492+
# one once every MAX_FAST_INLINE requests.
493+
check_for_more_data = false
494+
end
495+
496+
unless client.reset(check_for_more_data)
483497
close_socket = false
484498
client.set_timeout @persistent_timeout
485499
@reactor.add client

0 commit comments

Comments
 (0)