diff --git a/CVE-2018-20102.patch b/CVE-2018-20102.patch new file mode 100644 index 0000000000000000000000000000000000000000..69da7f2a70d5a2fcdf2c7deff5480c2449be15e2 --- /dev/null +++ b/CVE-2018-20102.patch @@ -0,0 +1,36 @@ +From efbbdf72992cd20458259962346044cafd9331c0 Mon Sep 17 00:00:00 2001 +From: Remi Gacogne +Date: Wed, 5 Dec 2018 17:56:29 +0100 +Subject: [PATCH] BUG: dns: Prevent out-of-bounds read in + dns_validate_dns_response() + +We need to make sure that the record length is not making us read +past the end of the data we received. +Before this patch we could for example read the 16 bytes +corresponding to an AAAA record from the non-initialized part of +the buffer, possibly accessing anything that was left on the stack, +or even past the end of the 8193-byte buffer, depending on the +value of accepted_payload_size. + +To be backported to 1.8, probably also 1.7. +--- + src/dns.c | 5 +++++ + 1 file changed, 5 insertions(+) + +Index: haproxy-1.8.13/src/dns.c +=================================================================== +--- haproxy-1.8.13.orig/src/dns.c ++++ haproxy-1.8.13/src/dns.c +@@ -798,6 +798,11 @@ static int dns_validate_dns_response(uns + /* Move forward 2 bytes for data len */ + reader += 2; + ++ if (reader + dns_answer_record->data_len >= bufend) { ++ pool_free(dns_answer_item_pool, dns_answer_record); ++ return DNS_RESP_INVALID; ++ } ++ + /* Analyzing record content */ + switch (dns_answer_record->type) { + case DNS_RTYPE_A: + diff --git a/CVE-2018-20103.patch b/CVE-2018-20103.patch new file mode 100644 index 0000000000000000000000000000000000000000..52fb6d4030f5244a4045d206d67106b1a6d9932c --- /dev/null +++ b/CVE-2018-20103.patch @@ -0,0 +1,85 @@ +From 58df5aea0a0c926b2238f65908f5e9f83d1cca25 Mon Sep 17 00:00:00 2001 +From: Remi Gacogne +Date: Wed, 5 Dec 2018 17:52:54 +0100 +Subject: [PATCH] BUG: dns: Prevent stack-exhaustion via recursion loop in + dns_read_name + +When a compressed pointer is encountered, dns_read_name() will call +itself with the pointed-to offset in the packet. +With a specially crafted packet, it was possible to trigger an +infinite-loop recursion by making the pointer points to itself. +While it would be possible to handle that particular case differently +by making sure that the target is different from the current offset, +it would still be possible to craft a packet with a very long chain +of valid pointers, always pointing backwards. To prevent a stack +exhaustion in that case, this patch restricts the number of recursive +calls to 100, which should be more than enough. + +To be backported to 1.8, probably also 1.7. +--- + src/dns.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +Index: haproxy-1.8.13/src/dns.c +=================================================================== +--- haproxy-1.8.13.orig/src/dns.c ++++ haproxy-1.8.13/src/dns.c +@@ -391,7 +391,7 @@ static inline unsigned short dns_respons + */ + int dns_read_name(unsigned char *buffer, unsigned char *bufend, + unsigned char *name, char *destination, int dest_len, +- int *offset) ++ int *offset, unsigned int depth) + { + int nb_bytes = 0, n = 0; + int label_len; +@@ -405,8 +405,11 @@ int dns_read_name(unsigned char *buffer, + if ((buffer + reader[1]) > reader) + goto err; + ++ if (depth++ > 100) ++ goto err; ++ + n = dns_read_name(buffer, bufend, buffer + reader[1], +- dest, dest_len - nb_bytes, offset); ++ dest, dest_len - nb_bytes, offset, depth); + if (n == 0) + goto err; + +@@ -692,7 +695,7 @@ static int dns_validate_dns_response(uns + * one query per response and the first one can't be compressed + * (using the 0x0c format) */ + offset = 0; +- len = dns_read_name(resp, bufend, reader, dns_query->name, DNS_MAX_NAME_SIZE, &offset); ++ len = dns_read_name(resp, bufend, reader, dns_query->name, DNS_MAX_NAME_SIZE, &offset, 0); + + if (len == 0) + return DNS_RESP_INVALID; +@@ -729,7 +732,7 @@ static int dns_validate_dns_response(uns + return (DNS_RESP_INVALID); + + offset = 0; +- len = dns_read_name(resp, bufend, reader, tmpname, DNS_MAX_NAME_SIZE, &offset); ++ len = dns_read_name(resp, bufend, reader, tmpname, DNS_MAX_NAME_SIZE, &offset, 0); + + if (len == 0) { + pool_free(dns_answer_item_pool, dns_answer_record); +@@ -831,7 +834,7 @@ static int dns_validate_dns_response(uns + } + + offset = 0; +- len = dns_read_name(resp, bufend, reader, tmpname, DNS_MAX_NAME_SIZE, &offset); ++ len = dns_read_name(resp, bufend, reader, tmpname, DNS_MAX_NAME_SIZE, &offset, 0); + if (len == 0) { + pool_free(dns_answer_item_pool, dns_answer_record); + return DNS_RESP_INVALID; +@@ -861,7 +864,7 @@ static int dns_validate_dns_response(uns + dns_answer_record->port = read_n16(reader); + reader += sizeof(uint16_t); + offset = 0; +- len = dns_read_name(resp, bufend, reader, tmpname, DNS_MAX_NAME_SIZE, &offset); ++ len = dns_read_name(resp, bufend, reader, tmpname, DNS_MAX_NAME_SIZE, &offset, 0); + if (len == 0) { + pool_free(dns_answer_item_pool, dns_answer_record); + return DNS_RESP_INVALID; + diff --git a/CVE-2018-20615-BUG-CRITICAL-mux-h2-re-check-the-frame-length-when-P.patch b/CVE-2018-20615-BUG-CRITICAL-mux-h2-re-check-the-frame-length-when-P.patch new file mode 100644 index 0000000000000000000000000000000000000000..2e7dc118ec8bee8fa5cea5ef59524ee7426f2c0b --- /dev/null +++ b/CVE-2018-20615-BUG-CRITICAL-mux-h2-re-check-the-frame-length-when-P.patch @@ -0,0 +1,44 @@ +From a01f45e3ced23c799f6e78b5efdbd32198a75354 Mon Sep 17 00:00:00 2001 +From: Willy Tarreau +Date: Mon, 31 Dec 2018 07:41:24 +0100 +Subject: [PATCH] BUG/CRITICAL: mux-h2: re-check the frame length when PRIORITY + is used +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Tim Düsterhus reported a possible crash in the H2 HEADERS frame decoder +when the PRIORITY flag is present. A check is missing to ensure the 5 +extra bytes needed with this flag are actually part of the frame. As per +RFC7540#4.2, let's return a connection error with code FRAME_SIZE_ERROR. + +Many thanks to Tim for responsibly reporting this issue with a working +config and reproducer. This issue was assigned CVE-2018-20615. + +This fix must be backported to 1.9 and 1.8. + +Signed-off-by: gaoyi +--- + src/mux_h2.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/mux_h2.c b/src/mux_h2.c +index dc67bc67..20ff9882 100644 +--- a/src/mux_h2.c ++++ b/src/mux_h2.c +@@ -3316,6 +3316,11 @@ next_frame: + goto fail; + } + ++ if (flen < 5) { ++ h2c_error(h2c, H2_ERR_FRAME_SIZE_ERROR); ++ goto fail; ++ } ++ + hdrs += 5; // stream dep = 4, weight = 1 + flen -= 5; + } +-- +2.19.1 + + diff --git a/haproxy-1.8.14.tar.gz b/haproxy-1.8.14.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..5aa159631537ef6abdfb761b86ff5859ceb9926c Binary files /dev/null and b/haproxy-1.8.14.tar.gz differ diff --git a/haproxy.cfg b/haproxy.cfg new file mode 100644 index 0000000000000000000000000000000000000000..d2614350d0685b7b1eb1d33a274da0f95b4ff3a3 --- /dev/null +++ b/haproxy.cfg @@ -0,0 +1,42 @@ +#--------------------------------------------------------------------- +# Example configuration for a possible web application. See the +# full configuration options online. +# +# https://www.haproxy.org/download/1.8/doc/configuration.txt +# +#--------------------------------------------------------------------- + +global + log 127.0.0.1 local2 + chroot /var/lib/haproxy + pidfile /var/run/haproxy.pid + user haproxy + group haproxy + daemon + maxconn 4000 + +defaults + mode http + log global + option httplog + option dontlognull + retries 3 + timeout http-request 5s + timeout queue 1m + timeout connect 5s + timeout client 1m + timeout server 1m + timeout http-keep-alive 5s + timeout check 5s + maxconn 3000 + +frontend main + bind *:80 + default_backend http_back + +backend http_back + balance roundrobin + server node1 127.0.0.1:5001 check + server node2 127.0.0.1:5002 check + server node3 127.0.0.1:5003 check + server node4 127.0.0.1:5004 check diff --git a/haproxy.logrotate b/haproxy.logrotate new file mode 100644 index 0000000000000000000000000000000000000000..c2c8c9c25515f6fbb70bff2014f5f590e375e0d8 --- /dev/null +++ b/haproxy.logrotate @@ -0,0 +1,13 @@ +/var/log/haproxy.log { + compress + daily + dateext + rotate 31 + missingok + notifempty + sharedscripts + postrotate + /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true + /bin/kill -HUP `cat /var/run/rsyslogd.pid 2> /dev/null` 2> /dev/null || true + endscript +} diff --git a/haproxy.service b/haproxy.service new file mode 100644 index 0000000000000000000000000000000000000000..b8c8ee4ba8bb51058868d8ee808cb4c1da0fa3c6 --- /dev/null +++ b/haproxy.service @@ -0,0 +1,16 @@ +[Unit] +Description=HAProxy Load Balancer +After=network.target + +[Service] +Environment="HAPROXY_CONF=/etc/haproxy/haproxy.cfg" "PIDFILE=/run/haproxy.pid" +ExecStartPre=/usr/sbin/haproxy -f $HAPROXY_CONF -c -q +# -W: master-worker mode +ExecStart=/usr/sbin/haproxy -Ws -f $HAPROXY_CONF -p $PIDFILE +ExecReload=/usr/sbin/haproxy -f $HAPROXY_CONF -c -q +ExecReload=/bin/kill -USR2 $MAINPID +KillMode=mixed +Type=notify + +[Install] +WantedBy=multi-user.target diff --git a/haproxy.spec b/haproxy.spec new file mode 100644 index 0000000000000000000000000000000000000000..a579c468e0456f3ecae27f80e3a5a47472527f24 --- /dev/null +++ b/haproxy.spec @@ -0,0 +1,129 @@ +%define haproxy_user haproxy +%define haproxy_group haproxy + +%global _hardened_build 1 + +Name: haproxy +Version: 1.8.14 +Release: 4 +Summary: The Reliable, High Performance TCP/HTTP Load Balancer + +License: GPLv2+ +URL: http://www.haproxy.org/ +Source0: http://www.haproxy.org/download/1.8/src/haproxy-%{version}.tar.gz +Source1: %{name}.service +Source2: %{name}.cfg +Source3: %{name}.logrotate +Source4: %{name}.sysconfig + +Patch6000: CVE-2018-20615-BUG-CRITICAL-mux-h2-re-check-the-frame-length-when-P.patch +Patch6001: CVE-2018-20103.patch +Patch6002: CVE-2018-20102.patch + +BuildRequires: gcc lua-devel pcre-devel zlib-devel openssl-devel systemd-devel systemd-units +Requires(pre): shadow-utils +Requires(post): systemd +Requires(preun): systemd +Requires(postun): systemd + +%package_help +%description +HAProxy is a free, very fast and reliable solution offering high availability, load balancing, +and proxying for TCP and HTTP-based applications. It is particularly suited for very high traffic +web sites and powers quite a number of the world's most visited ones. + +%prep +%autosetup -n %{name}-%{version} -p1 + +%build +use_regparm_opt= +%ifarch %ix86 x86_64 +use_regparm_opt="USE_REGPARM=1" +%endif + +%make_build CPU="generic" TARGET="linux2628" USE_OPENSSL=1 USE_PCRE=1 USE_ZLIB=1 \ + USE_LUA=1 USE_CRYPT_H=1 USE_SYSTEMD=1 USE_LINUX_TPROXY=1 USE_GETADDRINFO=1 ${use_regparm_opt} \ + ADDINC="%{optflags}" ADDLIB="%{__global_ldflags}" + +pushd contrib/halog +%make_build ${halog} OPTIMIZE="%{optflags} %{build_ldflags}" +popd + +pushd contrib/iprange +%make_build iprange OPTIMIZE="%{optflags} %{build_ldflags}" +popd + +%install +install -d %{buildroot}%{_sbindir} +install haproxy %{buildroot}%{_sbindir} +install -d %{buildroot}%{_mandir}/man1 +install -m 644 doc/haproxy.1 %{buildroot}%{_mandir}/man1 + +pushd %{buildroot} +install -p -D -m 0644 %{SOURCE1} .%{_unitdir}/%{name}.service +install -p -D -m 0644 %{SOURCE2} .%{_sysconfdir}/haproxy/%{name}.cfg +install -p -D -m 0644 %{SOURCE3} .%{_sysconfdir}/logrotate.d/%{name} +install -p -D -m 0644 %{SOURCE4} .%{_sysconfdir}/sysconfig/%{name} +install -d -m 0755 .%{_bindir} +install -d -m 0755 .%{_localstatedir}/lib/haproxy +install -d -m 0755 .%{_datadir}/haproxy +popd + +install -p -m 0755 ./contrib/halog/halog %{buildroot}%{_bindir}/halog +install -p -m 0755 ./contrib/iprange/iprange %{buildroot}%{_bindir}/iprange +install -p -m 0644 ./examples/errorfiles/* %{buildroot}%{_datadir}/haproxy + +for httpfile in $(find ./examples/errorfiles/ -type f) +do + install -p -m 0644 $httpfile %{buildroot}%{_datadir}/haproxy +done + +%{__rm} -rf ./examples/errorfiles/ +find ./examples/* -type f ! -name "*.cfg" -exec %{__rm} -f "{}" \; + +textfiles=$(find ./ -type f -name '*.txt') +for textfile in ${textfiles} +do + %{__mv} ${textfile} ${textfile}.old + iconv --from-code ISO8859-1 --to-code UTF-8 --output ${textfile} ${textfile}.old + %{__rm} -f ${textfile}.old +done + +%pre +getent group %{haproxy_group} >/dev/null || groupadd -r %{haproxy_group} +getent passwd %{haproxy_user} >/dev/null || useradd -r -g %{haproxy_user} -d \ + %{_localstatedir}/lib/haproxy -s /sbin/nologin -c "haproxy" %{haproxy_user} +exit 0 + +%post +%systemd_post %{name}.service + +%preun +%systemd_preun %{name}.service + +%postun +%systemd_postun_with_restart %{name}.service + +%files +%defattr(-,root,root) +%license LICENSE +%dir %{_sysconfdir}/haproxy +%config(noreplace) %{_sysconfdir}/haproxy/%{name}.cfg +%config(noreplace) %{_sysconfdir}/logrotate.d/%{name} +%config(noreplace) %{_sysconfdir}/sysconfig/%{name} +%{_bindir}/halog +%{_bindir}/iprange +%{_sbindir}/%{name} +%{_unitdir}/%{name}.service +%dir %{_localstatedir}/lib/haproxy +%dir %{_datadir}/haproxy +%{_datadir}/haproxy/* + +%files help +%defattr(-,root,root) +%doc doc/* examples/* CHANGELOG README ROADMAP VERSION +%{_mandir}/man1/* + +%changelog +* Wed Dec 4 2019 openEuler Buildteam - 1.8.14-4 +- Package init diff --git a/haproxy.sysconfig b/haproxy.sysconfig new file mode 100644 index 0000000000000000000000000000000000000000..2b38e3543c0ccc643617a6c49e7dd59d6e25bee9 --- /dev/null +++ b/haproxy.sysconfig @@ -0,0 +1,4 @@ +# Add extra options to the haproxy daemon here. This can be useful for +# specifying multiple configuration files with multiple -f options. +# See haproxy(1) for a complete list of options. +OPTIONS=""