From 969f12408b81852f9809c308ba6fc9fec9c36e51 Mon Sep 17 00:00:00 2001 From: chengyechun Date: Sat, 18 Jun 2022 18:26:42 +0800 Subject: [PATCH] fix som CVE --- backport-CVE-2022-26377.patch | 38 ++++ backport-CVE-2022-28614.patch | 60 +++++ backport-CVE-2022-29404.patch | 88 ++++++++ backport-CVE-2022-30522.patch | 408 ++++++++++++++++++++++++++++++++++ backport-CVE-2022-30556.patch | 246 ++++++++++++++++++++ backport-CVE-2022-31813.patch | 243 ++++++++++++++++++++ httpd.spec | 14 +- 7 files changed, 1096 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2022-26377.patch create mode 100644 backport-CVE-2022-28614.patch create mode 100644 backport-CVE-2022-29404.patch create mode 100644 backport-CVE-2022-30522.patch create mode 100644 backport-CVE-2022-30556.patch create mode 100644 backport-CVE-2022-31813.patch diff --git a/backport-CVE-2022-26377.patch b/backport-CVE-2022-26377.patch new file mode 100644 index 0000000..5bebf98 --- /dev/null +++ b/backport-CVE-2022-26377.patch @@ -0,0 +1,38 @@ +From f7f15f3d8bfe3032926c8c39eb8434529f680bd4 Mon Sep 17 00:00:00 2001 +From: ylavic +Date: Wed Jun 1 13:48:21 2022 UTC +Subject: [PATCH] mod_proxy_ajp: T-E has precedence over C-L. + +--- + modules/proxy/mod_proxy_ajp.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +diff --git a/modules/proxy/mod_proxy_ajp.c b/modules/proxy/mod_proxy_ajp.c +index e2992fc..a77a86b 100644 +--- a/modules/proxy/mod_proxy_ajp.c ++++ b/modules/proxy/mod_proxy_ajp.c +@@ -246,9 +246,18 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r, + /* read the first block of data */ + input_brigade = apr_brigade_create(p, r->connection->bucket_alloc); + tenc = apr_table_get(r->headers_in, "Transfer-Encoding"); +- if (tenc && (ap_cstr_casecmp(tenc, "chunked") == 0)) { +- /* The AJP protocol does not want body data yet */ +- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00870) "request is chunked"); ++ if (tenc) { ++ if (ap_cstr_casecmp(tenc, "chunked") == 0) { ++ /* The AJP protocol does not want body data yet */ ++ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00870) ++ "request is chunked"); ++ } ++ else { ++ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10396) ++ "%s Transfer-Encoding is not supported", ++ tenc); ++ return HTTP_INTERNAL_SERVER_ERROR; ++ } + } else { + /* Get client provided Content-Length header */ + content_length = get_content_length(r); +-- +1.8.3.1 + diff --git a/backport-CVE-2022-28614.patch b/backport-CVE-2022-28614.patch new file mode 100644 index 0000000..3f782ce --- /dev/null +++ b/backport-CVE-2022-28614.patch @@ -0,0 +1,60 @@ +From 8c14927162cf3b4f810683e1c5505e9ef9e1f123 Mon Sep 17 00:00:00 2001 +From: covener +Date: Wed Jun 1 07:51:04 2022 UTC +Subject: [PATCH] handle large writes in ap_rputs + +--- + include/http_protocol.h | 22 +++++++++++++++++++++- + server/protocol.c | 3 +++ + 2 files changed, 24 insertions(+), 1 deletion(-) + +diff --git a/include/http_protocol.h b/include/http_protocol.h +index 20bd202..94c481e 100644 +--- a/include/http_protocol.h ++++ b/include/http_protocol.h +@@ -475,7 +475,27 @@ AP_DECLARE(int) ap_rwrite(const void *buf, int nbyte, request_rec *r); + */ + static APR_INLINE int ap_rputs(const char *str, request_rec *r) + { +- return ap_rwrite(str, (int)strlen(str), r); ++ apr_size_t len; ++ ++ len = strlen(str); ++ ++ for (;;) { ++ if (len <= INT_MAX) { ++ return ap_rwrite(str, (int)len, r); ++ } ++ else { ++ int rc; ++ ++ rc = ap_rwrite(str, INT_MAX, r); ++ if (rc < 0) { ++ return rc; ++ } ++ else { ++ str += INT_MAX; ++ len -= INT_MAX; ++ } ++ } ++ } + } + + /** +diff --git a/server/protocol.c b/server/protocol.c +index 298f61e..7adc7f7 100644 +--- a/server/protocol.c ++++ b/server/protocol.c +@@ -2128,6 +2128,9 @@ AP_DECLARE(int) ap_rputc(int c, request_rec *r) + + AP_DECLARE(int) ap_rwrite(const void *buf, int nbyte, request_rec *r) + { ++ if (nbyte < 0) ++ return -1; ++ + if (r->connection->aborted) + return -1; + +-- +1.8.3.1 + diff --git a/backport-CVE-2022-29404.patch b/backport-CVE-2022-29404.patch new file mode 100644 index 0000000..33633d4 --- /dev/null +++ b/backport-CVE-2022-29404.patch @@ -0,0 +1,88 @@ +From 92499e20034485c5e2d29cb85940e309573d976e Mon Sep 17 00:00:00 2001 +From: covener +Date: Wed Jun 1 12:30:46 2022 UTC +Subject: [PATCH] use a liberal default limit for LimitRequestBody of 1GB + +--- + modules/http/http_filters.c | 8 +++++++- + modules/proxy/proxy_util.c | 13 ------------- + server/core.c | 2 +- + 3 files changed, 8 insertions(+), 15 deletions(-) + +diff --git a/modules/http/http_filters.c b/modules/http/http_filters.c +index 3e02da8..c3eab95 100644 +--- a/modules/http/http_filters.c ++++ b/modules/http/http_filters.c +@@ -1700,7 +1700,8 @@ AP_DECLARE(int) ap_setup_client_block(request_rec *r, int read_policy) + { + const char *tenc = apr_table_get(r->headers_in, "Transfer-Encoding"); + const char *lenp = apr_table_get(r->headers_in, "Content-Length"); +- ++ apr_off_t limit_req_body = ap_get_limit_req_body(r); ++ + r->read_body = read_policy; + r->read_chunked = 0; + r->remaining = 0; +@@ -1735,6 +1736,11 @@ AP_DECLARE(int) ap_setup_client_block(request_rec *r, int read_policy) + return HTTP_REQUEST_ENTITY_TOO_LARGE; + } + ++ if (limit_req_body > 0 && (r->remaining > limit_req_body)) { ++ /* will be logged when the body is discarded */ ++ return HTTP_REQUEST_ENTITY_TOO_LARGE; ++ } ++ + #ifdef AP_DEBUG + { + /* Make sure ap_getline() didn't leave any droppings. */ +diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c +index 4f1610f..04733f2 100644 +--- a/modules/proxy/proxy_util.c ++++ b/modules/proxy/proxy_util.c +@@ -4249,12 +4249,10 @@ PROXY_DECLARE(int) ap_proxy_spool_input(request_rec *r, + apr_bucket *e; + apr_off_t bytes, fsize = 0; + apr_file_t *tmpfile = NULL; +- apr_off_t limit; + + *bytes_spooled = 0; + body_brigade = apr_brigade_create(p, bucket_alloc); + +- limit = ap_get_limit_req_body(r); + + do { + if (APR_BRIGADE_EMPTY(input_brigade)) { +@@ -4273,17 +4271,6 @@ PROXY_DECLARE(int) ap_proxy_spool_input(request_rec *r, + apr_brigade_length(input_brigade, 1, &bytes); + + if (*bytes_spooled + bytes > max_mem_spool) { +- /* +- * LimitRequestBody does not affect Proxy requests (Should it?). +- * Let it take effect if we decide to store the body in a +- * temporary file on disk. +- */ +- if (limit && (*bytes_spooled + bytes > limit)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01088) +- "Request body is larger than the configured " +- "limit of %" APR_OFF_T_FMT, limit); +- return HTTP_REQUEST_ENTITY_TOO_LARGE; +- } + /* can't spool any more in memory; write latest brigade to disk */ + if (tmpfile == NULL) { + const char *temp_dir; +diff --git a/server/core.c b/server/core.c +index 957eeff..515047b 100644 +--- a/server/core.c ++++ b/server/core.c +@@ -71,7 +71,7 @@ + + /* LimitRequestBody handling */ + #define AP_LIMIT_REQ_BODY_UNSET ((apr_off_t) -1) +-#define AP_DEFAULT_LIMIT_REQ_BODY ((apr_off_t) 0) ++#define AP_DEFAULT_LIMIT_REQ_BODY ((apr_off_t) 1<<30) /* 1GB */ + + /* LimitXMLRequestBody handling */ + #define AP_LIMIT_UNSET ((long) -1) +-- +1.8.3.1 + diff --git a/backport-CVE-2022-30522.patch b/backport-CVE-2022-30522.patch new file mode 100644 index 0000000..b5f4c3a --- /dev/null +++ b/backport-CVE-2022-30522.patch @@ -0,0 +1,408 @@ +From 65b8fb947b144556c7ad1cf7ddc3941010ad77ba Mon Sep 17 00:00:00 2001 +From: covener +Date: Wed Jun 1 12:40:09 2022 UTC +Subject: [PATCH] limit mod_sed memory use + +--- + modules/filters/sed1.c | 156 +++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 113 insertions(+), 43 deletions(-) + +diff --git a/modules/filters/sed1.c b/modules/filters/sed1.c +index 67a8d06..a08068e 100644 +--- a/modules/filters/sed1.c ++++ b/modules/filters/sed1.c +@@ -87,18 +87,20 @@ static void eval_errf(sed_eval_t *eval, const char *fmt, ...) + } + + #define INIT_BUF_SIZE 1024 ++#define MAX_BUF_SIZE 1024*8192 + + /* + * grow_buffer + */ +-static void grow_buffer(apr_pool_t *pool, char **buffer, ++static apr_status_t grow_buffer(apr_pool_t *pool, char **buffer, + char **spend, apr_size_t *cursize, + apr_size_t newsize) + { + char* newbuffer = NULL; + apr_size_t spendsize = 0; +- if (*cursize >= newsize) +- return; ++ if (*cursize >= newsize) { ++ return APR_SUCCESS; ++ } + /* Avoid number of times realloc is called. It could cause huge memory + * requirement if line size is huge e.g 2 MB */ + if (newsize < *cursize * 2) { +@@ -107,6 +109,9 @@ static void grow_buffer(apr_pool_t *pool, char **buffer, + + /* Align it to 4 KB boundary */ + newsize = (newsize + ((1 << 12) - 1)) & ~((1 << 12) - 1); ++ if (newsize > MAX_BUF_SIZE) { ++ return APR_ENOMEM; ++ } + newbuffer = apr_pcalloc(pool, newsize); + if (*spend && *buffer && (*cursize > 0)) { + spendsize = *spend - *buffer; +@@ -119,63 +124,77 @@ static void grow_buffer(apr_pool_t *pool, char **buffer, + if (spend != buffer) { + *spend = *buffer + spendsize; + } ++ return APR_SUCCESS; + } + + /* + * grow_line_buffer + */ +-static void grow_line_buffer(sed_eval_t *eval, apr_size_t newsize) ++static apr_status_t grow_line_buffer(sed_eval_t *eval, apr_size_t newsize) + { +- grow_buffer(eval->pool, &eval->linebuf, &eval->lspend, ++ return grow_buffer(eval->pool, &eval->linebuf, &eval->lspend, + &eval->lsize, newsize); + } + + /* + * grow_hold_buffer + */ +-static void grow_hold_buffer(sed_eval_t *eval, apr_size_t newsize) ++static apr_status_t grow_hold_buffer(sed_eval_t *eval, apr_size_t newsize) + { +- grow_buffer(eval->pool, &eval->holdbuf, &eval->hspend, ++ return grow_buffer(eval->pool, &eval->holdbuf, &eval->hspend, + &eval->hsize, newsize); + } + + /* + * grow_gen_buffer + */ +-static void grow_gen_buffer(sed_eval_t *eval, apr_size_t newsize, ++static apr_status_t grow_gen_buffer(sed_eval_t *eval, apr_size_t newsize, + char **gspend) + { ++ apr_status_t rc = 0; + if (gspend == NULL) { + gspend = &eval->genbuf; + } +- grow_buffer(eval->pool, &eval->genbuf, gspend, ++ rc = grow_buffer(eval->pool, &eval->genbuf, gspend, + &eval->gsize, newsize); +- eval->lcomend = &eval->genbuf[71]; ++ if (rc == APR_SUCCESS) { ++ eval->lcomend = &eval->genbuf[71]; ++ } ++ return rc; + } + + /* + * appendmem_to_linebuf + */ +-static void appendmem_to_linebuf(sed_eval_t *eval, const char* sz, apr_size_t len) ++static apr_status_t appendmem_to_linebuf(sed_eval_t *eval, const char* sz, apr_size_t len) + { ++ apr_status_t rc = 0; + apr_size_t reqsize = (eval->lspend - eval->linebuf) + len; + if (eval->lsize < reqsize) { +- grow_line_buffer(eval, reqsize); ++ rc = grow_line_buffer(eval, reqsize); ++ if (rc != APR_SUCCESS) { ++ return rc; ++ } + } + memcpy(eval->lspend, sz, len); + eval->lspend += len; ++ return APR_SUCCESS; + } + + /* + * append_to_linebuf + */ +-static void append_to_linebuf(sed_eval_t *eval, const char* sz, ++static apr_status_t append_to_linebuf(sed_eval_t *eval, const char* sz, + step_vars_storage *step_vars) + { + apr_size_t len = strlen(sz); + char *old_linebuf = eval->linebuf; ++ apr_status_t rc = 0; + /* Copy string including null character */ +- appendmem_to_linebuf(eval, sz, len + 1); ++ rc = appendmem_to_linebuf(eval, sz, len + 1); ++ if (rc != APR_SUCCESS) { ++ return rc; ++ } + --eval->lspend; /* lspend will now point to NULL character */ + /* Sync step_vars after a possible linebuf expansion */ + if (step_vars && old_linebuf != eval->linebuf) { +@@ -189,68 +208,84 @@ static void append_to_linebuf(sed_eval_t *eval, const char* sz, + step_vars->locs = step_vars->locs - old_linebuf + eval->linebuf; + } + } ++ return APR_SUCCESS; + } + + /* + * copy_to_linebuf + */ +-static void copy_to_linebuf(sed_eval_t *eval, const char* sz, ++static apr_status_t copy_to_linebuf(sed_eval_t *eval, const char* sz, + step_vars_storage *step_vars) + { + eval->lspend = eval->linebuf; +- append_to_linebuf(eval, sz, step_vars); ++ return append_to_linebuf(eval, sz, step_vars); + } + + /* + * append_to_holdbuf + */ +-static void append_to_holdbuf(sed_eval_t *eval, const char* sz) ++static apr_status_t append_to_holdbuf(sed_eval_t *eval, const char* sz) + { + apr_size_t len = strlen(sz); + apr_size_t reqsize = (eval->hspend - eval->holdbuf) + len + 1; ++ apr_status_t rc = 0; + if (eval->hsize <= reqsize) { +- grow_hold_buffer(eval, reqsize); ++ rc = grow_hold_buffer(eval, reqsize); ++ if (rc != APR_SUCCESS) { ++ return rc; ++ } + } + memcpy(eval->hspend, sz, len + 1); + /* hspend will now point to NULL character */ + eval->hspend += len; ++ return APR_SUCCESS; + } + + /* + * copy_to_holdbuf + */ +-static void copy_to_holdbuf(sed_eval_t *eval, const char* sz) ++static apr_status_t copy_to_holdbuf(sed_eval_t *eval, const char* sz) + { + eval->hspend = eval->holdbuf; +- append_to_holdbuf(eval, sz); ++ return append_to_holdbuf(eval, sz); + } + + /* + * append_to_genbuf + */ +-static void append_to_genbuf(sed_eval_t *eval, const char* sz, char **gspend) ++static apr_status_t append_to_genbuf(sed_eval_t *eval, const char* sz, char **gspend) + { + apr_size_t len = strlen(sz); + apr_size_t reqsize = (*gspend - eval->genbuf) + len + 1; ++ apr_status_t rc = 0; + if (eval->gsize < reqsize) { +- grow_gen_buffer(eval, reqsize, gspend); ++ rc = grow_gen_buffer(eval, reqsize, gspend); ++ if (rc != APR_SUCCESS) { ++ return rc; ++ } + } + memcpy(*gspend, sz, len + 1); + /* *gspend will now point to NULL character */ + *gspend += len; ++ return APR_SUCCESS; + } + + /* + * copy_to_genbuf + */ +-static void copy_to_genbuf(sed_eval_t *eval, const char* sz) ++static apr_status_t copy_to_genbuf(sed_eval_t *eval, const char* sz) + { + apr_size_t len = strlen(sz); + apr_size_t reqsize = len + 1; ++ apr_status_t rc = APR_SUCCESS; + if (eval->gsize < reqsize) { +- grow_gen_buffer(eval, reqsize, NULL); ++ rc = grow_gen_buffer(eval, reqsize, NULL); ++ if (rc != APR_SUCCESS) { ++ return rc; ++ } + } + memcpy(eval->genbuf, sz, len + 1); ++ return rc; + } + + /* +@@ -397,6 +432,7 @@ apr_status_t sed_eval_buffer(sed_eval_t *eval, const char *buf, apr_size_t bufsz + } + + while (bufsz) { ++ apr_status_t rc = 0; + char *n; + apr_size_t llen; + +@@ -411,7 +447,10 @@ apr_status_t sed_eval_buffer(sed_eval_t *eval, const char *buf, apr_size_t bufsz + break; + } + +- appendmem_to_linebuf(eval, buf, llen + 1); ++ rc = appendmem_to_linebuf(eval, buf, llen + 1); ++ if (rc != APR_SUCCESS) { ++ return rc; ++ } + --eval->lspend; + /* replace new line character with NULL */ + *eval->lspend = '\0'; +@@ -426,7 +465,10 @@ apr_status_t sed_eval_buffer(sed_eval_t *eval, const char *buf, apr_size_t bufsz + + /* Save the leftovers for later */ + if (bufsz) { +- appendmem_to_linebuf(eval, buf, bufsz); ++ apr_status_t rc = appendmem_to_linebuf(eval, buf, bufsz); ++ if (rc != APR_SUCCESS) { ++ return rc; ++ } + } + + return APR_SUCCESS; +@@ -448,6 +490,7 @@ apr_status_t sed_finalize_eval(sed_eval_t *eval, void *fout) + /* Process leftovers */ + if (eval->lspend > eval->linebuf) { + apr_status_t rv; ++ apr_status_t rc = 0; + + if (eval->lreadyflag) { + eval->lreadyflag = 0; +@@ -457,7 +500,10 @@ apr_status_t sed_finalize_eval(sed_eval_t *eval, void *fout) + * buffer is not a newline. + */ + /* Assure space for NULL */ +- append_to_linebuf(eval, "", NULL); ++ rc = append_to_linebuf(eval, "", NULL); ++ if (rc != APR_SUCCESS) { ++ return rc; ++ } + } + + *eval->lspend = '\0'; +@@ -655,11 +701,15 @@ static apr_status_t dosub(sed_eval_t *eval, char *rhsbuf, int n, + sp = eval->genbuf; + rp = rhsbuf; + sp = place(eval, sp, lp, step_vars->loc1); ++ if (sp == NULL) { ++ return APR_EGENERAL; ++ } + while ((c = *rp++) != 0) { + if (c == '&') { + sp = place(eval, sp, step_vars->loc1, step_vars->loc2); +- if (sp == NULL) ++ if (sp == NULL) { + return APR_EGENERAL; ++ } + } + else if (c == '\\') { + c = *rp++; +@@ -675,13 +725,19 @@ static apr_status_t dosub(sed_eval_t *eval, char *rhsbuf, int n, + *sp++ = c; + if (sp >= eval->genbuf + eval->gsize) { + /* expand genbuf and set the sp appropriately */ +- grow_gen_buffer(eval, eval->gsize + 1024, &sp); ++ rv = grow_gen_buffer(eval, eval->gsize + 1024, &sp); ++ if (rv != APR_SUCCESS) { ++ return rv; ++ } + } + } + lp = step_vars->loc2; + step_vars->loc2 = sp - eval->genbuf + eval->linebuf; +- append_to_genbuf(eval, lp, &sp); +- copy_to_linebuf(eval, eval->genbuf, step_vars); ++ rv = append_to_genbuf(eval, lp, &sp); ++ if (rv != APR_SUCCESS) { ++ return rv; ++ } ++ rv = copy_to_linebuf(eval, eval->genbuf, step_vars); + return rv; + } + +@@ -695,7 +751,10 @@ static char *place(sed_eval_t *eval, char *asp, char *al1, char *al2) + apr_size_t reqsize = (sp - eval->genbuf) + n + 1; + + if (eval->gsize < reqsize) { +- grow_gen_buffer(eval, reqsize, &sp); ++ apr_status_t rc = grow_gen_buffer(eval, reqsize, &sp); ++ if (rc != APR_SUCCESS) { ++ return NULL; ++ } + } + memcpy(sp, al1, n); + return sp + n; +@@ -750,7 +809,8 @@ static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc, + } + + p1++; +- copy_to_linebuf(eval, p1, step_vars); ++ rv = copy_to_linebuf(eval, p1, step_vars); ++ if (rv != APR_SUCCESS) return rv; + eval->jflag++; + break; + +@@ -760,21 +820,27 @@ static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc, + break; + + case GCOM: +- copy_to_linebuf(eval, eval->holdbuf, step_vars); ++ rv = copy_to_linebuf(eval, eval->holdbuf, step_vars); ++ if (rv != APR_SUCCESS) return rv; + break; + + case CGCOM: +- append_to_linebuf(eval, "\n", step_vars); +- append_to_linebuf(eval, eval->holdbuf, step_vars); ++ rv = append_to_linebuf(eval, "\n", step_vars); ++ if (rv != APR_SUCCESS) return rv; ++ rv = append_to_linebuf(eval, eval->holdbuf, step_vars); ++ if (rv != APR_SUCCESS) return rv; + break; + + case HCOM: +- copy_to_holdbuf(eval, eval->linebuf); ++ rv = copy_to_holdbuf(eval, eval->linebuf); ++ if (rv != APR_SUCCESS) return rv; + break; + + case CHCOM: +- append_to_holdbuf(eval, "\n"); +- append_to_holdbuf(eval, eval->linebuf); ++ rv = append_to_holdbuf(eval, "\n"); ++ if (rv != APR_SUCCESS) return rv; ++ rv = append_to_holdbuf(eval, eval->linebuf); ++ if (rv != APR_SUCCESS) return rv; + break; + + case ICOM: +@@ -896,7 +962,8 @@ static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc, + if (rv != APR_SUCCESS) + return rv; + } +- append_to_linebuf(eval, "\n", step_vars); ++ rv = append_to_linebuf(eval, "\n", step_vars); ++ if (rv != APR_SUCCESS) return rv; + eval->pending = ipc->next; + break; + +@@ -970,9 +1037,12 @@ static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc, + break; + + case XCOM: +- copy_to_genbuf(eval, eval->linebuf); +- copy_to_linebuf(eval, eval->holdbuf, step_vars); +- copy_to_holdbuf(eval, eval->genbuf); ++ rv = copy_to_genbuf(eval, eval->linebuf); ++ if (rv != APR_SUCCESS) return rv; ++ rv = copy_to_linebuf(eval, eval->holdbuf, step_vars); ++ if (rv != APR_SUCCESS) return rv; ++ rv = copy_to_holdbuf(eval, eval->genbuf); ++ if (rv != APR_SUCCESS) return rv; + break; + + case YCOM: +-- +1.8.3.1 + diff --git a/backport-CVE-2022-30556.patch b/backport-CVE-2022-30556.patch new file mode 100644 index 0000000..4d54d14 --- /dev/null +++ b/backport-CVE-2022-30556.patch @@ -0,0 +1,246 @@ +From 11a3fcbf9e64239d8fe8402d941bbdcbc4532c88 Mon Sep 17 00:00:00 2001 +From: covener +Date: Wed Jun 1 12:36:13 2022 UTC +Subject: [PATCH] use filters consistently + +--- + modules/lua/lua_request.c | 145 +++++++++++++++++----------------------------- + 1 file changed, 54 insertions(+), 91 deletions(-) + +diff --git a/modules/lua/lua_request.c b/modules/lua/lua_request.c +index 1eab7b6..a7e501b 100644 +--- a/modules/lua/lua_request.c ++++ b/modules/lua/lua_request.c +@@ -2227,23 +2227,20 @@ static int lua_websocket_greet(lua_State *L) + return 0; + } + +-static apr_status_t lua_websocket_readbytes(conn_rec* c, char* buffer, +- apr_off_t len) ++static apr_status_t lua_websocket_readbytes(conn_rec* c, ++ apr_bucket_brigade *brigade, ++ char* buffer, apr_off_t len) + { +- apr_bucket_brigade *brigade = apr_brigade_create(c->pool, c->bucket_alloc); ++ apr_size_t delivered; + apr_status_t rv; ++ + rv = ap_get_brigade(c->input_filters, brigade, AP_MODE_READBYTES, + APR_BLOCK_READ, len); + if (rv == APR_SUCCESS) { +- if (!APR_BRIGADE_EMPTY(brigade)) { +- apr_bucket* bucket = APR_BRIGADE_FIRST(brigade); +- const char* data = NULL; +- apr_size_t data_length = 0; +- rv = apr_bucket_read(bucket, &data, &data_length, APR_BLOCK_READ); +- if (rv == APR_SUCCESS) { +- memcpy(buffer, data, len); +- } +- apr_bucket_delete(bucket); ++ delivered = len; ++ rv = apr_brigade_flatten(brigade, buffer, &delivered); ++ if ((rv == APR_SUCCESS) && (delivered < len)) { ++ rv = APR_INCOMPLETE; + } + } + apr_brigade_cleanup(brigade); +@@ -2273,35 +2270,29 @@ static int lua_websocket_peek(lua_State *L) + + static int lua_websocket_read(lua_State *L) + { +- apr_socket_t *sock; + apr_status_t rv; + int do_read = 1; + int n = 0; +- apr_size_t len = 1; + apr_size_t plen = 0; + unsigned short payload_short = 0; + apr_uint64_t payload_long = 0; + unsigned char *mask_bytes; + char byte; +- int plaintext; +- + +- request_rec *r = ap_lua_check_request_rec(L, 1); +- plaintext = ap_lua_ssl_is_https(r->connection) ? 0 : 1; ++ apr_bucket_brigade *brigade; ++ conn_rec* c; + ++ request_rec *r = ap_lua_check_request_rec(L, 1); ++ c = r->connection; + + mask_bytes = apr_pcalloc(r->pool, 4); +- sock = ap_get_conn_socket(r->connection); ++ ++ brigade = apr_brigade_create(r->pool, c->bucket_alloc); + + while (do_read) { + do_read = 0; + /* Get opcode and FIN bit */ +- if (plaintext) { +- rv = apr_socket_recv(sock, &byte, &len); +- } +- else { +- rv = lua_websocket_readbytes(r->connection, &byte, 1); +- } ++ rv = lua_websocket_readbytes(c, brigade, &byte, 1); + if (rv == APR_SUCCESS) { + unsigned char ubyte, fin, opcode, mask, payload; + ubyte = (unsigned char)byte; +@@ -2311,12 +2302,7 @@ static int lua_websocket_read(lua_State *L) + opcode = ubyte & 0xf; + + /* Get the payload length and mask bit */ +- if (plaintext) { +- rv = apr_socket_recv(sock, &byte, &len); +- } +- else { +- rv = lua_websocket_readbytes(r->connection, &byte, 1); +- } ++ rv = lua_websocket_readbytes(c, brigade, &byte, 1); + if (rv == APR_SUCCESS) { + ubyte = (unsigned char)byte; + /* Mask is the first bit */ +@@ -2327,40 +2313,25 @@ static int lua_websocket_read(lua_State *L) + + /* Extended payload? */ + if (payload == 126) { +- len = 2; +- if (plaintext) { +- /* XXX: apr_socket_recv does not receive len bits, only up to len bits! */ +- rv = apr_socket_recv(sock, (char*) &payload_short, &len); +- } +- else { +- rv = lua_websocket_readbytes(r->connection, +- (char*) &payload_short, 2); +- } +- payload_short = ntohs(payload_short); +- +- if (rv == APR_SUCCESS) { +- plen = payload_short; +- } +- else { ++ rv = lua_websocket_readbytes(c, brigade, ++ (char*) &payload_short, 2); ++ ++ if (rv != APR_SUCCESS) { + return 0; + } ++ ++ plen = ntohs(payload_short); + } + /* Super duper extended payload? */ + if (payload == 127) { +- len = 8; +- if (plaintext) { +- rv = apr_socket_recv(sock, (char*) &payload_long, &len); +- } +- else { +- rv = lua_websocket_readbytes(r->connection, +- (char*) &payload_long, 8); +- } +- if (rv == APR_SUCCESS) { +- plen = ap_ntoh64(&payload_long); +- } +- else { ++ rv = lua_websocket_readbytes(c, brigade, ++ (char*) &payload_long, 8); ++ ++ if (rv != APR_SUCCESS) { + return 0; + } ++ ++ plen = ap_ntoh64(&payload_long); + } + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03210) + "Websocket: Reading %" APR_SIZE_T_FMT " (%s) bytes, masking is %s. %s", +@@ -2369,46 +2340,27 @@ static int lua_websocket_read(lua_State *L) + mask ? "on" : "off", + fin ? "This is a final frame" : "more to follow"); + if (mask) { +- len = 4; +- if (plaintext) { +- rv = apr_socket_recv(sock, (char*) mask_bytes, &len); +- } +- else { +- rv = lua_websocket_readbytes(r->connection, +- (char*) mask_bytes, 4); +- } ++ rv = lua_websocket_readbytes(c, brigade, ++ (char*) mask_bytes, 4); ++ + if (rv != APR_SUCCESS) { + return 0; + } + } + if (plen < (HUGE_STRING_LEN*1024) && plen > 0) { + apr_size_t remaining = plen; +- apr_size_t received; +- apr_off_t at = 0; + char *buffer = apr_palloc(r->pool, plen+1); + buffer[plen] = 0; + +- if (plaintext) { +- while (remaining > 0) { +- received = remaining; +- rv = apr_socket_recv(sock, buffer+at, &received); +- if (received > 0 ) { +- remaining -= received; +- at += received; +- } +- } +- ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, +- "Websocket: Frame contained %" APR_OFF_T_FMT " bytes, pushed to Lua stack", +- at); +- } +- else { +- rv = lua_websocket_readbytes(r->connection, buffer, +- remaining); +- ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, +- "Websocket: SSL Frame contained %" APR_SIZE_T_FMT " bytes, "\ +- "pushed to Lua stack", +- remaining); ++ rv = lua_websocket_readbytes(c, brigade, buffer, remaining); ++ ++ if (rv != APR_SUCCESS) { ++ return 0; + } ++ ++ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, ++ "Websocket: Frame contained %" APR_SIZE_T_FMT \ ++ " bytes, pushed to Lua stack", remaining); + if (mask) { + for (n = 0; n < plen; n++) { + buffer[n] ^= mask_bytes[n%4]; +@@ -2420,14 +2372,25 @@ static int lua_websocket_read(lua_State *L) + return 2; + } + +- + /* Decide if we need to react to the opcode or not */ + if (opcode == 0x09) { /* ping */ + char frame[2]; +- plen = 2; ++ apr_bucket *b; ++ + frame[0] = 0x8A; + frame[1] = 0; +- apr_socket_send(sock, frame, &plen); /* Pong! */ ++ ++ /* Pong! */ ++ b = apr_bucket_transient_create(frame, 2, c->bucket_alloc); ++ APR_BRIGADE_INSERT_TAIL(brigade, b); ++ ++ rv = ap_pass_brigade(c->output_filters, brigade); ++ apr_brigade_cleanup(brigade); ++ ++ if (rv != APR_SUCCESS) { ++ return 0; ++ } ++ + do_read = 1; + } + } +-- +1.8.3.1 + diff --git a/backport-CVE-2022-31813.patch b/backport-CVE-2022-31813.patch new file mode 100644 index 0000000..962dd6b --- /dev/null +++ b/backport-CVE-2022-31813.patch @@ -0,0 +1,243 @@ +From 956f708b094698ac9ad570d640d4f30eb0df7305 Mon Sep 17 00:00:00 2001 +From: icing +Date: Wed Jun 1 07:51:04 2022 UTC +Subject: [PATCH] mod_proxy: ap_proxy_create_hdrbrgd() to clear hop-by-hop first and fixup last. + +--- + modules/proxy/proxy_util.c | 155 +++++++++++++++++++++++---------------------- + 1 file changed, 78 insertions(+), 77 deletions(-) + +diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c +index d578452..4f1610f 100644 +--- a/modules/proxy/proxy_util.c ++++ b/modules/proxy/proxy_util.c +@@ -3849,12 +3849,14 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p, + char **old_cl_val, + char **old_te_val) + { ++ int rc = OK; + conn_rec *c = r->connection; + int counter; + char *buf; ++ apr_table_t *saved_headers_in = r->headers_in; ++ const char *saved_host = apr_table_get(saved_headers_in, "Host"); + const apr_array_header_t *headers_in_array; + const apr_table_entry_t *headers_in; +- apr_table_t *saved_headers_in; + apr_bucket *e; + int do_100_continue; + conn_rec *origin = p_conn->connection; +@@ -3890,6 +3892,52 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p, + ap_xlate_proto_to_ascii(buf, strlen(buf)); + e = apr_bucket_pool_create(buf, strlen(buf), p, c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(header_brigade, e); ++ ++ /* ++ * Make a copy on r->headers_in for the request we make to the backend, ++ * modify the copy in place according to our configuration and connection ++ * handling, use it to fill in the forwarded headers' brigade, and finally ++ * restore the saved/original ones in r->headers_in. ++ * ++ * Note: We need to take r->pool for apr_table_copy as the key / value ++ * pairs in r->headers_in have been created out of r->pool and ++ * p might be (and actually is) a longer living pool. ++ * This would trigger the bad pool ancestry abort in apr_table_copy if ++ * apr is compiled with APR_POOL_DEBUG. ++ * ++ * icing: if p indeed lives longer than r->pool, we should allocate ++ * all new header values from r->pool as well and avoid leakage. ++ */ ++ r->headers_in = apr_table_copy(r->pool, saved_headers_in); ++ ++ /* Return the original Transfer-Encoding and/or Content-Length values ++ * then drop the headers, they must be set by the proxy handler based ++ * on the actual body being forwarded. ++ */ ++ if ((*old_te_val = (char *)apr_table_get(r->headers_in, ++ "Transfer-Encoding"))) { ++ apr_table_unset(r->headers_in, "Transfer-Encoding"); ++ } ++ if ((*old_cl_val = (char *)apr_table_get(r->headers_in, ++ "Content-Length"))) { ++ apr_table_unset(r->headers_in, "Content-Length"); ++ } ++ ++ /* Clear out hop-by-hop request headers not to forward */ ++ if (ap_proxy_clear_connection(r, r->headers_in) < 0) { ++ rc = HTTP_BAD_REQUEST; ++ goto cleanup; ++ } ++ ++ /* RFC2616 13.5.1 says we should strip these */ ++ apr_table_unset(r->headers_in, "Keep-Alive"); ++ apr_table_unset(r->headers_in, "Upgrade"); ++ apr_table_unset(r->headers_in, "Trailer"); ++ apr_table_unset(r->headers_in, "TE"); ++ ++ /* We used to send `Host: ` always first, so let's keep it that ++ * way. No telling which legacy backend is relying no this. ++ */ + if (dconf->preserve_host == 0) { + if (ap_strchr_c(uri->hostname, ':')) { /* if literal IPv6 address */ + if (uri->port_str && uri->port != DEFAULT_HTTP_PORT) { +@@ -3911,7 +3959,7 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p, + /* don't want to use r->hostname, as the incoming header might have a + * port attached + */ +- const char* hostname = apr_table_get(r->headers_in,"Host"); ++ const char* hostname = saved_host; + if (!hostname) { + hostname = r->server->server_hostname; + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01092) +@@ -3925,22 +3973,8 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p, + ap_xlate_proto_to_ascii(buf, strlen(buf)); + e = apr_bucket_pool_create(buf, strlen(buf), p, c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(header_brigade, e); +- +- /* +- * Save the original headers in here and restore them when leaving, since +- * we will apply proxy purpose only modifications (eg. clearing hop-by-hop +- * headers, add Via or X-Forwarded-* or Expect...), whereas the originals +- * will be needed later to prepare the correct response and logging. +- * +- * Note: We need to take r->pool for apr_table_copy as the key / value +- * pairs in r->headers_in have been created out of r->pool and +- * p might be (and actually is) a longer living pool. +- * This would trigger the bad pool ancestry abort in apr_table_copy if +- * apr is compiled with APR_POOL_DEBUG. +- */ +- saved_headers_in = r->headers_in; +- r->headers_in = apr_table_copy(r->pool, saved_headers_in); +- ++ apr_table_unset(r->headers_in, "Host"); ++ + /* handle Via */ + if (conf->viaopt == via_block) { + /* Block all outgoing Via: headers */ +@@ -4006,8 +4040,6 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p, + */ + if (dconf->add_forwarded_headers) { + if (PROXYREQ_REVERSE == r->proxyreq) { +- const char *buf; +- + /* Add X-Forwarded-For: so that the upstream has a chance to + * determine, where the original request came from. + */ +@@ -4017,8 +4049,9 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p, + /* Add X-Forwarded-Host: so that upstream knows what the + * original request hostname was. + */ +- if ((buf = apr_table_get(r->headers_in, "Host"))) { +- apr_table_mergen(r->headers_in, "X-Forwarded-Host", buf); ++ if (saved_host) { ++ apr_table_mergen(r->headers_in, "X-Forwarded-Host", ++ saved_host); + } + + /* Add X-Forwarded-Server: so that upstream knows what the +@@ -4029,67 +4062,37 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p, + r->server->server_hostname); + } + } ++ ++ /* Do we want to strip Proxy-Authorization ? ++ * If we haven't used it, then NO ++ * If we have used it then MAYBE: RFC2616 says we MAY propagate it. ++ * So let's make it configurable by env. ++ */ ++ if (r->user != NULL /* we've authenticated */ ++ && !apr_table_get(r->subprocess_env, "Proxy-Chain-Auth")) { ++ apr_table_unset(r->headers_in, "Proxy-Authorization"); ++ } + +- proxy_run_fixups(r); +- if (ap_proxy_clear_connection(r, r->headers_in) < 0) { +- return HTTP_BAD_REQUEST; ++ /* for sub-requests, ignore freshness/expiry headers */ ++ if (r->main) { ++ apr_table_unset(r->headers_in, "If-Match"); ++ apr_table_unset(r->headers_in, "If-Modified-Since"); ++ apr_table_unset(r->headers_in, "If-Range"); ++ apr_table_unset(r->headers_in, "If-Unmodified-Since"); ++ apr_table_unset(r->headers_in, "If-None-Match"); + } ++ ++ /* run hook to fixup the request we are about to send */ ++ proxy_run_fixups(r); + + /* send request headers */ + headers_in_array = apr_table_elts(r->headers_in); + headers_in = (const apr_table_entry_t *) headers_in_array->elts; + for (counter = 0; counter < headers_in_array->nelts; counter++) { + if (headers_in[counter].key == NULL +- || headers_in[counter].val == NULL +- +- /* Already sent */ +- || !ap_cstr_casecmp(headers_in[counter].key, "Host") +- +- /* Clear out hop-by-hop request headers not to send +- * RFC2616 13.5.1 says we should strip these headers +- */ +- || !ap_cstr_casecmp(headers_in[counter].key, "Keep-Alive") +- || !ap_cstr_casecmp(headers_in[counter].key, "TE") +- || !ap_cstr_casecmp(headers_in[counter].key, "Trailer") +- || !ap_cstr_casecmp(headers_in[counter].key, "Upgrade") +- +- ) { ++ || headers_in[counter].val == NULL) { + continue; + } +- /* Do we want to strip Proxy-Authorization ? +- * If we haven't used it, then NO +- * If we have used it then MAYBE: RFC2616 says we MAY propagate it. +- * So let's make it configurable by env. +- */ +- if (!ap_cstr_casecmp(headers_in[counter].key,"Proxy-Authorization")) { +- if (r->user != NULL) { /* we've authenticated */ +- if (!apr_table_get(r->subprocess_env, "Proxy-Chain-Auth")) { +- continue; +- } +- } +- } +- +- /* Skip Transfer-Encoding and Content-Length for now. +- */ +- if (!ap_cstr_casecmp(headers_in[counter].key, "Transfer-Encoding")) { +- *old_te_val = headers_in[counter].val; +- continue; +- } +- if (!ap_cstr_casecmp(headers_in[counter].key, "Content-Length")) { +- *old_cl_val = headers_in[counter].val; +- continue; +- } +- +- /* for sub-requests, ignore freshness/expiry headers */ +- if (r->main) { +- if ( !ap_cstr_casecmp(headers_in[counter].key, "If-Match") +- || !ap_cstr_casecmp(headers_in[counter].key, "If-Modified-Since") +- || !ap_cstr_casecmp(headers_in[counter].key, "If-Range") +- || !ap_cstr_casecmp(headers_in[counter].key, "If-Unmodified-Since") +- || !ap_cstr_casecmp(headers_in[counter].key, "If-None-Match")) { +- continue; +- } +- } + + buf = apr_pstrcat(p, headers_in[counter].key, ": ", + headers_in[counter].val, CRLF, +@@ -4099,11 +4102,9 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p, + APR_BRIGADE_INSERT_TAIL(header_brigade, e); + } + +- /* Restore the original headers in (see comment above), +- * we won't modify them anymore. +- */ ++cleanup: + r->headers_in = saved_headers_in; +- return OK; ++ return rc; + } + + PROXY_DECLARE(int) ap_proxy_prefetch_input(request_rec *r, +-- +1.8.3.1 + diff --git a/httpd.spec b/httpd.spec index f4965ad..190e4ec 100644 --- a/httpd.spec +++ b/httpd.spec @@ -8,7 +8,7 @@ Name: httpd Summary: Apache HTTP Server Version: 2.4.51 -Release: 4 +Release: 5 License: ASL 2.0 URL: https://httpd.apache.org/ Source0: https://archive.apache.org/dist/httpd/httpd-%{version}.tar.bz2 @@ -78,6 +78,12 @@ Patch24: backport-CVE-2021-44790.patch Patch25: backport-001-CVE-2021-44224.patch Patch26: backport-002-CVE-2021-44224.patch Patch27: backport-CVE-2022-28615.patch +Patch28: backport-CVE-2022-31813.patch +Patch29: backport-CVE-2022-28614.patch +Patch30: backport-CVE-2022-29404.patch +Patch31: backport-CVE-2022-26377.patch +Patch32: backport-CVE-2022-30522.patch +Patch33: backport-CVE-2022-30556.patch BuildRequires: gcc autoconf pkgconfig findutils xmlto perl-interpreter perl-generators systemd-devel BuildRequires: zlib-devel libselinux-devel lua-devel brotli-devel @@ -510,6 +516,12 @@ exit $rv %{_rpmconfigdir}/macros.d/macros.httpd %changelog +* Mon Jun 20 2022 chengyechun - 2.4.51-5 +- Type:CVE +- ID:NA +- SUG:restart +- DESC:fix CVE-2022-31813,CVE-2022-28614,CVE-2022-29404,CVE-2022-26377,CVE-2022-30522,CVE-2022-30556 + * Mon Jun 20 2022 chengyechun - 2.4.51-4 - Type:CVE - ID:NA