Merge ~bryce/ubuntu/+source/apache2:sru-lp1832182-graceful-revert-bionic into ubuntu/+source/apache2:ubuntu/devel

Proposed by Bryce Harrington
Status: Merged
Merge reported by: Bryce Harrington
Merged at revision: 95c238eedea3c6b7d877857d522e03f2d4e8e951
Proposed branch: ~bryce/ubuntu/+source/apache2:sru-lp1832182-graceful-revert-bionic
Merge into: ubuntu/+source/apache2:ubuntu/devel
Diff against target: 22219 lines (+21167/-0) (has conflicts)
81 files modified
debian/NEWS (+12/-0)
debian/apache2-systemd.conf (+3/-0)
debian/apache2.dirs (+4/-0)
debian/apache2.install (+4/-0)
debian/changelog (+249/-0)
debian/control (+16/-0)
debian/patches/086_svn_cross_compiles (+118/-0)
debian/patches/CVE-2017-15710.patch (+24/-0)
debian/patches/CVE-2017-15715.patch (+192/-0)
debian/patches/CVE-2018-1283.patch (+28/-0)
debian/patches/CVE-2018-1301.patch (+200/-0)
debian/patches/CVE-2018-1303.patch (+17/-0)
debian/patches/CVE-2018-1312.patch (+403/-0)
debian/patches/CVE-2018-17199.patch (+85/-0)
debian/patches/CVE-2019-0211.patch (+249/-0)
debian/patches/CVE-2019-0217.patch (+147/-0)
debian/patches/CVE-2019-0220-1.patch (+259/-0)
debian/patches/CVE-2019-0220-2.patch (+50/-0)
debian/patches/CVE-2019-0220-3.patch (+43/-0)
debian/patches/CVE-2019-10092-1.patch (+245/-0)
debian/patches/CVE-2019-10092-2.patch (+45/-0)
debian/patches/CVE-2019-10098.patch (+159/-0)
debian/patches/CVE-2020-11993-pre1.patch (+406/-0)
debian/patches/CVE-2020-11993.patch (+1905/-0)
debian/patches/CVE-2020-1927-1.patch (+93/-0)
debian/patches/CVE-2020-1927-2.patch (+99/-0)
debian/patches/CVE-2020-1934.patch (+103/-0)
debian/patches/CVE-2020-35452.patch (+51/-0)
debian/patches/CVE-2020-9490.patch (+436/-0)
debian/patches/CVE-2021-26690.patch (+25/-0)
debian/patches/CVE-2021-26691.patch (+39/-0)
debian/patches/CVE-2021-30641.patch (+60/-0)
debian/patches/CVE-2021-33193-pre1.patch (+175/-0)
debian/patches/CVE-2021-33193-pre2.patch (+521/-0)
debian/patches/CVE-2021-33193.patch (+197/-0)
debian/patches/CVE-2021-34798.patch (+6/-0)
debian/patches/CVE-2021-39275.patch (+4/-0)
debian/patches/CVE-2021-40438-2.patch (+4/-0)
debian/patches/CVE-2021-40438-3.patch (+8/-0)
debian/patches/CVE-2021-40438-pre1.patch (+16/-0)
debian/patches/CVE-2021-40438.patch (+12/-0)
debian/patches/balance-member-long-hostname-part1.patch (+30/-0)
debian/patches/balance-member-long-hostname-part2.patch (+430/-0)
debian/patches/clear-retry-flags-before-abort.patch (+67/-0)
debian/patches/disable-ssl-1.1.1-auto-retry.patch (+41/-0)
debian/patches/includeoptional-ignore-non-existent.patch (+61/-0)
debian/patches/mod_http2-1.14.1-backport-0001-On-the-2.4.x-branch.patch (+192/-0)
debian/patches/mod_http2-1.14.1-backport-0002-On-the-2.4.x-branch.patch (+73/-0)
debian/patches/mod_http2-1.14.1-backport-0003-On-the-2.4.x-branch.patch (+29/-0)
debian/patches/mod_http2-1.14.1-backport-0004-docco-fix.-correct-license-copyright-info.patch (+640/-0)
debian/patches/mod_http2-1.14.1-backport-0005-Merge-r1818804-r1818951-r1818958-r1818960-r1819027-r.patch (+263/-0)
debian/patches/mod_http2-1.14.1-backport-0006-On-the-2.4.x-branch-CVE-2018-1302.patch (+1530/-0)
debian/patches/mod_http2-1.14.1-backport-0008-Merge-r1822849-r1822858-r1822878-r1822879-r1822883-r.patch (+298/-0)
debian/patches/mod_http2-1.14.1-backport-0009-Merge-r1828879-from-trunk-CVE-2018-1333.patch (+65/-0)
debian/patches/mod_http2-1.14.1-backport-0010-Merge-r1826687-r1827166-r1828210-r1828232-r1828687-f.patch (+563/-0)
debian/patches/mod_http2-1.14.1-backport-0011-Merge-r1830562-from-trunk.patch (+108/-0)
debian/patches/mod_http2-1.14.1-backport-0012-fix-a-potential-NULL-dereference-spotted-by-gcc-8.1..patch (+114/-0)
debian/patches/mod_http2-1.14.1-backport-0013-Merge-r1837056-from-trunk.patch (+265/-0)
debian/patches/mod_http2-1.14.1-backport-0014-Merge-r1840010-from-trunk-CVE-2018-11763.patch (+527/-0)
debian/patches/mod_http2-1.14.1-backport-0015-Merge-r1835118-from-trunk.patch (+325/-0)
debian/patches/mod_http2-1.14.1-backport-0016-Merge-r1843426-from-trunk.patch (+110/-0)
debian/patches/mod_http2-1.14.1-backport-0017-Merge-of-r1846125-from-trunk-CVE-2018-17189.patch (+77/-0)
debian/patches/mod_http2-1.14.1-backport-0018-Merge-of-r1852986-from-trunk-CVE-2019-0196.patch (+30/-0)
debian/patches/mod_http2-1.14.1-backport-0019-Merge-r1852038-r1852101-from-trunk-CVE-2019-0197.patch (+159/-0)
debian/patches/mod_http2-1.14.1-backport-0020-Merge-r1853901-r1853906-r1853908-r1853929-r1853935-r.patch (+671/-0)
debian/patches/mod_http2-1.14.1-backport-0021-Merge-of-1849296-1852038-1852101-1852339-1853171-185.patch (+4605/-0)
debian/patches/mod_http2-1.14.1-backport-0022-adjust-per-r1855434.patch (+98/-0)
debian/patches/mod_http2-1.15.4-backport-0001.patch (+128/-0)
debian/patches/mod_http2-1.15.4-backport-0002.patch (+223/-0)
debian/patches/mod_http2-1.15.4-backport-0003.patch (+74/-0)
debian/patches/mod_http2-1.15.4-backport-0004-CVE-2019-9517.patch (+922/-0)
debian/patches/mod_http2-1.15.4-backport-0005.patch (+37/-0)
debian/patches/series (+105/-0)
debian/patches/ssl-read-rc-value-openssl-1.1.1.patch (+110/-0)
debian/patches/tlsv1.3-support-2.patch (+152/-0)
debian/patches/tlsv1.3-support-3.patch (+37/-0)
debian/patches/tlsv1.3-support-4.patch (+37/-0)
debian/patches/tlsv1.3-support-5.patch (+298/-0)
debian/patches/tlsv1.3-support.patch (+909/-0)
debian/patches/util_ldap_cache_lock_fix.patch (+48/-0)
debian/source/include-binaries (+4/-0)
Conflict in debian/apache2.dirs
Conflict in debian/apache2.install
Conflict in debian/changelog
Conflict in debian/control
Conflict in debian/patches/CVE-2021-33193.patch
Conflict in debian/patches/CVE-2021-34798.patch
Conflict in debian/patches/CVE-2021-39275.patch
Conflict in debian/patches/CVE-2021-40438-2.patch
Conflict in debian/patches/CVE-2021-40438-3.patch
Conflict in debian/patches/CVE-2021-40438-pre1.patch
Conflict in debian/patches/CVE-2021-40438.patch
Conflict in debian/patches/series
Conflict in debian/source/include-binaries
Reviewer Review Type Date Requested Status
Christian Ehrhardt  (community) Approve
Canonical Server Pending
Review via email: mp+412056@code.launchpad.net

Description of the change

This reverts an SRU fix that was reported to have a performance impact reported by focal users when supporting large numbers of vhosts. We reverted this in focal a few weeks ago and there's been no feedback regarding problems, so it's probably worth doing the same revert to the other releases.

After that, the plan will be to focus on a fix just for jammy, and then also get it accepted into Debian. After that we can evaluate whether or not to try SRUing again.

PPA: https://launchpad.net/~bryce/+archive/ubuntu/apache2-sru-lp1832182-graceful-revert

To post a comment you must log in.
Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

Again wrong target branch, but ok from git.

This revert is different than the one for H/I releases.
But that is intentional and ok as the change to Bionic was different when it was applied.

We are - as intended - back on the level of 2.4.29-1ubuntu4.18

$ git diff 0697199b656c588c0a7fdc80055795b9a837300c -- debian/ | diffstat
 changelog | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

LGTM
thanks!

review: Approve
Revision history for this message
Bryce Harrington (bryce) wrote :

Thanks Christian, I've uploaded the reverts. Sorry for the mistargeted branches.

I'll be keeping an eye on the uploads since with apache2 in focal we saw a ton of flaky test failures.

$ dput ubuntu ../apache2_2.4.29-1ubuntu4.20_source.changes
Checking signature on .changes
gpg: ../apache2_2.4.29-1ubuntu4.20_source.changes: Valid signature from E603B2578FB8F0FB
Checking signature on .dsc
gpg: ../apache2_2.4.29-1ubuntu4.20.dsc: Valid signature from E603B2578FB8F0FB
Uploading to ubuntu (via ftp to upload.ubuntu.com):
  Uploading apache2_2.4.29-1ubuntu4.20.dsc: done.
  Uploading apache2_2.4.29-1ubuntu4.20.debian.tar.xz: done.
  Uploading apache2_2.4.29-1ubuntu4.20_source.buildinfo: done.
  Uploading apache2_2.4.29-1ubuntu4.20_source.changes: done.
Successfully uploaded packages.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/debian/NEWS b/debian/NEWS
0new file mode 1006440new file mode 100644
index 0000000..db737ef
--- /dev/null
+++ b/debian/NEWS
@@ -0,0 +1,12 @@
1apache2 (2.4.29-1ubuntu4.10) bionic-security; urgency=medium
2
3 - To address HTTP/2 issues CVE-2019-9517, CVE-2019-0197,
4 CVE-2019-10081, and CVE-2019-10082, mod_http2 from 2.4.41 (aka
5 v1.15.4) was backported into this release of apache2, which
6 includes additional bug fixes as well.
7
8 - For CVE-2019-10098, PCRE_DOTALL flag is by default by default to
9 avoid unpredictable matches and substitutions with encoded line
10 break characters mod_rewrite and the apache core.
11
12 -- Steve Beattie <sbeattie@ubuntu.com> Mon, 26 Aug 2019 06:41:43 -0700
diff --git a/debian/apache2-systemd.conf b/debian/apache2-systemd.conf
0new file mode 10064413new file mode 100644
index 0000000..b031203
--- /dev/null
+++ b/debian/apache2-systemd.conf
@@ -0,0 +1,3 @@
1[Service]
2Type=forking
3RemainAfterExit=no
diff --git a/debian/apache2.dirs b/debian/apache2.dirs
index 1aa6d3c..fed7c9e 100644
--- a/debian/apache2.dirs
+++ b/debian/apache2.dirs
@@ -10,4 +10,8 @@ var/cache/apache2/mod_cache_disk
10var/lib/apache210var/lib/apache2
11var/log/apache211var/log/apache2
12var/www/html12var/www/html
13<<<<<<< debian/apache2.dirs
14=======
15usr/share/bug/apache2
16>>>>>>> debian/apache2.dirs
13/etc/ufw/applications.d/apache217/etc/ufw/applications.d/apache2
diff --git a/debian/apache2.install b/debian/apache2.install
index 92865fc..3d076c5 100644
--- a/debian/apache2.install
+++ b/debian/apache2.install
@@ -9,3 +9,7 @@ debian/config-dir/envvars /etc/apache2
9debian/config-dir/magic /etc/apache29debian/config-dir/magic /etc/apache2
10debian/debhelper/apache2-maintscript-helper /usr/share/apache2/10debian/debhelper/apache2-maintscript-helper /usr/share/apache2/
11debian/apache2-utils.ufw.profile /etc/ufw/applications.d/11debian/apache2-utils.ufw.profile /etc/ufw/applications.d/
12<<<<<<< debian/apache2.install
13=======
14debian/apache2-systemd.conf /lib/systemd/system/apache2.service.d/
15>>>>>>> debian/apache2.install
diff --git a/debian/changelog b/debian/changelog
index 0dbb7c5..27857c7 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,4 +1,25 @@
1<<<<<<< debian/changelog
1apache2 (2.4.48-3.1ubuntu3) impish; urgency=medium2apache2 (2.4.48-3.1ubuntu3) impish; urgency=medium
3=======
4apache2 (2.4.29-1ubuntu4.20) bionic; urgency=medium
5
6 * Revert fix from 2.4.29-1ubuntu4.19, due to performance regression.
7 (LP 1832182)
8
9 -- Bryce Harrington <bryce@canonical.com> Sun, 14 Nov 2021 23:52:18 +0000
10
11apache2 (2.4.29-1ubuntu4.19) bionic; urgency=medium
12
13 * d/apache2ctl: Also use systemd for graceful if it is in use.
14 (LP: #1832182)
15 - This extends an earlier fix for the start command to behave
16 similarly for restart / graceful. Fixes service failures on
17 unattended upgrade.
18
19 -- Bryce Harrington <bryce@canonical.com> Tue, 28 Sep 2021 22:27:27 +0000
20
21apache2 (2.4.29-1ubuntu4.18) bionic-security; urgency=medium
22>>>>>>> debian/changelog
223
3 * SECURITY REGRESSION: Issues in UDS URIs (LP: #1945311)24 * SECURITY REGRESSION: Issues in UDS URIs (LP: #1945311)
4 - debian/patches/CVE-2021-40438-2.patch: Fix UDS unix: scheme for P25 - debian/patches/CVE-2021-40438-2.patch: Fix UDS unix: scheme for P
@@ -7,11 +28,31 @@ apache2 (2.4.48-3.1ubuntu3) impish; urgency=medium
7 hostname in modules/mappers/mod_rewrite.c,28 hostname in modules/mappers/mod_rewrite.c,
8 modules/proxy/proxy_util.c.29 modules/proxy/proxy_util.c.
930
31<<<<<<< debian/changelog
10 -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Tue, 28 Sep 2021 08:52:26 -040032 -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Tue, 28 Sep 2021 08:52:26 -0400
1133
12apache2 (2.4.48-3.1ubuntu2) impish; urgency=medium34apache2 (2.4.48-3.1ubuntu2) impish; urgency=medium
1335
14 * SECURITY UPDATE: request splitting over HTTP/236 * SECURITY UPDATE: request splitting over HTTP/2
37=======
38 -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Tue, 28 Sep 2021 07:01:16 -0400
39
40apache2 (2.4.29-1ubuntu4.17) bionic-security; urgency=medium
41
42 * SECURITY UPDATE: request splitting over HTTP/2
43 - debian/patches/CVE-2021-33193-pre1.patch: process early errors via a
44 dummy HTTP/1.1 request as well in modules/http2/h2.h,
45 modules/http2/h2_request.c, modules/http2/h2_session.c,
46 modules/http2/h2_stream.c.
47 - debian/patches/CVE-2021-33193-pre2.patch: sync with github standalone
48 version 1.15.17 in modules/http2/h2_bucket_beam.c,
49 modules/http2/h2_config.c, modules/http2/h2_config.h,
50 modules/http2/h2_h2.c, modules/http2/h2_headers.c,
51 modules/http2/h2_headers.h, modules/http2/h2_mplx.c,
52 modules/http2/h2_request.c, modules/http2/h2_stream.h,
53 modules/http2/h2_task.c, modules/http2/h2_task.h,
54 modules/http2/h2_version.h.
55>>>>>>> debian/changelog
15 - debian/patches/CVE-2021-33193.patch: refactor request parsing in56 - debian/patches/CVE-2021-33193.patch: refactor request parsing in
16 include/ap_mmn.h, include/http_core.h, include/http_protocol.h,57 include/ap_mmn.h, include/http_core.h, include/http_protocol.h,
17 include/http_vhost.h, modules/http2/h2_request.c, server/core.c,58 include/http_vhost.h, modules/http2/h2_request.c, server/core.c,
@@ -21,10 +62,13 @@ apache2 (2.4.48-3.1ubuntu2) impish; urgency=medium
21 - debian/patches/CVE-2021-34798.patch: add NULL check in62 - debian/patches/CVE-2021-34798.patch: add NULL check in
22 server/scoreboard.c.63 server/scoreboard.c.
23 - CVE-2021-3479864 - CVE-2021-34798
65<<<<<<< debian/changelog
24 * SECURITY UPDATE: DoS in mod_proxy_uwsgi66 * SECURITY UPDATE: DoS in mod_proxy_uwsgi
25 - debian/patches/CVE-2021-36160.patch: fix PATH_INFO setting for67 - debian/patches/CVE-2021-36160.patch: fix PATH_INFO setting for
26 generic worker in modules/proxy/mod_proxy_uwsgi.c.68 generic worker in modules/proxy/mod_proxy_uwsgi.c.
27 - CVE-2021-3616069 - CVE-2021-36160
70=======
71>>>>>>> debian/changelog
28 * SECURITY UPDATE: buffer overflow in ap_escape_quotes72 * SECURITY UPDATE: buffer overflow in ap_escape_quotes
29 - debian/patches/CVE-2021-39275.patch: fix ap_escape_quotes73 - debian/patches/CVE-2021-39275.patch: fix ap_escape_quotes
30 substitution logic in server/util.c.74 substitution logic in server/util.c.
@@ -37,6 +81,7 @@ apache2 (2.4.48-3.1ubuntu2) impish; urgency=medium
37 configured UDS path in modules/proxy/proxy_util.c.81 configured UDS path in modules/proxy/proxy_util.c.
38 - CVE-2021-4043882 - CVE-2021-40438
3983
84<<<<<<< debian/changelog
40 -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Thu, 23 Sep 2021 12:51:16 -040085 -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Thu, 23 Sep 2021 12:51:16 -0400
4186
42apache2 (2.4.48-3.1ubuntu1) impish; urgency=medium87apache2 (2.4.48-3.1ubuntu1) impish; urgency=medium
@@ -174,6 +219,12 @@ apache2 (2.4.46-4ubuntu2) impish; urgency=medium
174 - debian/patches/CVE-2020-13950.patch: don't dereference NULL proxy219 - debian/patches/CVE-2020-13950.patch: don't dereference NULL proxy
175 connection in modules/proxy/mod_proxy_http.c.220 connection in modules/proxy/mod_proxy_http.c.
176 - CVE-2020-13950221 - CVE-2020-13950
222=======
223 -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Thu, 23 Sep 2021 13:01:10 -0400
224
225apache2 (2.4.29-1ubuntu4.16) bionic-security; urgency=medium
226
227>>>>>>> debian/changelog
177 * SECURITY UPDATE: stack overflow via Digest nonce in mod_auth_digest228 * SECURITY UPDATE: stack overflow via Digest nonce in mod_auth_digest
178 - debian/patches/CVE-2020-35452.patch: fast validation of the nonce's229 - debian/patches/CVE-2020-35452.patch: fast validation of the nonce's
179 base64 to fail early if the format can't match anyway in230 base64 to fail early if the format can't match anyway in
@@ -191,6 +242,7 @@ apache2 (2.4.46-4ubuntu2) impish; urgency=medium
191 - debian/patches/CVE-2021-30641.patch: change default behavior in242 - debian/patches/CVE-2021-30641.patch: change default behavior in
192 server/request.c.243 server/request.c.
193 - CVE-2021-30641244 - CVE-2021-30641
245<<<<<<< debian/changelog
194246
195 -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Thu, 17 Jun 2021 13:09:41 -0400247 -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Thu, 17 Jun 2021 13:09:41 -0400
196248
@@ -573,6 +625,143 @@ apache2 (2.4.38-3ubuntu1) eoan; urgency=low
573apache2 (2.4.38-3) unstable; urgency=high625apache2 (2.4.38-3) unstable; urgency=high
574626
575 [ Marc Deslauriers ]627 [ Marc Deslauriers ]
628=======
629 * This update does _not_ include the changes from 2.4.29-1ubuntu4.15 in
630 bionic-proposed.
631
632 -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Fri, 18 Jun 2021 07:06:22 -0400
633
634apache2 (2.4.29-1ubuntu4.14) bionic-security; urgency=medium
635
636 * SECURITY UPDATE: mod_rewrite redirect issue
637 - debian/patches/CVE-2020-1927-1.patch: factor out default regex flags
638 in include/ap_regex.h, server/core.c, server/util_pcre.c.
639 - debian/patches/CVE-2020-1927-2.patch: add AP_REG_NO_DEFAULT to allow
640 opt-out of pcre defaults in include/ap_regex.h,
641 modules/filters/mod_substitute.c, server/util_pcre.c,
642 server/util_regex.c.
643 - CVE-2020-1927
644 * SECURITY UPDATE: mod_proxy_ftp uninitialized memory issue
645 - debian/patches/CVE-2020-1934.patch: trap bad FTP responses in
646 modules/proxy/mod_proxy_ftp.c.
647 - CVE-2020-1934
648 * SECURITY UPDATE: DoS via invalid Cache-Digest header
649 - debian/patches/CVE-2020-9490.patch: remove support for abandoned
650 http-wg draft in modules/http2/h2_push.c, modules/http2/h2_push.h.
651 - CVE-2020-9490
652 * SECURITY UPDATE: concurrent use of memory pools in HTTP/2 module
653 - debian/patches/CVE-2020-11993-pre1.patch: fixed rare cases where a h2
654 worker could deadlock the main connection in modules/http2/*.
655 - debian/patches/CVE-2020-11993.patch: fix logging and rename
656 terminology in modules/http2/*.
657 - CVE-2020-11993
658
659 -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Wed, 12 Aug 2020 17:33:25 -0400
660
661apache2 (2.4.29-1ubuntu4.13) bionic-security; urgency=medium
662
663 * Add additional missing commits to TLSv1.3 support. (LP: #1867223)
664 - debian/patches/tlsv1.3-support-2.patch: fix whitespace and copy/paste
665 typos in modules/ssl/ssl_engine_kernel.c.
666 - debian/patches/tlsv1.3-support-3.patch: fail with 403 if
667 SSL_verify_client_post_handshake fails in
668 modules/ssl/ssl_engine_kernel.c.
669 - debian/patches/tlsv1.3-support-4.patch: disable AUTO_RETRY mode for
670 OpenSSL 1.1.1, which fixes post-handshake authentication in
671 modules/ssl/ssl_engine_init.c.
672 - debian/patches/tlsv1.3-support-5.patch: retrieve and set
673 sslconn->client_cert here for both "modern" and classic access
674 control in modules/ssl/ssl_engine_kernel.c.
675
676 -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Fri, 13 Mar 2020 08:26:16 -0400
677
678apache2 (2.4.29-1ubuntu4.12) bionic; urgency=medium
679
680 * Add TLSv1.3 support. (LP: #1845263)
681 - debian/patches/tlsv1.3-support.patch: backport upstream 2.4 commit
682 which introduced TLSv1.3 support.
683
684 -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Tue, 03 Dec 2019 10:55:03 -0500
685
686apache2 (2.4.29-1ubuntu4.11) bionic-security; urgency=medium
687
688 * SECURITY REGRESSION: mod_proxy balancer XSS/CSRF hardening broke
689 browsers which change case in headers and breaks balancers
690 loading in some configurations (LP: #1842701)
691 - drop d/p/CVE-2019-10092-3.patch
692
693 -- Steve Beattie <sbeattie@ubuntu.com> Mon, 16 Sep 2019 05:58:48 -0700
694
695apache2 (2.4.29-1ubuntu4.10) bionic-security; urgency=medium
696
697 * SECURITY UPDATE: HTTP/2 internal data buffering denial of service.
698 - d/p/mod_http2-1.15.4-backport-0004-CVE-2019-9517.patch: improve
699 http/2 module keepalive throttling.
700 - CVE-2019-9517
701 * SECURITY UPDATE: Upgrade request from http/1.1 to http/2 crash
702 denial of service (LP: #1840188)
703 - d/p/mod_http2-1.14.1-backport-0019-Merge-r1852038-r1852101-from-trunk-CVE-2019-0197.patch:
704 re-use slave connections and fix slave connection keepalives
705 counter.
706 - CVE-2019-0197
707 * SECURITY UPDATE: mod_http2 memory corruption on early pushes
708 - included in mod_http2 1.15.4 backport
709 - CVE-2019-10081
710 * SECURITY UPDATE: read-after-free in mod_http2 h2 connection
711 shutdown.
712 - included in mod_http2 1.15.4 backport
713 - CVE-2019-10082
714 * SECURITY UPDATE: Limited cross-site scripting in mod_proxy
715 error page.
716 - d/p/CVE-2019-10092-1.patch: Remove request details from built-in
717 error documents.
718 - d/p/CVE-2019-10092-2.patch: Add missing log numbers.
719 - d/p/CVE-2019-10092-3.patch: mod_proxy: Improve XSRF/XSS
720 protection.
721 - CVE-2019-10092-1
722 * SECURITY UPDATE: mod_rewrite potential open redirect.
723 - d/p/CVE-2019-10098.patch: Set PCRE_DOTALL by default.
724 - CVE-2019-10098
725 * Backport mod_http2 v1.14.1 and v1.15.4 for CVE-2019-9517,
726 CVE-2019-10081, and CVE-2019-10082 fixes:
727 - add d/p/mod_http2-1.14.1-backport-*.patches and
728 d/p/mod_http2-1.15.4-backport-*.patches
729 - dropped the following patches included above:
730 + d/p/CVE-2018-1302.patch
731 + d/p/CVE-2018-1333.patch
732 + d/p/CVE-2018-11763.patch
733 + d/p/CVE-2018-17189.patch
734 + d/p/CVE-2019-0196.patch
735
736 -- Steve Beattie <sbeattie@ubuntu.com> Mon, 26 Aug 2019 06:41:23 -0700
737
738apache2 (2.4.29-1ubuntu4.8) bionic; urgency=medium
739
740 * d/p/ssl-read-rc-value-openssl-1.1.1.patch: Handle SSL_read() return code 0
741 similarly to <0 with openssl 1.1.1
742 * d/p/clear-retry-flags-before-abort.patch: clear retry flags before
743 aborting on client-initiated reneg (LP: #1836329)
744
745 -- Andreas Hasenack <andreas@canonical.com> Tue, 16 Jul 2019 15:14:45 -0300
746
747apache2 (2.4.29-1ubuntu4.7) bionic; urgency=medium
748
749 * d/p/disable-ssl-1.1.1-auto-retry.patch: fix client certificate
750 authentication when built with openssl 1.1.1 (LP: #1833039)
751
752 -- Andreas Hasenack <andreas@canonical.com> Fri, 28 Jun 2019 13:49:35 -0300
753
754apache2 (2.4.29-1ubuntu4.6) bionic-security; urgency=medium
755
756 * SECURITY UPDATE: slowloris DoS in mod_http2
757 - debian/patches/CVE-2018-17189.patch: change cleanup strategy for
758 slave connections in modules/http2/h2_conn.c.
759 - CVE-2018-17189
760 * SECURITY UPDATE: mod_session expiry time issue
761 - debian/patches/CVE-2018-17199.patch: always decode session attributes
762 early in modules/session/mod_session.c.
763 - CVE-2018-17199
764>>>>>>> debian/changelog
576 * SECURITY UPDATE: read-after-free on a string compare in mod_http2765 * SECURITY UPDATE: read-after-free on a string compare in mod_http2
577 - debian/patches/CVE-2019-0196.patch: disentangelment of stream and766 - debian/patches/CVE-2019-0196.patch: disentangelment of stream and
578 request method in modules/http2/h2_request.c.767 request method in modules/http2/h2_request.c.
@@ -583,10 +772,13 @@ apache2 (2.4.38-3) unstable; urgency=high
583 server/mpm/event/event.c, server/mpm/prefork/prefork.c,772 server/mpm/event/event.c, server/mpm/prefork/prefork.c,
584 server/mpm/worker/worker.c.773 server/mpm/worker/worker.c.
585 - CVE-2019-0211774 - CVE-2019-0211
775<<<<<<< debian/changelog
586 * SECURITY UPDATE: mod_ssl access control bypass776 * SECURITY UPDATE: mod_ssl access control bypass
587 - debian/patches/CVE-2019-0215.patch: restore SSL verify state after777 - debian/patches/CVE-2019-0215.patch: restore SSL verify state after
588 PHA failure in TLSv1.3 in modules/ssl/ssl_engine_kernel.c.778 PHA failure in TLSv1.3 in modules/ssl/ssl_engine_kernel.c.
589 - CVE-2019-0215779 - CVE-2019-0215
780=======
781>>>>>>> debian/changelog
590 * SECURITY UPDATE: mod_auth_digest access control bypass782 * SECURITY UPDATE: mod_auth_digest access control bypass
591 - debian/patches/CVE-2019-0217.patch: fix a race condition in783 - debian/patches/CVE-2019-0217.patch: fix a race condition in
592 modules/aaa/mod_auth_digest.c.784 modules/aaa/mod_auth_digest.c.
@@ -601,6 +793,7 @@ apache2 (2.4.38-3) unstable; urgency=high
601 server/util.c.793 server/util.c.
602 - CVE-2019-0220794 - CVE-2019-0220
603795
796<<<<<<< debian/changelog
604 [ Stefan Fritsch ]797 [ Stefan Fritsch ]
605 * Pull security fixes from 2.4.39 via Ubuntu798 * Pull security fixes from 2.4.39 via Ubuntu
606 * CVE-2019-0197: mod_http2: Fix possible crash on late upgrade799 * CVE-2019-0197: mod_http2: Fix possible crash on late upgrade
@@ -765,11 +958,35 @@ apache2 (2.4.35-1) unstable; urgency=medium
765apache2 (2.4.34-1ubuntu2) cosmic; urgency=medium958apache2 (2.4.34-1ubuntu2) cosmic; urgency=medium
766959
767 * SECURITY UPDATE: denial of service in HTTP/2 via large SETTINGS frames960 * SECURITY UPDATE: denial of service in HTTP/2 via large SETTINGS frames
961=======
962 -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Wed, 03 Apr 2019 09:22:37 -0400
963
964apache2 (2.4.29-1ubuntu4.5) bionic; urgency=medium
965
966 * d/debhelper/apache2-maintscript-helper: fix typo in apache2_switch_mpm()'s
967 a2query call. (LP: #1782806)
968
969 -- Andreas Hasenack <andreas@canonical.com> Wed, 10 Oct 2018 15:59:25 -0300
970
971apache2 (2.4.29-1ubuntu4.4) bionic-security; urgency=medium
972
973 * SECURITY UPDATE: DoS in HTTP/2 via NULL pointer
974 - debian/patches/CVE-2018-1302.patch: remove obsolete stream detach
975 code in modules/http2/h2_bucket_beam.c, modules/http2/h2_stream.c,
976 modules/http2/h2_stream.h.
977 - CVE-2018-1302
978 * SECURITY UPDATE: DoS in HTTP/2 via worker exhaustion
979 - debian/patches/CVE-2018-1333.patch: always wake up any conditional
980 waits when streams are aborted in modules/http2/h2_bucket_beam.c.
981 - CVE-2018-1333
982 * SECURITY UPDATE: DoS in HTTP/2 via large SETTINGS frames
983>>>>>>> debian/changelog
768 - debian/patches/CVE-2018-11763.patch: rework connection IO event984 - debian/patches/CVE-2018-11763.patch: rework connection IO event
769 handling in modules/http2/h2_session.c, modules/http2/h2_session.h,985 handling in modules/http2/h2_session.c, modules/http2/h2_session.h,
770 modules/http2/h2_version.h.986 modules/http2/h2_version.h.
771 - CVE-2018-11763987 - CVE-2018-11763
772988
989<<<<<<< debian/changelog
773 -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Wed, 03 Oct 2018 09:57:22 -0400990 -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Wed, 03 Oct 2018 09:57:22 -0400
774991
775apache2 (2.4.34-1ubuntu1) cosmic; urgency=medium992apache2 (2.4.34-1ubuntu1) cosmic; urgency=medium
@@ -963,6 +1180,26 @@ apache2 (2.4.29-2) unstable; urgency=medium
963 * Add Build-Depends on libbrotli-dev and enable brotli module1180 * Add Build-Depends on libbrotli-dev and enable brotli module
9641181
965 -- Ondřej Surý <ondrej@debian.org> Sun, 14 Jan 2018 11:01:58 +00001182 -- Ondřej Surý <ondrej@debian.org> Sun, 14 Jan 2018 11:01:58 +0000
1183=======
1184 -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Wed, 03 Oct 2018 10:41:08 -0400
1185
1186apache2 (2.4.29-1ubuntu4.3) bionic; urgency=medium
1187
1188 * d/p/balance-member-long-hostname-part{1,2}.patch: Provide an RFC1035
1189 compliant version of the hostname in the
1190 proxy_worker_shared structure. A hostname that is too long is no longer a
1191 fatal error. (LP: #1750356)
1192
1193 -- Andreas Hasenack <andreas@canonical.com> Wed, 27 Jun 2018 14:05:04 -0300
1194
1195apache2 (2.4.29-1ubuntu4.2) bionic; urgency=medium
1196
1197 * debian/patches/includeoptional-ignore-non-existent.patch: silently
1198 ignore a not existent file path with IncludeOptional . Closes LP:
1199 #1766186.
1200
1201 -- Andreas Hasenack <andreas@canonical.com> Thu, 07 Jun 2018 18:10:10 -0300
1202>>>>>>> debian/changelog
9661203
967apache2 (2.4.29-1ubuntu4.1) bionic-security; urgency=medium1204apache2 (2.4.29-1ubuntu4.1) bionic-security; urgency=medium
9681205
@@ -3072,6 +3309,18 @@ apache2 (2.2.21-5ubuntu1) precise; urgency=low
30723309
3073 -- Chuck Short <zulcss@ubuntu.com> Mon, 09 Jan 2012 06:26:31 +00003310 -- Chuck Short <zulcss@ubuntu.com> Mon, 09 Jan 2012 06:26:31 +0000
30743311
3312apache2 (2.2.21-5ubuntu1) precise; urgency=low
3313
3314 * Merge from Debian testing. Remaining changes:
3315 - debian/{control, rules}: Enable PIE hardening.
3316 - debian/{control, rules, apache2.2-common.ufw.profile}: Add ufw profiles.
3317 - debian/control: Add bzr tag and point it to our tree
3318 - debian/apache2.py, debian/apache2.2-common.install: Add apport hook.
3319 - debian/control, debian/ask-for-passphrase, debian/config-dir/mods-available/ssl.conf:
3320 Plymouth aware passphrase dialog program ask-for-passphrase.
3321
3322 -- Chuck Short <zulcss@ubuntu.com> Mon, 09 Jan 2012 06:26:31 +0000
3323
3075apache2 (2.2.21-5) unstable; urgency=low3324apache2 (2.2.21-5) unstable; urgency=low
30763325
3077 [ Arno Töll ]3326 [ Arno Töll ]
diff --git a/debian/control b/debian/control
index c12b174..9c00a61 100644
--- a/debian/control
+++ b/debian/control
@@ -7,6 +7,7 @@ Uploaders: Stefan Fritsch <sf@debian.org>,
7 Yadd <yadd@debian.org>7 Yadd <yadd@debian.org>
8Section: httpd8Section: httpd
9Priority: optional9Priority: optional
10<<<<<<< debian/control
10Build-Depends: debhelper-compat (= 13),11Build-Depends: debhelper-compat (= 13),
11 dpkg-dev (>= 1.16.1~),12 dpkg-dev (>= 1.16.1~),
12 bison,13 bison,
@@ -25,6 +26,15 @@ Build-Depends: debhelper-compat (= 13),
25 zlib1g-dev,26 zlib1g-dev,
26 libcurl4-openssl-dev | libcurl4-dev,27 libcurl4-openssl-dev | libcurl4-dev,
27 libjansson-dev28 libjansson-dev
29=======
30Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
31XSBC-Original-Maintainer: Debian Apache Maintainers <debian-apache@lists.debian.org>
32Uploaders: Stefan Fritsch <sf@debian.org>, Arno Töll <arno@debian.org>
33Build-Depends: debhelper (>= 9.20160709~), lsb-release, dpkg-dev (>= 1.16.1~),
34 libaprutil1-dev (>= 1.5.0), libapr1-dev (>= 1.5.0), libpcre3-dev, zlib1g-dev,
35 libnghttp2-dev, libssl-dev (>= 1.1), perl,
36 liblua5.2-dev, libxml2-dev, autotools-dev, gawk | awk
37>>>>>>> debian/control
28Build-Conflicts: autoconf2.1338Build-Conflicts: autoconf2.13
29Standards-Version: 4.5.139Standards-Version: 4.5.1
30Vcs-Browser: https://salsa.debian.org/apache-team/apache240Vcs-Browser: https://salsa.debian.org/apache-team/apache2
@@ -43,6 +53,7 @@ Depends: apache2-bin (= ${binary:Version}),
43 procps [!hurd-i386],53 procps [!hurd-i386],
44 ${misc:Depends}54 ${misc:Depends}
45Recommends: ssl-cert55Recommends: ssl-cert
56<<<<<<< debian/control
46Suggests: apache2-doc,57Suggests: apache2-doc,
47 apache2-suexec-pristine | apache2-suexec-custom,58 apache2-suexec-pristine | apache2-suexec-custom,
48 www-browser,59 www-browser,
@@ -57,6 +68,11 @@ Provides: httpd,
57Replaces: apache2.2-bin,68Replaces: apache2.2-bin,
58 apache2.2-common,69 apache2.2-common,
59 libapache2-mod-proxy-uwsgi (<< 2.4.33)70 libapache2-mod-proxy-uwsgi (<< 2.4.33)
71=======
72Conflicts: apache2.2-common, apache2.2-bin
73Replaces: apache2.2-common, apache2.2-bin
74Suggests: www-browser, apache2-doc, apache2-suexec-pristine | apache2-suexec-custom, ufw
75>>>>>>> debian/control
60Description: Apache HTTP Server76Description: Apache HTTP Server
61 The Apache HTTP Server Project's goal is to build a secure, efficient and77 The Apache HTTP Server Project's goal is to build a secure, efficient and
62 extensible HTTP server as standards-compliant open source software. The78 extensible HTTP server as standards-compliant open source software. The
diff --git a/debian/patches/086_svn_cross_compiles b/debian/patches/086_svn_cross_compiles
63new file mode 10064479new file mode 100644
index 0000000..b237908
--- /dev/null
+++ b/debian/patches/086_svn_cross_compiles
@@ -0,0 +1,118 @@
1Description: Pull upstream fixes for autotools for cross-compiling
2Author: Adam Conrad <adconrad@ubuntu.com>
3Origin: upstream, http://svn.eu.apache.org/viewvc?view=revision&revision=1328445
4Origin: upstream, http://svn.eu.apache.org/viewvc?view=revision&revision=1327907
5Origin: upstream, http://svn.eu.apache.org/viewvc?view=revision&revision=1328390
6Origin: upstream, http://svn.eu.apache.org/viewvc?view=revision&revision=1328714
7Forwarded: not-needed
8
9Index: apache2-2.4.29/acinclude.m4
10===================================================================
11--- apache2-2.4.29.orig/acinclude.m4 2017-11-10 10:56:51.488205250 -0500
12+++ apache2-2.4.29/acinclude.m4 2017-11-10 10:56:51.484205199 -0500
13@@ -55,6 +55,8 @@ AC_DEFUN([APACHE_GEN_CONFIG_VARS],[
14 APACHE_SUBST(CPPFLAGS)
15 APACHE_SUBST(CFLAGS)
16 APACHE_SUBST(CXXFLAGS)
17+ APACHE_SUBST(CC_FOR_BUILD)
18+ APACHE_SUBST(CFLAGS_FOR_BUILD)
19 APACHE_SUBST(LTFLAGS)
20 APACHE_SUBST(LDFLAGS)
21 APACHE_SUBST(LT_LDFLAGS)
22@@ -697,7 +699,7 @@ int main(void)
23 {
24 return sizeof(void *) < sizeof(long);
25 }], [ap_cv_void_ptr_lt_long=no], [ap_cv_void_ptr_lt_long=yes],
26- [ap_cv_void_ptr_lt_long=yes])])
27+ [ap_cv_void_ptr_lt_long="cross compile - not checked"])])
28
29 if test "$ap_cv_void_ptr_lt_long" = "yes"; then
30 AC_MSG_ERROR([Size of "void *" is less than size of "long"])
31Index: apache2-2.4.29/configure
32===================================================================
33--- apache2-2.4.29.orig/configure 2017-11-10 10:56:51.488205250 -0500
34+++ apache2-2.4.29/configure 2017-11-10 10:56:51.488205250 -0500
35@@ -662,6 +662,8 @@ HTTPD_LDFLAGS
36 SH_LDFLAGS
37 LT_LDFLAGS
38 LTFLAGS
39+CFLAGS_FOR_BUILD
40+CC_FOR_BUILD
41 CXXFLAGS
42 CXX
43 other_targets
44@@ -6071,6 +6073,12 @@ fi
45
46
47
48+if test "x${build_alias}" != "x${host_alias}"; then
49+ if test "x${CC_FOR_BUILD}" = "x"; then
50+ CC_FOR_BUILD=cc
51+ fi
52+fi
53+
54 if test "x${cache_file}" = "x/dev/null"; then
55 # Likewise, ensure that CC and CPP are passed through to the pcre
56 # configure script iff caching is disabled (the autoconf 2.5x default).
57@@ -7698,7 +7706,7 @@ if ${ap_cv_void_ptr_lt_long+:} false; th
58 $as_echo_n "(cached) " >&6
59 else
60 if test "$cross_compiling" = yes; then :
61- ap_cv_void_ptr_lt_long=yes
62+ ap_cv_void_ptr_lt_long="cross compile - not checked"
63 else
64 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
65 /* end confdefs.h. */
66@@ -37522,6 +37530,14 @@ $as_echo "$as_me: " >&6;}
67
68
69
70+ APACHE_VAR_SUBST="$APACHE_VAR_SUBST CC_FOR_BUILD"
71+
72+
73+
74+ APACHE_VAR_SUBST="$APACHE_VAR_SUBST CFLAGS_FOR_BUILD"
75+
76+
77+
78 APACHE_VAR_SUBST="$APACHE_VAR_SUBST LTFLAGS"
79
80
81Index: apache2-2.4.29/configure.in
82===================================================================
83--- apache2-2.4.29.orig/configure.in 2017-11-10 10:56:51.488205250 -0500
84+++ apache2-2.4.29/configure.in 2017-11-10 10:56:51.488205250 -0500
85@@ -206,6 +206,14 @@ AC_PROG_CPP
86 dnl Try to get c99 support for variadic macros
87 ifdef([AC_PROG_CC_C99], [AC_PROG_CC_C99])
88
89+dnl In case of cross compilation we set CC_FOR_BUILD to cc unless
90+dnl we got already CC_FOR_BUILD from environment.
91+if test "x${build_alias}" != "x${host_alias}"; then
92+ if test "x${CC_FOR_BUILD}" = "x"; then
93+ CC_FOR_BUILD=cc
94+ fi
95+fi
96+
97 if test "x${cache_file}" = "x/dev/null"; then
98 # Likewise, ensure that CC and CPP are passed through to the pcre
99 # configure script iff caching is disabled (the autoconf 2.5x default).
100Index: apache2-2.4.29/server/Makefile.in
101===================================================================
102--- apache2-2.4.29.orig/server/Makefile.in 2017-11-10 10:56:51.488205250 -0500
103+++ apache2-2.4.29/server/Makefile.in 2017-11-10 10:56:51.488205250 -0500
104@@ -24,9 +24,14 @@ TARGETS = delete-exports $(LTLIBRARY_NAM
105 include $(top_builddir)/build/rules.mk
106 include $(top_srcdir)/build/library.mk
107
108+ifdef CC_FOR_BUILD
109+gen_test_char: gen_test_char.c
110+ $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) -DCROSS_COMPILE -o $@ $<
111+else
112 gen_test_char_OBJECTS = gen_test_char.lo
113 gen_test_char: $(gen_test_char_OBJECTS)
114 $(LINK) $(EXTRA_LDFLAGS) $(gen_test_char_OBJECTS) $(EXTRA_LIBS)
115+endif
116
117 test_char.h: gen_test_char
118 ./gen_test_char > test_char.h
diff --git a/debian/patches/CVE-2017-15710.patch b/debian/patches/CVE-2017-15710.patch
0new file mode 100644119new file mode 100644
index 0000000..a218970
--- /dev/null
+++ b/debian/patches/CVE-2017-15710.patch
@@ -0,0 +1,24 @@
1Description: fix DoS via missing header with AuthLDAPCharsetConfig
2Origin: upstream, http://svn.apache.org/viewvc?view=revision&revision=1824456
3
4Index: apache2-2.4.29/modules/aaa/mod_authnz_ldap.c
5===================================================================
6--- apache2-2.4.29.orig/modules/aaa/mod_authnz_ldap.c 2017-06-29 07:31:20.000000000 -0400
7+++ apache2-2.4.29/modules/aaa/mod_authnz_ldap.c 2018-04-18 09:14:38.995193064 -0400
8@@ -126,9 +126,13 @@ static char* derive_codepage_from_lang (
9
10 charset = (char*) apr_hash_get(charset_conversions, language, APR_HASH_KEY_STRING);
11
12- if (!charset) {
13- language[2] = '\0';
14- charset = (char*) apr_hash_get(charset_conversions, language, APR_HASH_KEY_STRING);
15+ /*
16+ * Test if language values like 'en-US' return a match from the charset
17+ * conversion map when shortened to 'en'.
18+ */
19+ if (!charset && strlen(language) > 3 && language[2] == '-') {
20+ char *language_short = apr_pstrndup(p, language, 2);
21+ charset = (char*) apr_hash_get(charset_conversions, language_short, APR_HASH_KEY_STRING);
22 }
23
24 if (charset) {
diff --git a/debian/patches/CVE-2017-15715.patch b/debian/patches/CVE-2017-15715.patch
0new file mode 10064425new file mode 100644
index 0000000..157a0b2
--- /dev/null
+++ b/debian/patches/CVE-2017-15715.patch
@@ -0,0 +1,192 @@
1Description: fix incorrect <FilesMatch> matching
2Origin: upstream, https://svn.apache.org/viewvc?view=revision&revision=1824472
3
4Index: apache2-2.4.29/include/ap_regex.h
5===================================================================
6--- apache2-2.4.29.orig/include/ap_regex.h 2014-01-05 11:14:26.000000000 -0500
7+++ apache2-2.4.29/include/ap_regex.h 2018-04-18 09:14:53.391220215 -0400
8@@ -77,6 +77,8 @@ extern "C" {
9 #define AP_REG_NOMEM 0x20 /* nomem in our code */
10 #define AP_REG_DOTALL 0x40 /* perl's /s flag */
11
12+#define AP_REG_DOLLAR_ENDONLY 0x200 /* '$' matches at end of subject string only */
13+
14 #define AP_REG_MATCH "MATCH_" /** suggested prefix for ap_regname */
15
16 /* Error values: */
17@@ -103,6 +105,26 @@ typedef struct {
18 /* The functions */
19
20 /**
21+ * Get default compile flags
22+ * @return Bitwise OR of AP_REG_* flags
23+ */
24+AP_DECLARE(int) ap_regcomp_get_default_cflags(void);
25+
26+/**
27+ * Set default compile flags
28+ * @param cflags Bitwise OR of AP_REG_* flags
29+ */
30+AP_DECLARE(void) ap_regcomp_set_default_cflags(int cflags);
31+
32+/**
33+ * Get the AP_REG_* corresponding to the string.
34+ * @param name The name (i.e. AP_REG_<name>)
35+ * @return The AP_REG_*, or zero if the string is unknown
36+ *
37+ */
38+AP_DECLARE(int) ap_regcomp_default_cflag_by_name(const char *name);
39+
40+/**
41 * Compile a regular expression.
42 * @param preg Returned compiled regex
43 * @param regex The regular expression string
44Index: apache2-2.4.29/server/core.c
45===================================================================
46--- apache2-2.4.29.orig/server/core.c 2017-09-08 09:13:11.000000000 -0400
47+++ apache2-2.4.29/server/core.c 2018-04-18 09:14:53.387220208 -0400
48@@ -48,6 +48,7 @@
49 #include "mod_core.h"
50 #include "mod_proxy.h"
51 #include "ap_listen.h"
52+#include "ap_regex.h"
53
54 #include "mod_so.h" /* for ap_find_loaded_module_symbol */
55
56@@ -2846,6 +2847,58 @@ static const char *virtualhost_section(c
57 return errmsg;
58 }
59
60+static const char *set_regex_default_options(cmd_parms *cmd,
61+ void *dummy,
62+ const char *arg)
63+{
64+ const command_rec *thiscmd = cmd->cmd;
65+ int cflags, cflag;
66+
67+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
68+ if (err != NULL) {
69+ return err;
70+ }
71+
72+ cflags = ap_regcomp_get_default_cflags();
73+ while (*arg) {
74+ const char *name = ap_getword_conf(cmd->pool, &arg);
75+ int how = 0;
76+
77+ if (strcasecmp(name, "none") == 0) {
78+ cflags = 0;
79+ continue;
80+ }
81+
82+ if (*name == '+') {
83+ name++;
84+ how = +1;
85+ }
86+ else if (*name == '-') {
87+ name++;
88+ how = -1;
89+ }
90+
91+ cflag = ap_regcomp_default_cflag_by_name(name);
92+ if (!cflag) {
93+ return apr_psprintf(cmd->pool, "%s: option '%s' unknown",
94+ thiscmd->name, name);
95+ }
96+
97+ if (how > 0) {
98+ cflags |= cflag;
99+ }
100+ else if (how < 0) {
101+ cflags &= ~cflag;
102+ }
103+ else {
104+ cflags = cflag;
105+ }
106+ }
107+ ap_regcomp_set_default_cflags(cflags);
108+
109+ return NULL;
110+}
111+
112 static const char *set_server_alias(cmd_parms *cmd, void *dummy,
113 const char *arg)
114 {
115@@ -4421,6 +4474,9 @@ AP_INIT_TAKE12("RLimitNPROC", no_set_lim
116 OR_ALL, "soft/hard limits for max number of processes per uid"),
117 #endif
118
119+AP_INIT_RAW_ARGS("RegexDefaultOptions", set_regex_default_options, NULL, RSRC_CONF,
120+ "default options for regexes (prefixed by '+' to add, '-' to del)"),
121+
122 /* internal recursion stopper */
123 AP_INIT_TAKE12("LimitInternalRecursion", set_recursion_limit, NULL, RSRC_CONF,
124 "maximum recursion depth of internal redirects and subrequests"),
125@@ -4856,6 +4912,8 @@ static int core_pre_config(apr_pool_t *p
126 apr_pool_cleanup_register(pconf, NULL, reset_config_defines,
127 apr_pool_cleanup_null);
128
129+ ap_regcomp_set_default_cflags(AP_REG_DOLLAR_ENDONLY);
130+
131 mpm_common_pre_config(pconf);
132
133 return OK;
134Index: apache2-2.4.29/server/util_pcre.c
135===================================================================
136--- apache2-2.4.29.orig/server/util_pcre.c 2014-01-05 11:14:26.000000000 -0500
137+++ apache2-2.4.29/server/util_pcre.c 2018-04-18 09:14:53.391220215 -0400
138@@ -111,6 +111,38 @@ AP_DECLARE(void) ap_regfree(ap_regex_t *
139 * Compile a regular expression *
140 *************************************************/
141
142+static int default_cflags = AP_REG_DOLLAR_ENDONLY;
143+
144+AP_DECLARE(int) ap_regcomp_get_default_cflags(void)
145+{
146+ return default_cflags;
147+}
148+
149+AP_DECLARE(void) ap_regcomp_set_default_cflags(int cflags)
150+{
151+ default_cflags = cflags;
152+}
153+
154+AP_DECLARE(int) ap_regcomp_default_cflag_by_name(const char *name)
155+{
156+ int cflag = 0;
157+
158+ if (ap_cstr_casecmp(name, "ICASE") == 0) {
159+ cflag = AP_REG_ICASE;
160+ }
161+ else if (ap_cstr_casecmp(name, "DOTALL") == 0) {
162+ cflag = AP_REG_DOTALL;
163+ }
164+ else if (ap_cstr_casecmp(name, "DOLLAR_ENDONLY") == 0) {
165+ cflag = AP_REG_DOLLAR_ENDONLY;
166+ }
167+ else if (ap_cstr_casecmp(name, "EXTENDED") == 0) {
168+ cflag = AP_REG_EXTENDED;
169+ }
170+
171+ return cflag;
172+}
173+
174 /*
175 * Arguments:
176 * preg points to a structure for recording the compiled expression
177@@ -127,12 +159,15 @@ AP_DECLARE(int) ap_regcomp(ap_regex_t *
178 int errcode = 0;
179 int options = PCRE_DUPNAMES;
180
181+ cflags |= default_cflags;
182 if ((cflags & AP_REG_ICASE) != 0)
183 options |= PCRE_CASELESS;
184 if ((cflags & AP_REG_NEWLINE) != 0)
185 options |= PCRE_MULTILINE;
186 if ((cflags & AP_REG_DOTALL) != 0)
187 options |= PCRE_DOTALL;
188+ if ((cflags & AP_REG_DOLLAR_ENDONLY) != 0)
189+ options |= PCRE_DOLLAR_ENDONLY;
190
191 preg->re_pcre =
192 pcre_compile2(pattern, options, &errcode, &errorptr, &erroffset, NULL);
diff --git a/debian/patches/CVE-2018-1283.patch b/debian/patches/CVE-2018-1283.patch
0new file mode 100644193new file mode 100644
index 0000000..b596b3c
--- /dev/null
+++ b/debian/patches/CVE-2018-1283.patch
@@ -0,0 +1,28 @@
1Description: fix mod_session header manipulation
2Origin: upstream, https://svn.apache.org/viewvc?view=revision&revision=1824477
3
4Index: apache2-2.4.29/modules/session/mod_session.c
5===================================================================
6--- apache2-2.4.29.orig/modules/session/mod_session.c 2016-11-14 06:15:08.000000000 -0500
7+++ apache2-2.4.29/modules/session/mod_session.c 2018-04-18 09:15:12.551256243 -0400
8@@ -510,12 +510,15 @@ static int session_fixups(request_rec *
9 */
10 ap_session_load(r, &z);
11
12- if (z && conf->env) {
13- session_identity_encode(r, z);
14- if (z->encoded) {
15- apr_table_set(r->subprocess_env, HTTP_SESSION, z->encoded);
16- z->encoded = NULL;
17+ if (conf->env) {
18+ if (z) {
19+ session_identity_encode(r, z);
20+ if (z->encoded) {
21+ apr_table_set(r->subprocess_env, HTTP_SESSION, z->encoded);
22+ z->encoded = NULL;
23+ }
24 }
25+ apr_table_unset(r->headers_in, "Session");
26 }
27
28 return OK;
diff --git a/debian/patches/CVE-2018-1301.patch b/debian/patches/CVE-2018-1301.patch
0new file mode 10064429new file mode 100644
index 0000000..c4fc07a
--- /dev/null
+++ b/debian/patches/CVE-2018-1301.patch
@@ -0,0 +1,200 @@
1Description: fix DoS via specially-crafted request
2Origin: upstream, https://svn.apache.org/viewvc?view=revision&revision=1824469
3
4Index: apache2-2.4.29/server/protocol.c
5===================================================================
6--- apache2-2.4.29.orig/server/protocol.c 2017-10-10 13:51:13.000000000 -0400
7+++ apache2-2.4.29/server/protocol.c 2018-04-18 09:15:27.027283380 -0400
8@@ -225,6 +225,11 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
9 int fold = flags & AP_GETLINE_FOLD;
10 int crlf = flags & AP_GETLINE_CRLF;
11
12+ if (!n) {
13+ /* Needs room for NUL byte at least */
14+ return APR_BADARG;
15+ }
16+
17 /*
18 * Initialize last_char as otherwise a random value will be compared
19 * against APR_ASCII_LF at the end of the loop if bb only contains
20@@ -238,14 +243,15 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
21 rv = ap_get_brigade(r->proto_input_filters, bb, AP_MODE_GETLINE,
22 APR_BLOCK_READ, 0);
23 if (rv != APR_SUCCESS) {
24- return rv;
25+ goto cleanup;
26 }
27
28 /* Something horribly wrong happened. Someone didn't block!
29 * (this also happens at the end of each keepalive connection)
30 */
31 if (APR_BRIGADE_EMPTY(bb)) {
32- return APR_EGENERAL;
33+ rv = APR_EGENERAL;
34+ goto cleanup;
35 }
36
37 for (e = APR_BRIGADE_FIRST(bb);
38@@ -263,7 +269,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
39
40 rv = apr_bucket_read(e, &str, &len, APR_BLOCK_READ);
41 if (rv != APR_SUCCESS) {
42- return rv;
43+ goto cleanup;
44 }
45
46 if (len == 0) {
47@@ -276,17 +282,8 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
48
49 /* Would this overrun our buffer? If so, we'll die. */
50 if (n < bytes_handled + len) {
51- *read = bytes_handled;
52- if (*s) {
53- /* ensure this string is NUL terminated */
54- if (bytes_handled > 0) {
55- (*s)[bytes_handled-1] = '\0';
56- }
57- else {
58- (*s)[0] = '\0';
59- }
60- }
61- return APR_ENOSPC;
62+ rv = APR_ENOSPC;
63+ goto cleanup;
64 }
65
66 /* Do we have to handle the allocation ourselves? */
67@@ -294,7 +291,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
68 /* We'll assume the common case where one bucket is enough. */
69 if (!*s) {
70 current_alloc = len;
71- *s = apr_palloc(r->pool, current_alloc);
72+ *s = apr_palloc(r->pool, current_alloc + 1);
73 }
74 else if (bytes_handled + len > current_alloc) {
75 /* Increase the buffer size */
76@@ -305,7 +302,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
77 new_size = (bytes_handled + len) * 2;
78 }
79
80- new_buffer = apr_palloc(r->pool, new_size);
81+ new_buffer = apr_palloc(r->pool, new_size + 1);
82
83 /* Copy what we already had. */
84 memcpy(new_buffer, *s, bytes_handled);
85@@ -329,19 +326,15 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
86 }
87 }
88
89- if (crlf && (last_char <= *s || last_char[-1] != APR_ASCII_CR)) {
90- *last_char = '\0';
91- bytes_handled = last_char - *s;
92- *read = bytes_handled;
93- return APR_EINVAL;
94- }
95-
96- /* Now NUL-terminate the string at the end of the line;
97+ /* Now terminate the string at the end of the line;
98 * if the last-but-one character is a CR, terminate there */
99 if (last_char > *s && last_char[-1] == APR_ASCII_CR) {
100 last_char--;
101 }
102- *last_char = '\0';
103+ else if (crlf) {
104+ rv = APR_EINVAL;
105+ goto cleanup;
106+ }
107 bytes_handled = last_char - *s;
108
109 /* If we're folding, we have more work to do.
110@@ -361,7 +354,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
111 rv = ap_get_brigade(r->proto_input_filters, bb, AP_MODE_SPECULATIVE,
112 APR_BLOCK_READ, 1);
113 if (rv != APR_SUCCESS) {
114- return rv;
115+ goto cleanup;
116 }
117
118 if (APR_BRIGADE_EMPTY(bb)) {
119@@ -378,7 +371,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
120 rv = apr_bucket_read(e, &str, &len, APR_BLOCK_READ);
121 if (rv != APR_SUCCESS) {
122 apr_brigade_cleanup(bb);
123- return rv;
124+ goto cleanup;
125 }
126
127 /* Found one, so call ourselves again to get the next line.
128@@ -395,10 +388,8 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
129 if (c == APR_ASCII_BLANK || c == APR_ASCII_TAB) {
130 /* Do we have enough space? We may be full now. */
131 if (bytes_handled >= n) {
132- *read = n;
133- /* ensure this string is terminated */
134- (*s)[n-1] = '\0';
135- return APR_ENOSPC;
136+ rv = APR_ENOSPC;
137+ goto cleanup;
138 }
139 else {
140 apr_size_t next_size, next_len;
141@@ -411,7 +402,6 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
142 tmp = NULL;
143 }
144 else {
145- /* We're null terminated. */
146 tmp = last_char;
147 }
148
149@@ -420,7 +410,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
150 rv = ap_rgetline_core(&tmp, next_size,
151 &next_len, r, 0, bb);
152 if (rv != APR_SUCCESS) {
153- return rv;
154+ goto cleanup;
155 }
156
157 if (do_alloc && next_len > 0) {
158@@ -434,7 +424,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
159 memcpy(new_buffer, *s, bytes_handled);
160
161 /* copy the new line, including the trailing null */
162- memcpy(new_buffer + bytes_handled, tmp, next_len + 1);
163+ memcpy(new_buffer + bytes_handled, tmp, next_len);
164 *s = new_buffer;
165 }
166
167@@ -447,8 +437,21 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
168 }
169 }
170 }
171+
172+cleanup:
173+ if (bytes_handled >= n) {
174+ bytes_handled = n - 1;
175+ }
176+ if (*s) {
177+ /* ensure the string is NUL terminated */
178+ (*s)[bytes_handled] = '\0';
179+ }
180 *read = bytes_handled;
181
182+ if (rv != APR_SUCCESS) {
183+ return rv;
184+ }
185+
186 /* PR#43039: We shouldn't accept NULL bytes within the line */
187 if (strlen(*s) < bytes_handled) {
188 return APR_EINVAL;
189@@ -487,6 +490,11 @@ AP_DECLARE(int) ap_getline(char *s, int
190 apr_size_t len;
191 apr_bucket_brigade *tmp_bb;
192
193+ if (n < 1) {
194+ /* Can't work since we always NUL terminate */
195+ return -1;
196+ }
197+
198 tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
199 rv = ap_rgetline(&tmp_s, n, &len, r, flags, tmp_bb);
200 apr_brigade_destroy(tmp_bb);
diff --git a/debian/patches/CVE-2018-1303.patch b/debian/patches/CVE-2018-1303.patch
0new file mode 100644201new file mode 100644
index 0000000..42192c8
--- /dev/null
+++ b/debian/patches/CVE-2018-1303.patch
@@ -0,0 +1,17 @@
1Description: fix mod_cache_socache DoS
2Origin: upstream, https://svn.apache.org/viewvc?view=revision&revision=1824475
3
4Index: apache2-2.4.29/modules/cache/mod_cache_socache.c
5===================================================================
6--- apache2-2.4.29.orig/modules/cache/mod_cache_socache.c 2017-06-29 07:31:20.000000000 -0400
7+++ apache2-2.4.29/modules/cache/mod_cache_socache.c 2018-04-18 09:15:39.675307037 -0400
8@@ -213,7 +213,8 @@ static apr_status_t read_table(cache_han
9 "Premature end of cache headers.");
10 return APR_EGENERAL;
11 }
12- while (apr_isspace(buffer[colon])) {
13+ /* Do not go past the \r from above as apr_isspace('\r') is true */
14+ while (apr_isspace(buffer[colon]) && (colon < *slider)) {
15 colon++;
16 }
17 apr_table_addn(table, apr_pstrndup(r->pool, (const char *) buffer
diff --git a/debian/patches/CVE-2018-1312.patch b/debian/patches/CVE-2018-1312.patch
0new file mode 10064418new file mode 100644
index 0000000..f91999a
--- /dev/null
+++ b/debian/patches/CVE-2018-1312.patch
@@ -0,0 +1,403 @@
1Description: fix insecure nonce generation
2Origin: upstream, https://svn.apache.org/viewvc?view=revision&revision=1824481
3Bug: https://bz.apache.org/bugzilla/show_bug.cgi?id=54637
4
5Index: apache2-2.4.29/modules/aaa/mod_auth_digest.c
6===================================================================
7--- apache2-2.4.29.orig/modules/aaa/mod_auth_digest.c 2017-07-05 20:02:54.000000000 -0400
8+++ apache2-2.4.29/modules/aaa/mod_auth_digest.c 2018-04-18 09:15:50.839327873 -0400
9@@ -26,20 +26,13 @@
10 * reports to the Apache bug-database, or send them directly to me
11 * at ronald@innovation.ch.
12 *
13- * Requires either /dev/random (or equivalent) or the truerand library,
14- * available for instance from
15- * ftp://research.att.com/dist/mab/librand.shar
16- *
17 * Open Issues:
18 * - qop=auth-int (when streams and trailer support available)
19 * - nonce-format configurability
20 * - Proxy-Authorization-Info header is set by this module, but is
21 * currently ignored by mod_proxy (needs patch to mod_proxy)
22- * - generating the secret takes a while (~ 8 seconds) if using the
23- * truerand library
24 * - The source of the secret should be run-time directive (with server
25- * scope: RSRC_CONF). However, that could be tricky when trying to
26- * choose truerand vs. file...
27+ * scope: RSRC_CONF)
28 * - shared-mem not completely tested yet. Seems to work ok for me,
29 * but... (definitely won't work on Windoze)
30 * - Sharing a realm among multiple servers has following problems:
31@@ -52,6 +45,8 @@
32 * captures a packet sent to one server and sends it to another
33 * one. Should we add "AuthDigestNcCheck Strict"?
34 * - expired nonces give amaya fits.
35+ * - MD5-sess and auth-int are not yet implemented. An incomplete
36+ * implementation has been removed and can be retrieved from svn history.
37 */
38
39 #include "apr_sha1.h"
40@@ -94,7 +89,6 @@ typedef struct digest_config_struct {
41 apr_array_header_t *qop_list;
42 apr_sha1_ctx_t nonce_ctx;
43 apr_time_t nonce_lifetime;
44- const char *nonce_format;
45 int check_nc;
46 const char *algorithm;
47 char *uri_list;
48@@ -112,7 +106,8 @@ typedef struct digest_config_struct {
49 #define NONCE_HASH_LEN (2*APR_SHA1_DIGESTSIZE)
50 #define NONCE_LEN (int )(NONCE_TIME_LEN + NONCE_HASH_LEN)
51
52-#define SECRET_LEN 20
53+#define SECRET_LEN 20
54+#define RETAINED_DATA_ID "mod_auth_digest"
55
56
57 /* client list definitions */
58@@ -121,7 +116,6 @@ typedef struct hash_entry {
59 unsigned long key; /* the key for this entry */
60 struct hash_entry *next; /* next entry in the bucket */
61 unsigned long nonce_count; /* for nonce-count checking */
62- char ha1[2*APR_MD5_DIGESTSIZE+1]; /* for algorithm=MD5-sess */
63 char last_nonce[NONCE_LEN+1]; /* for one-time nonce's */
64 } client_entry;
65
66@@ -170,7 +164,7 @@ typedef union time_union {
67 unsigned char arr[sizeof(apr_time_t)];
68 } time_rec;
69
70-static unsigned char secret[SECRET_LEN];
71+static unsigned char *secret;
72
73 /* client-list, opaque, and one-time-nonce stuff */
74
75@@ -228,35 +222,11 @@ static apr_status_t cleanup_tables(void
76 return APR_SUCCESS;
77 }
78
79-static apr_status_t initialize_secret(server_rec *s)
80-{
81- apr_status_t status;
82-
83- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01757)
84- "generating secret for digest authentication ...");
85-
86-#if APR_HAS_RANDOM
87- status = apr_generate_random_bytes(secret, sizeof(secret));
88-#else
89-#error APR random number support is missing; you probably need to install the truerand library.
90-#endif
91-
92- if (status != APR_SUCCESS) {
93- ap_log_error(APLOG_MARK, APLOG_CRIT, status, s, APLOGNO(01758)
94- "error generating secret");
95- return status;
96- }
97-
98- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01759) "done");
99-
100- return APR_SUCCESS;
101-}
102-
103 static void log_error_and_cleanup(char *msg, apr_status_t sts, server_rec *s)
104 {
105 ap_log_error(APLOG_MARK, APLOG_ERR, sts, s, APLOGNO(01760)
106- "%s - all nonce-count checking, one-time nonces, and "
107- "MD5-sess algorithm disabled", msg);
108+ "%s - all nonce-count checking and one-time nonces"
109+ "disabled", msg);
110
111 cleanup_tables(NULL);
112 }
113@@ -386,16 +356,32 @@ static int initialize_tables(server_rec
114 static int pre_init(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
115 {
116 apr_status_t rv;
117+ void *retained;
118
119 rv = ap_mutex_register(pconf, client_mutex_type, NULL, APR_LOCK_DEFAULT, 0);
120- if (rv == APR_SUCCESS) {
121- rv = ap_mutex_register(pconf, opaque_mutex_type, NULL, APR_LOCK_DEFAULT,
122- 0);
123- }
124- if (rv != APR_SUCCESS) {
125- return rv;
126- }
127+ if (rv != APR_SUCCESS)
128+ return !OK;
129+ rv = ap_mutex_register(pconf, opaque_mutex_type, NULL, APR_LOCK_DEFAULT, 0);
130+ if (rv != APR_SUCCESS)
131+ return !OK;
132
133+ retained = ap_retained_data_get(RETAINED_DATA_ID);
134+ if (retained == NULL) {
135+ retained = ap_retained_data_create(RETAINED_DATA_ID, SECRET_LEN);
136+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, APLOGNO(01757)
137+ "generating secret for digest authentication");
138+#if APR_HAS_RANDOM
139+ rv = apr_generate_random_bytes(retained, SECRET_LEN);
140+#else
141+#error APR random number support is missing
142+#endif
143+ if (rv != APR_SUCCESS) {
144+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, APLOGNO(01758)
145+ "error generating secret");
146+ return !OK;
147+ }
148+ }
149+ secret = retained;
150 return OK;
151 }
152
153@@ -408,10 +394,6 @@ static int initialize_module(apr_pool_t
154 if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG)
155 return OK;
156
157- if (initialize_secret(s) != APR_SUCCESS) {
158- return !OK;
159- }
160-
161 #if APR_HAS_SHARED_MEMORY
162 /* Note: this stuff is currently fixed for the lifetime of the server,
163 * i.e. even across restarts. This means that A) any shmem-size
164@@ -492,6 +474,16 @@ static void *create_digest_dir_config(ap
165 static const char *set_realm(cmd_parms *cmd, void *config, const char *realm)
166 {
167 digest_config_rec *conf = (digest_config_rec *) config;
168+#ifdef AP_DEBUG
169+ int i;
170+
171+ /* check that we got random numbers */
172+ for (i = 0; i < SECRET_LEN; i++) {
173+ if (secret[i] != 0)
174+ break;
175+ }
176+ ap_assert(i < SECRET_LEN);
177+#endif
178
179 /* The core already handles the realm, but it's just too convenient to
180 * grab it ourselves too and cache some setups. However, we need to
181@@ -505,7 +497,7 @@ static const char *set_realm(cmd_parms *
182 * and directives outside a virtual host section)
183 */
184 apr_sha1_init(&conf->nonce_ctx);
185- apr_sha1_update_binary(&conf->nonce_ctx, secret, sizeof(secret));
186+ apr_sha1_update_binary(&conf->nonce_ctx, secret, SECRET_LEN);
187 apr_sha1_update_binary(&conf->nonce_ctx, (const unsigned char *) realm,
188 strlen(realm));
189
190@@ -599,8 +591,7 @@ static const char *set_nonce_lifetime(cm
191 static const char *set_nonce_format(cmd_parms *cmd, void *config,
192 const char *fmt)
193 {
194- ((digest_config_rec *) config)->nonce_format = fmt;
195- return "AuthDigestNonceFormat is not implemented (yet)";
196+ return "AuthDigestNonceFormat is not implemented";
197 }
198
199 static const char *set_nc_check(cmd_parms *cmd, void *config, int flag)
200@@ -621,7 +612,7 @@ static const char *set_algorithm(cmd_par
201 {
202 if (!strcasecmp(alg, "MD5-sess")) {
203 return "AuthDigestAlgorithm: ERROR: algorithm `MD5-sess' "
204- "is not fully implemented";
205+ "is not implemented";
206 }
207 else if (strcasecmp(alg, "MD5")) {
208 return apr_pstrcat(cmd->pool, "Invalid algorithm in AuthDigestAlgorithm: ", alg, NULL);
209@@ -1147,7 +1138,7 @@ static const char *gen_nonce(apr_pool_t
210 static client_entry *gen_client(const request_rec *r)
211 {
212 unsigned long op;
213- client_entry new_entry = { 0, NULL, 0, "", "" }, *entry;
214+ client_entry new_entry = { 0, NULL, 0, "" }, *entry;
215
216 if (!opaque_cntr) {
217 return NULL;
218@@ -1168,92 +1159,6 @@ static client_entry *gen_client(const re
219
220
221 /*
222- * MD5-sess code.
223- *
224- * If you want to use algorithm=MD5-sess you must write get_userpw_hash()
225- * yourself (see below). The dummy provided here just uses the hash from
226- * the auth-file, i.e. it is only useful for testing client implementations
227- * of MD5-sess .
228- */
229-
230-/*
231- * get_userpw_hash() will be called each time a new session needs to be
232- * generated and is expected to return the equivalent of
233- *
234- * h_urp = ap_md5(r->pool,
235- * apr_pstrcat(r->pool, username, ":", ap_auth_name(r), ":", passwd))
236- * ap_md5(r->pool,
237- * (unsigned char *) apr_pstrcat(r->pool, h_urp, ":", resp->nonce, ":",
238- * resp->cnonce, NULL));
239- *
240- * or put differently, it must return
241- *
242- * MD5(MD5(username ":" realm ":" password) ":" nonce ":" cnonce)
243- *
244- * If something goes wrong, the failure must be logged and NULL returned.
245- *
246- * You must implement this yourself, which will probably consist of code
247- * contacting the password server with the necessary information (typically
248- * the username, realm, nonce, and cnonce) and receiving the hash from it.
249- *
250- * TBD: This function should probably be in a separate source file so that
251- * people need not modify mod_auth_digest.c each time they install a new
252- * version of apache.
253- */
254-static const char *get_userpw_hash(const request_rec *r,
255- const digest_header_rec *resp,
256- const digest_config_rec *conf)
257-{
258- return ap_md5(r->pool,
259- (unsigned char *) apr_pstrcat(r->pool, conf->ha1, ":", resp->nonce,
260- ":", resp->cnonce, NULL));
261-}
262-
263-
264-/* Retrieve current session H(A1). If there is none and "generate" is
265- * true then a new session for MD5-sess is generated and stored in the
266- * client struct; if generate is false, or a new session could not be
267- * generated then NULL is returned (in case of failure to generate the
268- * failure reason will have been logged already).
269- */
270-static const char *get_session_HA1(const request_rec *r,
271- digest_header_rec *resp,
272- const digest_config_rec *conf,
273- int generate)
274-{
275- const char *ha1 = NULL;
276-
277- /* return the current sessions if there is one */
278- if (resp->opaque && resp->client && resp->client->ha1[0]) {
279- return resp->client->ha1;
280- }
281- else if (!generate) {
282- return NULL;
283- }
284-
285- /* generate a new session */
286- if (!resp->client) {
287- resp->client = gen_client(r);
288- }
289- if (resp->client) {
290- ha1 = get_userpw_hash(r, resp, conf);
291- if (ha1) {
292- memcpy(resp->client->ha1, ha1, sizeof(resp->client->ha1));
293- }
294- }
295-
296- return ha1;
297-}
298-
299-
300-static void clear_session(const digest_header_rec *resp)
301-{
302- if (resp->client) {
303- resp->client->ha1[0] = '\0';
304- }
305-}
306-
307-/*
308 * Authorization challenge generation code (for WWW-Authenticate)
309 */
310
311@@ -1291,8 +1196,7 @@ static void note_digest_auth_failure(req
312
313 if (resp->opaque == NULL) {
314 /* new client */
315- if ((conf->check_nc || conf->nonce_lifetime == 0
316- || !strcasecmp(conf->algorithm, "MD5-sess"))
317+ if ((conf->check_nc || conf->nonce_lifetime == 0)
318 && (resp->client = gen_client(r)) != NULL) {
319 opaque = ltox(r->pool, resp->client->key);
320 }
321@@ -1332,15 +1236,6 @@ static void note_digest_auth_failure(req
322 memcpy(resp->client->last_nonce, nonce, NONCE_LEN+1);
323 }
324
325- /* Setup MD5-sess stuff. Note that we just clear out the session
326- * info here, since we can't generate a new session until the request
327- * from the client comes in with the cnonce.
328- */
329-
330- if (!strcasecmp(conf->algorithm, "MD5-sess")) {
331- clear_session(resp);
332- }
333-
334 /* setup domain attribute. We want to send this attribute wherever
335 * possible so that the client won't send the Authorization header
336 * unnecessarily (it's usually > 200 bytes!).
337@@ -1606,24 +1501,9 @@ static const char *new_digest(const requ
338 {
339 const char *ha1, *ha2, *a2;
340
341- if (resp->algorithm && !strcasecmp(resp->algorithm, "MD5-sess")) {
342- ha1 = get_session_HA1(r, resp, conf, 1);
343- if (!ha1) {
344- return NULL;
345- }
346- }
347- else {
348- ha1 = conf->ha1;
349- }
350+ ha1 = conf->ha1;
351
352- if (resp->message_qop && !strcasecmp(resp->message_qop, "auth-int")) {
353- a2 = apr_pstrcat(r->pool, resp->method, ":", resp->uri, ":",
354- ap_md5(r->pool, (const unsigned char*) ""), NULL);
355- /* TBD */
356- }
357- else {
358- a2 = apr_pstrcat(r->pool, resp->method, ":", resp->uri, NULL);
359- }
360+ a2 = apr_pstrcat(r->pool, resp->method, ":", resp->uri, NULL);
361 ha2 = ap_md5(r->pool, (const unsigned char *)a2);
362
363 return ap_md5(r->pool,
364@@ -1871,8 +1751,7 @@ static int authenticate_digest_user(requ
365 }
366
367 if (resp->algorithm != NULL
368- && strcasecmp(resp->algorithm, "MD5")
369- && strcasecmp(resp->algorithm, "MD5-sess")) {
370+ && strcasecmp(resp->algorithm, "MD5")) {
371 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01789)
372 "unknown algorithm `%s' received: %s",
373 resp->algorithm, r->uri);
374@@ -2024,27 +1903,9 @@ static int add_auth_info(request_rec *r)
375
376 /* calculate rspauth attribute
377 */
378- if (resp->algorithm && !strcasecmp(resp->algorithm, "MD5-sess")) {
379- ha1 = get_session_HA1(r, resp, conf, 0);
380- if (!ha1) {
381- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01795)
382- "internal error: couldn't find session "
383- "info for user %s", resp->username);
384- return !OK;
385- }
386- }
387- else {
388- ha1 = conf->ha1;
389- }
390+ ha1 = conf->ha1;
391
392- if (resp->message_qop && !strcasecmp(resp->message_qop, "auth-int")) {
393- a2 = apr_pstrcat(r->pool, ":", resp->uri, ":",
394- ap_md5(r->pool,(const unsigned char *) ""), NULL);
395- /* TBD */
396- }
397- else {
398- a2 = apr_pstrcat(r->pool, ":", resp->uri, NULL);
399- }
400+ a2 = apr_pstrcat(r->pool, ":", resp->uri, NULL);
401 ha2 = ap_md5(r->pool, (const unsigned char *)a2);
402
403 resp_dig = ap_md5(r->pool,
diff --git a/debian/patches/CVE-2018-17199.patch b/debian/patches/CVE-2018-17199.patch
0new file mode 100644404new file mode 100644
index 0000000..e42f56b
--- /dev/null
+++ b/debian/patches/CVE-2018-17199.patch
@@ -0,0 +1,85 @@
1From 34f58ae20d9a85f2a1508a9a732874239491d456 Mon Sep 17 00:00:00 2001
2From: Hank Ibell <hwibell@apache.org>
3Date: Tue, 15 Jan 2019 19:54:41 +0000
4Subject: [PATCH] mod_session: Always decode session attributes early.
5
6Backport r1850947 from trunk
7Submitted by: hwibell
8Reviewed by: hwibell, covener, wrowe
9
10
11git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1851409 13f79535-47bb-0310-9956-ffa450edef68
12---
13 CHANGES | 2 ++
14 STATUS | 5 -----
15 modules/session/mod_session.c | 25 ++++++++++++++-----------
16 3 files changed, 16 insertions(+), 16 deletions(-)
17
18#diff --git a/CHANGES b/CHANGES
19#index c4d9f6c2ea8..4b0a07fdcf5 100644
20#--- a/CHANGES
21#+++ b/CHANGES
22#@@ -9,6 +9,8 @@ Changes with Apache 2.4.38
23# and we should just set the value for the environment variable
24# like in the pattern case. [Ruediger Pluem]
25#
26#+ *) mod_session: Always decode session attributes early. [Hank Ibell]
27#+
28# *) core: Incorrect values for environment variables are substituted when
29# multiple environment variables are specified in a directive. [Hank Ibell]
30#
31#diff --git a/STATUS b/STATUS
32#index 00070f9f247..45a92ba4d81 100644
33#--- a/STATUS
34#+++ b/STATUS
35#@@ -125,11 +125,6 @@ RELEASE SHOWSTOPPERS:
36# PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
37# [ start all new proposals below, under PATCHES PROPOSED. ]
38#
39#- *) mod_session: Always decode session attributes early.
40#- trunk patch: http://svn.apache.org/r1850947
41#- 2.4.x patch: svn merge -c 1850947 ^/httpd/httpd/trunk .
42#- +1: hwibell, covener, wrowe
43#-
44# *) mod_ssl (ssl_engine_io.c: bio_filter_out_write, bio_filter_in_read)
45# Clear retry flags before aborting on client-initiated reneg. [Joe Orton]
46# PR: 63052
47diff --git a/modules/session/mod_session.c b/modules/session/mod_session.c
48index d517020d995..64e6e4a8132 100644
49--- a/modules/session/mod_session.c
50+++ b/modules/session/mod_session.c
51@@ -126,20 +126,23 @@ static apr_status_t ap_session_load(request_rec * r, session_rec ** z)
52
53 /* found a session that hasn't expired? */
54 now = apr_time_now();
55+
56 if (zz) {
57- if (zz->expiry && zz->expiry < now) {
58+ /* load the session attibutes */
59+ rv = ap_run_session_decode(r, zz);
60+
61+ /* having a session we cannot decode is just as good as having
62+ none at all */
63+ if (OK != rv) {
64+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01817)
65+ "error while decoding the session, "
66+ "session not loaded: %s", r->uri);
67 zz = NULL;
68 }
69- else {
70- /* having a session we cannot decode is just as good as having
71- none at all */
72- rv = ap_run_session_decode(r, zz);
73- if (OK != rv) {
74- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01817)
75- "error while decoding the session, "
76- "session not loaded: %s", r->uri);
77- zz = NULL;
78- }
79+
80+ /* invalidate session if session is expired */
81+ if (zz && zz->expiry && zz->expiry < now) {
82+ zz = NULL;
83 }
84 }
85
diff --git a/debian/patches/CVE-2019-0211.patch b/debian/patches/CVE-2019-0211.patch
0new file mode 10064486new file mode 100644
index 0000000..be70aac
--- /dev/null
+++ b/debian/patches/CVE-2019-0211.patch
@@ -0,0 +1,249 @@
1From df7edb5ddae609ea1fd4285f7439f0d590d97b37 Mon Sep 17 00:00:00 2001
2From: Yann Ylavic <ylavic@apache.org>
3Date: Wed, 13 Mar 2019 08:59:54 +0000
4Subject: [PATCH] Merge r1855306 from trunk:
5
6MPMs unix: bind the bucket number of each child to its slot number
7
8We need not remember each child's bucket number in SHM for restarts, for the
9lifetime of the httpd main process the bucket number can be bound to the slot
10number such that: bucket = slot % num_buckets.
11
12This both simplifies the logic and helps children maintenance per bucket in
13threaded MPMs, where previously perform_idle_server_maintenance() could create
14or kill children processes for the buckets it was not in charge of.
15
16Submitted by: ylavic
17Reviewed by: ylavic, rpluem, jorton
18
19
20git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1855378 13f79535-47bb-0310-9956-ffa450edef68
21---
22 CHANGES | 3 +++
23 include/scoreboard.h | 4 +++-
24 server/mpm/event/event.c | 13 ++++++++-----
25 server/mpm/prefork/prefork.c | 19 +++++++------------
26 server/mpm/worker/worker.c | 10 ++++++----
27 5 files changed, 27 insertions(+), 22 deletions(-)
28
29#diff --git a/CHANGES b/CHANGES
30#index e79251389d5..6b560802119 100644
31#--- a/CHANGES
32#+++ b/CHANGES
33#@@ -1,6 +1,9 @@
34# -*- coding: utf-8 -*-
35# Changes with Apache 2.4.39
36#
37#+ *) MPMs unix: bind the bucket number of each child to its slot number, for a
38#+ more efficient per bucket maintenance. [Yann Ylavic]
39#+
40# *) mod_auth_digest: Fix a race condition. Authentication with valid
41# credentials could be refused in case of concurrent accesses from
42# different users. PR 63124. [Simon Kappel <simon.kappel axis.com>]
43Index: apache2-2.4.29/include/scoreboard.h
44===================================================================
45--- apache2-2.4.29.orig/include/scoreboard.h 2019-04-03 09:22:04.140590533 -0400
46+++ apache2-2.4.29/include/scoreboard.h 2019-04-03 09:22:04.140590533 -0400
47@@ -143,7 +143,9 @@ struct process_score {
48 apr_uint32_t lingering_close; /* async connections in lingering close */
49 apr_uint32_t keep_alive; /* async connections in keep alive */
50 apr_uint32_t suspended; /* connections suspended by some module */
51- int bucket; /* Listener bucket used by this child */
52+ int bucket; /* Listener bucket used by this child; this field is DEPRECATED
53+ * and no longer updated by the MPMs (i.e. always zero).
54+ */
55 };
56
57 /* Scoreboard is now in 'local' memory, since it isn't updated once created,
58Index: apache2-2.4.29/server/mpm/event/event.c
59===================================================================
60--- apache2-2.4.29.orig/server/mpm/event/event.c 2019-04-03 09:22:04.140590533 -0400
61+++ apache2-2.4.29/server/mpm/event/event.c 2019-04-03 09:22:04.140590533 -0400
62@@ -2553,7 +2553,6 @@ static int make_child(server_rec * s, in
63
64 ap_scoreboard_image->parent[slot].quiescing = 0;
65 ap_scoreboard_image->parent[slot].not_accepting = 0;
66- ap_scoreboard_image->parent[slot].bucket = bucket;
67 event_note_child_started(slot, pid);
68 active_daemons++;
69 retained->total_daemons++;
70@@ -2592,6 +2591,7 @@ static void perform_idle_server_maintena
71 * that threads_per_child is always > 0 */
72 int status = SERVER_DEAD;
73 int child_threads_active = 0;
74+ int bucket = i % num_buckets;
75
76 if (i >= retained->max_daemons_limit &&
77 free_length == retained->idle_spawn_rate[child_bucket]) {
78@@ -2615,7 +2615,7 @@ static void perform_idle_server_maintena
79 */
80 if (status <= SERVER_READY && !ps->quiescing && !ps->not_accepting
81 && ps->generation == retained->mpm->my_generation
82- && ps->bucket == child_bucket)
83+ && bucket == child_bucket)
84 {
85 ++idle_thread_count;
86 }
87@@ -2626,7 +2626,9 @@ static void perform_idle_server_maintena
88 last_non_dead = i;
89 }
90 active_thread_count += child_threads_active;
91- if (!ps->pid && free_length < retained->idle_spawn_rate[child_bucket])
92+ if (!ps->pid
93+ && bucket == child_bucket
94+ && free_length < retained->idle_spawn_rate[child_bucket])
95 free_slots[free_length++] = i;
96 else if (child_threads_active == threads_per_child)
97 had_healthy_child = 1;
98@@ -2809,13 +2811,14 @@ static void server_main_loop(int remaini
99 retained->total_daemons--;
100 if (processed_status == APEXIT_CHILDSICK) {
101 /* resource shortage, minimize the fork rate */
102- retained->idle_spawn_rate[ps->bucket] = 1;
103+ retained->idle_spawn_rate[child_slot % num_buckets] = 1;
104 }
105 else if (remaining_children_to_start) {
106 /* we're still doing a 1-for-1 replacement of dead
107 * children with new children
108 */
109- make_child(ap_server_conf, child_slot, ps->bucket);
110+ make_child(ap_server_conf, child_slot,
111+ child_slot % num_buckets);
112 --remaining_children_to_start;
113 }
114 }
115Index: apache2-2.4.29/server/mpm/prefork/prefork.c
116===================================================================
117--- apache2-2.4.29.orig/server/mpm/prefork/prefork.c 2019-04-03 09:22:04.140590533 -0400
118+++ apache2-2.4.29/server/mpm/prefork/prefork.c 2019-04-03 09:22:04.140590533 -0400
119@@ -637,8 +637,9 @@ static void child_main(int child_num_arg
120 }
121
122
123-static int make_child(server_rec *s, int slot, int bucket)
124+static int make_child(server_rec *s, int slot)
125 {
126+ int bucket = slot % retained->mpm->num_buckets;
127 int pid;
128
129 if (slot + 1 > retained->max_daemons_limit) {
130@@ -716,7 +717,6 @@ static int make_child(server_rec *s, int
131 child_main(slot, bucket);
132 }
133
134- ap_scoreboard_image->parent[slot].bucket = bucket;
135 prefork_note_child_started(slot, pid);
136
137 return 0;
138@@ -732,7 +732,7 @@ static void startup_children(int number_
139 if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) {
140 continue;
141 }
142- if (make_child(ap_server_conf, i, i % retained->mpm->num_buckets) < 0) {
143+ if (make_child(ap_server_conf, i) < 0) {
144 break;
145 }
146 --number_to_start;
147@@ -741,8 +741,6 @@ static void startup_children(int number_
148
149 static void perform_idle_server_maintenance(apr_pool_t *p)
150 {
151- static int bucket_make_child_record = -1;
152- static int bucket_kill_child_record = -1;
153 int i;
154 int idle_count;
155 worker_score *ws;
156@@ -789,6 +787,7 @@ static void perform_idle_server_maintena
157 }
158 retained->max_daemons_limit = last_non_dead + 1;
159 if (idle_count > ap_daemons_max_free) {
160+ static int bucket_kill_child_record = -1;
161 /* kill off one child... we use the pod because that'll cause it to
162 * shut down gracefully, in case it happened to pick up a request
163 * while we were counting
164@@ -819,10 +818,7 @@ static void perform_idle_server_maintena
165 idle_count, total_non_dead);
166 }
167 for (i = 0; i < free_length; ++i) {
168- bucket_make_child_record++;
169- bucket_make_child_record %= retained->mpm->num_buckets;
170- make_child(ap_server_conf, free_slots[i],
171- bucket_make_child_record);
172+ make_child(ap_server_conf, free_slots[i]);
173 }
174 /* the next time around we want to spawn twice as many if this
175 * wasn't good enough, but not if we've just done a graceful
176@@ -867,7 +863,7 @@ static int prefork_run(apr_pool_t *_pcon
177
178 if (one_process) {
179 AP_MONCONTROL(1);
180- make_child(ap_server_conf, 0, 0);
181+ make_child(ap_server_conf, 0);
182 /* NOTREACHED */
183 ap_assert(0);
184 return !OK;
185@@ -976,8 +972,7 @@ static int prefork_run(apr_pool_t *_pcon
186 /* we're still doing a 1-for-1 replacement of dead
187 * children with new children
188 */
189- make_child(ap_server_conf, child_slot,
190- ap_get_scoreboard_process(child_slot)->bucket);
191+ make_child(ap_server_conf, child_slot);
192 --remaining_children_to_start;
193 }
194 #if APR_HAS_OTHER_CHILD
195Index: apache2-2.4.29/server/mpm/worker/worker.c
196===================================================================
197--- apache2-2.4.29.orig/server/mpm/worker/worker.c 2019-04-03 09:22:04.140590533 -0400
198+++ apache2-2.4.29/server/mpm/worker/worker.c 2019-04-03 09:22:04.140590533 -0400
199@@ -1312,7 +1312,6 @@ static int make_child(server_rec *s, int
200 worker_note_child_lost_slot(slot, pid);
201 }
202 ap_scoreboard_image->parent[slot].quiescing = 0;
203- ap_scoreboard_image->parent[slot].bucket = bucket;
204 worker_note_child_started(slot, pid);
205 return 0;
206 }
207@@ -1361,6 +1360,7 @@ static void perform_idle_server_maintena
208 int any_dead_threads = 0;
209 int all_dead_threads = 1;
210 int child_threads_active = 0;
211+ int bucket = i % num_buckets;
212
213 if (i >= retained->max_daemons_limit &&
214 totally_free_length == retained->idle_spawn_rate[child_bucket]) {
215@@ -1393,7 +1393,7 @@ static void perform_idle_server_maintena
216 if (status <= SERVER_READY &&
217 !ps->quiescing &&
218 ps->generation == retained->mpm->my_generation &&
219- ps->bucket == child_bucket) {
220+ bucket == child_bucket) {
221 ++idle_thread_count;
222 }
223 if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
224@@ -1403,6 +1403,7 @@ static void perform_idle_server_maintena
225 }
226 active_thread_count += child_threads_active;
227 if (any_dead_threads
228+ && bucket == child_bucket
229 && totally_free_length < retained->idle_spawn_rate[child_bucket]
230 && free_length < MAX_SPAWN_RATE / num_buckets
231 && (!ps->pid /* no process in the slot */
232@@ -1588,14 +1589,15 @@ static void server_main_loop(int remaini
233 ps->quiescing = 0;
234 if (processed_status == APEXIT_CHILDSICK) {
235 /* resource shortage, minimize the fork rate */
236- retained->idle_spawn_rate[ps->bucket] = 1;
237+ retained->idle_spawn_rate[child_slot % num_buckets] = 1;
238 }
239 else if (remaining_children_to_start
240 && child_slot < ap_daemons_limit) {
241 /* we're still doing a 1-for-1 replacement of dead
242 * children with new children
243 */
244- make_child(ap_server_conf, child_slot, ps->bucket);
245+ make_child(ap_server_conf, child_slot,
246+ child_slot % num_buckets);
247 --remaining_children_to_start;
248 }
249 }
diff --git a/debian/patches/CVE-2019-0217.patch b/debian/patches/CVE-2019-0217.patch
0new file mode 100644250new file mode 100644
index 0000000..e8f1090
--- /dev/null
+++ b/debian/patches/CVE-2019-0217.patch
@@ -0,0 +1,147 @@
1From 44b3ddc560c490c60600998fa2bf59b142d08e05 Mon Sep 17 00:00:00 2001
2From: Joe Orton <jorton@apache.org>
3Date: Tue, 12 Mar 2019 09:24:26 +0000
4Subject: [PATCH] Merge r1853190 from trunk:
5
6Fix a race condition. Authentication with valid credentials could be
7refused in case of concurrent accesses from different users.
8
9PR: 63124
10Submitted by: Simon Kappel <simon.kappel axis.com>
11Reviewed by: jailletc36, icing, jorton
12
13
14git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1855298 13f79535-47bb-0310-9956-ffa450edef68
15---
16 CHANGES | 4 ++++
17 modules/aaa/mod_auth_digest.c | 26 ++++++++++++--------------
18 2 files changed, 16 insertions(+), 14 deletions(-)
19
20#diff --git a/CHANGES b/CHANGES
21#index 08fc740db30..e79251389d5 100644
22#--- a/CHANGES
23#+++ b/CHANGES
24#@@ -1,6 +1,10 @@
25# -*- coding: utf-8 -*-
26# Changes with Apache 2.4.39
27#
28#+ *) mod_auth_digest: Fix a race condition. Authentication with valid
29#+ credentials could be refused in case of concurrent accesses from
30#+ different users. PR 63124. [Simon Kappel <simon.kappel axis.com>]
31#+
32# *) mod_proxy_wstunnel: Fix websocket proxy over UDS.
33# PR 62932 <pavel dcmsys.com>
34#
35diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c
36index a67f06986f2..b76094114dd 100644
37--- a/modules/aaa/mod_auth_digest.c
38+++ b/modules/aaa/mod_auth_digest.c
39@@ -92,7 +92,6 @@ typedef struct digest_config_struct {
40 int check_nc;
41 const char *algorithm;
42 char *uri_list;
43- const char *ha1;
44 } digest_config_rec;
45
46
47@@ -153,6 +152,7 @@ typedef struct digest_header_struct {
48 apr_time_t nonce_time;
49 enum hdr_sts auth_hdr_sts;
50 int needed_auth;
51+ const char *ha1;
52 client_entry *client;
53 } digest_header_rec;
54
55@@ -1304,7 +1304,7 @@ static int hook_note_digest_auth_failure(request_rec *r, const char *auth_type)
56 */
57
58 static authn_status get_hash(request_rec *r, const char *user,
59- digest_config_rec *conf)
60+ digest_config_rec *conf, const char **rethash)
61 {
62 authn_status auth_result;
63 char *password;
64@@ -1356,7 +1356,7 @@ static authn_status get_hash(request_rec *r, const char *user,
65 } while (current_provider);
66
67 if (auth_result == AUTH_USER_FOUND) {
68- conf->ha1 = password;
69+ *rethash = password;
70 }
71
72 return auth_result;
73@@ -1483,25 +1483,24 @@ static int check_nonce(request_rec *r, digest_header_rec *resp,
74
75 /* RFC-2069 */
76 static const char *old_digest(const request_rec *r,
77- const digest_header_rec *resp, const char *ha1)
78+ const digest_header_rec *resp)
79 {
80 const char *ha2;
81
82 ha2 = ap_md5(r->pool, (unsigned char *)apr_pstrcat(r->pool, resp->method, ":",
83 resp->uri, NULL));
84 return ap_md5(r->pool,
85- (unsigned char *)apr_pstrcat(r->pool, ha1, ":", resp->nonce,
86- ":", ha2, NULL));
87+ (unsigned char *)apr_pstrcat(r->pool, resp->ha1, ":",
88+ resp->nonce, ":", ha2, NULL));
89 }
90
91 /* RFC-2617 */
92 static const char *new_digest(const request_rec *r,
93- digest_header_rec *resp,
94- const digest_config_rec *conf)
95+ digest_header_rec *resp)
96 {
97 const char *ha1, *ha2, *a2;
98
99- ha1 = conf->ha1;
100+ ha1 = resp->ha1;
101
102 a2 = apr_pstrcat(r->pool, resp->method, ":", resp->uri, NULL);
103 ha2 = ap_md5(r->pool, (const unsigned char *)a2);
104@@ -1514,7 +1513,6 @@ static const char *new_digest(const request_rec *r,
105 NULL));
106 }
107
108-
109 static void copy_uri_components(apr_uri_t *dst,
110 apr_uri_t *src, request_rec *r) {
111 if (src->scheme && src->scheme[0] != '\0') {
112@@ -1759,7 +1757,7 @@ static int authenticate_digest_user(request_rec *r)
113 return HTTP_UNAUTHORIZED;
114 }
115
116- return_code = get_hash(r, r->user, conf);
117+ return_code = get_hash(r, r->user, conf, &resp->ha1);
118
119 if (return_code == AUTH_USER_NOT_FOUND) {
120 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01790)
121@@ -1789,7 +1787,7 @@ static int authenticate_digest_user(request_rec *r)
122
123 if (resp->message_qop == NULL) {
124 /* old (rfc-2069) style digest */
125- if (strcmp(resp->digest, old_digest(r, resp, conf->ha1))) {
126+ if (strcmp(resp->digest, old_digest(r, resp))) {
127 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01792)
128 "user %s: password mismatch: %s", r->user,
129 r->uri);
130@@ -1819,7 +1817,7 @@ static int authenticate_digest_user(request_rec *r)
131 return HTTP_UNAUTHORIZED;
132 }
133
134- exp_digest = new_digest(r, resp, conf);
135+ exp_digest = new_digest(r, resp);
136 if (!exp_digest) {
137 /* we failed to allocate a client struct */
138 return HTTP_INTERNAL_SERVER_ERROR;
139@@ -1903,7 +1901,7 @@ static int add_auth_info(request_rec *r)
140
141 /* calculate rspauth attribute
142 */
143- ha1 = conf->ha1;
144+ ha1 = resp->ha1;
145
146 a2 = apr_pstrcat(r->pool, ":", resp->uri, NULL);
147 ha2 = ap_md5(r->pool, (const unsigned char *)a2);
diff --git a/debian/patches/CVE-2019-0220-1.patch b/debian/patches/CVE-2019-0220-1.patch
0new file mode 100644148new file mode 100644
index 0000000..86cc667
--- /dev/null
+++ b/debian/patches/CVE-2019-0220-1.patch
@@ -0,0 +1,259 @@
1Backport of:
2
3From 9bc1917a27a2323e535aadb081e38172ae0e3fc2 Mon Sep 17 00:00:00 2001
4From: Stefan Eissing <icing@apache.org>
5Date: Mon, 18 Mar 2019 08:49:59 +0000
6Subject: [PATCH] Merge of r1855705 from trunk:
7
8core: merge consecutive slashes in the path
9
10
11
12git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1855737 13f79535-47bb-0310-9956-ffa450edef68
13---
14 CHANGES | 4 ++++
15 docs/manual/mod/core.xml | 26 ++++++++++++++++++++++++++
16 include/ap_mmn.h | 4 +++-
17 include/http_core.h | 2 +-
18 include/httpd.h | 14 ++++++++++++--
19 server/core.c | 13 +++++++++++++
20 server/request.c | 25 +++++++++----------------
21 server/util.c | 10 +++++++---
22 8 files changed, 75 insertions(+), 23 deletions(-)
23
24#diff --git a/CHANGES b/CHANGES
25#index e3e8a98db24..9dd7045c232 100644
26#--- a/CHANGES
27#+++ b/CHANGES
28#@@ -1,6 +1,10 @@
29# -*- coding: utf-8 -*-
30# Changes with Apache 2.4.39
31#
32#+ *) core: new configuration option 'MergeSlashes on|off' that controls handling of
33#+ multiple, consecutive slash ('/') characters in the path component of the request URL.
34#+ [Eric Covener]
35#+
36# *) mod_http2: when SSL renegotiation is inhibited and a 403 ErrorDocument is
37# in play, the proper HTTP/2 stream reset did not trigger with H2_ERR_HTTP_1_1_REQUIRED.
38# Fixed. [Michael Kaufmann]
39#diff --git a/docs/manual/mod/core.xml b/docs/manual/mod/core.xml
40#index fc664116727..460b4367621 100644
41#--- a/docs/manual/mod/core.xml
42#+++ b/docs/manual/mod/core.xml
43#@@ -5138,4 +5138,30 @@ recognized methods to modules.</p>
44# <seealso><directive module="mod_allowmethods">AllowMethods</directive></seealso>
45# </directivesynopsis>
46#
47#+<directivesynopsis>
48#+<name>MergeSlashes</name>
49#+<description>Controls whether the server merges consecutive slashes in URLs.
50#+</description>
51#+<syntax>MergeSlashes ON|OFF</syntax>
52#+<default>MergeSlashes ON</default>
53#+<contextlist><context>server config</context><context>virtual host</context>
54#+</contextlist>
55#+<compatibility>Added in 2.5.1</compatibility>
56#+
57#+<usage>
58#+ <p>By default, the server merges (or collapses) multiple consecutive slash
59#+ ('/') characters in the path component of the request URL.</p>
60#+
61#+ <p>When mapping URL's to the filesystem, these multiple slashes are not
62#+ significant. However, URL's handled other ways, such as by CGI or proxy,
63#+ might prefer to retain the significance of multiple consecutive slashes.
64#+ In these cases <directive>MergeSlashes</directive> can be set to
65#+ <em>OFF</em> to retain the multiple consecutive slashes. In these
66#+ configurations, regular expressions used in the configuration file that match
67#+ the path component of the URL (<directive>LocationMatch</directive>,
68#+ <directive>RewriteRule</directive>, ...) need to take into account multiple
69#+ consecutive slashes.</p>
70#+</usage>
71#+</directivesynopsis>
72#+
73# </modulesynopsis>
74Index: apache2-2.4.29/include/http_core.h
75===================================================================
76--- apache2-2.4.29.orig/include/http_core.h 2019-04-03 09:22:24.452651658 -0400
77+++ apache2-2.4.29/include/http_core.h 2019-04-03 09:22:24.448651645 -0400
78@@ -740,7 +740,7 @@ typedef struct {
79 #define AP_HTTP_METHODS_LENIENT 1
80 #define AP_HTTP_METHODS_REGISTERED 2
81 char http_methods;
82-
83+ unsigned int merge_slashes;
84 } core_server_config;
85
86 /* for AddOutputFiltersByType in core.c */
87Index: apache2-2.4.29/include/httpd.h
88===================================================================
89--- apache2-2.4.29.orig/include/httpd.h 2019-04-03 09:22:24.452651658 -0400
90+++ apache2-2.4.29/include/httpd.h 2019-04-03 09:22:24.448651645 -0400
91@@ -1691,12 +1691,22 @@ AP_DECLARE(int) ap_unescape_url_keep2f(c
92 AP_DECLARE(int) ap_unescape_urlencoded(char *query);
93
94 /**
95- * Convert all double slashes to single slashes
96- * @param name The string to convert
97+ * Convert all double slashes to single slashes, except where significant
98+ * to the filesystem on the current platform.
99+ * @param name The string to convert, assumed to be a filesystem path
100 */
101 AP_DECLARE(void) ap_no2slash(char *name);
102
103 /**
104+ * Convert all double slashes to single slashes, except where significant
105+ * to the filesystem on the current platform.
106+ * @param name The string to convert
107+ * @param is_fs_path if set to 0, the significance of any double-slashes is
108+ * ignored.
109+ */
110+AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path);
111+
112+/**
113 * Remove all ./ and xx/../ substrings from a file name. Also remove
114 * any leading ../ or /../ substrings.
115 * @param name the file name to parse
116Index: apache2-2.4.29/server/core.c
117===================================================================
118--- apache2-2.4.29.orig/server/core.c 2019-04-03 09:22:24.452651658 -0400
119+++ apache2-2.4.29/server/core.c 2019-04-03 09:22:24.448651645 -0400
120@@ -490,6 +490,7 @@ static void *create_core_server_config(a
121
122 conf->protocols = apr_array_make(a, 5, sizeof(const char *));
123 conf->protocols_honor_order = -1;
124+ conf->merge_slashes = AP_CORE_CONFIG_UNSET;
125
126 return (void *)conf;
127 }
128@@ -555,6 +556,7 @@ static void *merge_core_server_configs(a
129 conf->protocols_honor_order = ((virt->protocols_honor_order < 0)?
130 base->protocols_honor_order :
131 virt->protocols_honor_order);
132+ AP_CORE_MERGE_FLAG(merge_slashes, conf, base, virt);
133
134 return conf;
135 }
136@@ -1862,6 +1864,13 @@ static const char *set_qualify_redirect_
137 return NULL;
138 }
139
140+static const char *set_core_server_flag(cmd_parms *cmd, void *s_, int flag)
141+{
142+ core_server_config *conf =
143+ ap_get_core_module_config(cmd->server->module_config);
144+ return ap_set_flag_slot(cmd, conf, flag);
145+}
146+
147 static const char *set_override_list(cmd_parms *cmd, void *d_, int argc, char *const argv[])
148 {
149 core_dir_config *d = d_;
150@@ -4551,6 +4560,10 @@ AP_INIT_ITERATE("HttpProtocolOptions", s
151 "'Unsafe' or 'Strict' (default). Sets HTTP acceptance rules"),
152 AP_INIT_ITERATE("RegisterHttpMethod", set_http_method, NULL, RSRC_CONF,
153 "Registers non-standard HTTP methods"),
154+AP_INIT_FLAG("MergeSlashes", set_core_server_flag,
155+ (void *)APR_OFFSETOF(core_server_config, merge_slashes),
156+ RSRC_CONF,
157+ "Controls whether consecutive slashes in the URI path are merged"),
158 { NULL }
159 };
160
161Index: apache2-2.4.29/server/request.c
162===================================================================
163--- apache2-2.4.29.orig/server/request.c 2019-04-03 09:22:24.452651658 -0400
164+++ apache2-2.4.29/server/request.c 2019-04-03 09:22:24.448651645 -0400
165@@ -167,6 +167,8 @@ AP_DECLARE(int) ap_process_request_inter
166 int file_req = (r->main && r->filename);
167 int access_status;
168 core_dir_config *d;
169+ core_server_config *sconf =
170+ ap_get_core_module_config(r->server->module_config);
171
172 /* Ignore embedded %2F's in path for proxy requests */
173 if (!r->proxyreq && r->parsed_uri.path) {
174@@ -191,6 +193,10 @@ AP_DECLARE(int) ap_process_request_inter
175 }
176
177 ap_getparents(r->uri); /* OK --- shrinking transformations... */
178+ if (sconf->merge_slashes != AP_CORE_CONFIG_OFF) {
179+ ap_no2slash(r->uri);
180+ ap_no2slash(r->parsed_uri.path);
181+ }
182
183 /* All file subrequests are a huge pain... they cannot bubble through the
184 * next several steps. Only file subrequests are allowed an empty uri,
185@@ -1411,20 +1417,7 @@ AP_DECLARE(int) ap_location_walk(request
186
187 cache = prep_walk_cache(AP_NOTE_LOCATION_WALK, r);
188 cached = (cache->cached != NULL);
189-
190- /* Location and LocationMatch differ on their behaviour w.r.t. multiple
191- * slashes. Location matches multiple slashes with a single slash,
192- * LocationMatch doesn't. An exception, for backwards brokenness is
193- * absoluteURIs... in which case neither match multiple slashes.
194- */
195- if (r->uri[0] != '/') {
196- entry_uri = r->uri;
197- }
198- else {
199- char *uri = apr_pstrdup(r->pool, r->uri);
200- ap_no2slash(uri);
201- entry_uri = uri;
202- }
203+ entry_uri = r->uri;
204
205 /* If we have an cache->cached location that matches r->uri,
206 * and the vhost's list of locations hasn't changed, we can skip
207@@ -1491,7 +1484,7 @@ AP_DECLARE(int) ap_location_walk(request
208 pmatch = apr_palloc(rxpool, nmatch*sizeof(ap_regmatch_t));
209 }
210
211- if (ap_regexec(entry_core->r, r->uri, nmatch, pmatch, 0)) {
212+ if (ap_regexec(entry_core->r, entry_uri, nmatch, pmatch, 0)) {
213 continue;
214 }
215
216@@ -1501,7 +1494,7 @@ AP_DECLARE(int) ap_location_walk(request
217 apr_table_setn(r->subprocess_env,
218 ((const char **)entry_core->refs->elts)[i],
219 apr_pstrndup(r->pool,
220- r->uri + pmatch[i].rm_so,
221+ entry_uri + pmatch[i].rm_so,
222 pmatch[i].rm_eo - pmatch[i].rm_so));
223 }
224 }
225Index: apache2-2.4.29/server/util.c
226===================================================================
227--- apache2-2.4.29.orig/server/util.c 2019-04-03 09:22:24.452651658 -0400
228+++ apache2-2.4.29/server/util.c 2019-04-03 09:22:24.448651645 -0400
229@@ -561,16 +561,16 @@ AP_DECLARE(void) ap_getparents(char *nam
230 name[l] = '\0';
231 }
232 }
233-
234-AP_DECLARE(void) ap_no2slash(char *name)
235+AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path)
236 {
237+
238 char *d, *s;
239
240 s = d = name;
241
242 #ifdef HAVE_UNC_PATHS
243 /* Check for UNC names. Leave leading two slashes. */
244- if (s[0] == '/' && s[1] == '/')
245+ if (is_fs_path && s[0] == '/' && s[1] == '/')
246 *d++ = *s++;
247 #endif
248
249@@ -587,6 +587,10 @@ AP_DECLARE(void) ap_no2slash(char *name)
250 *d = '\0';
251 }
252
253+AP_DECLARE(void) ap_no2slash(char *name)
254+{
255+ ap_no2slash_ex(name, 1);
256+}
257
258 /*
259 * copy at most n leading directories of s into d
diff --git a/debian/patches/CVE-2019-0220-2.patch b/debian/patches/CVE-2019-0220-2.patch
0new file mode 100644260new file mode 100644
index 0000000..0204259
--- /dev/null
+++ b/debian/patches/CVE-2019-0220-2.patch
@@ -0,0 +1,50 @@
1From c4ef468b25718a26f2b92cbea3ca093729b79331 Mon Sep 17 00:00:00 2001
2From: Eric Covener <covener@apache.org>
3Date: Mon, 18 Mar 2019 12:10:15 +0000
4Subject: [PATCH] merge 1855743,1855744 ^/httpd/httpd/trunk .
5
6r->parsed_uri.path safety in recent backport
7
8*) core: fix SEGFAULT in CONNECT with recent change
9 2.4.x: svn merge -c 1855743,1855744 ^/httpd/httpd/trunk .
10 +1: rpluem, icing, covener
11
12
13
14
15git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1855751 13f79535-47bb-0310-9956-ffa450edef68
16---
17 server/request.c | 4 +++-
18 server/util.c | 4 ++++
19 2 files changed, 7 insertions(+), 1 deletion(-)
20
21diff --git a/server/request.c b/server/request.c
22index 1ce8908824b..d5c558afa30 100644
23--- a/server/request.c
24+++ b/server/request.c
25@@ -195,7 +195,9 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
26 ap_getparents(r->uri); /* OK --- shrinking transformations... */
27 if (sconf->merge_slashes != AP_CORE_CONFIG_OFF) {
28 ap_no2slash(r->uri);
29- ap_no2slash(r->parsed_uri.path);
30+ if (r->parsed_uri.path) {
31+ ap_no2slash(r->parsed_uri.path);
32+ }
33 }
34
35 /* All file subrequests are a huge pain... they cannot bubble through the
36diff --git a/server/util.c b/server/util.c
37index 607c4850d86..f3b17f1581e 100644
38--- a/server/util.c
39+++ b/server/util.c
40@@ -566,6 +566,10 @@ AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path)
41
42 char *d, *s;
43
44+ if (!name || !*name) {
45+ return;
46+ }
47+
48 s = d = name;
49
50 #ifdef HAVE_UNC_PATHS
diff --git a/debian/patches/CVE-2019-0220-3.patch b/debian/patches/CVE-2019-0220-3.patch
0new file mode 10064451new file mode 100644
index 0000000..7b3ff6f
--- /dev/null
+++ b/debian/patches/CVE-2019-0220-3.patch
@@ -0,0 +1,43 @@
1From 3451fc2bf8708b0dc8cd6a7d0ac0fe5b6401befc Mon Sep 17 00:00:00 2001
2From: Eric Covener <covener@apache.org>
3Date: Tue, 19 Mar 2019 18:01:21 +0000
4Subject: [PATCH] *) maintainer mode fix for util.c no2slash_ex trunk
5 patch: http://svn.apache.org/r1855755 2.4.x patch svn merge -c 1855755
6 ^/httpd/httpd/trunk . +1: covener, rpluem, jim, ylavic
7
8git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1855853 13f79535-47bb-0310-9956-ffa450edef68
9---
10 STATUS | 6 ------
11 server/util.c | 2 +-
12 2 files changed, 1 insertion(+), 7 deletions(-)
13
14#diff --git a/STATUS b/STATUS
15#index ffe5d22550c..1f8cb2f7884 100644
16#--- a/STATUS
17#+++ b/STATUS
18#@@ -126,12 +126,6 @@ RELEASE SHOWSTOPPERS:
19# PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
20# [ start all new proposals below, under PATCHES PROPOSED. ]
21#
22#- *) maintainer mode fix for util.c no2slash_ex
23#- trunk patch: http://svn.apache.org/r1855755
24#- 2.4.x patch svn merge -c 1855755 ^/httpd/httpd/trunk .
25#- +1: covener, rpluem, jim, ylavic
26#-
27#-
28# PATCHES PROPOSED TO BACKPORT FROM TRUNK:
29# [ New proposals should be added at the end of the list ]
30#
31diff --git a/server/util.c b/server/util.c
32index f3b17f1581e..e0c558cee2d 100644
33--- a/server/util.c
34+++ b/server/util.c
35@@ -566,7 +566,7 @@ AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path)
36
37 char *d, *s;
38
39- if (!name || !*name) {
40+ if (!*name) {
41 return;
42 }
43
diff --git a/debian/patches/CVE-2019-10092-1.patch b/debian/patches/CVE-2019-10092-1.patch
0new file mode 10064444new file mode 100644
index 0000000..102b18e
--- /dev/null
+++ b/debian/patches/CVE-2019-10092-1.patch
@@ -0,0 +1,245 @@
1From b5aa97e7c9792ba31055507eaf9a54e1fbb17464 Mon Sep 17 00:00:00 2001
2From: Stefan Eissing <icing@apache.org>
3Date: Fri, 2 Aug 2019 09:10:06 +0000
4Subject: [PATCH] Merge of r1864191 from trunk:
5
6 *) core, proxy: remove request URL and headers from error docs
7 [Eric Covener]
8
9
10
11
12git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1864207 13f79535-47bb-0310-9956-ffa450edef68
13---
14 CHANGES | 2 +
15 STATUS | 5 --
16 modules/http/http_protocol.c | 86 +++++++++++------------------------
17 modules/proxy/mod_proxy.c | 7 +--
18 modules/proxy/mod_proxy_ftp.c | 5 +-
19 modules/proxy/proxy_util.c | 5 +-
20 6 files changed, 36 insertions(+), 74 deletions(-)
21
22# diff --git a/CHANGES b/CHANGES
23# index 01f232c613..bf00b5114b 100644
24# --- a/CHANGES
25# +++ b/CHANGES
26# @@ -1,6 +1,8 @@
27# -*- coding: utf-8 -*-
28# Changes with Apache 2.4.40
29#
30# + *) core: Remove request details from built-in error documents [Eric Covener]
31# +
32# *) mod_http2: core setting "LimitRequestFieldSize" is not additionally checked on
33# merged header fields, just as HTTP/1.1 does. [Stefan Eissing, Michael Kaufmann]
34#
35# diff --git a/STATUS b/STATUS
36# index a6f3548511..1ce0436916 100644
37# --- a/STATUS
38# +++ b/STATUS
39# @@ -150,11 +150,6 @@ PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
40# 2.4.x patch: svn merge -c 1863635 ^/httpd/httpd/trunk .
41# +1: jim, icing, rpluem
42#
43# - *) core, proxy: remove request URL and headers from error docs
44# - trunk: http://svn.apache.org/1864191
45# - 2.4.x: svn merge -c 1864191 ^/httpd/httpd/trunk .
46# - +1: covener, rpluem, icing
47# -
48#
49# PATCHES PROPOSED TO BACKPORT FROM TRUNK:
50# [ New proposals should be added at the end of the list ]
51diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c
52index e419eb6cd4..dcafa9c68a 100644
53--- a/modules/http/http_protocol.c
54+++ b/modules/http/http_protocol.c
55@@ -1132,13 +1132,10 @@ static const char *get_canned_error_string(int status,
56 "\">here</a>.</p>\n",
57 NULL));
58 case HTTP_USE_PROXY:
59- return(apr_pstrcat(p,
60- "<p>This resource is only accessible "
61- "through the proxy\n",
62- ap_escape_html(r->pool, location),
63- "<br />\nYou will need to configure "
64- "your client to use that proxy.</p>\n",
65- NULL));
66+ return("<p>This resource is only accessible "
67+ "through the proxy\n"
68+ "<br />\nYou will need to configure "
69+ "your client to use that proxy.</p>\n");
70 case HTTP_PROXY_AUTHENTICATION_REQUIRED:
71 case HTTP_UNAUTHORIZED:
72 return("<p>This server could not verify that you\n"
73@@ -1154,34 +1151,20 @@ static const char *get_canned_error_string(int status,
74 "error-notes",
75 "</p>\n"));
76 case HTTP_FORBIDDEN:
77- s1 = apr_pstrcat(p,
78- "<p>You don't have permission to access ",
79- ap_escape_html(r->pool, r->uri),
80- "\non this server.<br />\n",
81- NULL);
82- return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
83+ return(add_optional_notes(r, "<p>You don't have permission to access this resource.", "error-notes", "</p>\n"));
84 case HTTP_NOT_FOUND:
85- return(apr_pstrcat(p,
86- "<p>The requested URL ",
87- ap_escape_html(r->pool, r->uri),
88- " was not found on this server.</p>\n",
89- NULL));
90+ return("<p>The requested URL was not found on this server.</p>\n");
91 case HTTP_METHOD_NOT_ALLOWED:
92 return(apr_pstrcat(p,
93 "<p>The requested method ",
94 ap_escape_html(r->pool, r->method),
95- " is not allowed for the URL ",
96- ap_escape_html(r->pool, r->uri),
97- ".</p>\n",
98+ " is not allowed for this URL.</p>\n",
99 NULL));
100 case HTTP_NOT_ACCEPTABLE:
101- s1 = apr_pstrcat(p,
102- "<p>An appropriate representation of the "
103- "requested resource ",
104- ap_escape_html(r->pool, r->uri),
105- " could not be found on this server.</p>\n",
106- NULL);
107- return(add_optional_notes(r, s1, "variant-list", ""));
108+ return(add_optional_notes(r,
109+ "<p>An appropriate representation of the requested resource "
110+ "could not be found on this server.</p>\n",
111+ "variant-list", ""));
112 case HTTP_MULTIPLE_CHOICES:
113 return(add_optional_notes(r, "", "variant-list", ""));
114 case HTTP_LENGTH_REQUIRED:
115@@ -1192,18 +1175,13 @@ static const char *get_canned_error_string(int status,
116 NULL);
117 return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
118 case HTTP_PRECONDITION_FAILED:
119- return(apr_pstrcat(p,
120- "<p>The precondition on the request "
121- "for the URL ",
122- ap_escape_html(r->pool, r->uri),
123- " evaluated to false.</p>\n",
124- NULL));
125+ return("<p>The precondition on the request "
126+ "for this URL evaluated to false.</p>\n");
127 case HTTP_NOT_IMPLEMENTED:
128 s1 = apr_pstrcat(p,
129 "<p>",
130- ap_escape_html(r->pool, r->method), " to ",
131- ap_escape_html(r->pool, r->uri),
132- " not supported.<br />\n",
133+ ap_escape_html(r->pool, r->method), " ",
134+ " not supported for current URL.<br />\n",
135 NULL);
136 return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
137 case HTTP_BAD_GATEWAY:
138@@ -1211,29 +1189,19 @@ static const char *get_canned_error_string(int status,
139 "response from an upstream server.<br />" CRLF;
140 return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
141 case HTTP_VARIANT_ALSO_VARIES:
142- return(apr_pstrcat(p,
143- "<p>A variant for the requested "
144- "resource\n<pre>\n",
145- ap_escape_html(r->pool, r->uri),
146- "\n</pre>\nis itself a negotiable resource. "
147- "This indicates a configuration error.</p>\n",
148- NULL));
149+ return("<p>A variant for the requested "
150+ "resource\n<pre>\n"
151+ "\n</pre>\nis itself a negotiable resource. "
152+ "This indicates a configuration error.</p>\n");
153 case HTTP_REQUEST_TIME_OUT:
154 return("<p>Server timeout waiting for the HTTP request from the client.</p>\n");
155 case HTTP_GONE:
156- return(apr_pstrcat(p,
157- "<p>The requested resource<br />",
158- ap_escape_html(r->pool, r->uri),
159- "<br />\nis no longer available on this server "
160- "and there is no forwarding address.\n"
161- "Please remove all references to this "
162- "resource.</p>\n",
163- NULL));
164+ return("<p>The requested resource is no longer available on this server"
165+ " and there is no forwarding address.\n"
166+ "Please remove all references to this resource.</p>\n");
167 case HTTP_REQUEST_ENTITY_TOO_LARGE:
168 return(apr_pstrcat(p,
169- "The requested resource<br />",
170- ap_escape_html(r->pool, r->uri), "<br />\n",
171- "does not allow request data with ",
172+ "The requested resource does not allow request data with ",
173 ap_escape_html(r->pool, r->method),
174 " requests, or the amount of data provided in\n"
175 "the request exceeds the capacity limit.\n",
176@@ -1317,11 +1285,9 @@ static const char *get_canned_error_string(int status,
177 "the Server Name Indication (SNI) in use for this\n"
178 "connection.</p>\n");
179 case HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
180- s1 = apr_pstrcat(p,
181- "<p>Access to ", ap_escape_html(r->pool, r->uri),
182- "\nhas been denied for legal reasons.<br />\n",
183- NULL);
184- return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
185+ return(add_optional_notes(r,
186+ "<p>Access to this URL has been denied for legal reasons.<br />\n",
187+ "error-notes", "</p>\n"));
188 default: /* HTTP_INTERNAL_SERVER_ERROR */
189 /*
190 * This comparison to expose error-notes could be modified to
191diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
192index 91c2b4cdd4..5d9854b11d 100644
193--- a/modules/proxy/mod_proxy.c
194+++ b/modules/proxy/mod_proxy.c
195@@ -1049,9 +1049,10 @@ static int proxy_handler(request_rec *r)
196 char *end;
197 maxfwd = apr_strtoi64(str, &end, 10);
198 if (maxfwd < 0 || maxfwd == APR_INT64_MAX || *end) {
199- return ap_proxyerror(r, HTTP_BAD_REQUEST,
200- apr_psprintf(r->pool,
201- "Max-Forwards value '%s' could not be parsed", str));
202+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO()
203+ "Max-Forwards value '%s' could not be parsed", str);
204+ return ap_proxyerror(r, HTTP_BAD_REQUEST,
205+ "Max-Forwards request header could not be parsed");
206 }
207 else if (maxfwd == 0) {
208 switch (r->method_number) {
209diff --git a/modules/proxy/mod_proxy_ftp.c b/modules/proxy/mod_proxy_ftp.c
210index 49acdcbc1c..86ce69b45c 100644
211--- a/modules/proxy/mod_proxy_ftp.c
212+++ b/modules/proxy/mod_proxy_ftp.c
213@@ -1026,8 +1026,9 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
214 /* We break the URL into host, port, path-search */
215 if (r->parsed_uri.hostname == NULL) {
216 if (APR_SUCCESS != apr_uri_parse(p, url, &uri)) {
217- return ap_proxyerror(r, HTTP_BAD_REQUEST,
218- apr_psprintf(p, "URI cannot be parsed: %s", url));
219+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO()
220+ "URI cannot be parsed: %s", url);
221+ return ap_proxyerror(r, HTTP_BAD_REQUEST, "URI cannot be parsed");
222 }
223 connectname = uri.hostname;
224 connectport = uri.port;
225diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
226index 0315668296..5482ab8a48 100644
227--- a/modules/proxy/proxy_util.c
228+++ b/modules/proxy/proxy_util.c
229@@ -368,12 +368,9 @@ PROXY_DECLARE(char *)
230
231 PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message)
232 {
233- const char *uri = ap_escape_html(r->pool, r->uri);
234 apr_table_setn(r->notes, "error-notes",
235 apr_pstrcat(r->pool,
236- "The proxy server could not handle the request <em><a href=\"",
237- uri, "\">", ap_escape_html(r->pool, r->method), "&nbsp;", uri,
238- "</a></em>.<p>\n"
239+ "The proxy server could not handle the request<p>"
240 "Reason: <strong>", ap_escape_html(r->pool, message),
241 "</strong></p>",
242 NULL));
243--
2442.17.1
245
diff --git a/debian/patches/CVE-2019-10092-2.patch b/debian/patches/CVE-2019-10092-2.patch
0new file mode 100644246new file mode 100644
index 0000000..2eec9fb
--- /dev/null
+++ b/debian/patches/CVE-2019-10092-2.patch
@@ -0,0 +1,45 @@
1From 7106a941f8086e06d4c1b26a8dd6d2a4695eee5a Mon Sep 17 00:00:00 2001
2From: Eric Covener <covener@apache.org>
3Date: Thu, 8 Aug 2019 13:09:10 +0000
4Subject: [PATCH] Merge r1864699 from trunk:
5
6lognos
7
8
9
10
11git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1864702 13f79535-47bb-0310-9956-ffa450edef68
12---
13 modules/proxy/mod_proxy.c | 2 +-
14 modules/proxy/mod_proxy_ftp.c | 2 +-
15 2 files changed, 2 insertions(+), 2 deletions(-)
16
17diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
18index 5d9854b11d..8661a2dbaa 100644
19--- a/modules/proxy/mod_proxy.c
20+++ b/modules/proxy/mod_proxy.c
21@@ -1049,7 +1049,7 @@ static int proxy_handler(request_rec *r)
22 char *end;
23 maxfwd = apr_strtoi64(str, &end, 10);
24 if (maxfwd < 0 || maxfwd == APR_INT64_MAX || *end) {
25- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO()
26+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10188)
27 "Max-Forwards value '%s' could not be parsed", str);
28 return ap_proxyerror(r, HTTP_BAD_REQUEST,
29 "Max-Forwards request header could not be parsed");
30diff --git a/modules/proxy/mod_proxy_ftp.c b/modules/proxy/mod_proxy_ftp.c
31index 86ce69b45c..7ad803b97c 100644
32--- a/modules/proxy/mod_proxy_ftp.c
33+++ b/modules/proxy/mod_proxy_ftp.c
34@@ -1026,7 +1026,7 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
35 /* We break the URL into host, port, path-search */
36 if (r->parsed_uri.hostname == NULL) {
37 if (APR_SUCCESS != apr_uri_parse(p, url, &uri)) {
38- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO()
39+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10189)
40 "URI cannot be parsed: %s", url);
41 return ap_proxyerror(r, HTTP_BAD_REQUEST, "URI cannot be parsed");
42 }
43--
442.17.1
45
diff --git a/debian/patches/CVE-2019-10098.patch b/debian/patches/CVE-2019-10098.patch
0new file mode 10064446new file mode 100644
index 0000000..0ad57ba
--- /dev/null
+++ b/debian/patches/CVE-2019-10098.patch
@@ -0,0 +1,159 @@
1From 3b3117e96bc9c2afaeb5b98e9b60315006679a6d Mon Sep 17 00:00:00 2001
2From: Stefan Eissing <icing@apache.org>
3Date: Fri, 2 Aug 2019 09:24:58 +0000
4Subject: [PATCH] Merge of r1864192 from trunk:
5
6 *) core, rewrite: Set PCRE_DOTALL by default
7
8
9
10git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1864213 13f79535-47bb-0310-9956-ffa450edef68
11---
12 CHANGES | 3 +++
13 STATUS | 5 -----
14 docs/manual/mod/core.xml | 20 +++++++++++---------
15 server/util_pcre.c | 3 ++-
16 4 files changed, 16 insertions(+), 15 deletions(-)
17
18# diff --git a/CHANGES b/CHANGES
19# index bf00b5114b..ad4fd27625 100644
20# --- a/CHANGES
21# +++ b/CHANGES
22# @@ -1,6 +1,9 @@
23# -*- coding: utf-8 -*-
24# Changes with Apache 2.4.40
25#
26# + *) core, mod_rewrite: Set PCRE_DOTALL by default. Revert via
27# + RegexDefaultOptions -DOTALL [Yann Ylavic]
28# +
29# *) core: Remove request details from built-in error documents [Eric Covener]
30#
31# *) mod_http2: core setting "LimitRequestFieldSize" is not additionally checked on
32# diff --git a/STATUS b/STATUS
33# index 3c3cf39f48..f9bfc678fd 100644
34# --- a/STATUS
35# +++ b/STATUS
36# @@ -127,11 +127,6 @@ RELEASE SHOWSTOPPERS:
37# PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
38# [ start all new proposals below, under PATCHES PROPOSED. ]
39#
40# - *) core, rewrite: Set PCRE_DOTALL by default
41# - trunk: http://svn.apache.org/1864192
42# - 2.4.x: svn merge -c 1864192 ^/httpd/httpd/trunk .
43# - +1: covener, rpluem, icing
44# -
45#
46# PATCHES PROPOSED TO BACKPORT FROM TRUNK:
47# [ New proposals should be added at the end of the list ]
48# diff --git a/docs/manual/mod/core.xml b/docs/manual/mod/core.xml
49# index d9f0895af4..d4d6030dc5 100644
50# --- a/docs/manual/mod/core.xml
51# +++ b/docs/manual/mod/core.xml
52# @@ -4061,7 +4061,7 @@ Protocols h2 http/1.1
53# <name>RegexDefaultOptions</name>
54# <description>Allow to configure global/default options for regexes</description>
55# <syntax>RegexDefaultOptions [none] [+|-]<var>option</var> [[+|-]<var>option</var>] ...</syntax>
56# - <default>RegexDefaultOptions DOLLAR_ENDONLY</default>
57# + <default>RegexDefaultOptions DOTALL DOLLAR_ENDONLY</default>
58# <contextlist><context>server config</context></contextlist>
59# <compatibility>Only available from Apache 2.4.30 and later.</compatibility>
60#
61# @@ -4080,24 +4080,26 @@ Protocols h2 http/1.1
62# <dt><code>ICASE</code></dt>
63# <dd>Use a case-insensitive match.</dd>
64#
65# + <dt><code>EXTENDED</code></dt>
66# + <dd>Perl's /x flag, ignore (unescaped-)spaces and comments in the pattern.</dd>
67# +
68# <dt><code>DOTALL</code></dt>
69# - <dd>Perl's /s flag.</dd>
70# + <dd>Perl's /s flag, '.' matches newline characters.</dd>
71#
72# <dt><code>DOLLAR_ENDONLY</code></dt>
73# <dd>'$' matches at end of subject string only.</dd>
74# - <dd>.</dd>
75# </dl>
76# <highlight language="config">
77# -#
78# -RegexDefaultOptions +ICASE +DOLLAR_ENDONLY
79# +# Add the ICASE option for all regexes by default
80# +RegexDefaultOptions +ICASE
81# ...
82# -# Remove the ICASE option, but keep all the other already set options
83# -RegexDefaultOptions -ICASE
84# +# Remove the default DOLLAR_ENDONLY option, but keep any other one
85# +RegexDefaultOptions -DOLLAR_ENDONLY
86# ...
87# -# Set the default option to DOTALL, resetting any other option
88# +# Set the DOTALL option only, resetting any other one
89# RegexDefaultOptions DOTALL
90# ...
91# -# Reset all defined option
92# +# Reset all defined options
93# RegexDefaultOptions none
94# ...
95# </highlight>
96# diff --git a/docs/manual/mod/core.html.en b/docs/manual/mod/core.html.en
97# index 1cc985eb65..4c0b2fd744 100644
98# --- a/docs/manual/mod/core.html.en
99# +++ b/docs/manual/mod/core.html.en
100# @@ -4069,7 +4069,7 @@ as if 'QualifyRedirectURL ON' was configured.</td></tr>
101# <table class="directive">
102# <tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Allow to configure global/default options for regexes</td></tr>
103# <tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>RegexDefaultOptions [none] [+|-]<var>option</var> [[+|-]<var>option</var>] ...</code></td></tr>
104# -<tr><th><a href="directive-dict.html#Default">Default:</a></th><td><code>RegexDefaultOptions DOLLAR_ENDONLY</code></td></tr>
105# +<tr><th><a href="directive-dict.html#Default">Default:</a></th><td><code>RegexDefaultOptions DOTALL DOLLAR_ENDONLY</code></td></tr>
106# <tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config</td></tr>
107# <tr><th><a href="directive-dict.html#Status">Status:</a></th><td>Core</td></tr>
108# <tr><th><a href="directive-dict.html#Module">Module:</a></th><td>core</td></tr>
109# @@ -4089,23 +4089,25 @@ as if 'QualifyRedirectURL ON' was configured.</td></tr>
110# <dt><code>ICASE</code></dt>
111# <dd>Use a case-insensitive match.</dd>
112#
113# + <dt><code>EXTENDED</code></dt>
114# + <dd>Perl's /x flag, ignore (unescaped-)spaces and comments in the pattern.</dd>
115# +
116# <dt><code>DOTALL</code></dt>
117# - <dd>Perl's /s flag.</dd>
118# + <dd>Perl's /s flag, '.' matches newline characters.</dd>
119#
120# <dt><code>DOLLAR_ENDONLY</code></dt>
121# <dd>'$' matches at end of subject string only.</dd>
122# - <dd>.</dd>
123# </dl>
124# - <pre class="prettyprint lang-config">#
125# -RegexDefaultOptions +ICASE +DOLLAR_ENDONLY
126# + <pre class="prettyprint lang-config"># Add the ICASE option for all regexes by default
127# +RegexDefaultOptions +ICASE
128# ...
129# -# Remove the ICASE option, but keep all the other already set options
130# -RegexDefaultOptions -ICASE
131# +# Remove the default DOLLAR_ENDONLY option, but keep any other one
132# +RegexDefaultOptions -DOLLAR_ENDONLY
133# ...
134# -# Set the default option to DOTALL, resetting any other option
135# +# Set the DOTALL option only, resetting any other one
136# RegexDefaultOptions DOTALL
137# ...
138# -# Reset all defined option
139# +# Reset all defined options
140# RegexDefaultOptions none
141# ...</pre>
142#
143diff --git a/server/util_pcre.c b/server/util_pcre.c
144index f2cb1bb01e..35831f500f 100644
145--- a/server/util_pcre.c
146+++ b/server/util_pcre.c
147@@ -120,7 +120,8 @@ AP_DECLARE(void) ap_regfree(ap_regex_t *preg)
148 * Compile a regular expression *
149 *************************************************/
150
151-static int default_cflags = AP_REG_DOLLAR_ENDONLY;
152+static int default_cflags = AP_REG_DOTALL |
153+ AP_REG_DOLLAR_ENDONLY;
154
155 AP_DECLARE(int) ap_regcomp_get_default_cflags(void)
156 {
157--
1582.17.1
159
diff --git a/debian/patches/CVE-2020-11993-pre1.patch b/debian/patches/CVE-2020-11993-pre1.patch
0new file mode 100644160new file mode 100644
index 0000000..25d6669
--- /dev/null
+++ b/debian/patches/CVE-2020-11993-pre1.patch
@@ -0,0 +1,406 @@
1Backport of:
2
3From 3060a9dd4d160af2e82829ce801a3a89127e36a1 Mon Sep 17 00:00:00 2001
4From: Jim Jagielski <jim@apache.org>
5Date: Thu, 30 Jan 2020 15:14:40 +0000
6Subject: [PATCH] Merge r1871810 from trunk:
7
8 *) mod_http2: Fixed rare cases where a h2 worker could deadlock the main connection.
9
10
11Submitted by: icing
12Reviewed by: icing, jim, steffenal
13
14
15git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1873368 13f79535-47bb-0310-9956-ffa450edef68
16---
17 CHANGES | 3 ++
18 STATUS | 4 --
19 modules/http2/h2_mplx.c | 54 ++++++++++++--------
20 modules/http2/h2_session.c | 2 +-
21 modules/http2/h2_util.c | 89 ++++++++++-----------------------
22 modules/http2/h2_util.h | 2 -
23 modules/http2/h2_version.h | 4 +-
24 modules/http2/h2_workers.c | 1 -
25 modules/http2/mod_proxy_http2.c | 8 +++
26 9 files changed, 72 insertions(+), 95 deletions(-)
27
28#diff --git a/CHANGES b/CHANGES
29#index ded0ecce34c..e12ef389501 100644
30#--- a/CHANGES
31#+++ b/CHANGES
32#@@ -5,6 +5,9 @@ Changes with Apache 2.4.42
33# r:notes_table, r:subprocess_env_table as read-only native table alternatives
34# that can be iterated over. [Eric Covener]
35#
36#+ *) mod_http2: Fixed rare cases where a h2 worker could deadlock the main connection.
37#+ [Yann Ylavic, Stefan Eissing]
38#+
39# *) mod_lua: Accept nil assignments to the exposed tables (r.subprocess_env,
40# r.headers_out, etc) to remove the key from the table. PR63971.
41# [Eric Covener]
42#diff --git a/STATUS b/STATUS
43#index 991ed406b23..a610953ed89 100644
44#--- a/STATUS
45#+++ b/STATUS
46#@@ -132,10 +132,6 @@ RELEASE SHOWSTOPPERS:
47# PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
48# [ start all new proposals below, under PATCHES PROPOSED. ]
49#
50#- *) mod_http2: Fixed rare cases where a h2 worker could deadlock the main connection.
51#- trunk patch: http://svn.apache.org/r1871810
52#- 2.4.x patch: svn merge -c 1871810 ^/httpd/httpd/trunk
53#- +1: icing, jim, steffenal(tested with 1.15.5-git)
54#
55# PATCHES PROPOSED TO BACKPORT FROM TRUNK:
56# [ New proposals should be added at the end of the list ]
57--- a/modules/http2/h2_mplx.c
58+++ b/modules/http2/h2_mplx.c
59@@ -75,13 +75,13 @@ apr_status_t h2_mplx_child_init(apr_pool
60 #define H2_MPLX_ENTER_ALWAYS(m) \
61 apr_thread_mutex_lock(m->lock)
62
63-#define H2_MPLX_ENTER_MAYBE(m, lock) \
64- if (lock) apr_thread_mutex_lock(m->lock)
65+#define H2_MPLX_ENTER_MAYBE(m, dolock) \
66+ if (dolock) apr_thread_mutex_lock(m->lock)
67
68-#define H2_MPLX_LEAVE_MAYBE(m, lock) \
69- if (lock) apr_thread_mutex_unlock(m->lock)
70+#define H2_MPLX_LEAVE_MAYBE(m, dolock) \
71+ if (dolock) apr_thread_mutex_unlock(m->lock)
72
73-static void check_data_for(h2_mplx *m, h2_stream *stream, int lock);
74+static void check_data_for(h2_mplx *m, h2_stream *stream, int mplx_is_locked);
75
76 static void stream_output_consumed(void *ctx,
77 h2_bucket_beam *beam, apr_off_t length)
78@@ -104,6 +104,7 @@ static void stream_joined(h2_mplx *m, h2
79 {
80 ap_assert(!h2_task_has_started(stream->task) || stream->task->worker_done);
81
82+ h2_ififo_remove(m->readyq, stream->id);
83 h2_ihash_remove(m->shold, stream->id);
84 h2_ihash_add(m->spurge, stream);
85 }
86@@ -125,14 +126,16 @@ static void stream_cleanup(h2_mplx *m, h
87
88 h2_ihash_remove(m->streams, stream->id);
89 h2_iq_remove(m->q, stream->id);
90- h2_ififo_remove(m->readyq, stream->id);
91- h2_ihash_add(m->shold, stream);
92
93 if (!h2_task_has_started(stream->task) || stream->task->done_done) {
94 stream_joined(m, stream);
95 }
96- else if (stream->task) {
97- stream->task->c->aborted = 1;
98+ else {
99+ h2_ififo_remove(m->readyq, stream->id);
100+ h2_ihash_add(m->shold, stream);
101+ if (stream->task) {
102+ stream->task->c->aborted = 1;
103+ }
104 }
105 }
106
107@@ -509,12 +512,11 @@ static void output_produced(void *ctx, h
108 h2_stream *stream = ctx;
109 h2_mplx *m = stream->session->mplx;
110
111- check_data_for(m, stream, 1);
112+ check_data_for(m, stream, 0);
113 }
114
115 static apr_status_t out_open(h2_mplx *m, int stream_id, h2_bucket_beam *beam)
116 {
117- apr_status_t status = APR_SUCCESS;
118 h2_stream *stream = h2_ihash_get(m->streams, stream_id);
119
120 if (!stream || !stream->task || m->aborted) {
121@@ -528,7 +530,7 @@ static apr_status_t out_open(h2_mplx *m,
122 h2_beam_log(beam, m->c, APLOG_TRACE2, "out_open");
123 }
124 else {
125- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, m->c,
126+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
127 "h2_mplx(%s): out open", stream->task->id);
128 }
129
130@@ -540,8 +542,8 @@ static apr_status_t out_open(h2_mplx *m,
131
132 /* we might see some file buckets in the output, see
133 * if we have enough handles reserved. */
134- check_data_for(m, stream, 0);
135- return status;
136+ check_data_for(m, stream, 1);
137+ return APR_SUCCESS;
138 }
139
140 apr_status_t h2_mplx_out_open(h2_mplx *m, int stream_id, h2_bucket_beam *beam)
141@@ -583,7 +585,7 @@ static apr_status_t out_close(h2_mplx *m
142 status = h2_beam_close(task->output.beam);
143 h2_beam_log(task->output.beam, m->c, APLOG_TRACE2, "out_close");
144 output_consumed_signal(m, task);
145- check_data_for(m, stream, 0);
146+ check_data_for(m, stream, 1);
147 return status;
148 }
149
150@@ -617,15 +619,23 @@ apr_status_t h2_mplx_out_trywait(h2_mplx
151 return status;
152 }
153
154-static void check_data_for(h2_mplx *m, h2_stream *stream, int lock)
155+static void check_data_for(h2_mplx *m, h2_stream *stream, int mplx_is_locked)
156 {
157+ /* If m->lock is already held, we must release during h2_ififo_push()
158+ * which can wait on its not_full condition, causing a deadlock because
159+ * no one would then be able to acquire m->lock to empty the fifo.
160+ */
161+ H2_MPLX_LEAVE_MAYBE(m, mplx_is_locked);
162 if (h2_ififo_push(m->readyq, stream->id) == APR_SUCCESS) {
163+ H2_MPLX_ENTER_ALWAYS(m);
164 apr_atomic_set32(&m->event_pending, 1);
165- H2_MPLX_ENTER_MAYBE(m, lock);
166 if (m->added_output) {
167 apr_thread_cond_signal(m->added_output);
168 }
169- H2_MPLX_LEAVE_MAYBE(m, lock);
170+ H2_MPLX_LEAVE_MAYBE(m, !mplx_is_locked);
171+ }
172+ else {
173+ H2_MPLX_ENTER_MAYBE(m, mplx_is_locked);
174 }
175 }
176
177@@ -678,7 +688,7 @@ apr_status_t h2_mplx_process(h2_mplx *m,
178 h2_ihash_add(m->streams, stream);
179 if (h2_stream_is_ready(stream)) {
180 /* already have a response */
181- check_data_for(m, stream, 0);
182+ check_data_for(m, stream, 1);
183 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
184 H2_STRM_MSG(stream, "process, add to readyq"));
185 }
186@@ -809,7 +819,7 @@ static void task_done(h2_mplx *m, h2_tas
187 }
188
189 /* more data will not arrive, resume the stream */
190- check_data_for(m, stream, 0);
191+ check_data_for(m, stream, 1);
192 }
193 }
194 else if ((stream = h2_ihash_get(m->shold, task->stream_id)) != NULL) {
195@@ -1062,7 +1072,7 @@ apr_status_t h2_mplx_idle(h2_mplx *m)
196 h2_beam_is_closed(stream->output),
197 (long)h2_beam_get_buffered(stream->output));
198 h2_ihash_add(m->streams, stream);
199- check_data_for(m, stream, 0);
200+ check_data_for(m, stream, 1);
201 stream->out_checked = 1;
202 status = APR_EAGAIN;
203 }
204@@ -1114,7 +1124,7 @@ apr_status_t h2_mplx_dispatch_master_eve
205
206 apr_status_t h2_mplx_keep_active(h2_mplx *m, h2_stream *stream)
207 {
208- check_data_for(m, stream, 1);
209+ check_data_for(m, stream, 0);
210 return APR_SUCCESS;
211 }
212
213--- a/modules/http2/h2_session.c
214+++ b/modules/http2/h2_session.c
215@@ -2141,7 +2141,7 @@ apr_status_t h2_session_process(h2_sessi
216 break;
217
218 case H2_SESSION_ST_IDLE:
219- if (session->idle_until && (apr_time_now() + session->idle_delay) > session->idle_until) {
220+ if (session->idle_until && (now + session->idle_delay) > session->idle_until) {
221 ap_log_cerror( APLOG_MARK, APLOG_TRACE1, status, c,
222 H2_SSSN_MSG(session, "idle, timeout reached, closing"));
223 if (session->idle_delay) {
224--- a/modules/http2/h2_util.c
225+++ b/modules/http2/h2_util.c
226@@ -638,15 +638,6 @@ apr_status_t h2_fifo_term(h2_fifo *fifo)
227 apr_status_t rv;
228 if ((rv = apr_thread_mutex_lock(fifo->lock)) == APR_SUCCESS) {
229 fifo->aborted = 1;
230- apr_thread_mutex_unlock(fifo->lock);
231- }
232- return rv;
233-}
234-
235-apr_status_t h2_fifo_interrupt(h2_fifo *fifo)
236-{
237- apr_status_t rv;
238- if ((rv = apr_thread_mutex_lock(fifo->lock)) == APR_SUCCESS) {
239 apr_thread_cond_broadcast(fifo->not_empty);
240 apr_thread_cond_broadcast(fifo->not_full);
241 apr_thread_mutex_unlock(fifo->lock);
242@@ -710,10 +701,6 @@ static apr_status_t fifo_push(h2_fifo *f
243 {
244 apr_status_t rv;
245
246- if (fifo->aborted) {
247- return APR_EOF;
248- }
249-
250 if ((rv = apr_thread_mutex_lock(fifo->lock)) == APR_SUCCESS) {
251 rv = fifo_push_int(fifo, elem, block);
252 apr_thread_mutex_unlock(fifo->lock);
253@@ -754,10 +741,6 @@ static apr_status_t fifo_pull(h2_fifo *f
254 {
255 apr_status_t rv;
256
257- if (fifo->aborted) {
258- return APR_EOF;
259- }
260-
261 if ((rv = apr_thread_mutex_lock(fifo->lock)) == APR_SUCCESS) {
262 rv = pull_head(fifo, pelem, block);
263 apr_thread_mutex_unlock(fifo->lock);
264@@ -946,15 +929,6 @@ apr_status_t h2_ififo_term(h2_ififo *fif
265 apr_status_t rv;
266 if ((rv = apr_thread_mutex_lock(fifo->lock)) == APR_SUCCESS) {
267 fifo->aborted = 1;
268- apr_thread_mutex_unlock(fifo->lock);
269- }
270- return rv;
271-}
272-
273-apr_status_t h2_ififo_interrupt(h2_ififo *fifo)
274-{
275- apr_status_t rv;
276- if ((rv = apr_thread_mutex_lock(fifo->lock)) == APR_SUCCESS) {
277 apr_thread_cond_broadcast(fifo->not_empty);
278 apr_thread_cond_broadcast(fifo->not_full);
279 apr_thread_mutex_unlock(fifo->lock);
280@@ -1018,10 +992,6 @@ static apr_status_t ififo_push(h2_ififo
281 {
282 apr_status_t rv;
283
284- if (fifo->aborted) {
285- return APR_EOF;
286- }
287-
288 if ((rv = apr_thread_mutex_lock(fifo->lock)) == APR_SUCCESS) {
289 rv = ififo_push_int(fifo, id, block);
290 apr_thread_mutex_unlock(fifo->lock);
291@@ -1062,10 +1032,6 @@ static apr_status_t ififo_pull(h2_ififo
292 {
293 apr_status_t rv;
294
295- if (fifo->aborted) {
296- return APR_EOF;
297- }
298-
299 if ((rv = apr_thread_mutex_lock(fifo->lock)) == APR_SUCCESS) {
300 rv = ipull_head(fifo, pi, block);
301 apr_thread_mutex_unlock(fifo->lock);
302@@ -1088,10 +1054,6 @@ static apr_status_t ififo_peek(h2_ififo
303 apr_status_t rv;
304 int id;
305
306- if (fifo->aborted) {
307- return APR_EOF;
308- }
309-
310 if (APR_SUCCESS == (rv = apr_thread_mutex_lock(fifo->lock))) {
311 if (APR_SUCCESS == (rv = ipull_head(fifo, &id, block))) {
312 switch (fn(id, ctx)) {
313@@ -1117,39 +1079,40 @@ apr_status_t h2_ififo_try_peek(h2_ififo
314 return ififo_peek(fifo, fn, ctx, 0);
315 }
316
317-apr_status_t h2_ififo_remove(h2_ififo *fifo, int id)
318+static apr_status_t ififo_remove(h2_ififo *fifo, int id)
319 {
320- apr_status_t rv;
321+ int rc, i;
322
323 if (fifo->aborted) {
324 return APR_EOF;
325 }
326
327- if ((rv = apr_thread_mutex_lock(fifo->lock)) == APR_SUCCESS) {
328- int i, rc;
329- int e;
330-
331- rc = 0;
332- for (i = 0; i < fifo->count; ++i) {
333- e = fifo->elems[inth_index(fifo, i)];
334- if (e == id) {
335- ++rc;
336- }
337- else if (rc) {
338- fifo->elems[inth_index(fifo, i-rc)] = e;
339- }
340- }
341- if (rc) {
342- fifo->count -= rc;
343- if (fifo->count + rc == fifo->nelems) {
344- apr_thread_cond_broadcast(fifo->not_full);
345- }
346- rv = APR_SUCCESS;
347+ rc = 0;
348+ for (i = 0; i < fifo->count; ++i) {
349+ int e = fifo->elems[inth_index(fifo, i)];
350+ if (e == id) {
351+ ++rc;
352 }
353- else {
354- rv = APR_EAGAIN;
355+ else if (rc) {
356+ fifo->elems[inth_index(fifo, i-rc)] = e;
357 }
358-
359+ }
360+ if (!rc) {
361+ return APR_EAGAIN;
362+ }
363+ fifo->count -= rc;
364+ if (fifo->count + rc == fifo->nelems) {
365+ apr_thread_cond_broadcast(fifo->not_full);
366+ }
367+ return APR_SUCCESS;
368+}
369+
370+apr_status_t h2_ififo_remove(h2_ififo *fifo, int id)
371+{
372+ apr_status_t rv;
373+
374+ if ((rv = apr_thread_mutex_lock(fifo->lock)) == APR_SUCCESS) {
375+ rv = ififo_remove(fifo, id);
376 apr_thread_mutex_unlock(fifo->lock);
377 }
378 return rv;
379--- a/modules/http2/h2_util.h
380+++ b/modules/http2/h2_util.h
381@@ -209,7 +209,6 @@ apr_status_t h2_fifo_create(h2_fifo **pf
382 apr_status_t h2_fifo_set_create(h2_fifo **pfifo, apr_pool_t *pool, int capacity);
383
384 apr_status_t h2_fifo_term(h2_fifo *fifo);
385-apr_status_t h2_fifo_interrupt(h2_fifo *fifo);
386
387 int h2_fifo_count(h2_fifo *fifo);
388
389@@ -280,7 +279,6 @@ apr_status_t h2_ififo_create(h2_ififo **
390 apr_status_t h2_ififo_set_create(h2_ififo **pfifo, apr_pool_t *pool, int capacity);
391
392 apr_status_t h2_ififo_term(h2_ififo *fifo);
393-apr_status_t h2_ififo_interrupt(h2_ififo *fifo);
394
395 int h2_ififo_count(h2_ififo *fifo);
396
397--- a/modules/http2/h2_workers.c
398+++ b/modules/http2/h2_workers.c
399@@ -269,7 +269,6 @@ static apr_status_t workers_pool_cleanup
400 }
401
402 h2_fifo_term(workers->mplxs);
403- h2_fifo_interrupt(workers->mplxs);
404
405 cleanup_zombies(workers);
406 }
diff --git a/debian/patches/CVE-2020-11993.patch b/debian/patches/CVE-2020-11993.patch
0new file mode 100644407new file mode 100644
index 0000000..1002f87
--- /dev/null
+++ b/debian/patches/CVE-2020-11993.patch
@@ -0,0 +1,1905 @@
1Backport of:
2
3From 63a0a87efa0925514d15c211b508f6594669888c Mon Sep 17 00:00:00 2001
4From: Graham Leggett <minfrin@apache.org>
5Date: Wed, 8 Jul 2020 11:53:48 +0000
6Subject: [PATCH] *) mod_http2: connection terminology renamed to
7 master/secondary. trunk patch: http://svn.apache.org/r1878926
8 http://svn.apache.org/r1879156 2.4.x patch:
9 https://svn.apache.org/repos/asf/httpd/httpd/patches/2.4.x/h2-master-secondary.patch
10 +1: icing, ylavic, minfrin ylavic: nitpicking, mixed
11 "H2_secondary_IN" and "H2_secondary_OUT" case to register the
12 filters, but not for adding them. IIRC filters names are case
13 insentive so shouldn't matter, just popped at my eyes.. icing: updated
14 patch and added r1879156 to fix the eye bleed. jailletc36: CHANGES could
15 also be looked at if it makes sense to update the terminology
16 also here
17
18git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1879642 13f79535-47bb-0310-9956-ffa450edef68
19---
20 CHANGES | 3 +
21 STATUS | 11 --
22 modules/http2/h2_conn.c | 52 +++----
23 modules/http2/h2_conn.h | 8 +-
24 modules/http2/h2_filter.c | 4 +-
25 modules/http2/h2_h2.c | 10 +-
26 modules/http2/h2_mplx.c | 283 +++++++++++++++++++------------------
27 modules/http2/h2_mplx.h | 160 ++++++---------------
28 modules/http2/h2_request.c | 7 +-
29 modules/http2/h2_session.c | 30 ++--
30 modules/http2/h2_session.h | 2 +-
31 modules/http2/h2_stream.c | 2 +-
32 modules/http2/h2_task.c | 68 ++++-----
33 modules/http2/h2_task.h | 2 +-
34 modules/http2/h2_workers.c | 6 +-
35 modules/http2/mod_http2.c | 4 +-
36 16 files changed, 288 insertions(+), 364 deletions(-)
37
38#diff --git a/CHANGES b/CHANGES
39#index 50432a7ca09..31ad6741715 100644
40#--- a/CHANGES
41#+++ b/CHANGES
42#@@ -1,6 +1,9 @@
43# -*- coding: utf-8 -*-
44# Changes with Apache 2.4.44
45#
46#+ *) mod_http2: The module now handles master/secondary connections and has marked
47#+ methods according to use. [Stefan Eissing]
48#+
49# *) core: Drop an invalid Last-Modified header value coming
50# from a FCGI/CGI script instead of replacing it with Unix epoch.
51# [Luca Toscano]
52#diff --git a/STATUS b/STATUS
53#index c4d0dde0534..72220708a70 100644
54#--- a/STATUS
55#+++ b/STATUS
56#@@ -135,17 +135,6 @@ RELEASE SHOWSTOPPERS:
57# PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
58# [ start all new proposals below, under PATCHES PROPOSED. ]
59#
60#- *) mod_http2: connection terminology renamed to master/secondary.
61#- trunk patch: http://svn.apache.org/r1878926
62#- http://svn.apache.org/r1879156
63#- 2.4.x patch: https://svn.apache.org/repos/asf/httpd/httpd/patches/2.4.x/h2-master-secondary.patch
64#- +1: icing, ylavic, minfrin
65#- ylavic: nitpicking, mixed "H2_secondary_IN" and "H2_secondary_OUT" case to
66#- register the filters, but not for adding them. IIRC filters names
67#- are case insentive so shouldn't matter, just popped at my eyes..
68#- icing: updated patch and added r1879156 to fix the eye bleed.
69#- jailletc36: CHANGES could also be looked at if it makes sense to update the terminology
70#- also here
71#
72# PATCHES PROPOSED TO BACKPORT FROM TRUNK:
73# [ New proposals should be added at the end of the list ]
74--- a/modules/http2/h2_conn.c
75+++ b/modules/http2/h2_conn.c
76@@ -138,7 +138,7 @@ apr_status_t h2_conn_child_init(apr_pool
77 ap_register_input_filter("H2_IN", h2_filter_core_input,
78 NULL, AP_FTYPE_CONNECTION);
79
80- status = h2_mplx_child_init(pool, s);
81+ status = h2_mplx_m_child_init(pool, s);
82
83 if (status == APR_SUCCESS) {
84 status = apr_socket_create(&dummy_socket, APR_INET, SOCK_STREAM,
85@@ -260,7 +260,7 @@ apr_status_t h2_conn_pre_close(struct h2
86 return DONE;
87 }
88
89-conn_rec *h2_slave_create(conn_rec *master, int slave_id, apr_pool_t *parent)
90+conn_rec *h2_secondary_create(conn_rec *master, int sec_id, apr_pool_t *parent)
91 {
92 apr_allocator_t *allocator;
93 apr_status_t status;
94@@ -271,7 +271,7 @@ conn_rec *h2_slave_create(conn_rec *mast
95
96 ap_assert(master);
97 ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, master,
98- "h2_stream(%ld-%d): create slave", master->id, slave_id);
99+ "h2_stream(%ld-%d): create secondary", master->id, sec_id);
100
101 /* We create a pool with its own allocator to be used for
102 * processing a request. This is the only way to have the processing
103@@ -284,18 +284,18 @@ conn_rec *h2_slave_create(conn_rec *mast
104 status = apr_pool_create_ex(&pool, parent, NULL, allocator);
105 if (status != APR_SUCCESS) {
106 ap_log_cerror(APLOG_MARK, APLOG_ERR, status, master,
107- APLOGNO(10004) "h2_session(%ld-%d): create slave pool",
108- master->id, slave_id);
109+ APLOGNO(10004) "h2_session(%ld-%d): create secondary pool",
110+ master->id, sec_id);
111 return NULL;
112 }
113 apr_allocator_owner_set(allocator, pool);
114- apr_pool_tag(pool, "h2_slave_conn");
115+ apr_pool_tag(pool, "h2_secondary_conn");
116
117 c = (conn_rec *) apr_palloc(pool, sizeof(conn_rec));
118 if (c == NULL) {
119 ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_ENOMEM, master,
120- APLOGNO(02913) "h2_session(%ld-%d): create slave",
121- master->id, slave_id);
122+ APLOGNO(02913) "h2_session(%ld-%d): create secondary",
123+ master->id, sec_id);
124 apr_pool_destroy(pool);
125 return NULL;
126 }
127@@ -322,19 +322,19 @@ conn_rec *h2_slave_create(conn_rec *mast
128 c->clogging_input_filters = 1;
129 c->log = NULL;
130 c->log_id = apr_psprintf(pool, "%ld-%d",
131- master->id, slave_id);
132+ master->id, sec_id);
133 c->aborted = 0;
134- /* We cannot install the master connection socket on the slaves, as
135+ /* We cannot install the master connection socket on the secondary, as
136 * modules mess with timeouts/blocking of the socket, with
137 * unwanted side effects to the master connection processing.
138- * Fortunately, since we never use the slave socket, we can just install
139+ * Fortunately, since we never use the secondary socket, we can just install
140 * a single, process-wide dummy and everyone is happy.
141 */
142 ap_set_module_config(c->conn_config, &core_module, dummy_socket);
143 /* TODO: these should be unique to this thread */
144 c->sbh = master->sbh;
145- /* TODO: not all mpm modules have learned about slave connections yet.
146- * copy their config from master to slave.
147+ /* TODO: not all mpm modules have learned about secondary connections yet.
148+ * copy their config from master to secondary.
149 */
150 if ((mpm = h2_conn_mpm_module()) != NULL) {
151 cfg = ap_get_module_config(master->conn_config, mpm);
152@@ -342,38 +342,38 @@ conn_rec *h2_slave_create(conn_rec *mast
153 }
154
155 ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c,
156- "h2_slave(%s): created", c->log_id);
157+ "h2_secondary(%s): created", c->log_id);
158 return c;
159 }
160
161-void h2_slave_destroy(conn_rec *slave)
162+void h2_secondary_destroy(conn_rec *secondary)
163 {
164- ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, slave,
165- "h2_slave(%s): destroy", slave->log_id);
166- slave->sbh = NULL;
167- apr_pool_destroy(slave->pool);
168+ ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, secondary,
169+ "h2_secondary(%s): destroy", secondary->log_id);
170+ secondary->sbh = NULL;
171+ apr_pool_destroy(secondary->pool);
172 }
173
174-apr_status_t h2_slave_run_pre_connection(conn_rec *slave, apr_socket_t *csd)
175+apr_status_t h2_secondary_run_pre_connection(conn_rec *secondary, apr_socket_t *csd)
176 {
177- if (slave->keepalives == 0) {
178+ if (secondary->keepalives == 0) {
179 /* Simulate that we had already a request on this connection. Some
180 * hooks trigger special behaviour when keepalives is 0.
181 * (Not necessarily in pre_connection, but later. Set it here, so it
182 * is in place.) */
183- slave->keepalives = 1;
184+ secondary->keepalives = 1;
185 /* We signal that this connection will be closed after the request.
186 * Which is true in that sense that we throw away all traffic data
187- * on this slave connection after each requests. Although we might
188+ * on this secondary connection after each requests. Although we might
189 * reuse internal structures like memory pools.
190 * The wanted effect of this is that httpd does not try to clean up
191 * any dangling data on this connection when a request is done. Which
192 * is unneccessary on a h2 stream.
193 */
194- slave->keepalive = AP_CONN_CLOSE;
195- return ap_run_pre_connection(slave, csd);
196+ secondary->keepalive = AP_CONN_CLOSE;
197+ return ap_run_pre_connection(secondary, csd);
198 }
199- ap_assert(slave->output_filters);
200+ ap_assert(secondary->output_filters);
201 return APR_SUCCESS;
202 }
203
204--- a/modules/http2/h2_conn.h
205+++ b/modules/http2/h2_conn.h
206@@ -68,10 +68,10 @@ h2_mpm_type_t h2_conn_mpm_type(void);
207 const char *h2_conn_mpm_name(void);
208 int h2_mpm_supported(void);
209
210-conn_rec *h2_slave_create(conn_rec *master, int slave_id, apr_pool_t *parent);
211-void h2_slave_destroy(conn_rec *slave);
212+conn_rec *h2_secondary_create(conn_rec *master, int sec_id, apr_pool_t *parent);
213+void h2_secondary_destroy(conn_rec *secondary);
214
215-apr_status_t h2_slave_run_pre_connection(conn_rec *slave, apr_socket_t *csd);
216-void h2_slave_run_connection(conn_rec *slave);
217+apr_status_t h2_secondary_run_pre_connection(conn_rec *secondary, apr_socket_t *csd);
218+void h2_secondary_run_connection(conn_rec *secondary);
219
220 #endif /* defined(__mod_h2__h2_conn__) */
221--- a/modules/http2/h2_filter.c
222+++ b/modules/http2/h2_filter.c
223@@ -370,7 +370,7 @@ static void add_streams(apr_bucket_briga
224 x.s = s;
225 x.idx = 0;
226 bbout(bb, " \"streams\": {");
227- h2_mplx_stream_do(s->mplx, add_stream, &x);
228+ h2_mplx_m_stream_do(s->mplx, add_stream, &x);
229 bbout(bb, "\n }%s\n", last? "" : ",");
230 }
231
232@@ -433,7 +433,7 @@ static void add_stats(apr_bucket_brigade
233 static apr_status_t h2_status_insert(h2_task *task, apr_bucket *b)
234 {
235 h2_mplx *m = task->mplx;
236- h2_stream *stream = h2_mplx_stream_get(m, task->stream_id);
237+ h2_stream *stream = h2_mplx_t_stream_get(m, task);
238 h2_session *s;
239 conn_rec *c;
240
241--- a/modules/http2/h2_h2.c
242+++ b/modules/http2/h2_h2.c
243@@ -668,7 +668,7 @@ static int h2_h2_pre_close_conn(conn_rec
244 {
245 h2_ctx *ctx;
246
247- /* slave connection? */
248+ /* secondary connection? */
249 if (c->master) {
250 return DECLINED;
251 }
252@@ -712,7 +712,7 @@ static void check_push(request_rec *r, c
253
254 static int h2_h2_post_read_req(request_rec *r)
255 {
256- /* slave connection? */
257+ /* secondary connection? */
258 if (r->connection->master) {
259 struct h2_task *task = h2_ctx_get_task(r->connection);
260 /* This hook will get called twice on internal redirects. Take care
261@@ -731,7 +731,7 @@ static int h2_h2_post_read_req(request_r
262 ap_add_output_filter("H2_RESPONSE", task, r, r->connection);
263
264 for (f = r->input_filters; f; f = f->next) {
265- if (!strcmp("H2_SLAVE_IN", f->frec->name)) {
266+ if (!strcmp("H2_SECONDARY_IN", f->frec->name)) {
267 f->r = r;
268 break;
269 }
270@@ -745,7 +745,7 @@ static int h2_h2_post_read_req(request_r
271
272 static int h2_h2_late_fixups(request_rec *r)
273 {
274- /* slave connection? */
275+ /* secondary connection? */
276 if (r->connection->master) {
277 struct h2_task *task = h2_ctx_get_task(r->connection);
278 if (task) {
279@@ -753,7 +753,7 @@ static int h2_h2_late_fixups(request_rec
280 task->output.copy_files = h2_config_rgeti(r, H2_CONF_COPY_FILES);
281 if (task->output.copy_files) {
282 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, task->c,
283- "h2_slave_out(%s): copy_files on", task->id);
284+ "h2_secondary_out(%s): copy_files on", task->id);
285 h2_beam_on_file_beam(task->output.beam, h2_beam_no_files, NULL);
286 }
287 check_push(r, "late_fixup");
288--- a/modules/http2/h2_mplx.c
289+++ b/modules/http2/h2_mplx.c
290@@ -56,10 +56,18 @@ typedef struct {
291 apr_size_t count;
292 } stream_iter_ctx;
293
294-static apr_status_t mplx_be_happy(h2_mplx *m);
295-static apr_status_t mplx_be_annoyed(h2_mplx *m);
296+/**
297+ * Naming convention for static functions:
298+ * - m_*: function only called from the master connection
299+ * - s_*: function only called from a secondary connection
300+ * - t_*: function only called from a h2_task holder
301+ * - mst_*: function called from everyone
302+ */
303
304-apr_status_t h2_mplx_child_init(apr_pool_t *pool, server_rec *s)
305+static apr_status_t s_mplx_be_happy(h2_mplx *m, h2_task *task);
306+static apr_status_t m_be_annoyed(h2_mplx *m);
307+
308+apr_status_t h2_mplx_m_child_init(apr_pool_t *pool, server_rec *s)
309 {
310 return APR_SUCCESS;
311 }
312@@ -81,26 +89,25 @@ apr_status_t h2_mplx_child_init(apr_pool
313 #define H2_MPLX_LEAVE_MAYBE(m, dolock) \
314 if (dolock) apr_thread_mutex_unlock(m->lock)
315
316-static void check_data_for(h2_mplx *m, h2_stream *stream, int mplx_is_locked);
317+static void mst_check_data_for(h2_mplx *m, h2_stream *stream, int mplx_is_locked);
318
319-static void stream_output_consumed(void *ctx,
320- h2_bucket_beam *beam, apr_off_t length)
321+static void mst_stream_output_consumed(void *ctx, h2_bucket_beam *beam, apr_off_t length)
322 {
323 }
324
325-static void stream_input_ev(void *ctx, h2_bucket_beam *beam)
326+static void mst_stream_input_ev(void *ctx, h2_bucket_beam *beam)
327 {
328 h2_stream *stream = ctx;
329 h2_mplx *m = stream->session->mplx;
330 apr_atomic_set32(&m->event_pending, 1);
331 }
332
333-static void stream_input_consumed(void *ctx, h2_bucket_beam *beam, apr_off_t length)
334+static void m_stream_input_consumed(void *ctx, h2_bucket_beam *beam, apr_off_t length)
335 {
336 h2_stream_in_consumed(ctx, length);
337 }
338
339-static void stream_joined(h2_mplx *m, h2_stream *stream)
340+static void ms_stream_joined(h2_mplx *m, h2_stream *stream)
341 {
342 ap_assert(!h2_task_has_started(stream->task) || stream->task->worker_done);
343
344@@ -109,7 +116,7 @@ static void stream_joined(h2_mplx *m, h2
345 h2_ihash_add(m->spurge, stream);
346 }
347
348-static void stream_cleanup(h2_mplx *m, h2_stream *stream)
349+static void m_stream_cleanup(h2_mplx *m, h2_stream *stream)
350 {
351 ap_assert(stream->state == H2_SS_CLEANUP);
352
353@@ -128,7 +135,7 @@ static void stream_cleanup(h2_mplx *m, h
354 h2_iq_remove(m->q, stream->id);
355
356 if (!h2_task_has_started(stream->task) || stream->task->done_done) {
357- stream_joined(m, stream);
358+ ms_stream_joined(m, stream);
359 }
360 else {
361 h2_ififo_remove(m->readyq, stream->id);
362@@ -150,8 +157,8 @@ static void stream_cleanup(h2_mplx *m, h
363 * their HTTP/1 cousins, the separate allocator seems to work better
364 * than protecting a shared h2_session one with an own lock.
365 */
366-h2_mplx *h2_mplx_create(conn_rec *c, server_rec *s, apr_pool_t *parent,
367- h2_workers *workers)
368+h2_mplx *h2_mplx_m_create(conn_rec *c, server_rec *s, apr_pool_t *parent,
369+ h2_workers *workers)
370 {
371 apr_status_t status = APR_SUCCESS;
372 apr_allocator_t *allocator;
373@@ -165,7 +172,7 @@ h2_mplx *h2_mplx_create(conn_rec *c, ser
374 m->s = s;
375
376 /* We create a pool with its own allocator to be used for
377- * processing slave connections. This is the only way to have the
378+ * processing secondary connections. This is the only way to have the
379 * processing independant of its parent pool in the sense that it
380 * can work in another thread. Also, the new allocator needs its own
381 * mutex to synchronize sub-pools.
382@@ -217,12 +224,12 @@ h2_mplx *h2_mplx_create(conn_rec *c, ser
383 m->last_mood_change = apr_time_now();
384 m->mood_update_interval = apr_time_from_msec(100);
385
386- m->spare_slaves = apr_array_make(m->pool, 10, sizeof(conn_rec*));
387+ m->spare_secondary = apr_array_make(m->pool, 10, sizeof(conn_rec*));
388 }
389 return m;
390 }
391
392-int h2_mplx_shutdown(h2_mplx *m)
393+int h2_mplx_m_shutdown(h2_mplx *m)
394 {
395 int max_stream_started = 0;
396
397@@ -236,7 +243,7 @@ int h2_mplx_shutdown(h2_mplx *m)
398 return max_stream_started;
399 }
400
401-static int input_consumed_signal(h2_mplx *m, h2_stream *stream)
402+static int m_input_consumed_signal(h2_mplx *m, h2_stream *stream)
403 {
404 if (stream->input) {
405 return h2_beam_report_consumption(stream->input);
406@@ -244,12 +251,12 @@ static int input_consumed_signal(h2_mplx
407 return 0;
408 }
409
410-static int report_consumption_iter(void *ctx, void *val)
411+static int m_report_consumption_iter(void *ctx, void *val)
412 {
413 h2_stream *stream = val;
414 h2_mplx *m = ctx;
415
416- input_consumed_signal(m, stream);
417+ m_input_consumed_signal(m, stream);
418 if (stream->state == H2_SS_CLOSED_L
419 && (!stream->task || stream->task->worker_done)) {
420 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, m->c,
421@@ -260,7 +267,7 @@ static int report_consumption_iter(void
422 return 1;
423 }
424
425-static int output_consumed_signal(h2_mplx *m, h2_task *task)
426+static int s_output_consumed_signal(h2_mplx *m, h2_task *task)
427 {
428 if (task->output.beam) {
429 return h2_beam_report_consumption(task->output.beam);
430@@ -268,7 +275,7 @@ static int output_consumed_signal(h2_mpl
431 return 0;
432 }
433
434-static int stream_destroy_iter(void *ctx, void *val)
435+static int m_stream_destroy_iter(void *ctx, void *val)
436 {
437 h2_mplx *m = ctx;
438 h2_stream *stream = val;
439@@ -278,7 +285,7 @@ static int stream_destroy_iter(void *ctx
440
441 if (stream->input) {
442 /* Process outstanding events before destruction */
443- input_consumed_signal(m, stream);
444+ m_input_consumed_signal(m, stream);
445 h2_beam_log(stream->input, m->c, APLOG_TRACE2, "stream_destroy");
446 h2_beam_destroy(stream->input);
447 stream->input = NULL;
448@@ -286,12 +293,12 @@ static int stream_destroy_iter(void *ctx
449
450 if (stream->task) {
451 h2_task *task = stream->task;
452- conn_rec *slave;
453- int reuse_slave = 0;
454+ conn_rec *secondary;
455+ int reuse_secondary = 0;
456
457 stream->task = NULL;
458- slave = task->c;
459- if (slave) {
460+ secondary = task->c;
461+ if (secondary) {
462 /* On non-serialized requests, the IO logging has not accounted for any
463 * meta data send over the network: response headers and h2 frame headers. we
464 * counted this on the stream and need to add this now.
465@@ -300,26 +307,25 @@ static int stream_destroy_iter(void *ctx
466 if (task->request && !task->request->serialize && h2_task_logio_add_bytes_out) {
467 apr_off_t unaccounted = stream->out_frame_octets - stream->out_data_octets;
468 if (unaccounted > 0) {
469- h2_task_logio_add_bytes_out(slave, unaccounted);
470+ h2_task_logio_add_bytes_out(secondary, unaccounted);
471 }
472 }
473
474- if (m->s->keep_alive_max == 0 || slave->keepalives < m->s->keep_alive_max) {
475- reuse_slave = ((m->spare_slaves->nelts < (m->limit_active * 3 / 2))
476- && !task->rst_error);
477+ if (m->s->keep_alive_max == 0 || secondary->keepalives < m->s->keep_alive_max) {
478+ reuse_secondary = ((m->spare_secondary->nelts < (m->limit_active * 3 / 2))
479+ && !task->rst_error);
480 }
481
482- task->c = NULL;
483- if (reuse_slave) {
484+ if (reuse_secondary) {
485 h2_beam_log(task->output.beam, m->c, APLOG_DEBUG,
486- APLOGNO(03385) "h2_task_destroy, reuse slave");
487+ APLOGNO(03385) "h2_task_destroy, reuse secondary");
488 h2_task_destroy(task);
489- APR_ARRAY_PUSH(m->spare_slaves, conn_rec*) = slave;
490+ APR_ARRAY_PUSH(m->spare_secondary, conn_rec*) = secondary;
491 }
492 else {
493 h2_beam_log(task->output.beam, m->c, APLOG_TRACE1,
494- "h2_task_destroy, destroy slave");
495- h2_slave_destroy(slave);
496+ "h2_task_destroy, destroy secondary");
497+ h2_secondary_destroy(secondary);
498 }
499 }
500 }
501@@ -327,11 +333,11 @@ static int stream_destroy_iter(void *ctx
502 return 0;
503 }
504
505-static void purge_streams(h2_mplx *m, int lock)
506+static void m_purge_streams(h2_mplx *m, int lock)
507 {
508 if (!h2_ihash_empty(m->spurge)) {
509 H2_MPLX_ENTER_MAYBE(m, lock);
510- while (!h2_ihash_iter(m->spurge, stream_destroy_iter, m)) {
511+ while (!h2_ihash_iter(m->spurge, m_stream_destroy_iter, m)) {
512 /* repeat until empty */
513 }
514 H2_MPLX_LEAVE_MAYBE(m, lock);
515@@ -343,13 +349,13 @@ typedef struct {
516 void *ctx;
517 } stream_iter_ctx_t;
518
519-static int stream_iter_wrap(void *ctx, void *stream)
520+static int m_stream_iter_wrap(void *ctx, void *stream)
521 {
522 stream_iter_ctx_t *x = ctx;
523 return x->cb(stream, x->ctx);
524 }
525
526-apr_status_t h2_mplx_stream_do(h2_mplx *m, h2_mplx_stream_cb *cb, void *ctx)
527+apr_status_t h2_mplx_m_stream_do(h2_mplx *m, h2_mplx_stream_cb *cb, void *ctx)
528 {
529 stream_iter_ctx_t x;
530
531@@ -357,13 +363,13 @@ apr_status_t h2_mplx_stream_do(h2_mplx *
532
533 x.cb = cb;
534 x.ctx = ctx;
535- h2_ihash_iter(m->streams, stream_iter_wrap, &x);
536+ h2_ihash_iter(m->streams, m_stream_iter_wrap, &x);
537
538 H2_MPLX_LEAVE(m);
539 return APR_SUCCESS;
540 }
541
542-static int report_stream_iter(void *ctx, void *val) {
543+static int m_report_stream_iter(void *ctx, void *val) {
544 h2_mplx *m = ctx;
545 h2_stream *stream = val;
546 h2_task *task = stream->task;
547@@ -388,7 +394,7 @@ static int report_stream_iter(void *ctx,
548 return 1;
549 }
550
551-static int unexpected_stream_iter(void *ctx, void *val) {
552+static int m_unexpected_stream_iter(void *ctx, void *val) {
553 h2_mplx *m = ctx;
554 h2_stream *stream = val;
555 ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, m->c, /* NO APLOGNO */
556@@ -397,7 +403,7 @@ static int unexpected_stream_iter(void *
557 return 1;
558 }
559
560-static int stream_cancel_iter(void *ctx, void *val) {
561+static int m_stream_cancel_iter(void *ctx, void *val) {
562 h2_mplx *m = ctx;
563 h2_stream *stream = val;
564
565@@ -411,11 +417,11 @@ static int stream_cancel_iter(void *ctx,
566 h2_stream_rst(stream, H2_ERR_NO_ERROR);
567 /* All connection data has been sent, simulate cleanup */
568 h2_stream_dispatch(stream, H2_SEV_EOS_SENT);
569- stream_cleanup(m, stream);
570+ m_stream_cleanup(m, stream);
571 return 0;
572 }
573
574-void h2_mplx_release_and_join(h2_mplx *m, apr_thread_cond_t *wait)
575+void h2_mplx_m_release_and_join(h2_mplx *m, apr_thread_cond_t *wait)
576 {
577 apr_status_t status;
578 int i, wait_secs = 60, old_aborted;
579@@ -429,7 +435,7 @@ void h2_mplx_release_and_join(h2_mplx *m
580
581 H2_MPLX_ENTER_ALWAYS(m);
582
583- /* While really terminating any slave connections, treat the master
584+ /* While really terminating any secondary connections, treat the master
585 * connection as aborted. It's not as if we could send any more data
586 * at this point. */
587 old_aborted = m->c->aborted;
588@@ -441,7 +447,7 @@ void h2_mplx_release_and_join(h2_mplx *m
589 "h2_mplx(%ld): release, %d/%d/%d streams (total/hold/purge), %d active tasks",
590 m->id, (int)h2_ihash_count(m->streams),
591 (int)h2_ihash_count(m->shold), (int)h2_ihash_count(m->spurge), m->tasks_active);
592- while (!h2_ihash_iter(m->streams, stream_cancel_iter, m)) {
593+ while (!h2_ihash_iter(m->streams, m_stream_cancel_iter, m)) {
594 /* until empty */
595 }
596
597@@ -463,7 +469,7 @@ void h2_mplx_release_and_join(h2_mplx *m
598 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, m->c, APLOGNO(03198)
599 "h2_mplx(%ld): waited %d sec for %d tasks",
600 m->id, i*wait_secs, (int)h2_ihash_count(m->shold));
601- h2_ihash_iter(m->shold, report_stream_iter, m);
602+ h2_ihash_iter(m->shold, m_report_stream_iter, m);
603 }
604 }
605 m->join_wait = NULL;
606@@ -474,7 +480,7 @@ void h2_mplx_release_and_join(h2_mplx *m
607 ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, m->c, APLOGNO(03516)
608 "h2_mplx(%ld): unexpected %d streams in hold",
609 m->id, (int)h2_ihash_count(m->shold));
610- h2_ihash_iter(m->shold, unexpected_stream_iter, m);
611+ h2_ihash_iter(m->shold, m_unexpected_stream_iter, m);
612 }
613
614 m->c->aborted = old_aborted;
615@@ -483,39 +489,39 @@ void h2_mplx_release_and_join(h2_mplx *m
616 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c, "h2_mplx(%ld): released", m->id);
617 }
618
619-apr_status_t h2_mplx_stream_cleanup(h2_mplx *m, h2_stream *stream)
620+apr_status_t h2_mplx_m_stream_cleanup(h2_mplx *m, h2_stream *stream)
621 {
622 H2_MPLX_ENTER(m);
623
624 ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c,
625 H2_STRM_MSG(stream, "cleanup"));
626- stream_cleanup(m, stream);
627+ m_stream_cleanup(m, stream);
628
629 H2_MPLX_LEAVE(m);
630 return APR_SUCCESS;
631 }
632
633-h2_stream *h2_mplx_stream_get(h2_mplx *m, int id)
634+h2_stream *h2_mplx_t_stream_get(h2_mplx *m, h2_task *task)
635 {
636 h2_stream *s = NULL;
637
638 H2_MPLX_ENTER_ALWAYS(m);
639
640- s = h2_ihash_get(m->streams, id);
641+ s = h2_ihash_get(m->streams, task->stream_id);
642
643 H2_MPLX_LEAVE(m);
644 return s;
645 }
646
647-static void output_produced(void *ctx, h2_bucket_beam *beam, apr_off_t bytes)
648+static void mst_output_produced(void *ctx, h2_bucket_beam *beam, apr_off_t bytes)
649 {
650 h2_stream *stream = ctx;
651 h2_mplx *m = stream->session->mplx;
652
653- check_data_for(m, stream, 0);
654+ mst_check_data_for(m, stream, 0);
655 }
656
657-static apr_status_t out_open(h2_mplx *m, int stream_id, h2_bucket_beam *beam)
658+static apr_status_t t_out_open(h2_mplx *m, int stream_id, h2_bucket_beam *beam)
659 {
660 h2_stream *stream = h2_ihash_get(m->streams, stream_id);
661
662@@ -527,26 +533,26 @@ static apr_status_t out_open(h2_mplx *m,
663 stream->output = beam;
664
665 if (APLOGctrace2(m->c)) {
666- h2_beam_log(beam, m->c, APLOG_TRACE2, "out_open");
667+ h2_beam_log(beam, stream->task->c, APLOG_TRACE2, "out_open");
668 }
669 else {
670- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
671+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, stream->task->c,
672 "h2_mplx(%s): out open", stream->task->id);
673 }
674
675- h2_beam_on_consumed(stream->output, NULL, stream_output_consumed, stream);
676- h2_beam_on_produced(stream->output, output_produced, stream);
677+ h2_beam_on_consumed(stream->output, NULL, mst_stream_output_consumed, stream);
678+ h2_beam_on_produced(stream->output, mst_output_produced, stream);
679 if (stream->task->output.copy_files) {
680 h2_beam_on_file_beam(stream->output, h2_beam_no_files, NULL);
681 }
682
683 /* we might see some file buckets in the output, see
684 * if we have enough handles reserved. */
685- check_data_for(m, stream, 1);
686+ mst_check_data_for(m, stream, 1);
687 return APR_SUCCESS;
688 }
689
690-apr_status_t h2_mplx_out_open(h2_mplx *m, int stream_id, h2_bucket_beam *beam)
691+apr_status_t h2_mplx_t_out_open(h2_mplx *m, int stream_id, h2_bucket_beam *beam)
692 {
693 apr_status_t status;
694
695@@ -556,14 +562,14 @@ apr_status_t h2_mplx_out_open(h2_mplx *m
696 status = APR_ECONNABORTED;
697 }
698 else {
699- status = out_open(m, stream_id, beam);
700+ status = t_out_open(m, stream_id, beam);
701 }
702
703 H2_MPLX_LEAVE(m);
704 return status;
705 }
706
707-static apr_status_t out_close(h2_mplx *m, h2_task *task)
708+static apr_status_t s_out_close(h2_mplx *m, h2_task *task)
709 {
710 apr_status_t status = APR_SUCCESS;
711 h2_stream *stream;
712@@ -580,17 +586,17 @@ static apr_status_t out_close(h2_mplx *m
713 return APR_ECONNABORTED;
714 }
715
716- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, m->c,
717+ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, task->c,
718 "h2_mplx(%s): close", task->id);
719 status = h2_beam_close(task->output.beam);
720- h2_beam_log(task->output.beam, m->c, APLOG_TRACE2, "out_close");
721- output_consumed_signal(m, task);
722- check_data_for(m, stream, 1);
723+ h2_beam_log(task->output.beam, task->c, APLOG_TRACE2, "out_close");
724+ s_output_consumed_signal(m, task);
725+ mst_check_data_for(m, stream, 1);
726 return status;
727 }
728
729-apr_status_t h2_mplx_out_trywait(h2_mplx *m, apr_interval_time_t timeout,
730- apr_thread_cond_t *iowait)
731+apr_status_t h2_mplx_m_out_trywait(h2_mplx *m, apr_interval_time_t timeout,
732+ apr_thread_cond_t *iowait)
733 {
734 apr_status_t status;
735
736@@ -599,12 +605,12 @@ apr_status_t h2_mplx_out_trywait(h2_mplx
737 if (m->aborted) {
738 status = APR_ECONNABORTED;
739 }
740- else if (h2_mplx_has_master_events(m)) {
741+ else if (h2_mplx_m_has_master_events(m)) {
742 status = APR_SUCCESS;
743 }
744 else {
745- purge_streams(m, 0);
746- h2_ihash_iter(m->streams, report_consumption_iter, m);
747+ m_purge_streams(m, 0);
748+ h2_ihash_iter(m->streams, m_report_consumption_iter, m);
749 m->added_output = iowait;
750 status = apr_thread_cond_timedwait(m->added_output, m->lock, timeout);
751 if (APLOGctrace2(m->c)) {
752@@ -619,7 +625,7 @@ apr_status_t h2_mplx_out_trywait(h2_mplx
753 return status;
754 }
755
756-static void check_data_for(h2_mplx *m, h2_stream *stream, int mplx_is_locked)
757+static void mst_check_data_for(h2_mplx *m, h2_stream *stream, int mplx_is_locked)
758 {
759 /* If m->lock is already held, we must release during h2_ififo_push()
760 * which can wait on its not_full condition, causing a deadlock because
761@@ -639,7 +645,7 @@ static void check_data_for(h2_mplx *m, h
762 }
763 }
764
765-apr_status_t h2_mplx_reprioritize(h2_mplx *m, h2_stream_pri_cmp *cmp, void *ctx)
766+apr_status_t h2_mplx_m_reprioritize(h2_mplx *m, h2_stream_pri_cmp *cmp, void *ctx)
767 {
768 apr_status_t status;
769
770@@ -659,22 +665,22 @@ apr_status_t h2_mplx_reprioritize(h2_mpl
771 return status;
772 }
773
774-static void register_if_needed(h2_mplx *m)
775+static void ms_register_if_needed(h2_mplx *m, int from_master)
776 {
777 if (!m->aborted && !m->is_registered && !h2_iq_empty(m->q)) {
778 apr_status_t status = h2_workers_register(m->workers, m);
779 if (status == APR_SUCCESS) {
780 m->is_registered = 1;
781 }
782- else {
783+ else if (from_master) {
784 ap_log_cerror(APLOG_MARK, APLOG_ERR, status, m->c, APLOGNO(10021)
785 "h2_mplx(%ld): register at workers", m->id);
786 }
787 }
788 }
789
790-apr_status_t h2_mplx_process(h2_mplx *m, struct h2_stream *stream,
791- h2_stream_pri_cmp *cmp, void *ctx)
792+apr_status_t h2_mplx_m_process(h2_mplx *m, struct h2_stream *stream,
793+ h2_stream_pri_cmp *cmp, void *ctx)
794 {
795 apr_status_t status;
796
797@@ -688,13 +694,13 @@ apr_status_t h2_mplx_process(h2_mplx *m,
798 h2_ihash_add(m->streams, stream);
799 if (h2_stream_is_ready(stream)) {
800 /* already have a response */
801- check_data_for(m, stream, 1);
802+ mst_check_data_for(m, stream, 1);
803 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
804 H2_STRM_MSG(stream, "process, add to readyq"));
805 }
806 else {
807 h2_iq_add(m->q, stream->id, cmp, ctx);
808- register_if_needed(m);
809+ ms_register_if_needed(m, 1);
810 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
811 H2_STRM_MSG(stream, "process, added to q"));
812 }
813@@ -704,7 +710,7 @@ apr_status_t h2_mplx_process(h2_mplx *m,
814 return status;
815 }
816
817-static h2_task *next_stream_task(h2_mplx *m)
818+static h2_task *s_next_stream_task(h2_mplx *m)
819 {
820 h2_stream *stream;
821 int sid;
822@@ -713,15 +719,15 @@ static h2_task *next_stream_task(h2_mplx
823
824 stream = h2_ihash_get(m->streams, sid);
825 if (stream) {
826- conn_rec *slave, **pslave;
827+ conn_rec *secondary, **psecondary;
828
829- pslave = (conn_rec **)apr_array_pop(m->spare_slaves);
830- if (pslave) {
831- slave = *pslave;
832- slave->aborted = 0;
833+ psecondary = (conn_rec **)apr_array_pop(m->spare_secondary);
834+ if (psecondary) {
835+ secondary = *psecondary;
836+ secondary->aborted = 0;
837 }
838 else {
839- slave = h2_slave_create(m->c, stream->id, m->pool);
840+ secondary = h2_secondary_create(m->c, stream->id, m->pool);
841 }
842
843 if (!stream->task) {
844@@ -729,16 +735,16 @@ static h2_task *next_stream_task(h2_mplx
845 m->max_stream_started = sid;
846 }
847 if (stream->input) {
848- h2_beam_on_consumed(stream->input, stream_input_ev,
849- stream_input_consumed, stream);
850+ h2_beam_on_consumed(stream->input, mst_stream_input_ev,
851+ m_stream_input_consumed, stream);
852 }
853
854- stream->task = h2_task_create(slave, stream->id,
855+ stream->task = h2_task_create(secondary, stream->id,
856 stream->request, m, stream->input,
857 stream->session->s->timeout,
858 m->stream_max_mem);
859 if (!stream->task) {
860- ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_ENOMEM, slave,
861+ ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_ENOMEM, secondary,
862 H2_STRM_LOG(APLOGNO(02941), stream,
863 "create task"));
864 return NULL;
865@@ -753,7 +759,7 @@ static h2_task *next_stream_task(h2_mplx
866 return NULL;
867 }
868
869-apr_status_t h2_mplx_pop_task(h2_mplx *m, h2_task **ptask)
870+apr_status_t h2_mplx_s_pop_task(h2_mplx *m, h2_task **ptask)
871 {
872 apr_status_t rv = APR_EOF;
873
874@@ -769,7 +775,7 @@ apr_status_t h2_mplx_pop_task(h2_mplx *m
875 rv = APR_EOF;
876 }
877 else {
878- *ptask = next_stream_task(m);
879+ *ptask = s_next_stream_task(m);
880 rv = (*ptask != NULL && !h2_iq_empty(m->q))? APR_EAGAIN : APR_SUCCESS;
881 }
882 if (APR_EAGAIN != rv) {
883@@ -779,22 +785,22 @@ apr_status_t h2_mplx_pop_task(h2_mplx *m
884 return rv;
885 }
886
887-static void task_done(h2_mplx *m, h2_task *task)
888+static void s_task_done(h2_mplx *m, h2_task *task)
889 {
890 h2_stream *stream;
891
892- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
893+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, task->c,
894 "h2_mplx(%ld): task(%s) done", m->id, task->id);
895- out_close(m, task);
896+ s_out_close(m, task);
897
898 task->worker_done = 1;
899 task->done_at = apr_time_now();
900- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c,
901+ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, task->c,
902 "h2_mplx(%s): request done, %f ms elapsed", task->id,
903 (task->done_at - task->started_at) / 1000.0);
904
905 if (task->c && !task->c->aborted && task->started_at > m->last_mood_change) {
906- mplx_be_happy(m);
907+ s_mplx_be_happy(m, task);
908 }
909
910 ap_assert(task->done_done == 0);
911@@ -806,60 +812,60 @@ static void task_done(h2_mplx *m, h2_tas
912 /* reset and schedule again */
913 h2_task_redo(task);
914 h2_iq_add(m->q, stream->id, NULL, NULL);
915- ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, m->c,
916+ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, task->c,
917 H2_STRM_MSG(stream, "redo, added to q"));
918 }
919 else {
920 /* stream not cleaned up, stay around */
921 task->done_done = 1;
922- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c,
923+ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, task->c,
924 H2_STRM_MSG(stream, "task_done, stream open"));
925 if (stream->input) {
926 h2_beam_leave(stream->input);
927 }
928
929 /* more data will not arrive, resume the stream */
930- check_data_for(m, stream, 1);
931+ mst_check_data_for(m, stream, 1);
932 }
933 }
934 else if ((stream = h2_ihash_get(m->shold, task->stream_id)) != NULL) {
935 /* stream is done, was just waiting for this. */
936 task->done_done = 1;
937- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c,
938+ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, task->c,
939 H2_STRM_MSG(stream, "task_done, in hold"));
940 if (stream->input) {
941 h2_beam_leave(stream->input);
942 }
943- stream_joined(m, stream);
944+ ms_stream_joined(m, stream);
945 }
946 else if ((stream = h2_ihash_get(m->spurge, task->stream_id)) != NULL) {
947- ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, m->c,
948+ ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, task->c,
949 H2_STRM_LOG(APLOGNO(03517), stream, "already in spurge"));
950 ap_assert("stream should not be in spurge" == NULL);
951 }
952 else {
953- ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, m->c, APLOGNO(03518)
954+ ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, task->c, APLOGNO(03518)
955 "h2_mplx(%s): task_done, stream not found",
956 task->id);
957 ap_assert("stream should still be available" == NULL);
958 }
959 }
960
961-void h2_mplx_task_done(h2_mplx *m, h2_task *task, h2_task **ptask)
962+void h2_mplx_s_task_done(h2_mplx *m, h2_task *task, h2_task **ptask)
963 {
964 H2_MPLX_ENTER_ALWAYS(m);
965
966 --m->tasks_active;
967- task_done(m, task);
968+ s_task_done(m, task);
969
970 if (m->join_wait) {
971 apr_thread_cond_signal(m->join_wait);
972 }
973 if (ptask) {
974 /* caller wants another task */
975- *ptask = next_stream_task(m);
976+ *ptask = s_next_stream_task(m);
977 }
978- register_if_needed(m);
979+ ms_register_if_needed(m, 0);
980
981 H2_MPLX_LEAVE(m);
982 }
983@@ -868,7 +874,7 @@ void h2_mplx_task_done(h2_mplx *m, h2_ta
984 * h2_mplx DoS protection
985 ******************************************************************************/
986
987-static int timed_out_busy_iter(void *data, void *val)
988+static int m_timed_out_busy_iter(void *data, void *val)
989 {
990 stream_iter_ctx *ctx = data;
991 h2_stream *stream = val;
992@@ -881,17 +887,17 @@ static int timed_out_busy_iter(void *dat
993 return 1;
994 }
995
996-static h2_stream *get_timed_out_busy_stream(h2_mplx *m)
997+static h2_stream *m_get_timed_out_busy_stream(h2_mplx *m)
998 {
999 stream_iter_ctx ctx;
1000 ctx.m = m;
1001 ctx.stream = NULL;
1002 ctx.now = apr_time_now();
1003- h2_ihash_iter(m->streams, timed_out_busy_iter, &ctx);
1004+ h2_ihash_iter(m->streams, m_timed_out_busy_iter, &ctx);
1005 return ctx.stream;
1006 }
1007
1008-static int latest_repeatable_unsubmitted_iter(void *data, void *val)
1009+static int m_latest_repeatable_unsubmitted_iter(void *data, void *val)
1010 {
1011 stream_iter_ctx *ctx = data;
1012 h2_stream *stream = val;
1013@@ -917,7 +923,7 @@ leave:
1014 return 1;
1015 }
1016
1017-static apr_status_t assess_task_to_throttle(h2_task **ptask, h2_mplx *m)
1018+static apr_status_t m_assess_task_to_throttle(h2_task **ptask, h2_mplx *m)
1019 {
1020 stream_iter_ctx ctx;
1021
1022@@ -927,7 +933,7 @@ static apr_status_t assess_task_to_throt
1023 ctx.m = m;
1024 ctx.stream = NULL;
1025 ctx.count = 0;
1026- h2_ihash_iter(m->streams, latest_repeatable_unsubmitted_iter, &ctx);
1027+ h2_ihash_iter(m->streams, m_latest_repeatable_unsubmitted_iter, &ctx);
1028 if (m->tasks_active - ctx.count > m->limit_active) {
1029 /* we are above the limit of running tasks, accounting for the ones
1030 * already throttled. */
1031@@ -936,7 +942,7 @@ static apr_status_t assess_task_to_throt
1032 return APR_EAGAIN;
1033 }
1034 /* above limit, be seeing no candidate for easy throttling */
1035- if (get_timed_out_busy_stream(m)) {
1036+ if (m_get_timed_out_busy_stream(m)) {
1037 /* Too many busy workers, unable to cancel enough streams
1038 * and with a busy, timed out stream, we tell the client
1039 * to go away... */
1040@@ -946,7 +952,7 @@ static apr_status_t assess_task_to_throt
1041 return APR_SUCCESS;
1042 }
1043
1044-static apr_status_t unschedule_slow_tasks(h2_mplx *m)
1045+static apr_status_t m_unschedule_slow_tasks(h2_mplx *m)
1046 {
1047 h2_task *task;
1048 apr_status_t rv;
1049@@ -954,7 +960,7 @@ static apr_status_t unschedule_slow_task
1050 /* Try to get rid of streams that occupy workers. Look for safe requests
1051 * that are repeatable. If none found, fail the connection.
1052 */
1053- while (APR_EAGAIN == (rv = assess_task_to_throttle(&task, m))) {
1054+ while (APR_EAGAIN == (rv = m_assess_task_to_throttle(&task, m))) {
1055 ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c,
1056 "h2_mplx(%s): unschedule, resetting task for redo later",
1057 task->id);
1058@@ -965,7 +971,7 @@ static apr_status_t unschedule_slow_task
1059 return rv;
1060 }
1061
1062-static apr_status_t mplx_be_happy(h2_mplx *m)
1063+static apr_status_t s_mplx_be_happy(h2_mplx *m, h2_task *task)
1064 {
1065 apr_time_t now;
1066
1067@@ -977,14 +983,14 @@ static apr_status_t mplx_be_happy(h2_mpl
1068 m->limit_active = H2MIN(m->limit_active * 2, m->max_active);
1069 m->last_mood_change = now;
1070 m->irritations_since = 0;
1071- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
1072+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, task->c,
1073 "h2_mplx(%ld): mood update, increasing worker limit to %d",
1074 m->id, m->limit_active);
1075 }
1076 return APR_SUCCESS;
1077 }
1078
1079-static apr_status_t mplx_be_annoyed(h2_mplx *m)
1080+static apr_status_t m_be_annoyed(h2_mplx *m)
1081 {
1082 apr_status_t status = APR_SUCCESS;
1083 apr_time_t now;
1084@@ -1015,12 +1021,12 @@ static apr_status_t mplx_be_annoyed(h2_m
1085 }
1086
1087 if (m->tasks_active > m->limit_active) {
1088- status = unschedule_slow_tasks(m);
1089+ status = m_unschedule_slow_tasks(m);
1090 }
1091 return status;
1092 }
1093
1094-apr_status_t h2_mplx_idle(h2_mplx *m)
1095+apr_status_t h2_mplx_m_idle(h2_mplx *m)
1096 {
1097 apr_status_t status = APR_SUCCESS;
1098 apr_size_t scount;
1099@@ -1042,7 +1048,7 @@ apr_status_t h2_mplx_idle(h2_mplx *m)
1100 * of busy workers we allow for this connection until it
1101 * well behaves.
1102 */
1103- status = mplx_be_annoyed(m);
1104+ status = m_be_annoyed(m);
1105 }
1106 else if (!h2_iq_empty(m->q)) {
1107 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
1108@@ -1072,14 +1078,14 @@ apr_status_t h2_mplx_idle(h2_mplx *m)
1109 h2_beam_is_closed(stream->output),
1110 (long)h2_beam_get_buffered(stream->output));
1111 h2_ihash_add(m->streams, stream);
1112- check_data_for(m, stream, 1);
1113+ mst_check_data_for(m, stream, 1);
1114 stream->out_checked = 1;
1115 status = APR_EAGAIN;
1116 }
1117 }
1118 }
1119 }
1120- register_if_needed(m);
1121+ ms_register_if_needed(m, 1);
1122
1123 H2_MPLX_LEAVE(m);
1124 return status;
1125@@ -1089,14 +1095,13 @@ apr_status_t h2_mplx_idle(h2_mplx *m)
1126 * mplx master events dispatching
1127 ******************************************************************************/
1128
1129-int h2_mplx_has_master_events(h2_mplx *m)
1130+int h2_mplx_m_has_master_events(h2_mplx *m)
1131 {
1132 return apr_atomic_read32(&m->event_pending) > 0;
1133 }
1134
1135-apr_status_t h2_mplx_dispatch_master_events(h2_mplx *m,
1136- stream_ev_callback *on_resume,
1137- void *on_ctx)
1138+apr_status_t h2_mplx_m_dispatch_master_events(h2_mplx *m, stream_ev_callback *on_resume,
1139+ void *on_ctx)
1140 {
1141 h2_stream *stream;
1142 int n, id;
1143@@ -1106,8 +1111,8 @@ apr_status_t h2_mplx_dispatch_master_eve
1144 apr_atomic_set32(&m->event_pending, 0);
1145
1146 /* update input windows for streams */
1147- h2_ihash_iter(m->streams, report_consumption_iter, m);
1148- purge_streams(m, 1);
1149+ h2_ihash_iter(m->streams, m_report_consumption_iter, m);
1150+ m_purge_streams(m, 1);
1151
1152 n = h2_ififo_count(m->readyq);
1153 while (n > 0
1154@@ -1122,13 +1127,13 @@ apr_status_t h2_mplx_dispatch_master_eve
1155 return APR_SUCCESS;
1156 }
1157
1158-apr_status_t h2_mplx_keep_active(h2_mplx *m, h2_stream *stream)
1159+apr_status_t h2_mplx_m_keep_active(h2_mplx *m, h2_stream *stream)
1160 {
1161- check_data_for(m, stream, 0);
1162+ mst_check_data_for(m, stream, 0);
1163 return APR_SUCCESS;
1164 }
1165
1166-int h2_mplx_awaits_data(h2_mplx *m)
1167+int h2_mplx_m_awaits_data(h2_mplx *m)
1168 {
1169 int waiting = 1;
1170
1171@@ -1145,7 +1150,7 @@ int h2_mplx_awaits_data(h2_mplx *m)
1172 return waiting;
1173 }
1174
1175-apr_status_t h2_mplx_client_rst(h2_mplx *m, int stream_id)
1176+apr_status_t h2_mplx_m_client_rst(h2_mplx *m, int stream_id)
1177 {
1178 h2_stream *stream;
1179 apr_status_t status = APR_SUCCESS;
1180@@ -1153,7 +1158,7 @@ apr_status_t h2_mplx_client_rst(h2_mplx
1181 H2_MPLX_ENTER_ALWAYS(m);
1182 stream = h2_ihash_get(m->streams, stream_id);
1183 if (stream && stream->task) {
1184- status = mplx_be_annoyed(m);
1185+ status = m_be_annoyed(m);
1186 }
1187 H2_MPLX_LEAVE(m);
1188 return status;
1189--- a/modules/http2/h2_mplx.h
1190+++ b/modules/http2/h2_mplx.h
1191@@ -31,8 +31,10 @@
1192 * queued in the multiplexer. If a task thread tries to write more
1193 * data, it is blocked until space becomes available.
1194 *
1195- * Writing input is never blocked. In order to use flow control on the input,
1196- * the mplx can be polled for input data consumption.
1197+ * Naming Convention:
1198+ * "h2_mplx_m_" are methods only to be called by the main connection
1199+ * "h2_mplx_s_" are method only to be called by a secondary connection
1200+ * "h2_mplx_t_" are method only to be called by a task handler (can be master or secondary)
1201 */
1202
1203 struct apr_pool_t;
1204@@ -88,25 +90,23 @@ struct h2_mplx {
1205 apr_size_t stream_max_mem;
1206
1207 apr_pool_t *spare_io_pool;
1208- apr_array_header_t *spare_slaves; /* spare slave connections */
1209+ apr_array_header_t *spare_secondary; /* spare secondary connections */
1210
1211 struct h2_workers *workers;
1212 };
1213
1214-
1215-
1216 /*******************************************************************************
1217- * Object lifecycle and information.
1218+ * From the main connection processing: h2_mplx_m_*
1219 ******************************************************************************/
1220
1221-apr_status_t h2_mplx_child_init(apr_pool_t *pool, server_rec *s);
1222+apr_status_t h2_mplx_m_child_init(apr_pool_t *pool, server_rec *s);
1223
1224 /**
1225 * Create the multiplexer for the given HTTP2 session.
1226 * Implicitly has reference count 1.
1227 */
1228-h2_mplx *h2_mplx_create(conn_rec *c, server_rec *s, apr_pool_t *master,
1229- struct h2_workers *workers);
1230+h2_mplx *h2_mplx_m_create(conn_rec *c, server_rec *s, apr_pool_t *master,
1231+ struct h2_workers *workers);
1232
1233 /**
1234 * Decreases the reference counter of this mplx and waits for it
1235@@ -116,26 +116,14 @@ h2_mplx *h2_mplx_create(conn_rec *c, ser
1236 * @param m the mplx to be released and destroyed
1237 * @param wait condition var to wait on for ref counter == 0
1238 */
1239-void h2_mplx_release_and_join(h2_mplx *m, struct apr_thread_cond_t *wait);
1240-
1241-apr_status_t h2_mplx_pop_task(h2_mplx *m, struct h2_task **ptask);
1242-
1243-void h2_mplx_task_done(h2_mplx *m, struct h2_task *task, struct h2_task **ptask);
1244+void h2_mplx_m_release_and_join(h2_mplx *m, struct apr_thread_cond_t *wait);
1245
1246 /**
1247 * Shut down the multiplexer gracefully. Will no longer schedule new streams
1248 * but let the ongoing ones finish normally.
1249 * @return the highest stream id being/been processed
1250 */
1251-int h2_mplx_shutdown(h2_mplx *m);
1252-
1253-int h2_mplx_is_busy(h2_mplx *m);
1254-
1255-/*******************************************************************************
1256- * IO lifetime of streams.
1257- ******************************************************************************/
1258-
1259-struct h2_stream *h2_mplx_stream_get(h2_mplx *m, int id);
1260+int h2_mplx_m_shutdown(h2_mplx *m);
1261
1262 /**
1263 * Notifies mplx that a stream has been completely handled on the main
1264@@ -144,20 +132,16 @@ struct h2_stream *h2_mplx_stream_get(h2_
1265 * @param m the mplx itself
1266 * @param stream the stream ready for cleanup
1267 */
1268-apr_status_t h2_mplx_stream_cleanup(h2_mplx *m, struct h2_stream *stream);
1269+apr_status_t h2_mplx_m_stream_cleanup(h2_mplx *m, struct h2_stream *stream);
1270
1271 /**
1272 * Waits on output data from any stream in this session to become available.
1273 * Returns APR_TIMEUP if no data arrived in the given time.
1274 */
1275-apr_status_t h2_mplx_out_trywait(h2_mplx *m, apr_interval_time_t timeout,
1276- struct apr_thread_cond_t *iowait);
1277-
1278-apr_status_t h2_mplx_keep_active(h2_mplx *m, struct h2_stream *stream);
1279+apr_status_t h2_mplx_m_out_trywait(h2_mplx *m, apr_interval_time_t timeout,
1280+ struct apr_thread_cond_t *iowait);
1281
1282-/*******************************************************************************
1283- * Stream processing.
1284- ******************************************************************************/
1285+apr_status_t h2_mplx_m_keep_active(h2_mplx *m, struct h2_stream *stream);
1286
1287 /**
1288 * Process a stream request.
1289@@ -168,8 +152,8 @@ apr_status_t h2_mplx_keep_active(h2_mplx
1290 * @param cmp the stream priority compare function
1291 * @param ctx context data for the compare function
1292 */
1293-apr_status_t h2_mplx_process(h2_mplx *m, struct h2_stream *stream,
1294- h2_stream_pri_cmp *cmp, void *ctx);
1295+apr_status_t h2_mplx_m_process(h2_mplx *m, struct h2_stream *stream,
1296+ h2_stream_pri_cmp *cmp, void *ctx);
1297
1298 /**
1299 * Stream priorities have changed, reschedule pending requests.
1300@@ -178,7 +162,7 @@ apr_status_t h2_mplx_process(h2_mplx *m,
1301 * @param cmp the stream priority compare function
1302 * @param ctx context data for the compare function
1303 */
1304-apr_status_t h2_mplx_reprioritize(h2_mplx *m, h2_stream_pri_cmp *cmp, void *ctx);
1305+apr_status_t h2_mplx_m_reprioritize(h2_mplx *m, h2_stream_pri_cmp *cmp, void *ctx);
1306
1307 typedef apr_status_t stream_ev_callback(void *ctx, struct h2_stream *stream);
1308
1309@@ -186,7 +170,7 @@ typedef apr_status_t stream_ev_callback(
1310 * Check if the multiplexer has events for the master connection pending.
1311 * @return != 0 iff there are events pending
1312 */
1313-int h2_mplx_has_master_events(h2_mplx *m);
1314+int h2_mplx_m_has_master_events(h2_mplx *m);
1315
1316 /**
1317 * Dispatch events for the master connection, such as
1318@@ -194,108 +178,46 @@ int h2_mplx_has_master_events(h2_mplx *m
1319 * @param on_resume new output data has arrived for a suspended stream
1320 * @param ctx user supplied argument to invocation.
1321 */
1322-apr_status_t h2_mplx_dispatch_master_events(h2_mplx *m,
1323- stream_ev_callback *on_resume,
1324- void *ctx);
1325+apr_status_t h2_mplx_m_dispatch_master_events(h2_mplx *m, stream_ev_callback *on_resume,
1326+ void *ctx);
1327
1328-int h2_mplx_awaits_data(h2_mplx *m);
1329+int h2_mplx_m_awaits_data(h2_mplx *m);
1330
1331 typedef int h2_mplx_stream_cb(struct h2_stream *s, void *ctx);
1332
1333-apr_status_t h2_mplx_stream_do(h2_mplx *m, h2_mplx_stream_cb *cb, void *ctx);
1334+apr_status_t h2_mplx_m_stream_do(h2_mplx *m, h2_mplx_stream_cb *cb, void *ctx);
1335
1336-apr_status_t h2_mplx_client_rst(h2_mplx *m, int stream_id);
1337-
1338-/*******************************************************************************
1339- * Output handling of streams.
1340- ******************************************************************************/
1341+apr_status_t h2_mplx_m_client_rst(h2_mplx *m, int stream_id);
1342
1343 /**
1344- * Opens the output for the given stream with the specified response.
1345+ * Master connection has entered idle mode.
1346+ * @param m the mplx instance of the master connection
1347+ * @return != SUCCESS iff connection should be terminated
1348 */
1349-apr_status_t h2_mplx_out_open(h2_mplx *mplx, int stream_id,
1350- struct h2_bucket_beam *beam);
1351+apr_status_t h2_mplx_m_idle(h2_mplx *m);
1352
1353 /*******************************************************************************
1354- * h2_mplx list Manipulation.
1355+ * From a secondary connection processing: h2_mplx_s_*
1356 ******************************************************************************/
1357+apr_status_t h2_mplx_s_pop_task(h2_mplx *m, struct h2_task **ptask);
1358+void h2_mplx_s_task_done(h2_mplx *m, struct h2_task *task, struct h2_task **ptask);
1359
1360-/**
1361- * The magic pointer value that indicates the head of a h2_mplx list
1362- * @param b The mplx list
1363- * @return The magic pointer value
1364- */
1365-#define H2_MPLX_LIST_SENTINEL(b) APR_RING_SENTINEL((b), h2_mplx, link)
1366-
1367-/**
1368- * Determine if the mplx list is empty
1369- * @param b The list to check
1370- * @return true or false
1371- */
1372-#define H2_MPLX_LIST_EMPTY(b) APR_RING_EMPTY((b), h2_mplx, link)
1373-
1374-/**
1375- * Return the first mplx in a list
1376- * @param b The list to query
1377- * @return The first mplx in the list
1378- */
1379-#define H2_MPLX_LIST_FIRST(b) APR_RING_FIRST(b)
1380-
1381-/**
1382- * Return the last mplx in a list
1383- * @param b The list to query
1384- * @return The last mplx int he list
1385- */
1386-#define H2_MPLX_LIST_LAST(b) APR_RING_LAST(b)
1387-
1388-/**
1389- * Insert a single mplx at the front of a list
1390- * @param b The list to add to
1391- * @param e The mplx to insert
1392- */
1393-#define H2_MPLX_LIST_INSERT_HEAD(b, e) do { \
1394-h2_mplx *ap__b = (e); \
1395-APR_RING_INSERT_HEAD((b), ap__b, h2_mplx, link); \
1396-} while (0)
1397-
1398-/**
1399- * Insert a single mplx at the end of a list
1400- * @param b The list to add to
1401- * @param e The mplx to insert
1402- */
1403-#define H2_MPLX_LIST_INSERT_TAIL(b, e) do { \
1404-h2_mplx *ap__b = (e); \
1405-APR_RING_INSERT_TAIL((b), ap__b, h2_mplx, link); \
1406-} while (0)
1407+/*******************************************************************************
1408+ * From a h2_task owner: h2_mplx_s_*
1409+ * (a task is transfered from master to secondary connection and back in
1410+ * its normal lifetime).
1411+ ******************************************************************************/
1412
1413 /**
1414- * Get the next mplx in the list
1415- * @param e The current mplx
1416- * @return The next mplx
1417- */
1418-#define H2_MPLX_NEXT(e) APR_RING_NEXT((e), link)
1419-/**
1420- * Get the previous mplx in the list
1421- * @param e The current mplx
1422- * @return The previous mplx
1423+ * Opens the output for the given stream with the specified response.
1424 */
1425-#define H2_MPLX_PREV(e) APR_RING_PREV((e), link)
1426+apr_status_t h2_mplx_t_out_open(h2_mplx *mplx, int stream_id,
1427+ struct h2_bucket_beam *beam);
1428
1429 /**
1430- * Remove a mplx from its list
1431- * @param e The mplx to remove
1432+ * Get the stream that belongs to the given task.
1433 */
1434-#define H2_MPLX_REMOVE(e) APR_RING_REMOVE((e), link)
1435-
1436-/*******************************************************************************
1437- * h2_mplx DoS protection
1438- ******************************************************************************/
1439+struct h2_stream *h2_mplx_t_stream_get(h2_mplx *m, struct h2_task *task);
1440
1441-/**
1442- * Master connection has entered idle mode.
1443- * @param m the mplx instance of the master connection
1444- * @return != SUCCESS iff connection should be terminated
1445- */
1446-apr_status_t h2_mplx_idle(h2_mplx *m);
1447
1448 #endif /* defined(__mod_h2__h2_mplx__) */
1449--- a/modules/http2/h2_request.c
1450+++ b/modules/http2/h2_request.c
1451@@ -288,6 +288,9 @@ request_rec *h2_request_create_rec(const
1452 if (r->method_number == M_GET && r->method[0] == 'H') {
1453 r->header_only = 1;
1454 }
1455+ r->the_request = apr_psprintf(r->pool, "%s %s HTTP/2.0",
1456+ req->method, req->path ? req->path : "");
1457+ r->headers_in = apr_table_clone(r->pool, req->headers);
1458
1459 rpath = (req->path ? req->path : "");
1460 ap_parse_uri(r, rpath);
1461@@ -304,7 +307,9 @@ request_rec *h2_request_create_rec(const
1462 */
1463 r->hostname = NULL;
1464 ap_update_vhost_from_headers(r);
1465-
1466+ r->protocol = "HTTP/2.0";
1467+ r->proto_num = HTTP_VERSION(2, 0);
1468+
1469 /* we may have switched to another server */
1470 r->per_dir_config = r->server->lookup_defaults;
1471
1472--- a/modules/http2/h2_session.c
1473+++ b/modules/http2/h2_session.c
1474@@ -106,7 +106,7 @@ static int rst_unprocessed_stream(h2_str
1475
1476 static void cleanup_unprocessed_streams(h2_session *session)
1477 {
1478- h2_mplx_stream_do(session->mplx, rst_unprocessed_stream, session);
1479+ h2_mplx_m_stream_do(session->mplx, rst_unprocessed_stream, session);
1480 }
1481
1482 static h2_stream *h2_session_open_stream(h2_session *session, int stream_id,
1483@@ -397,7 +397,7 @@ static int on_frame_recv_cb(nghttp2_sess
1484 else {
1485 /* A stream reset on a request it sent us. Could happen in a browser
1486 * when the user navigates away or cancels loading - maybe. */
1487- h2_mplx_client_rst(session->mplx, frame->hd.stream_id);
1488+ h2_mplx_m_client_rst(session->mplx, frame->hd.stream_id);
1489 ++session->streams_reset;
1490 }
1491 break;
1492@@ -467,7 +467,7 @@ static int on_frame_recv_cb(nghttp2_sess
1493 }
1494
1495 static int h2_session_continue_data(h2_session *session) {
1496- if (h2_mplx_has_master_events(session->mplx)) {
1497+ if (h2_mplx_m_has_master_events(session->mplx)) {
1498 return 0;
1499 }
1500 if (h2_conn_io_needs_flush(&session->io)) {
1501@@ -729,7 +729,7 @@ static apr_status_t h2_session_shutdown(
1502 * Remove all streams greater than this number without submitting
1503 * a RST_STREAM frame, since that should be clear from the GOAWAY
1504 * we send. */
1505- session->local.accepted_max = h2_mplx_shutdown(session->mplx);
1506+ session->local.accepted_max = h2_mplx_m_shutdown(session->mplx);
1507 session->local.error = error;
1508 }
1509 else {
1510@@ -779,7 +779,7 @@ static apr_status_t session_cleanup(h2_s
1511 }
1512
1513 transit(session, trigger, H2_SESSION_ST_CLEANUP);
1514- h2_mplx_release_and_join(session->mplx, session->iowait);
1515+ h2_mplx_m_release_and_join(session->mplx, session->iowait);
1516 session->mplx = NULL;
1517
1518 ap_assert(session->ngh2);
1519@@ -800,7 +800,7 @@ static apr_status_t session_pool_cleanup
1520 /* if the session is still there, now is the last chance
1521 * to perform cleanup. Normally, cleanup should have happened
1522 * earlier in the connection pre_close. Main reason is that
1523- * any ongoing requests on slave connections might still access
1524+ * any ongoing requests on secondary connections might still access
1525 * data which has, at this time, already been freed. An example
1526 * is mod_ssl that uses request hooks. */
1527 ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c,
1528@@ -893,7 +893,7 @@ apr_status_t h2_session_create(h2_sessio
1529 session->monitor->on_state_event = on_stream_state_event;
1530 session->monitor->on_event = on_stream_event;
1531
1532- session->mplx = h2_mplx_create(c, s, session->pool, workers);
1533+ session->mplx = h2_mplx_m_create(c, s, session->pool, workers);
1534
1535 /* connection input filter that feeds the session */
1536 session->cin = h2_filter_cin_create(session);
1537@@ -1552,7 +1552,7 @@ static void h2_session_in_flush(h2_sessi
1538 if (stream) {
1539 ap_assert(!stream->scheduled);
1540 if (h2_stream_prep_processing(stream) == APR_SUCCESS) {
1541- h2_mplx_process(session->mplx, stream, stream_pri_cmp, session);
1542+ h2_mplx_m_process(session->mplx, stream, stream_pri_cmp, session);
1543 }
1544 else {
1545 h2_stream_rst(stream, H2_ERR_INTERNAL_ERROR);
1546@@ -1824,7 +1824,7 @@ static void h2_session_ev_no_io(h2_sessi
1547 session->open_streams);
1548 h2_conn_io_flush(&session->io);
1549 if (session->open_streams > 0) {
1550- if (h2_mplx_awaits_data(session->mplx)) {
1551+ if (h2_mplx_m_awaits_data(session->mplx)) {
1552 /* waiting for at least one stream to produce data */
1553 transit(session, "no io", H2_SESSION_ST_WAIT);
1554 }
1555@@ -1983,7 +1983,7 @@ static void on_stream_state_enter(void *
1556 break;
1557 case H2_SS_CLEANUP:
1558 nghttp2_session_set_stream_user_data(session->ngh2, stream->id, NULL);
1559- h2_mplx_stream_cleanup(session->mplx, stream);
1560+ h2_mplx_m_stream_cleanup(session->mplx, stream);
1561 break;
1562 default:
1563 break;
1564@@ -2073,7 +2073,7 @@ static void dispatch_event(h2_session *s
1565 static apr_status_t dispatch_master(h2_session *session) {
1566 apr_status_t status;
1567
1568- status = h2_mplx_dispatch_master_events(session->mplx,
1569+ status = h2_mplx_m_dispatch_master_events(session->mplx,
1570 on_stream_resume, session);
1571 if (status == APR_EAGAIN) {
1572 ap_log_cerror(APLOG_MARK, APLOG_TRACE3, status, session->c,
1573@@ -2175,7 +2175,7 @@ apr_status_t h2_session_process(h2_sessi
1574 session->have_read = 1;
1575 }
1576 else if (APR_STATUS_IS_EAGAIN(status) || APR_STATUS_IS_TIMEUP(status)) {
1577- status = h2_mplx_idle(session->mplx);
1578+ status = h2_mplx_m_idle(session->mplx);
1579 if (status == APR_EAGAIN) {
1580 break;
1581 }
1582@@ -2205,7 +2205,7 @@ apr_status_t h2_session_process(h2_sessi
1583 /* We wait in smaller increments, using a 1 second timeout.
1584 * That gives us the chance to check for MPMQ_STOPPING often.
1585 */
1586- status = h2_mplx_idle(session->mplx);
1587+ status = h2_mplx_m_idle(session->mplx);
1588 if (status == APR_EAGAIN) {
1589 break;
1590 }
1591@@ -2319,7 +2319,7 @@ apr_status_t h2_session_process(h2_sessi
1592 "h2_session: wait for data, %ld micros",
1593 (long)session->wait_us);
1594 }
1595- status = h2_mplx_out_trywait(session->mplx, session->wait_us,
1596+ status = h2_mplx_m_out_trywait(session->mplx, session->wait_us,
1597 session->iowait);
1598 if (status == APR_SUCCESS) {
1599 session->wait_us = 0;
1600@@ -2356,7 +2356,7 @@ apr_status_t h2_session_process(h2_sessi
1601 dispatch_event(session, H2_SESSION_EV_NGH2_DONE, 0, NULL);
1602 }
1603 if (session->reprioritize) {
1604- h2_mplx_reprioritize(session->mplx, stream_pri_cmp, session);
1605+ h2_mplx_m_reprioritize(session->mplx, stream_pri_cmp, session);
1606 session->reprioritize = 0;
1607 }
1608 }
1609--- a/modules/http2/h2_session.h
1610+++ b/modules/http2/h2_session.h
1611@@ -132,7 +132,7 @@ typedef struct h2_session {
1612 const char *last_status_msg; /* the one already reported */
1613
1614 struct h2_iqueue *in_pending; /* all streams with input pending */
1615- struct h2_iqueue *in_process; /* all streams ready for processing on slave */
1616+ struct h2_iqueue *in_process; /* all streams ready for processing on a secondary */
1617
1618 } h2_session;
1619
1620--- a/modules/http2/h2_stream.c
1621+++ b/modules/http2/h2_stream.c
1622@@ -903,7 +903,7 @@ apr_status_t h2_stream_out_prepare(h2_st
1623
1624 if (status == APR_EAGAIN) {
1625 /* TODO: ugly, someone needs to retrieve the response first */
1626- h2_mplx_keep_active(stream->session->mplx, stream);
1627+ h2_mplx_m_keep_active(stream->session->mplx, stream);
1628 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
1629 H2_STRM_MSG(stream, "prep, response eagain"));
1630 return status;
1631--- a/modules/http2/h2_task.c
1632+++ b/modules/http2/h2_task.c
1633@@ -86,7 +86,7 @@ static apr_status_t open_output(h2_task
1634 task->request->authority,
1635 task->request->path);
1636 task->output.opened = 1;
1637- return h2_mplx_out_open(task->mplx, task->stream_id, task->output.beam);
1638+ return h2_mplx_t_out_open(task->mplx, task->stream_id, task->output.beam);
1639 }
1640
1641 static apr_status_t send_out(h2_task *task, apr_bucket_brigade* bb, int block)
1642@@ -126,8 +126,8 @@ static apr_status_t send_out(h2_task *ta
1643 * request_rec out filter chain) into the h2_mplx for further sending
1644 * on the master connection.
1645 */
1646-static apr_status_t slave_out(h2_task *task, ap_filter_t* f,
1647- apr_bucket_brigade* bb)
1648+static apr_status_t secondary_out(h2_task *task, ap_filter_t* f,
1649+ apr_bucket_brigade* bb)
1650 {
1651 apr_bucket *b;
1652 apr_status_t rv = APR_SUCCESS;
1653@@ -175,7 +175,7 @@ send:
1654 if (APR_SUCCESS == rv) {
1655 /* could not write all, buffer the rest */
1656 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, task->c, APLOGNO(03405)
1657- "h2_slave_out(%s): saving brigade", task->id);
1658+ "h2_secondary_out(%s): saving brigade", task->id);
1659 ap_assert(NULL);
1660 rv = ap_save_brigade(f, &task->output.bb, &bb, task->pool);
1661 flush = 1;
1662@@ -189,7 +189,7 @@ send:
1663 }
1664 out:
1665 ap_log_cerror(APLOG_MARK, APLOG_TRACE2, rv, task->c,
1666- "h2_slave_out(%s): slave_out leave", task->id);
1667+ "h2_secondary_out(%s): secondary_out leave", task->id);
1668 return rv;
1669 }
1670
1671@@ -202,14 +202,14 @@ static apr_status_t output_finish(h2_tas
1672 }
1673
1674 /*******************************************************************************
1675- * task slave connection filters
1676+ * task secondary connection filters
1677 ******************************************************************************/
1678
1679-static apr_status_t h2_filter_slave_in(ap_filter_t* f,
1680- apr_bucket_brigade* bb,
1681- ap_input_mode_t mode,
1682- apr_read_type_e block,
1683- apr_off_t readbytes)
1684+static apr_status_t h2_filter_secondary_in(ap_filter_t* f,
1685+ apr_bucket_brigade* bb,
1686+ ap_input_mode_t mode,
1687+ apr_read_type_e block,
1688+ apr_off_t readbytes)
1689 {
1690 h2_task *task;
1691 apr_status_t status = APR_SUCCESS;
1692@@ -224,7 +224,7 @@ static apr_status_t h2_filter_slave_in(a
1693
1694 if (trace1) {
1695 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, f->c,
1696- "h2_slave_in(%s): read, mode=%d, block=%d, readbytes=%ld",
1697+ "h2_secondary_in(%s): read, mode=%d, block=%d, readbytes=%ld",
1698 task->id, mode, block, (long)readbytes);
1699 }
1700
1701@@ -254,7 +254,7 @@ static apr_status_t h2_filter_slave_in(a
1702 /* Get more input data for our request. */
1703 if (trace1) {
1704 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, f->c,
1705- "h2_slave_in(%s): get more data from mplx, block=%d, "
1706+ "h2_secondary_in(%s): get more data from mplx, block=%d, "
1707 "readbytes=%ld", task->id, block, (long)readbytes);
1708 }
1709 if (task->input.beam) {
1710@@ -267,7 +267,7 @@ static apr_status_t h2_filter_slave_in(a
1711
1712 if (trace1) {
1713 ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, f->c,
1714- "h2_slave_in(%s): read returned", task->id);
1715+ "h2_secondary_in(%s): read returned", task->id);
1716 }
1717 if (APR_STATUS_IS_EAGAIN(status)
1718 && (mode == AP_MODE_GETLINE || block == APR_BLOCK_READ)) {
1719@@ -306,7 +306,7 @@ static apr_status_t h2_filter_slave_in(a
1720 if (APR_BRIGADE_EMPTY(task->input.bb)) {
1721 if (trace1) {
1722 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, f->c,
1723- "h2_slave_in(%s): no data", task->id);
1724+ "h2_secondary_in(%s): no data", task->id);
1725 }
1726 return (block == APR_NONBLOCK_READ)? APR_EAGAIN : APR_EOF;
1727 }
1728@@ -334,7 +334,7 @@ static apr_status_t h2_filter_slave_in(a
1729 buffer[len] = 0;
1730 if (trace1) {
1731 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, f->c,
1732- "h2_slave_in(%s): getline: %s",
1733+ "h2_secondary_in(%s): getline: %s",
1734 task->id, buffer);
1735 }
1736 }
1737@@ -344,7 +344,7 @@ static apr_status_t h2_filter_slave_in(a
1738 * to support it. Seems to work. */
1739 ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_ENOTIMPL, f->c,
1740 APLOGNO(03472)
1741- "h2_slave_in(%s), unsupported READ mode %d",
1742+ "h2_secondary_in(%s), unsupported READ mode %d",
1743 task->id, mode);
1744 status = APR_ENOTIMPL;
1745 }
1746@@ -352,19 +352,19 @@ static apr_status_t h2_filter_slave_in(a
1747 if (trace1) {
1748 apr_brigade_length(bb, 0, &bblen);
1749 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, f->c,
1750- "h2_slave_in(%s): %ld data bytes", task->id, (long)bblen);
1751+ "h2_secondary_in(%s): %ld data bytes", task->id, (long)bblen);
1752 }
1753 return status;
1754 }
1755
1756-static apr_status_t h2_filter_slave_output(ap_filter_t* filter,
1757- apr_bucket_brigade* brigade)
1758+static apr_status_t h2_filter_secondary_output(ap_filter_t* filter,
1759+ apr_bucket_brigade* brigade)
1760 {
1761 h2_task *task = h2_ctx_get_task(filter->c);
1762 apr_status_t status;
1763
1764 ap_assert(task);
1765- status = slave_out(task, filter, brigade);
1766+ status = secondary_out(task, filter, brigade);
1767 if (status != APR_SUCCESS) {
1768 h2_task_rst(task, H2_ERR_INTERNAL_ERROR);
1769 }
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches