1
0
Fork 0
mirror of https://github.com/puma/puma.git synced 2022-11-09 13:48:40 -05:00

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>
This commit is contained in:
Nate Berkopec 2019-12-05 14:19:32 +07:00 committed by GitHub
parent 9f4f87cb60
commit 6baa4d8e1c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 1 deletions

View file

@ -118,6 +118,13 @@ module Puma
# sending data back # sending data back
WRITE_TIMEOUT = 10 WRITE_TIMEOUT = 10
# How many requests to attempt inline before sending a client back to
# the reactor to be subject to normal ordering. The idea here is that
# we amortize the cost of going back to the reactor for a well behaved
# but very "greedy" client across 10 requests. This prevents a not
# well behaved client from monopolizing the thread forever.
MAX_FAST_INLINE = 10
# The original URI requested by the client. # The original URI requested by the client.
REQUEST_URI= 'REQUEST_URI'.freeze REQUEST_URI= 'REQUEST_URI'.freeze
REQUEST_PATH = 'REQUEST_PATH'.freeze REQUEST_PATH = 'REQUEST_PATH'.freeze

View file

@ -466,6 +466,8 @@ module Puma
clean_thread_locals = @options[:clean_thread_locals] clean_thread_locals = @options[:clean_thread_locals]
close_socket = true close_socket = true
requests = 0
while true while true
case handle_request(client, buffer) case handle_request(client, buffer)
when false when false
@ -479,7 +481,19 @@ module Puma
ThreadPool.clean_thread_locals if clean_thread_locals ThreadPool.clean_thread_locals if clean_thread_locals
unless client.reset(@status == :run) requests += 1
check_for_more_data = @status == :run
if requests >= MAX_FAST_INLINE
# This will mean that reset will only try to use the data it already
# has buffered and won't try to read more data. What this means is that
# every client, independent of their request speed, gets treated like a slow
# one once every MAX_FAST_INLINE requests.
check_for_more_data = false
end
unless client.reset(check_for_more_data)
close_socket = false close_socket = false
client.set_timeout @persistent_timeout client.set_timeout @persistent_timeout
@reactor.add client @reactor.add client