Return-Path: X-Original-To: apmail-couchdb-commits-archive@www.apache.org Delivered-To: apmail-couchdb-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 039FC18FB1 for ; Tue, 25 Aug 2015 17:38:24 +0000 (UTC) Received: (qmail 86363 invoked by uid 500); 25 Aug 2015 17:38:21 -0000 Delivered-To: apmail-couchdb-commits-archive@couchdb.apache.org Received: (qmail 86224 invoked by uid 500); 25 Aug 2015 17:38:21 -0000 Mailing-List: contact commits-help@couchdb.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@couchdb.apache.org Delivered-To: mailing list commits@couchdb.apache.org Received: (qmail 85151 invoked by uid 99); 25 Aug 2015 17:38:20 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 25 Aug 2015 17:38:20 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 78E22E7D9A; Tue, 25 Aug 2015 17:38:20 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: rnewson@apache.org To: commits@couchdb.apache.org Date: Tue, 25 Aug 2015 17:38:51 -0000 Message-Id: In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [33/45] mochiweb commit: updated refs/heads/master to cb521b3 mitigate SSL and emfile related conditions per #138 Project: http://git-wip-us.apache.org/repos/asf/couchdb-mochiweb/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb-mochiweb/commit/f4e2daaf Tree: http://git-wip-us.apache.org/repos/asf/couchdb-mochiweb/tree/f4e2daaf Diff: http://git-wip-us.apache.org/repos/asf/couchdb-mochiweb/diff/f4e2daaf Branch: refs/heads/master Commit: f4e2daafb8a98363d1b9d63e90edfff7dc5d1c82 Parents: 0dccaaa Author: Bob Ippolito Authored: Mon Jan 12 15:55:44 2015 +1300 Committer: Bob Ippolito Committed: Mon Jan 12 15:55:44 2015 +1300 ---------------------------------------------------------------------- CHANGES.md | 9 +++++++++ src/mochiweb.app.src | 2 +- src/mochiweb_acceptor.erl | 40 ++++++++++++++++++++++++++-------------- src/mochiweb_socket.erl | 40 +++++++++++++++++++++++++--------------- 4 files changed, 61 insertions(+), 30 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb-mochiweb/blob/f4e2daaf/CHANGES.md ---------------------------------------------------------------------- diff --git a/CHANGES.md b/CHANGES.md index 673d759..19f96d1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,12 @@ +Version 2.11.0 released 2015-01-12 + +* Perform SSL handshake after releasing acceptor back into the pool, + and slow accept rate when file descriptors are not available, + to mitigate a potential DoS attack. Adds new mochiweb_socket + functions transport_accept/1 and finish_accept/1 which should be + used in preference to the now deprecated accept/1 function. + https://github.com/mochi/mochiweb/issues/138 + Version 2.10.1 released 2015-01-11 * Fixes issue with SSL and mochiweb_websocket. Note that http://git-wip-us.apache.org/repos/asf/couchdb-mochiweb/blob/f4e2daaf/src/mochiweb.app.src ---------------------------------------------------------------------- diff --git a/src/mochiweb.app.src b/src/mochiweb.app.src index ccad5bc..4754266 100644 --- a/src/mochiweb.app.src +++ b/src/mochiweb.app.src @@ -1,7 +1,7 @@ %% This is generated from src/mochiweb.app.src {application, mochiweb, [{description, "MochiMedia Web Server"}, - {vsn, "2.10.1"}, + {vsn, "2.11.0"}, {modules, []}, {registered, []}, {env, []}, http://git-wip-us.apache.org/repos/asf/couchdb-mochiweb/blob/f4e2daaf/src/mochiweb_acceptor.erl ---------------------------------------------------------------------- diff --git a/src/mochiweb_acceptor.erl b/src/mochiweb_acceptor.erl index 208f861..8a58fcf 100644 --- a/src/mochiweb_acceptor.erl +++ b/src/mochiweb_acceptor.erl @@ -10,25 +10,44 @@ -export([start_link/3, start_link/4, init/4]). +-define(EMFILE_SLEEP_MSEC, 100). + start_link(Server, Listen, Loop) -> start_link(Server, Listen, Loop, []). start_link(Server, Listen, Loop, Opts) -> proc_lib:spawn_link(?MODULE, init, [Server, Listen, Loop, Opts]). -init(Server, Listen, Loop, Opts) -> +do_accept(Server, Listen) -> T1 = os:timestamp(), - case catch mochiweb_socket:accept(Listen) of + case mochiweb_socket:transport_accept(Listen) of {ok, Socket} -> gen_server:cast(Server, {accepted, self(), timer:now_diff(os:timestamp(), T1)}), + mochiweb_socket:finish_accept(Socket); + Other -> + Other + end. + +init(Server, Listen, Loop, Opts) -> + case catch do_accept(Server, Listen) of + {ok, Socket} -> call_loop(Loop, Socket, Opts); - {error, closed} -> - exit(normal); - {error, timeout} -> - init(Server, Listen, Loop, Opts); - {error, esslaccept} -> + {error, Err} when Err =:= closed orelse + Err =:= esslaccept orelse + Err =:= timeout -> exit(normal); Other -> + %% Mitigate out of file descriptor scenario by sleeping for a + %% short time to slow error rate + case Other of + {error, emfile} -> + receive + after ?EMFILE_SLEEP_MSEC -> + ok + end; + _ -> + ok + end, error_logger:error_report( [{application, mochiweb}, "Accept failed error", @@ -44,10 +63,3 @@ call_loop({M, F, A}, Socket, Opts) -> erlang:apply(M, F, [Socket, Opts | A]); call_loop(Loop, Socket, Opts) -> Loop(Socket, Opts). - -%% -%% Tests -%% --ifdef(TEST). --include_lib("eunit/include/eunit.hrl"). --endif. http://git-wip-us.apache.org/repos/asf/couchdb-mochiweb/blob/f4e2daaf/src/mochiweb_socket.erl ---------------------------------------------------------------------- diff --git a/src/mochiweb_socket.erl b/src/mochiweb_socket.erl index f4b8bfb..1e35e15 100644 --- a/src/mochiweb_socket.erl +++ b/src/mochiweb_socket.erl @@ -4,7 +4,9 @@ -module(mochiweb_socket). --export([listen/4, accept/1, recv/3, send/2, close/1, port/1, peername/1, +-export([listen/4, + accept/1, transport_accept/1, finish_accept/1, + recv/3, send/2, close/1, port/1, peername/1, setopts/2, getopts/2, type/1]). -define(ACCEPT_TIMEOUT, 2000). @@ -66,27 +68,35 @@ filter_unsafe_protcol_versions(Versions) -> end, Versions). +%% Provided for backwards compatibility only +accept(ListenSocket) -> + case transport_accept(ListenSocket) of + {ok, Socket} -> + finish_accept(Socket); + {error, _} = Err -> + Err + end. -accept({ssl, ListenSocket}) -> - % There's a bug in ssl:transport_accept/2 at the moment, which is the - % reason for the try...catch block. Should be fixed in OTP R14. - try ssl:transport_accept(ListenSocket, ?SSL_TIMEOUT) of +transport_accept({ssl, ListenSocket}) -> + case ssl:transport_accept(ListenSocket, ?SSL_TIMEOUT) of {ok, Socket} -> - case ssl:ssl_accept(Socket, ?SSL_HANDSHAKE_TIMEOUT) of - ok -> - {ok, {ssl, Socket}}; - {error, _} = Err -> - Err - end; + {ok, {ssl, Socket}}; {error, _} = Err -> Err - catch - error:{badmatch, {error, Reason}} -> - {error, Reason} end; -accept(ListenSocket) -> +transport_accept(ListenSocket) -> gen_tcp:accept(ListenSocket, ?ACCEPT_TIMEOUT). +finish_accept({ssl, Socket}) -> + case ssl:ssl_accept(Socket, ?SSL_HANDSHAKE_TIMEOUT) of + ok -> + {ok, {ssl, Socket}}; + {error, _} = Err -> + Err + end; +finish_accept(Socket) -> + {ok, Socket}. + recv({ssl, Socket}, Length, Timeout) -> ssl:recv(Socket, Length, Timeout); recv(Socket, Length, Timeout) ->