summaryrefslogtreecommitdiffstats
path: root/debian/patches/CVE-2019-0211.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/CVE-2019-0211.patch')
-rw-r--r--debian/patches/CVE-2019-0211.patch249
1 files changed, 249 insertions, 0 deletions
diff --git a/debian/patches/CVE-2019-0211.patch b/debian/patches/CVE-2019-0211.patch
new file mode 100644
index 0000000..1b69f45
--- /dev/null
+++ b/debian/patches/CVE-2019-0211.patch
@@ -0,0 +1,249 @@
+From df7edb5ddae609ea1fd4285f7439f0d590d97b37 Mon Sep 17 00:00:00 2001
+From: Yann Ylavic <ylavic@apache.org>
+Date: Wed, 13 Mar 2019 08:59:54 +0000
+Subject: [PATCH] Merge r1855306 from trunk:
+
+MPMs unix: bind the bucket number of each child to its slot number
+
+We need not remember each child's bucket number in SHM for restarts, for the
+lifetime of the httpd main process the bucket number can be bound to the slot
+number such that: bucket = slot % num_buckets.
+
+This both simplifies the logic and helps children maintenance per bucket in
+threaded MPMs, where previously perform_idle_server_maintenance() could create
+or kill children processes for the buckets it was not in charge of.
+
+Submitted by: ylavic
+Reviewed by: ylavic, rpluem, jorton
+
+
+git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1855378 13f79535-47bb-0310-9956-ffa450edef68
+---
+ CHANGES | 3 +++
+ include/scoreboard.h | 4 +++-
+ server/mpm/event/event.c | 13 ++++++++-----
+ server/mpm/prefork/prefork.c | 19 +++++++------------
+ server/mpm/worker/worker.c | 10 ++++++----
+ 5 files changed, 27 insertions(+), 22 deletions(-)
+
+#diff --git a/CHANGES b/CHANGES
+#index e79251389d5..6b560802119 100644
+#--- a/CHANGES
+#+++ b/CHANGES
+#@@ -1,6 +1,9 @@
+# -*- coding: utf-8 -*-
+# Changes with Apache 2.4.39
+#
+#+ *) MPMs unix: bind the bucket number of each child to its slot number, for a
+#+ more efficient per bucket maintenance. [Yann Ylavic]
+#+
+# *) mod_auth_digest: Fix a race condition. Authentication with valid
+# credentials could be refused in case of concurrent accesses from
+# different users. PR 63124. [Simon Kappel <simon.kappel axis.com>]
+diff --git a/include/scoreboard.h b/include/scoreboard.h
+index 9376da246b0..92d198d6de1 100644
+--- a/include/scoreboard.h
++++ b/include/scoreboard.h
+@@ -148,7 +148,9 @@ struct process_score {
+ apr_uint32_t lingering_close; /* async connections in lingering close */
+ apr_uint32_t keep_alive; /* async connections in keep alive */
+ apr_uint32_t suspended; /* connections suspended by some module */
+- int bucket; /* Listener bucket used by this child */
++ int bucket; /* Listener bucket used by this child; this field is DEPRECATED
++ * and no longer updated by the MPMs (i.e. always zero).
++ */
+ };
+
+ /* Scoreboard is now in 'local' memory, since it isn't updated once created,
+diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c
+index 4cfb09c5b28..5e5af339adc 100644
+--- a/server/mpm/event/event.c
++++ b/server/mpm/event/event.c
+@@ -2696,7 +2696,6 @@ static int make_child(server_rec * s, int slot, int bucket)
+
+ ap_scoreboard_image->parent[slot].quiescing = 0;
+ ap_scoreboard_image->parent[slot].not_accepting = 0;
+- ap_scoreboard_image->parent[slot].bucket = bucket;
+ event_note_child_started(slot, pid);
+ active_daemons++;
+ retained->total_daemons++;
+@@ -2735,6 +2734,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
+ * that threads_per_child is always > 0 */
+ int status = SERVER_DEAD;
+ int child_threads_active = 0;
++ int bucket = i % num_buckets;
+
+ if (i >= retained->max_daemons_limit &&
+ free_length == retained->idle_spawn_rate[child_bucket]) {
+@@ -2758,7 +2758,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
+ */
+ if (status <= SERVER_READY && !ps->quiescing && !ps->not_accepting
+ && ps->generation == retained->mpm->my_generation
+- && ps->bucket == child_bucket)
++ && bucket == child_bucket)
+ {
+ ++idle_thread_count;
+ }
+@@ -2769,7 +2769,9 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
+ last_non_dead = i;
+ }
+ active_thread_count += child_threads_active;
+- if (!ps->pid && free_length < retained->idle_spawn_rate[child_bucket])
++ if (!ps->pid
++ && bucket == child_bucket
++ && free_length < retained->idle_spawn_rate[child_bucket])
+ free_slots[free_length++] = i;
+ else if (child_threads_active == threads_per_child)
+ had_healthy_child = 1;
+@@ -2962,13 +2964,14 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets)
+ retained->total_daemons--;
+ if (processed_status == APEXIT_CHILDSICK) {
+ /* resource shortage, minimize the fork rate */
+- retained->idle_spawn_rate[ps->bucket] = 1;
++ retained->idle_spawn_rate[child_slot % num_buckets] = 1;
+ }
+ else if (remaining_children_to_start) {
+ /* we're still doing a 1-for-1 replacement of dead
+ * children with new children
+ */
+- make_child(ap_server_conf, child_slot, ps->bucket);
++ make_child(ap_server_conf, child_slot,
++ child_slot % num_buckets);
+ --remaining_children_to_start;
+ }
+ }
+diff --git a/server/mpm/prefork/prefork.c b/server/mpm/prefork/prefork.c
+index 8efda72ee18..7c006257301 100644
+--- a/server/mpm/prefork/prefork.c
++++ b/server/mpm/prefork/prefork.c
+@@ -637,8 +637,9 @@ static void child_main(int child_num_arg, int child_bucket)
+ }
+
+
+-static int make_child(server_rec *s, int slot, int bucket)
++static int make_child(server_rec *s, int slot)
+ {
++ int bucket = slot % retained->mpm->num_buckets;
+ int pid;
+
+ if (slot + 1 > retained->max_daemons_limit) {
+@@ -716,7 +717,6 @@ static int make_child(server_rec *s, int slot, int bucket)
+ child_main(slot, bucket);
+ }
+
+- ap_scoreboard_image->parent[slot].bucket = bucket;
+ prefork_note_child_started(slot, pid);
+
+ return 0;
+@@ -732,7 +732,7 @@ static void startup_children(int number_to_start)
+ if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) {
+ continue;
+ }
+- if (make_child(ap_server_conf, i, i % retained->mpm->num_buckets) < 0) {
++ if (make_child(ap_server_conf, i) < 0) {
+ break;
+ }
+ --number_to_start;
+@@ -741,8 +741,6 @@ static void startup_children(int number_to_start)
+
+ static void perform_idle_server_maintenance(apr_pool_t *p)
+ {
+- static int bucket_make_child_record = -1;
+- static int bucket_kill_child_record = -1;
+ int i;
+ int idle_count;
+ worker_score *ws;
+@@ -789,6 +787,7 @@ static void perform_idle_server_maintenance(apr_pool_t *p)
+ }
+ retained->max_daemons_limit = last_non_dead + 1;
+ if (idle_count > ap_daemons_max_free) {
++ static int bucket_kill_child_record = -1;
+ /* kill off one child... we use the pod because that'll cause it to
+ * shut down gracefully, in case it happened to pick up a request
+ * while we were counting
+@@ -819,10 +818,7 @@ static void perform_idle_server_maintenance(apr_pool_t *p)
+ idle_count, total_non_dead);
+ }
+ for (i = 0; i < free_length; ++i) {
+- bucket_make_child_record++;
+- bucket_make_child_record %= retained->mpm->num_buckets;
+- make_child(ap_server_conf, free_slots[i],
+- bucket_make_child_record);
++ make_child(ap_server_conf, free_slots[i]);
+ }
+ /* the next time around we want to spawn twice as many if this
+ * wasn't good enough, but not if we've just done a graceful
+@@ -867,7 +863,7 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
+
+ if (one_process) {
+ AP_MONCONTROL(1);
+- make_child(ap_server_conf, 0, 0);
++ make_child(ap_server_conf, 0);
+ /* NOTREACHED */
+ ap_assert(0);
+ return !OK;
+@@ -976,8 +972,7 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
+ /* we're still doing a 1-for-1 replacement of dead
+ * children with new children
+ */
+- make_child(ap_server_conf, child_slot,
+- ap_get_scoreboard_process(child_slot)->bucket);
++ make_child(ap_server_conf, child_slot);
+ --remaining_children_to_start;
+ }
+ #if APR_HAS_OTHER_CHILD
+diff --git a/server/mpm/worker/worker.c b/server/mpm/worker/worker.c
+index 8012fe29d8d..a92794245c5 100644
+--- a/server/mpm/worker/worker.c
++++ b/server/mpm/worker/worker.c
+@@ -1339,7 +1339,6 @@ static int make_child(server_rec *s, int slot, int bucket)
+ worker_note_child_lost_slot(slot, pid);
+ }
+ ap_scoreboard_image->parent[slot].quiescing = 0;
+- ap_scoreboard_image->parent[slot].bucket = bucket;
+ worker_note_child_started(slot, pid);
+ return 0;
+ }
+@@ -1388,6 +1387,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
+ int any_dead_threads = 0;
+ int all_dead_threads = 1;
+ int child_threads_active = 0;
++ int bucket = i % num_buckets;
+
+ if (i >= retained->max_daemons_limit &&
+ totally_free_length == retained->idle_spawn_rate[child_bucket]) {
+@@ -1420,7 +1420,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
+ if (status <= SERVER_READY &&
+ !ps->quiescing &&
+ ps->generation == retained->mpm->my_generation &&
+- ps->bucket == child_bucket) {
++ bucket == child_bucket) {
+ ++idle_thread_count;
+ }
+ if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
+@@ -1430,6 +1430,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
+ }
+ active_thread_count += child_threads_active;
+ if (any_dead_threads
++ && bucket == child_bucket
+ && totally_free_length < retained->idle_spawn_rate[child_bucket]
+ && free_length < MAX_SPAWN_RATE / num_buckets
+ && (!ps->pid /* no process in the slot */
+@@ -1615,14 +1616,15 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets)
+ ps->quiescing = 0;
+ if (processed_status == APEXIT_CHILDSICK) {
+ /* resource shortage, minimize the fork rate */
+- retained->idle_spawn_rate[ps->bucket] = 1;
++ retained->idle_spawn_rate[child_slot % num_buckets] = 1;
+ }
+ else if (remaining_children_to_start
+ && child_slot < ap_daemons_limit) {
+ /* we're still doing a 1-for-1 replacement of dead
+ * children with new children
+ */
+- make_child(ap_server_conf, child_slot, ps->bucket);
++ make_child(ap_server_conf, child_slot,
++ child_slot % num_buckets);
+ --remaining_children_to_start;
+ }
+ }