Bug 56924 - mod_cache segmentation fault when Content-Type has empty value
Summary: mod_cache segmentation fault when Content-Type has empty value
Status: RESOLVED FIXED
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mod_cache (show other bugs)
Version: 2.4.10
Hardware: PC Linux
: P2 normal (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL:
Keywords: FixedInTrunk, PatchAvailable
Depends on:
Blocks:
 
Reported: 2014-09-08 04:45 UTC by Mark Montague
Modified: 2015-01-23 08:42 UTC (History)
1 user (show)



Attachments
complete but minimal httpd.conf for reproducing the problem (1.09 KB, text/plain)
2014-09-08 04:45 UTC, Mark Montague
Details
patch to fix Content-Type empty value segfault (1.31 KB, patch)
2014-09-08 04:52 UTC, Mark Montague
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Mark Montague 2014-09-08 04:45:14 UTC
Created attachment 31972 [details]
complete but minimal httpd.conf for reproducing the problem

Unmodified httpd 2.4.10 compiled from apache.org source on Fedora 19 x86_64.

The problem described below happens for certain PHP syntax errors (but not others) in WordPress 3.9 scripts when run WordPress is run via mod_proxy_fcgi under PHP-FPM (PHP 5.5.5).

Enable mod_cache (a complete but minimal httpd.conf for reproducing the problem is attached):

CacheRoot /opt/httpd/cache
CacheEnable disk /
CacheIgnoreNoLastMod On

Generate a response containing a Content-Type header with an empty value:

#!/usr/bin/perl
print "Content-Type:\n\n";
print localtime() . "\n";

Result is a segmentation fault due to dereferencing a NULL pointer for the Content-Type value in the output headers table:

[Mon Sep 08 00:01:49.413618 2014] [core:notice] [pid 36893:tid 140015984838528] AH00051: child pid 23242 exit signal Segmentation fault (11), possible coredump in /var/tmp

[root@f19debug tmp]# gdb /opt/httpd/bin/httpd core.httpd.23242
GNU gdb (GDB) Fedora 7.6.1-46.fc19
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /opt/httpd/bin/httpd...done.
[New LWP 23262]
[New LWP 23242]
[New LWP 23266]
[New LWP 23267]
[New LWP 23265]
[New LWP 23268]
[New LWP 23264]
[New LWP 23263]
[New LWP 23269]
[New LWP 23270]
[New LWP 23271]
[New LWP 23272]
[New LWP 23246]
[New LWP 23247]
[New LWP 23248]
[New LWP 23249]
[New LWP 23250]
[New LWP 23251]
[New LWP 23252]
[New LWP 23253]
[New LWP 23254]
[New LWP 23255]
[New LWP 23256]
[New LWP 23257]
[New LWP 23258]
[New LWP 23260]
[New LWP 23259]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Core was generated by `/opt/httpd/bin/httpd -k start'.
Program terminated with signal 11, Segmentation fault.
#0  __strlen_sse2_pminub ()
    at ../sysdeps/x86_64/multiarch/strlen-sse2-pminub.S:38
38              movdqu  (%rdi), %xmm1
(gdb) where
#0  __strlen_sse2_pminub ()
    at ../sysdeps/x86_64/multiarch/strlen-sse2-pminub.S:38
#1  0x00007f5801c550d1 in store_table (fd=0x7f57e800bb28, table=0x7f57e8008128)
    at mod_cache_disk.c:916
#2  0x00007f5801c55a0b in write_headers (h=0x7f57e8007cc8, r=0x7f57e8002970)
    at mod_cache_disk.c:1087
#3  0x00007f5801c5681e in commit_entity (h=0x7f57e8007cc8, r=0x7f57e8002970)
    at mod_cache_disk.c:1322
#4  0x00007f5801e5f36c in cache_save_store (f=0x7f57e80040f0,
    in=0x7f57e8007748, conf=0x253e210, cache=0x7f57e8003d88) at mod_cache.c:734
#5  0x00007f5801e614ca in cache_save_filter (f=0x7f57e80040f0,
    in=0x7f57e8007748) at mod_cache.c:1576
#6  0x00000000004370b9 in ap_pass_brigade (next=0x7f57e80040f0,
    bb=0x7f57e8007748) at util_filter.c:590
#7  0x00007f5802071b85 in cgi_handler (r=0x7f57e8002970) at mod_cgi.c:1014
#8  0x0000000000454539 in ap_run_handler (r=0x7f57e8002970) at config.c:169
#9  0x0000000000454ff2 in ap_invoke_handler (r=0x7f57e8002970) at config.c:433
#10 0x00000000004702d5 in ap_process_async_request (r=0x7f57e8002970)
    at http_request.c:317
#11 0x000000000046c6df in ap_process_http_async_connection (c=0x7f57fc0376b0)
    at http_core.c:143
#12 0x000000000046c8c9 in ap_process_http_connection (c=0x7f57fc0376b0)
    at http_core.c:228
---Type <return> to continue, or q <return> to quit---
#13 0x0000000000461b48 in ap_run_process_connection (c=0x7f57fc0376b0)
    at connection.c:41
#14 0x00007f5802e94a12 in process_socket (thd=0x2553e60, p=0x7f57fc0373a8,
    sock=0x7f57fc037420, cs=0x7f57fc037628, my_child_num=0, my_thread_num=15)
    at event.c:1035
#15 0x00007f5802e96f78 in worker_thread (thd=0x2553e60, dummy=0x7f57fc01fd60)
    at event.c:1875
#16 0x000000367e807c53 in start_thread (arg=0x7f57f4ff1700)
    at pthread_create.c:308
#17 0x000000367e0f5dbd in clone ()
    at ../sysdeps/unix/sysv/linux/x86_64/clone.S:113
(gdb) frame 1
#1  0x00007f5801c550d1 in store_table (fd=0x7f57e800bb28, table=0x7f57e8008128)
    at mod_cache_disk.c:916
916                 iov[2].iov_len = strlen(elts[i].val);
(gdb) print i
$1 = 0
(gdb) print elts[i].key
$2 = 0x7f5801e6a545 "Content-Type"
(gdb) print elts[i].val
$3 = 0x0
(gdb)
Comment 1 Mark Montague 2014-09-08 04:52:23 UTC
Created attachment 31973 [details]
patch to fix Content-Type empty value segfault

modules/cache/cache_util.c: Fix the segfault by checking the return value of ap_make_content_type() before adding it to the output headers table (only add it if it is not NULL).

server/util_script.c: Correct a logic error in processing the Content-Type script header, although the error does not appear to negatively affect anything and is unrelated to the segmentation fault.
Comment 2 jkaluza 2014-09-11 08:24:32 UTC
I'm going to apply this patch to trunk, but I think the second part of the patch is not needed. Current code looks like this (shorter version just to show the "l" variable):

w is "ContentType:\n\n\0"

>        l = strchr(w, ':')

l is ":\n\n\0"

>        *l++ = '\0';

l is "\n\n\0"
w is "ContentType\0"

>        while (apr_isspace(*l)) {
>            ++l;
>        }

l is "\0" (\n\n is skipped)

>        if (!strcasecmp(w, "Content-type")) {
>            char *endp = l + strlen(l) - 1;

endp is l - 0 - 1.

>            while (endp > l && apr_isspace(*endp)) {
>                *endp-- = '\0';
>            }

This is skipped because enpd < l.

>            tmp = apr_pstrdup(r->pool, l);

This just copies '\0', so everything looks OK. Do you agree or there was something I'm missing here?
Comment 3 jkaluza 2014-09-11 13:03:57 UTC
Committed in trunk in r1624234.
Comment 4 Mark Montague 2014-09-11 14:54:24 UTC
(In reply to jkaluza from comment #2)
> I'm going to apply this patch to trunk, but I think the second part of the
> patch is not needed. [...]
> This just copies '\0', so everything looks OK. Do you agree or there was
> something I'm missing here?

I agree that the second part of the patch is not needed and does not affect anything.

My concern was that if the original value for w was "ContentType:\0" then the '\0' that got copied would be the one that replaced the ':' rather than the one immediately after it.  This is purely an academic point.

I won't be able to check whether w is actually w is "ContentType:\n\n\0" or "ContentType:\0" until tonight.

Thanks for the quick and helpful handling of this bug!
Comment 5 venkatunix02 2014-10-16 17:54:18 UTC
This issue may be impacting Apache 2.2 also. 

cache_merge_headers_out() function is not available in apache 2.2, but the code which got corrected(i.e., check return value of ap_make_content_type()) is present in different function of apache 2.2 as mentioned below. 

http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/cache/mod_mem_cache.c?revision=1343951&view=markup
635	        apr_table_setn(headers_out, "Content-Type",
636	                       ap_make_content_type(r, r->content_type));
637	    }

http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/cache/mod_disk_cache.c?view=markup
932	        if (!apr_table_get(headers_out, "Content-Type")
933	            && r->content_type) {
934	            apr_table_setn(headers_out, "Content-Type",
935	                           ap_make_content_type(r, r->content_type));
936	        }

Can someone please confirm this.
Comment 6 Yann Ylavic 2014-10-17 11:58:20 UTC
(In reply to venkatunix02 from comment #5)
> This issue may be impacting Apache 2.2 also. 

As discussed here (https://www.mail-archive.com/dev@httpd.apache.org/msg60793.html), ap_make_content_type() can't return NULL in 2.2, so it not concerned by this bug.
Comment 7 Eric Covener 2014-12-29 20:31:09 UTC
CVE-2014-3581, waiting for next 2.4.x release
Comment 8 Yann Ylavic 2015-01-23 08:42:26 UTC
Backported to 2.4.11 in r1627749, thanks Mark.