From 769d0e98b8bad60258bcf1ec90bfd9534fa9b825 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Fri, 22 Mar 2019 14:23:18 +0100 Subject: [PATCH] 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. --- src/proto_http.c | 10 +++------- src/proto_htx.c | 9 +++------ src/stream.c | 5 ++--- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/proto_http.c b/src/proto_http.c index a1bcbb923..0a91091b2 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 bdfd4ba71..d6144fb06 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 d4cda4bc8..25618aebb 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,