Bug 45049 - mod_mem_cache caches partial content when client connection is terminated.
Summary: mod_mem_cache caches partial content when client connection is terminated.
Status: REOPENED
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mod_cache (show other bugs)
Version: 2.2.8
Hardware: PC All
: P2 normal (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL:
Keywords: PatchAvailable
Depends on:
Blocks:
 
Reported: 2008-05-20 13:11 UTC by nick pace
Modified: 2015-09-01 18:25 UTC (History)
3 users (show)



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description nick pace 2008-05-20 13:11:37 UTC
Hi, 

I’m running apache 2.2.8 with mod_cache + mod_mem_cache. I’ve configured all content to be cached. Content is served from a backend server. I’ve found if a “non cached page” is requested and the socket to apache is terminated before all content is read from backend server and dispatched to client, mod_mem_cache caches partial content! When I make a subsequent request for the same page, the partial content is returned from cache. 
In apache 2.0 the configuration value CacheForceCompletion details the cache will only be populated with complete content. This config value has now been removed! Is there a flag to control such behaviour? I require all content stored in cache to be 100% and never partial. 

At present to no avail I’ve found nothing detailing the above issues! So, I had a look at mod_mem_cache and plugged in the below code as a temporary solution which works a treat. 

    /*
     * FD cacheing is not enabled or the content was not
     * suitable for fd caching.
     */
    if (mobj->m == NULL) {
        mobj->m = malloc(mobj->m_len);
        if (mobj->m == NULL) {
            return APR_ENOMEM;
        }
        obj->count = 0;
    }
    cur = (char*) mobj->m + obj->count;

// START CHANGE
	if (r->connection->aborted==1) {
		// Connection aborted, do not cache this page! 
ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server, "socket aborted!“);
obj->count = 0;
return APR_ENOMEM;
	}
// END CHANGE

    /* Iterate accross the brigade and populate the cache storage */
    for (e = APR_BRIGADE_FIRST(b);
         e != APR_BRIGADE_SENTINEL(b);
         e = APR_BUCKET_NEXT(e))
    {

I need to understand if I’ve missed something or the behaviour I’m experiencing is a feature! 

Thanks again...I've already posted a number of questions on other sites but no one has been able to answer. 

Cheers, Nick
Comment 1 Filip Moritz 2009-06-11 10:32:28 UTC
Just want to briefly confirm this one (using debian etch's 2.2.3)

Ran into it in a reverse proxy setup and did now switch to using mod_disk_cache + tmpfs. That seems to have solved the problem for us. 

It's a nasty show-stopper and opens gates for denial-of-service (or call it corrupt-service?) attacks. Think a warning should be added to the docs.

Will drop back when I have found time to do some synthetic tests so I may give more detail.
Comment 2 Graham Leggett 2009-10-03 08:02:06 UTC
If possible, please add the change as a unified diff (diff -u).
Comment 3 Edward Lu 2015-09-01 14:33:47 UTC
This behavior was still around in 2.2.x. Fixed in r1700578.
Comment 4 Edward Lu 2015-09-01 18:25:11 UTC
(In reply to Edward Lu from comment #3)
> This behavior was still around in 2.2.x. Fixed in r1700578.

Sorry, not actually fixed yet - only proposed for integration.