diff --git a/SOURCES/httpd-2.4.34-CVE-2019-0211.patch b/SOURCES/httpd-2.4.34-CVE-2019-0211.patch new file mode 100644 index 0000000..25994fb --- /dev/null +++ b/SOURCES/httpd-2.4.34-CVE-2019-0211.patch @@ -0,0 +1,207 @@ +diff --git a/include/scoreboard.h b/include/scoreboard.h +index 57cf3df..b714a8c 100644 +--- a/include/scoreboard.h ++++ b/include/scoreboard.h +@@ -143,7 +143,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 f07b757..16e39be 100644 +--- a/server/mpm/event/event.c ++++ b/server/mpm/event/event.c +@@ -2670,7 +2670,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++; +@@ -2709,6 +2708,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]) { +@@ -2732,7 +2732,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; + } +@@ -2743,7 +2743,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; +@@ -2926,13 +2928,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 3fb3284..4517f88 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 7804efc..79b2769 100644 +--- a/server/mpm/worker/worker.c ++++ b/server/mpm/worker/worker.c +@@ -1311,7 +1311,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; + } +@@ -1360,6 +1359,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]) { +@@ -1392,7 +1392,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) { +@@ -1402,6 +1402,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 */ +@@ -1587,14 +1588,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; + } + } diff --git a/SPECS/httpd.spec b/SPECS/httpd.spec index dd85ff6..8131f36 100644 --- a/SPECS/httpd.spec +++ b/SPECS/httpd.spec @@ -51,7 +51,7 @@ Summary: Apache HTTP Server Name: %{?scl:%scl_prefix}httpd Version: 2.4.34 -Release: 7%{?dist} +Release: 7%{?dist}.1 URL: http://httpd.apache.org/ Source0: http://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2 Source1: index.html @@ -121,6 +121,8 @@ Patch80: httpd-2.4.34-statements-comment.patch # Security fixes Patch200: httpd-2.4.34-CVE-2018-11763.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1694980 +Patch201: httpd-2.4.34-CVE-2019-0211.patch License: ASL 2.0 Group: System Environment/Daemons @@ -328,6 +330,7 @@ export LD_LIBRARY_PATH=%{_libdir}:$LD_LIBRARY_PATH %patch80 -p1 -b .statementscomment %patch200 -p1 -b .CVE-2018-11763 +%patch201 -p1 -b .CVE-2019-0211 # Patch in the vendor string and the release string sed -i '/^#define PLATFORM/s/Unix/%{vstring}/' os/unix/os.h @@ -991,6 +994,10 @@ rm -rf $RPM_BUILD_ROOT %endif %changelog +* Wed Apr 03 2019 Lubos Uhliarik - 2.4.34-7.1 +- Resolves: #1695428 - CVE-2019-0211 httpd24-httpd: httpd: privilege escalation + from modules scripts + * Tue Nov 06 2018 Luboš Uhliarik - 2.4.34-7 - Resolves: #1646937 - Unable to start httpd - Resolves: #1638711 - comments should be allowed at the end of Allow from