From: Willy Tarreau Date: Sun, 10 Aug 2008 22:21:56 +0000 (+0200) Subject: [BUG] fix segfault with url_param + check_post X-Git-Tag: v1.3.16-rc1~213 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fb0528bd56063e9800c7dd6fbd96b3c5c6a687f2;p=thirdparty%2Fhaproxy.git [BUG] fix segfault with url_param + check_post If an HTTP/0.9-like POST request is sent to haproxy while configured with url_param + check_post, it will crash. The reason is that the total buffer length was computed based on req->total (which equals the number of bytes read) and not req->l (number of bytes in the buffer), thus leading to wrong size calculations when calling memchr(). The affected code does not look like it could have been exploited to run arbitrary code, only reads were performed at wrong locations. --- diff --git a/src/backend.c b/src/backend.c index f1346719f6..48859b0930 100644 --- a/src/backend.c +++ b/src/backend.c @@ -1196,7 +1196,7 @@ struct server *get_server_ph_post(struct session *s) return NULL; body = msg->sol[msg->eoh] == '\r' ? msg->eoh + 2 : msg->eoh + 1; - len = req->total - body; + len = req->l - body; params = req->data + body; if ( len == 0 ) diff --git a/src/proto_http.c b/src/proto_http.c index ea7c764a95..b4672755f9 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -2290,7 +2290,7 @@ int process_cli(struct session *t) */ if (!(t->flags & (SN_ASSIGNED|SN_DIRECT)) && t->txn.meth == HTTP_METH_POST && t->be->url_param_name != NULL && - t->be->url_param_post_limit != 0 && req->total < BUFSIZE && + t->be->url_param_post_limit != 0 && req->l < BUFSIZE && memchr(msg->sol + msg->sl.rq.u, '?', msg->sl.rq.u_l) == NULL) { /* are there enough bytes here? total == l || r || rlim ? * len is unsigned, but eoh is int, @@ -2298,7 +2298,7 @@ int process_cli(struct session *t) * eoh is the first empty line of the header */ /* already established CRLF or LF at eoh, move to start of message, find message length in buffer */ - unsigned long len = req->total - (msg->sol[msg->eoh] == '\r' ? msg->eoh + 2 : msg->eoh + 1); + unsigned long len = req->l - (msg->sol[msg->eoh] == '\r' ? msg->eoh + 2 : msg->eoh + 1); /* If we have HTTP/1.1 and Expect: 100-continue, then abort. * We can't assume responsibility for the server's decision, @@ -3790,7 +3790,7 @@ int process_srv(struct session *t) */ struct http_msg * msg = &t->txn.req; unsigned long body = msg->sol[msg->eoh] == '\r' ? msg->eoh + 2 :msg->eoh + 1; - unsigned long len = req->total - body; + unsigned long len = req->l - body; long long limit = t->be->url_param_post_limit; struct hdr_ctx ctx; ctx.idx = 0; @@ -3798,7 +3798,7 @@ int process_srv(struct session *t) http_find_header2("Transfer-Encoding", 17, msg->sol, &txn->hdr_idx, &ctx); if ( ctx.idx && strncasecmp(ctx.line+ctx.val,"chunked",ctx.vlen)==0) { unsigned int chunk = 0; - while ( body < req->total && !HTTP_IS_CRLF(msg->sol[body])) { + while ( body < req->l && !HTTP_IS_CRLF(msg->sol[body])) { char c = msg->sol[body]; if (ishex(c)) { unsigned int hex = toupper(c) - '0'; @@ -3810,7 +3810,7 @@ int process_srv(struct session *t) body++; len--; } - if ( body == req->total ) + if ( body + 2 >= req->l ) return 0; /* end of buffer? data missing! */ if ( memcmp(msg->sol+body, "\r\n", 2) != 0 )