Mailing List Archive

[Bug 66119] New: Segmentation fault in libcpre when processing Location regex match for a long request path when MPM worked is used in 2.4.53+
https://bz.apache.org/bugzilla/show_bug.cgi?id=66119

Bug ID: 66119
Summary: Segmentation fault in libcpre when processing Location
regex match for a long request path when MPM worked is
used in 2.4.53+
Product: Apache httpd-2
Version: 2.4.53
Hardware: PC
OS: Linux
Status: NEW
Severity: normal
Priority: P2
Component: Core
Assignee: bugs@httpd.apache.org
Reporter: Krystian.Nowak@gmail.com
Target Milestone: ---

Created attachment 38316
--> https://bz.apache.org/bugzilla/attachment.cgi?id=38316&action=edit
httpd 2.4.53 MPM-worker segfault backtrace

Apache 2.4.53+ worker process (in MPM worker mode) crashes with a segmentation
fault when processing a request with path that is equal or longer than 145
characters when virtual host has a Location directive with regex match as
follows:

<Location ~ "^((?!/errors/).)*$">

An example request making segfault crash (with a minimal URI length causing the
crash - 145):
GET
/1234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234

An example request working OK (with a maximal URI length NOT causing a crash -
144):
GET
/123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123

Result of a crashed request in httpd logs:

==> /var/www/logs/error.log <==
[Tue Jun 14 14:18:42.790169 2022] [core:notice] [pid 21:tid 140397196118856]
AH00051: child pid 25 exit signal Segmentation fault (11), possible coredump in
/tmp

Crash backtrace generated from core dump attached to the issue.


The request fails both in 2.4.53 and 2.4.54 e.g. Alpine-based (using PCRE
8.45):

fetch https://dl-cdn.alpinelinux.org/alpine/v3.16/main/x86_64/APKINDEX.tar.gz
fetch
https://dl-cdn.alpinelinux.org/alpine/v3.16/community/x86_64/APKINDEX.tar.gz
(1/9) Installing libuuid (2.38-r1)
(2/9) Installing apr (1.7.0-r2)
(3/9) Installing expat (2.4.8-r0)
(4/9) Installing apr-util (1.6.1-r12)
(5/9) Installing pcre (8.45-r2)
(6/9) Installing apache2 (2.4.54-r0)
Executing apache2-2.4.54-r0.pre-install
(7/9) Installing libpcre16 (8.45-r2)
(8/9) Installing libpcre32 (8.45-r2)
(9/9) Installing pcre-tools (8.45-r2)
AH00292: Apache/2.4.54 (Unix) configured -- resuming normal operations

but works well in old Alpine 3.13.11 bringing still 2.4.51 (using PCRE 8.43):

fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/main/x86_64/APKINDEX.tar.gz
fetch
http://dl-cdn.alpinelinux.org/alpine/v3.11/community/x86_64/APKINDEX.tar.gz
(1/9) Installing libuuid (2.34-r1)
(2/9) Installing apr (1.7.0-r0)
(3/9) Installing expat (2.2.9-r1)
(4/9) Installing apr-util (1.6.1-r6)
(5/9) Installing pcre (8.43-r1)
(6/9) Installing apache2 (2.4.51-r0)
Executing apache2-2.4.51-r0.pre-install
(7/9) Installing libpcre16 (8.43-r1)
(8/9) Installing libpcre32 (8.43-r1)
(9/9) Installing pcre-tools (8.43-r1)
AH00292: Apache/2.4.51 (Unix) configured -- resuming normal operations


Worth noting are the following facts:
1) the issue does not occur in non-threaded MPM prefork mode, but since 2.4.53
occurs in threaded e.g. MPM worker mode
2) the pattern used in Location regexp match does not fail via pcretest call
from pcre-tools (in neither version) - content of this input:
/^((?!\/errors\/).)*$/I
/this/is/normal/matching/path
/errors/notmatching

/012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012

/0123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123
does not fail:

PCRE version 8.45 2021-06-15

/^((?!\/errors\/).)*$/I
Capturing subpattern count = 1
May match empty string
Options: anchored
No first char
No need char
/this/is/normal/matching/path
0: /this/is/normal/matching/path
1: h
/errors/notmatching
No match

/012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012
0:
/012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012
1: 2

/0123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123
0:
/0123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123
1: 3

3) between 2.4.52 and 2.4.53 the following change has been incorporated:
ap_regex: Use Thread Local Storage (if efficient) to avoid allocations.
https://github.com/apache/httpd/commit/285b6285e799d3480150375cb853d40973d3ab4c#diff-4d479e1bf17e6539c339b182d3c0861a1bd0b0ccbad5226c437d0e30f8cae0c7R395
which (among other things) also ap_regexec in server/util_pcre.c also when
HAVE_PCRE2 condition is not met (e.g. ovector and nmatch/ncaps and around
pcre_exec call), although please note that I am neither acquainted to this code
nor am I C-lang specialist.


The scripts and configuration files which might help to reproduce the issue:

* run.sh - script to run httpd via Alpine in Docker:

#!/bin/sh

ALPINE_VERSION=${ALPINE_VERSION:-"latest"}
HTTP_PORT=${HTTP_PORT:-8080}
CONTAINER_NAME=${CONTAINER_NAME:-"httpd"}

CONFIG_DIR=$(pwd)/httpd-config

docker run \
-it \
--rm \
--name ${CONTAINER_NAME} \
--init --privileged --ulimit core=-1 --security-opt seccomp=unconfined
--cap-add=SYS_PTRACE \
-p ${HTTP_PORT}:80 \
-v ${CONFIG_DIR}/conf.d/vhost.conf:/etc/apache2/conf.d/vhost.conf:ro \
-v $(pwd)/httpd-conf-sed.txt:/mnt/httpd-conf-sed.txt:ro \
-v $(pwd)/pcretest-input.txt:/mnt/pcretest-input.txt:ro \
-v $(pwd)/tmp:/tmp \
alpine:${ALPINE_VERSION} \
sh -c 'sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t; apk add
apache2 pcre-tools; pcretest /mnt/pcretest-input.txt; sed -f
/mnt/httpd-conf-sed.txt -i /etc/apache2/httpd.conf; echo "CoreDumpDirectory
/tmp" >> /etc/apache2/httpd.conf; httpd; tail -F /var/www/logs/*'


* httpd-config/conf.d/vhost.conf - Simple vhost.conf file:

ServerName segfaultserver

<VirtualHost *:80>

ServerName caselocation
ServerAlias "*"

<IfModule mod_rewrite.c>
RewriteEngine on

# Location pattern PCRE -> ap_location_walk -> ap_regexec_len
-> pcre_exec -> libpcre.so.1 (multiple entries) -> Program terminated with
signal SIGSEGV, Segmentation fault.
<Location ~ "^((?!/errors/).)*$">
</Location>

</IfModule>

</VirtualHost>


* httpd-conf-sed.txt - Sed input file to enable mpm_worker_module and
rewrite_module:

s#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so#\#LoadModule
mpm_prefork_module modules/mod_mpm_prefork.so#
s#\#LoadModule mpm_worker_module modules/mod_mpm_worker.so#LoadModule
mpm_worker_module modules/mod_mpm_worker.so#
s#\#LoadModule rewrite_module modules/mod_rewrite.so#LoadModule rewrite_module
modules/mod_rewrite.so#


* pcretest-input.txt - PCRE test input file to verify regexp pattern works by
pcretest using given version of PCRE with requests used in testing:

/^((?!\/errors\/).)*$/I
/this/is/normal/matching/path
/errors/notmatching

/012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012

/0123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123


* request.sh - script to make requests against started Docker container with
given httpd version from Alpine:

#!/bin/sh

HTTP_PORT=${HTTP_PORT:-8080}

CORRECT_URI="/123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123"
# len<=144
FAILING_URI="/1234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234"
# len>=145


echo "request correct URI: ${CORRECT_URI}"
curl -svo /dev/null http://localhost:${HTTP_PORT}${CORRECT_URI}

echo "request failing URI: ${FAILING_URI}"
curl -svo /dev/null http://localhost:${HTTP_PORT}${FAILING_URI}


This issue _might_ be related to another one reported for 2.4.53 and PCRE regex
patterns processing - https://bz.apache.org/bugzilla/show_bug.cgi?id=66021

--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: bugs-unsubscribe@httpd.apache.org
For additional commands, e-mail: bugs-help@httpd.apache.org