Description
Describe the bug
Apache segfaults during processing of requests when the persistent collection is being processed to remove stale records.
Logs and dumps
Note: IP addresses have been obfuscated
(gdb) bt full
#0 0x00007236e618c456 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
No symbol table info available.
#1 0x00007236e65bb2f8 in memcpy (__len=4294967295, __src=0x7236bc01deae, __dest=<optimized out>)
at /usr/include/x86_64-linux-gnu/bits/string_fortified.h:34
No locals.
#2 apr_pstrmemdup (a=<optimized out>, s=s@entry=0x7236bc01deae "\017\061\070\061.123.123.12",
n=4294967295) at strings/apr_strings.c:107
res = <optimized out>
#3 0x00007236e5fb4664 in collection_unpack (msr=msr@entry=0x7236bc020eb0, blob=0x7236bc01de76 "7",
blob_size=228, log_vars=log_vars@entry=0) at persist_dbm.c:71
var = 0x7236bc0b2e60
col = 0x7236bc0b2a38
blob_offset = 56
#4 0x00007236e5fb5c96 in collections_remove_stale (msr=msr@entry=0x7236bc020eb0,
col_name=0x7236bc009020 "ip") at persist_dbm.c:781
col = 0x0
var = 0x0
dbm_filename = 0x7236bc02d578 "/var/cache/httpd/www-ip"
key = {dptr = 0x7236bc030ea0 "127.12.12.123", dsize = 14}
value = {dptr = 0x7236bc01de76 "7", dsize = 228}
dbm = <optimized out>
rc = <optimized out>
keys_arr = 0x7236bc02d700
keys = 0x7236bc031ae8
now = <optimized out>
i = 314
userinfo = 0x7236bc02d570 "www"
[snip]
To Reproduce
Not sure, I guess: have corrupt persistent collection data files (I made backups, if you're interested) and perform some specific requests to trigger a segfault (don't known exactly when it triggers).
Expected behavior
Webserver doesn't crash
Server (please complete the following information):
- ModSecurity version: 2.9.7
- WebServer: Apache 2.4.57
- OS (and distro): Debian bullseye/bookworm
Additional context
ModSecurity/apache2/persist_dbm.c
Line 71 in 705002b
collection_unpack()
checks if blob_offset + var->value_len
expands beyond blob_size
, but then runs apr_pstrmemdup()
with a size of var->value_len - 1
. If var->value_len = 0
the size value will wrap around to 4294967295
.
The following patch might help:
--- a/apache2/persist_dbm.c
+++ b/apache2/persist_dbm.c
@@ -67,7 +67,7 @@
var->value_len = (blob[blob_offset] << 8) + blob[blob_offset + 1];
blob_offset += 2;
- if (blob_offset + var->value_len > blob_size) return NULL;
+ if (blob_offset + (var->value_len - 1) > blob_size) return NULL;
var->value = apr_pstrmemdup(msr->mp, (const char *)blob + blob_offset, var->value_len - 1);
blob_offset += var->value_len;
var->value_len--;