From 8d45841ff585710b79a99c93d104d521ca979207 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 12 Jun 2024 14:04:42 +0800 Subject: [PATCH] fix-cve-2023-40225/45539 --- fix-cve-2023-40225-45539.patch | 252 +++++++++++++++++++++++++++++++++ haproxy.spec | 8 +- 2 files changed, 258 insertions(+), 2 deletions(-) create mode 100644 fix-cve-2023-40225-45539.patch diff --git a/fix-cve-2023-40225-45539.patch b/fix-cve-2023-40225-45539.patch new file mode 100644 index 0000000..9faaba0 --- /dev/null +++ b/fix-cve-2023-40225-45539.patch @@ -0,0 +1,252 @@ +From b8ed15214f8e6efb40d1f98c243504157dbb0aea Mon Sep 17 00:00:00 2001 +From: root +Date: Tue, 11 Jun 2024 14:12:01 +0800 +Subject: [PATCH] fix-cve-2023-40225/45539 + +--- + reg-tests/http-messaging/h1_to_h1.vtc | 26 ++++++++++++ + reg-tests/http-messaging/h2_to_h1.vtc | 58 +++++++++++++++++++++++++++ + src/h1.c | 33 +++++++++++---- + src/h2.c | 17 ++++++-- + 4 files changed, 124 insertions(+), 10 deletions(-) + +diff --git a/reg-tests/http-messaging/h1_to_h1.vtc b/reg-tests/http-messaging/h1_to_h1.vtc +index c7d0085..797be34 100644 +--- a/reg-tests/http-messaging/h1_to_h1.vtc ++++ b/reg-tests/http-messaging/h1_to_h1.vtc +@@ -275,3 +275,29 @@ client c3h1 -connect ${h1_feh1_sock} { + # arrive here. + expect_close + } -run ++ ++client c4h1 -connect ${h1_feh1_sock} { ++ # this request is invalid and advertises an invalid C-L ending with an ++ # empty value, which results in a stream error. ++ txreq \ ++ -req "GET" \ ++ -url "/test31.html" \ ++ -hdr "content-length: 0," \ ++ -hdr "connection: close" ++ rxresp ++ expect resp.status == 400 ++ expect_close ++} -run ++ ++client c5h1 -connect ${h1_feh1_sock} { ++ # this request is invalid and advertises an empty C-L, which results ++ # in a stream error. ++ txreq \ ++ -req "GET" \ ++ -url "/test41.html" \ ++ -hdr "content-length:" \ ++ -hdr "connection: close" ++ rxresp ++ expect resp.status == 400 ++ expect_close ++} -run +diff --git a/reg-tests/http-messaging/h2_to_h1.vtc b/reg-tests/http-messaging/h2_to_h1.vtc +index 0d2b1e5..0e6dfa4 100644 +--- a/reg-tests/http-messaging/h2_to_h1.vtc ++++ b/reg-tests/http-messaging/h2_to_h1.vtc +@@ -10,6 +10,8 @@ barrier b1 cond 2 -cyclic + barrier b2 cond 2 -cyclic + barrier b3 cond 2 -cyclic + barrier b4 cond 2 -cyclic ++barrier b5 cond 2 -cyclic ++barrier b6 cond 2 -cyclic + + server s1 { + rxreq +@@ -31,6 +33,12 @@ server s1 { + + barrier b4 sync + # the next request is never received ++ ++ barrier b5 cond 2 -cyclic ++ # the next request is never received ++ ++ barrier b6 cond 2 -cyclic ++ # the next request is never received + } -repeat 2 -start + + haproxy h1 -conf { +@@ -121,6 +129,31 @@ client c1h2 -connect ${h1_feh2_sock} { + txdata -data "this is sent and ignored" + rxrst + } -run ++ # fifth request is invalid and advertises an invalid C-L ending with an ++ # empty value, which results in a stream error. ++ stream 9 { ++ barrier b5 sync ++ txreq \ ++ -req "GET" \ ++ -scheme "https" \ ++ -url "/test5.html" \ ++ -hdr "content-length" "0," \ ++ -nostrend ++ rxrst ++ } -run ++ ++ # sixth request is invalid and advertises an empty C-L, which results ++ # in a stream error. ++ stream 11 { ++ barrier b6 sync ++ txreq \ ++ -req "GET" \ ++ -scheme "https" \ ++ -url "/test6.html" \ ++ -hdr "content-length" "" \ ++ -nostrend ++ rxrst ++ } -run + } -run + + # HEAD requests : don't work well yet +@@ -194,6 +227,31 @@ client c1h2 -connect ${h1_feh2_sock} { + # rxdata -all + # expect resp.bodylen == 0 + # } -run ++# # fifth request is invalid and advertises invalid C-L ending with an ++# # empty value, which results in a stream error. ++# stream 9 { ++# barrier b5 sync ++# txreq \ ++# -req "POST" \ ++# -scheme "https" \ ++# -url "/test25.html" \ ++# -hdr "content-length" "0," \ ++# -nostrend ++# rxrst ++# } -run ++# ++# # sixth request is invalid and advertises an empty C-L, which results ++# # in a stream error. ++# stream 11 { ++# barrier b6 sync ++# txreq \ ++# -req "POST" \ ++# -scheme "https" \ ++# -url "/test26.html" \ ++# -hdr "content-length" "" \ ++# -nostrend ++# rxrst ++# } -run + #} -run + + # POST requests +diff --git a/src/h1.c b/src/h1.c +index 73de48b..57e0016 100644 +--- a/src/h1.c ++++ b/src/h1.c +@@ -34,13 +34,19 @@ int h1_parse_cont_len_header(struct h1m *h1m, struct ist *value) + int not_first = !!(h1m->flags & H1_MF_CLEN); + struct ist word; + +- word.ptr = value->ptr - 1; // -1 for next loop's pre-increment ++ word.ptr = value->ptr; + e = value->ptr + value->len; + +- while (++word.ptr < e) { ++ while (1) { ++ if (word.ptr >= e) { ++ /* empty header or empty value */ ++ goto fail; ++ } + /* skip leading delimiter and blanks */ +- if (unlikely(HTTP_IS_LWS(*word.ptr))) ++ if (unlikely(HTTP_IS_LWS(*word.ptr))){ ++ word.ptr++; + continue; ++ } + + /* digits only now */ + for (cl = 0, n = word.ptr; n < e; n++) { +@@ -79,6 +85,12 @@ int h1_parse_cont_len_header(struct h1m *h1m, struct ist *value) + h1m->flags |= H1_MF_CLEN; + h1m->curr_len = h1m->body_len = cl; + *value = word; ++ ++ /* Now either n==e and we're done, or n points to the comma, ++ * and we skip it and continue. ++ */ ++ if (n++ == e) ++ break; + word.ptr = n; + } + /* here we've reached the end with a single value or a series of +@@ -466,13 +478,13 @@ int h1_headers_to_hdr_list(char *start, const char *stop, + case H1_MSG_RQURI: + http_msg_rquri: + #ifdef HA_UNALIGNED_LE +- /* speedup: skip bytes not between 0x21 and 0x7e inclusive */ ++ /* speedup: skip bytes not between 0x24 and 0x7e inclusive */ + while (ptr <= end - sizeof(int)) { +- int x = *(int *)ptr - 0x21212121; ++ int x = *(int *)ptr - 0x24242424; + if (x & 0x80808080) + break; + +- x -= 0x5e5e5e5e; ++ x -= 0x5b5b5b5b; + if (!(x & 0x80808080)) + break; + +@@ -484,8 +496,15 @@ int h1_headers_to_hdr_list(char *start, const char *stop, + goto http_msg_ood; + } + http_msg_rquri2: +- if (likely((unsigned char)(*ptr - 33) <= 93)) /* 33 to 126 included */ ++ if (likely((unsigned char)(*ptr - 33) <= 93)) {/* 33 to 126 included */ ++ if (*ptr == '#') { ++ if (h1m->err_pos < -1) /* PR_O2_REQBUG_OK not set */ ++ goto invalid_char; ++ if (h1m->err_pos == -1) /* PR_O2_REQBUG_OK set: just log */ ++ h1m->err_pos = ptr - start + skip; ++ } + EAT_AND_JUMP_OR_RETURN(ptr, end, http_msg_rquri2, http_msg_ood, state, H1_MSG_RQURI); ++ } + + if (likely(HTTP_IS_SPHT(*ptr))) { + sl.rq.u.len = ptr - sl.rq.u.ptr; +diff --git a/src/h2.c b/src/h2.c +index dd1f7d9..f239419 100644 +--- a/src/h2.c ++++ b/src/h2.c +@@ -80,13 +80,19 @@ int h2_parse_cont_len_header(unsigned int *msgf, struct ist *value, unsigned lon + int not_first = !!(*msgf & H2_MSGF_BODY_CL); + struct ist word; + +- word.ptr = value->ptr - 1; // -1 for next loop's pre-increment ++ word.ptr = value->ptr; + e = value->ptr + value->len; + +- while (++word.ptr < e) { ++ while (1) { ++ if (word.ptr >= e) { ++ /* empty header or empty value */ ++ goto fail; ++ } + /* skip leading delimiter and blanks */ +- if (unlikely(HTTP_IS_LWS(*word.ptr))) ++ if (unlikely(HTTP_IS_LWS(*word.ptr))){ ++ word.ptr++; + continue; ++ } + + /* digits only now */ + for (cl = 0, n = word.ptr; n < e; n++) { +@@ -125,6 +131,11 @@ int h2_parse_cont_len_header(unsigned int *msgf, struct ist *value, unsigned lon + *msgf |= H2_MSGF_BODY_CL; + *body_len = cl; + *value = word; ++ /* Now either n==e and we're done, or n points to the comma, ++ * and we skip it and continue. ++ */ ++ if (n++ == e) ++ break; + word.ptr = n; + } + /* here we've reached the end with a single value or a series of +-- +2.33.0 + diff --git a/haproxy.spec b/haproxy.spec index 5db7565..e8f74e6 100644 --- a/haproxy.spec +++ b/haproxy.spec @@ -1,4 +1,4 @@ -%define anolis_release .0.1 +%define anolis_release .0.2 %define haproxy_user haproxy %define haproxy_group %{haproxy_user} %define haproxy_homedir %{_localstatedir}/lib/haproxy @@ -14,7 +14,7 @@ Summary: HAProxy reverse proxy for high availability environments License: GPLv2+ -URL: http://www.haproxy.org/ +URL: http://www.haproxy.org Source0: %{url}/download/2.4/src/haproxy-%{version}.tar.gz Source1: %{name}.service Source2: %{name}.cfg @@ -23,6 +23,7 @@ Source4: %{name}.sysconfig Source5: %{name}.sysusers Source6: halog.1 +Patch1: fix-cve-2023-40225-45539.patch BuildRequires: gcc BuildRequires: lua-devel BuildRequires: pcre2-devel @@ -51,6 +52,7 @@ availability environments. Indeed, it can: %prep %setup -q +%patch1 -p1 %build regparm_opts= @@ -138,6 +140,8 @@ exit 0 %{_sysusersdir}/%{name}.conf %changelog +* Tue Jun 11 2024 yangxinyu - 2.4.22-1.0.2 +- fix-cve-2023-40225-45539 * Mon Dec 11 2023 Bo Ren - 2.4.22-1.0.1 - change user/group creation way -- Gitee