https://bz.apache.org/bugzilla/show_bug.cgi?id=63516
Bug ID: 63516
Summary: Use-after-free segfault in ap_server_config_defines
Product: Apache httpd-2
Version: 2.4.39
Hardware: All
OS: All
Status: NEW
Severity: critical
Priority: P2
Component: Core
Assignee: [email protected]
Reporter: [email protected]
Target Milestone: ---
- - - - Summary - - - -
httpd2 segfaults when scanning the ap_server_config_defines array, because an
entry in the array was allocated using the pconf pool, which has since been
cleared.
- - - - Description - - - -
In main(), the httpd2 process creates the ap_server_config_defines array and
populates it with either string literals or strings backed with memory
allocated from the pcommands pool.
It then makes its first call to ap_read_config(), which parses the config file
and loads the configured modules. Each module's register hook is passed the
main process's pconf pool as an argument. If mod_perl is installed and
configured to load, the modperl_register_hooks() function allocates a string on
the pconf pool and adds it to the ap_server_config_defines array. This appears
to be long-standing behaviour for mod_perl - SVN shows that this code has been
there since at least version 2.0.0 back in 2005.
When execution reaches the do/while loop in main(), reset_process_pconf() is
called, which invalidates all previously allocated memory from the pconf pool.
At this point, if mod_perl is loaded, the ap_server_config_defines array will
contain a pointer to freed memory.
A few lines later, ap_read_config() is called again, which calls
ap_exists_config_define() and traverses the ap_server_config_defines array,
triggering the segfault.
- - - - Step-by-Step in gdb - - - -
1. Run gdb on httpd2 as root and set a breakpoint at the top of the do/while
loop:
# gdb /usr/local/sbin/httpd2
GNU gdb 6.3
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "amd64-unknown-openbsd6.5"...
(gdb) b main.c:749
Breakpoint 1 at 0x59b10: file main.c, line 749.
Run the httpd2 process with the -X argument and let it hit the breakpoint:
(gdb) r -X
Starting program: /usr/local/sbin/httpd2 -X
Breakpoint 1 at 0xad0a9cb1b10: file main.c, line 749.
[New process 40607]
Breakpoint 1, main (argc=2, argv=0x7f7ffffe5988) at main.c:749
749 ap_main_state = AP_SQ_MS_DESTROY_CONFIG;
Current language: auto; currently minimal
Print the contents of the ap_server_config_defines array. It contains a string
literal "DEBUG" from the parsing of the -X argument, and the string "MODPERL2"
allocated from the pconf pool by mod_perl:
(gdb) p *ap_server_config_defines
$1 = {pool = 0xad2bbc85028, elt_size = 8, nelts = 2, nalloc = 2, elts =
0xad366f8c950 ")?ɩ?\n"}
(gdb) p *(char* (*)[2])ap_server_config_defines->elts
$2 = {0xad0a9c9f029 "DEBUG", 0xad3781d6bc8 "MODPERL2"}
Step through to the apr_pool_clear() call that clears the pconf pool, then
examine the ap_server_config_defines array again. The second entry now points
to an invalid memory address:
(gdb) s
290 if (process->pconf) {
(gdb)
291 apr_pool_clear(process->pconf);
(gdb)
292 ap_server_conf = NULL;
(gdb) p *ap_server_config_defines
$3 = {pool = 0xad2cb0bf028, elt_size = 8, nelts = 2, nalloc = 2, elts =
0xad2cb0bf178 ")?ɩ?\n"}
(gdb) p *(char* (*)[2])ap_server_config_defines->elts
$4 = {0xad0a9c9f029 "DEBUG", 0xad3781d6bc8 <Address 0xad3781d6bc8 out of
bounds>}
Continue and allow it to crash:
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
strcmp () at /usr/src/lib/libc/arch/amd64/string/strcmp.S:59
59 /usr/src/lib/libc/arch/amd64/string/strcmp.S: No such file or
directory.
in /usr/src/lib/libc/arch/amd64/string/strcmp.S
Current language: auto; currently asm
(gdb) bt
#0 strcmp () at /usr/src/lib/libc/arch/amd64/string/strcmp.S:59
#1 0x00000ad0a9cc3cfd in ap_array_str_contains (array=Variable "array" is not
available.
) at util.c:3178
#2 0x00000ad0a9cb7341 in ap_read_config (process=Variable "process" is not
available.
) at config.c:2491
#3 0x00000ad0a9cb1c16 in main (argc=2, argv=0x7f7ffffe5988) at main.c:766
(gdb)
- - - - Relevant Code from mod_perl - - - -
void modperl_register_hooks(apr_pool_t *p)
{
...
/* for <IfDefine MODPERL2> and Apache2->define("MODPERL2") */
*(char **)apr_array_push(ap_server_config_defines) =
apr_pstrdup(p, "MODPERL2");
- - - - Version Information - - - -
Testing was performed on OpenBSD 6.5 amd64 with Apache 2.4.39 and mod_perl
2.0.10:
# uname -a
OpenBSD openbsd65.my.domain 6.5 GENERIC.MP#1 amd64
# pkg_info | egrep -i 'apr|apache'
ap2-mod_perl-2.0.10p0 module that embeds a Perl interpreter into Apache2
apache-httpd-2.4.39p1 apache HTTP server
apr-1.6.5p0 Apache Portable Runtime
apr-util-1.6.1p2 companion library to APR
p5-libapreq2-2.08p7 apache HTTP server request library
# httpd2 -V
Server version: Apache/2.4.39 (Unix)
Server built: Jun 9 2019 18:56:53
Server's Module Magic Number: 20120211:84
Server loaded: APR 1.6.5, APR-UTIL 1.6.1
Compiled using: APR 1.6.5, APR-UTIL 1.6.1
Architecture: 64-bit
Server MPM: prefork
threaded: no
forked: yes (variable process count)
Server compiled with....
-D APR_HAS_MMAP
-D APR_HAVE_IPV6 (IPv4-mapped addresses disabled)
-D APR_USE_FLOCK_SERIALIZE
-D APR_USE_PTHREAD_SERIALIZE
-D APR_HAS_OTHER_CHILD
-D AP_HAVE_RELIABLE_PIPED_LOGS
-D DYNAMIC_MODULE_LIMIT=256
-D HTTPD_ROOT="/var/www"
-D SUEXEC_BIN="/usr/local/sbin/suexec2"
-D DEFAULT_PIDLOG="logs/httpd.pid"
-D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
-D DEFAULT_ERRORLOG="logs/error_log"
-D AP_TYPES_CONFIG_FILE="/etc/apache2/mime.types"
-D SERVER_CONFIG_FILE="/etc/apache2/httpd2.conf"
# grep mod_perl /etc/apache2/httpd2.conf
LoadModule perl_module /usr/local/lib/apache2/mod_perl.so
# /etc/rc.d/apache2 -d start
...
Segmentation fault (core dumped)
(failed)
--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]