httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dean Gaudet <dgau...@arctic.org>
Subject Re: Anti-Sioux patch for Apache 1.2.6 (fwd)
Date Thu, 13 Aug 1998 23:44:46 GMT
Just in case, -1.  Sure, no O(n^2) space attack, but there's yet another
O(n^2) cpu time attack against this... 

I'd rather just try to figure out how the !@#$ to deal with set-cookie and
get my patch finished. 

Dean

On Thu, 13 Aug 1998, Marc Slemko wrote:

> In followup mail to me, the person who posted the original exploit and
> didn't have "time" to fill out a form decided that it would be trivial to
> implement pfree() in five lines and kept going on about it and how I was
> wrong for saying it was impossible (regardless of the fact that I never
> said any such thing).
> 
> The below is the result of his work, after he figured out that it is a
> little tougher than he thought when he hadn't even looked at it.
> 
> I have a few... erm... comments to make, but will leave them until I have
> time.
> 
> ---------- Forwarded message ----------
> Date: 12 Aug 1998 22:03:17 +0200
> From: "Dag-Erling Coidan [iso-8859-1] Smørgrav" <dag-erli@ifi.uio.no>
> To: marcs@znep.com
> Subject: Anti-Sioux patch for Apache 1.2.6
> 
> Here's the promised unidiff. Note that this was a quick job, and my
> first contact with Apache source code, so I may have overlooked
> something. The patch successfully prevents memory DoS on my machine,
> though it converts it to a (less severe) CPU DoS. Combining this patch
> with Ben Laurie's header-limiting patch is probably the best solution
> (though you might want to raise the limit a little).
> 
> The usual fee applies (i.e. my name in the changelog or at the top of
> alloc.c)
> 
> ===cut===
> --- alloc.c.orig	Wed Aug 12 18:50:14 1998
> +++ alloc.c	Wed Aug 12 21:51:07 1998
> @@ -92,6 +92,7 @@
>      char *endp;
>      union block_hdr *next;
>      char *first_avail;
> +    int refcount;
>    } h;
>  };
>  
> @@ -114,6 +115,7 @@
>    blok->h.next = NULL;
>    blok->h.first_avail = (char *)(blok + 1);
>    blok->h.endp = size + blok->h.first_avail;
> +  blok->h.refcount = 0;
>    
>    return blok;
>  }
> @@ -328,7 +330,6 @@
>   * Allocating stuff...
>   */
>  
> -
>  void *palloc (struct pool *a, int reqsize)
>  {
>    /* Round up requested size to an even number of alignment units (core clicks)
> @@ -352,6 +353,7 @@
>    
>    if (new_first_avail <= blok->h.endp) {
>      blok->h.first_avail = new_first_avail;
> +    blok->h.refcount++;
>      return (void *)first_avail;
>    }
>  
> @@ -365,10 +367,70 @@
>  
>    first_avail = blok->h.first_avail;
>    blok->h.first_avail += size;
> +  blok->h.refcount = 1;
>  
>    return (void *)first_avail;
>  }
>  
> +void pfree(struct pool *a, void *p)
> +{
> +    union block_hdr *blok = a->first, *_blok = NULL, *__blok;
> +
> +    /* release a block of memory unless it's shared between several
> +     * allocations
> +     *
> +     * some of this code is prolly too defensive and can be relaxed a
> +     * little if you really care
> +     */
> +    
> +    /* find relevant block */
> +    do {
> +	if ((p >= (void *)blok) && (p <= (void *)(blok->h.endp)))
> +	    break;
> +	_blok = blok;
> +	blok = blok->h.next;
> +    } while (blok);
> +
> +    /* oopsie, this indicates a bug in the caller and should probably
> +     * be logged
> +     */
> +    if (!blok) {
> +	return;
> +    }
> +
> +    /* block is shared by several objects and can't be safely freed
> +     */
> +    if (blok->h.refcount > 1) {
> +	blok->h.refcount--;
> +	return;
> +    }
> +    
> +#if 1
> +    /* solution A: disconnect block from chain and release it */
> +    if (_blok)
> +	_blok->h.next = blok->h.next;
> +    else
> +	a->first = blok->h.next;
> +    
> +    /* free block */
> +    free(blok);
> +#else
> +    /* solution B: leave block in place but shrink it */
> +    /* XXX Untested! */
> +    if ((__blok = realloc(blok, sizeof(union block_hdr))) == NULL) {
> +	/* ouch! this probably indicates some major fuckup in the
> +	 * malloc arena (we really should log something here too...)
> +	 */
> +	return;
> +    }
> +    blok = __blok;
> +    if (_blok)
> +	_blok->h.next = __blok;
> +    blok->h.first_avail = (char *)(blok + 1);
> +    blok->h.endp = blok->h.first_avail - 1;
> +#endif
> +}
> +
>  void *pcalloc(struct pool *a, int size)
>  {
>    void *res = palloc (a, size);
> @@ -580,12 +642,14 @@
>  
>      for (i = 0; i < t->nelts;) {
>  	if (!strcasecmp (elts[i].key, key)) {
> +	    pfree(t->pool, elts[i].val);
>  	    if (!done) {
>  	        elts[i].val = pstrdup(t->pool, val);
>  	        done = 1;
>  		++i;
>  	    }
>  	    else {     /* delete an extraneous element */
> +		pfree(t->pool, elts[i].key);
>                  for (j = i, k = i + 1; k < t->nelts; ++j, ++k) {
>                      elts[j].key = elts[k].key;
>                      elts[j].val = elts[k].val;
> @@ -618,6 +682,8 @@
>               * a contiguous block of memory.  I've chosen one that
>               * doesn't do a memcpy/bcopy/array_delete, *shrug*...
>               */
> +	    pfree(t->pool, elts[i].key);
> +	    pfree(t->pool, elts[i].val);
>              for (j = i, k = i + 1; k < t->nelts; ++j, ++k) {
>                  elts[j].key = elts[k].key;
>                  elts[j].val = elts[k].val;
> @@ -633,11 +699,14 @@
>  void table_merge (table *t, const char *key, const char *val)
>  {
>      table_entry *elts = (table_entry *)t->elts;
> +    char *oldval;
>      int i;
>  
>      for (i = 0; i < t->nelts; ++i)
>          if (!strcasecmp (elts[i].key, key)) {
> +	    oldval = elts[i].val;
>  	    elts[i].val = pstrcat (t->pool, elts[i].val, ", ", val, NULL);
> +	    pfree(t->pool, oldval);
>  	    return;
>  	}
>  
> ===cut===
> 
> DES
> -- 
> Dag-Erling Smørgrav - dag-erli@ifi.uio.no
> 
> 


Mime
View raw message