From: Christopher Faulet Date: Fri, 22 Mar 2019 13:23:18 +0000 (+0100) Subject: BUG/MEDIUM: http/htx: Fix handling of the option abortonclose X-Git-Tag: v2.0-dev2~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=769d0e98b8bad60258bcf1ec90bfd9534fa9b825;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: http/htx: Fix handling of the option abortonclose Because the flag CF_SHUTR is no more set to mark the end of the message by the H2 multiplexer, we can rely on it again to detect aborts. there is no more need to make a check on the flag SI_FL_CLEAN_ABRT when the option abortonclose is enabled. So, this option should work as before for h2 clients. This patch must be backported to 1.9 with the previous EOI patches. --- diff --git a/src/proto_http.c b/src/proto_http.c index a1bcbb923a..0a91091b25 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -1777,7 +1777,6 @@ resume_execution: case ACT_CUSTOM: if ((s->req.flags & CF_READ_ERROR) || ((s->req.flags & (CF_SHUTR|CF_READ_NULL)) && - !(s->si[0].flags & SI_FL_CLEAN_ABRT) && (px->options & PR_O_ABRT_CLOSE))) act_flags |= ACT_FLAG_FINAL; @@ -2184,7 +2183,6 @@ resume_execution: case ACT_CUSTOM: if ((s->req.flags & CF_READ_ERROR) || ((s->req.flags & (CF_SHUTR|CF_READ_NULL)) && - !(s->si[0].flags & SI_FL_CLEAN_ABRT) && (px->options & PR_O_ABRT_CLOSE))) act_flags |= ACT_FLAG_FINAL; @@ -3612,8 +3610,7 @@ int http_sync_req_state(struct stream *s) */ if (((txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_SCL) && ((txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_KAL) && - (!(s->be->options & PR_O_ABRT_CLOSE) || - (s->si[0].flags & SI_FL_CLEAN_ABRT)) && + !(s->be->options & PR_O_ABRT_CLOSE) && txn->meth != HTTP_METH_POST) channel_dont_read(chn); @@ -3708,8 +3705,7 @@ int http_sync_req_state(struct stream *s) /* see above in MSG_DONE why we only do this in these states */ if (((txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_SCL) && ((txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_KAL) && - (!(s->be->options & PR_O_ABRT_CLOSE) || - (s->si[0].flags & SI_FL_CLEAN_ABRT))) + !(s->be->options & PR_O_ABRT_CLOSE)) channel_dont_read(chn); goto wait_other_side; } @@ -4070,7 +4066,7 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit) * server, which will decide whether to close or to go on processing the * request. We only do that in tunnel mode, and not in other modes since * it can be abused to exhaust source ports. */ - if ((s->be->options & PR_O_ABRT_CLOSE) && !(s->si[0].flags & SI_FL_CLEAN_ABRT)) { + if (s->be->options & PR_O_ABRT_CLOSE) { channel_auto_read(req); if ((req->flags & (CF_SHUTR|CF_READ_NULL)) && ((txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN)) diff --git a/src/proto_htx.c b/src/proto_htx.c index bdfd4ba71e..d6144fb061 100644 --- a/src/proto_htx.c +++ b/src/proto_htx.c @@ -1285,7 +1285,7 @@ int htx_request_forward_body(struct stream *s, struct channel *req, int an_bit) * server, which will decide whether to close or to go on processing the * request. We only do that in tunnel mode, and not in other modes since * it can be abused to exhaust source ports. */ - if ((s->be->options & PR_O_ABRT_CLOSE) && !(s->si[0].flags & SI_FL_CLEAN_ABRT)) { + if (s->be->options & PR_O_ABRT_CLOSE) { channel_auto_read(req); if ((req->flags & (CF_SHUTR|CF_READ_NULL)) && ((txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN)) @@ -3012,7 +3012,6 @@ static enum rule_result htx_req_get_intercept_rule(struct proxy *px, struct list case ACT_CUSTOM: if ((s->req.flags & CF_READ_ERROR) || ((s->req.flags & (CF_SHUTR|CF_READ_NULL)) && - !(s->si[0].flags & SI_FL_CLEAN_ABRT) && (px->options & PR_O_ABRT_CLOSE))) act_flags |= ACT_FLAG_FINAL; @@ -3402,7 +3401,6 @@ resume_execution: case ACT_CUSTOM: if ((s->req.flags & CF_READ_ERROR) || ((s->req.flags & (CF_SHUTR|CF_READ_NULL)) && - !(s->si[0].flags & SI_FL_CLEAN_ABRT) && (px->options & PR_O_ABRT_CLOSE))) act_flags |= ACT_FLAG_FINAL; @@ -5055,8 +5053,7 @@ static void htx_end_request(struct stream *s) * buffers, otherwise a close could cause an RST on some systems * (eg: Linux). */ - if ((!(s->be->options & PR_O_ABRT_CLOSE) || (s->si[0].flags & SI_FL_CLEAN_ABRT)) && - txn->meth != HTTP_METH_POST) + if (!(s->be->options & PR_O_ABRT_CLOSE) && txn->meth != HTTP_METH_POST) channel_dont_read(chn); /* if the server closes the connection, we want to immediately react @@ -5136,7 +5133,7 @@ static void htx_end_request(struct stream *s) if (txn->rsp.flags & HTTP_MSGF_XFER_LEN) s->si[1].flags |= SI_FL_NOLINGER; /* we want to close ASAP */ /* see above in MSG_DONE why we only do this in these states */ - if ((!(s->be->options & PR_O_ABRT_CLOSE) || (s->si[0].flags & SI_FL_CLEAN_ABRT))) + if (!(s->be->options & PR_O_ABRT_CLOSE)) channel_dont_read(chn); goto end; } diff --git a/src/stream.c b/src/stream.c index d4cda4bc82..25618aebba 100644 --- a/src/stream.c +++ b/src/stream.c @@ -670,7 +670,7 @@ static int sess_update_st_con_tcp(struct stream *s) unlikely((rep->flags & CF_SHUTW) || ((req->flags & CF_SHUTW_NOW) && /* FIXME: this should not prevent a connection from establishing */ ((!(req->flags & CF_WRITE_ACTIVITY) && channel_is_empty(req)) || - ((s->be->options & PR_O_ABRT_CLOSE) && !(s->si[0].flags & SI_FL_CLEAN_ABRT)))))) { + (s->be->options & PR_O_ABRT_CLOSE))))) { /* give up */ si_shutw(si); si->err_type |= SI_ET_CONN_ABRT; @@ -890,8 +890,7 @@ static int check_req_may_abort(struct channel *req, struct stream *s) { return ((req->flags & (CF_READ_ERROR)) || ((req->flags & (CF_SHUTW_NOW|CF_SHUTW)) && /* empty and client aborted */ - (channel_is_empty(req) || - ((s->be->options & PR_O_ABRT_CLOSE) && !(s->si[0].flags & SI_FL_CLEAN_ABRT))))); + (channel_is_empty(req) || (s->be->options & PR_O_ABRT_CLOSE)))); } /* Update back stream interface status for input states SI_ST_ASS, SI_ST_QUE,