components/lighttpd/patches/lighttpd_fix_slow_request_dos.patch
branchs11-update
changeset 2925 d64f6e80d9b1
parent 2924 894dcec4ac14
child 2928 43b3da52b84a
equal deleted inserted replaced
2924:894dcec4ac14 2925:d64f6e80d9b1
     1 diff -u -r lighttpd-1.4.23-orig/src/base.h lighttpd-1.4.23/src/base.h
       
     2 --- src/base.h	Thu Jun 11 02:44:17 2009
       
     3 +++ src/base.h	Tue Aug 24 04:16:29 2010
       
     4 @@ -421,7 +421,6 @@
       
     5  
       
     6  #ifdef USE_OPENSSL
       
     7  	SSL *ssl;
       
     8 -	buffer *ssl_error_want_reuse_buffer;
       
     9  #endif
       
    10  	/* etag handling */
       
    11  	etag_flags_t etag_flags;
       
    12 Only in lighttpd-1.4.23/src: base.h.orig
       
    13 diff -u -r lighttpd-1.4.23-orig/src/chunk.c lighttpd-1.4.23/src/chunk.c
       
    14 --- src/chunk.c	Mon Mar 30 15:16:59 2009
       
    15 +++ src/chunk.c	Tue Aug 24 04:12:50 2010
       
    16 @@ -197,8 +197,6 @@
       
    17  int chunkqueue_append_buffer_weak(chunkqueue *cq, buffer *mem) {
       
    18  	chunk *c;
       
    19  
       
    20 -	if (mem->used == 0) return 0;
       
    21 -
       
    22  	c = chunkqueue_get_unused_chunk(cq);
       
    23  	c->type = MEM_CHUNK;
       
    24  	c->offset = 0;
       
    25 diff -u -r lighttpd-1.4.23-orig/src/connections.c lighttpd-1.4.23/src/connections.c
       
    26 --- src/connections.c	Thu Jun 11 06:54:30 2009
       
    27 +++ src/connections.c	Tue Aug 24 04:12:50 2010
       
    28 @@ -192,40 +192,42 @@
       
    29  
       
    30  static int connection_handle_read_ssl(server *srv, connection *con) {
       
    31  #ifdef USE_OPENSSL
       
    32 -	int r, ssl_err, len, count = 0;
       
    33 +	int r, ssl_err, len, count = 0, read_offset, toread;
       
    34  	buffer *b = NULL;
       
    35  
       
    36  	if (!con->conf.is_ssl) return -1;
       
    37  
       
    38 -	/* don't resize the buffer if we were in SSL_ERROR_WANT_* */
       
    39 -
       
    40  	ERR_clear_error();
       
    41  	do {
       
    42 -		if (!con->ssl_error_want_reuse_buffer) {
       
    43 -			b = buffer_init();
       
    44 -			buffer_prepare_copy(b, SSL_pending(con->ssl) + (16 * 1024)); /* the pending bytes + 16kb */
       
    45 +		if (NULL != con->read_queue->last) {
       
    46 +			b = con->read_queue->last->mem;
       
    47 +		}
       
    48  
       
    49 +		if (NULL == b || b->size - b->used < 1024) {
       
    50 +			b = chunkqueue_get_append_buffer(con->read_queue);
       
    51 +			len = SSL_pending(con->ssl);
       
    52 +			if (len < 4*1024) len = 4*1024; /* always alloc >= 4k buffer */
       
    53 +			buffer_prepare_copy(b, len + 1);
       
    54 +
       
    55  			/* overwrite everything with 0 */
       
    56  			memset(b->ptr, 0, b->size);
       
    57 -		} else {
       
    58 -			b = con->ssl_error_want_reuse_buffer;
       
    59  		}
       
    60  
       
    61 -		len = SSL_read(con->ssl, b->ptr, b->size - 1);
       
    62 -		con->ssl_error_want_reuse_buffer = NULL; /* reuse it only once */
       
    63 +		read_offset = (b->used > 0) ? b->used - 1 : 0;
       
    64 +		toread = b->size - 1 - read_offset;
       
    65  
       
    66 +		len = SSL_read(con->ssl, b->ptr + read_offset, toread);
       
    67 +
       
    68  		if (len > 0) {
       
    69 -			b->used = len;
       
    70 +			if (b->used > 0) b->used--;
       
    71 +			b->used += len;
       
    72  			b->ptr[b->used++] = '\0';
       
    73  
       
    74 -		       	/* we move the buffer to the chunk-queue, no need to free it */
       
    75 +			con->bytes_read += len;
       
    76  
       
    77 -			chunkqueue_append_buffer_weak(con->read_queue, b);
       
    78  			count += len;
       
    79 -			con->bytes_read += len;
       
    80 -			b = NULL;
       
    81  		}
       
    82 -	} while (len > 0 && count < MAX_READ_LIMIT);
       
    83 +	} while (len == toread && count < MAX_READ_LIMIT);
       
    84  
       
    85  
       
    86  	if (len < 0) {
       
    87 @@ -234,11 +236,11 @@
       
    88  		case SSL_ERROR_WANT_READ:
       
    89  		case SSL_ERROR_WANT_WRITE:
       
    90  			con->is_readable = 0;
       
    91 -			con->ssl_error_want_reuse_buffer = b;
       
    92  
       
    93 -			b = NULL;
       
    94 +			/* the manual says we have to call SSL_read with the same arguments next time.
       
    95 +			 * we ignore this restriction; no one has complained about it in 1.5 yet, so it probably works anyway.
       
    96 +			 */
       
    97  
       
    98 -			/* we have to steal the buffer from the queue-queue */
       
    99  			return 0;
       
   100  		case SSL_ERROR_SYSCALL:
       
   101  			/**
       
   102 @@ -297,16 +299,11 @@
       
   103  
       
   104  		connection_set_state(srv, con, CON_STATE_ERROR);
       
   105  
       
   106 -		buffer_free(b);
       
   107 -
       
   108  		return -1;
       
   109  	} else if (len == 0) {
       
   110  		con->is_readable = 0;
       
   111  		/* the other end close the connection -> KEEP-ALIVE */
       
   112  
       
   113 -		/* pipelining */
       
   114 -		buffer_free(b);
       
   115 -
       
   116  		return -2;
       
   117  	}
       
   118  
       
   119 @@ -321,26 +318,41 @@
       
   120  static int connection_handle_read(server *srv, connection *con) {
       
   121  	int len;
       
   122  	buffer *b;
       
   123 -	int toread;
       
   124 +	int toread, read_offset;
       
   125  
       
   126  	if (con->conf.is_ssl) {
       
   127  		return connection_handle_read_ssl(srv, con);
       
   128  	}
       
   129  
       
   130 +	b = (NULL != con->read_queue->last) ? con->read_queue->last->mem : NULL;
       
   131 +
       
   132 +	/* default size for chunks is 4kb; only use bigger chunks if FIONREAD tells
       
   133 +	 *  us more than 4kb is available
       
   134 +	 * if FIONREAD doesn't signal a big chunk we fill the previous buffer
       
   135 +	 *  if it has >= 1kb free
       
   136 +	 */
       
   137  #if defined(__WIN32)
       
   138 -	b = chunkqueue_get_append_buffer(con->read_queue);
       
   139 -	buffer_prepare_copy(b, 4 * 1024);
       
   140 -	len = recv(con->fd, b->ptr, b->size - 1, 0);
       
   141 -#else
       
   142 -	if (ioctl(con->fd, FIONREAD, &toread) || toread == 0) {
       
   143 +	if (NULL == b || b->size - b->used < 1024) {
       
   144  		b = chunkqueue_get_append_buffer(con->read_queue);
       
   145  		buffer_prepare_copy(b, 4 * 1024);
       
   146 +	}
       
   147 +
       
   148 +	read_offset = (b->used == 0) ? 0 : b->used - 1;
       
   149 +	len = recv(con->fd, b->ptr + read_offset, b->size - 1 - read_offset, 0);
       
   150 +#else
       
   151 +	if (ioctl(con->fd, FIONREAD, &toread) || toread == 0 || toread <= 4*1024) {
       
   152 +		if (NULL == b || b->size - b->used < 1024) {
       
   153 +			b = chunkqueue_get_append_buffer(con->read_queue);
       
   154 +			buffer_prepare_copy(b, 4 * 1024);
       
   155 +		}
       
   156  	} else {
       
   157  		if (toread > MAX_READ_LIMIT) toread = MAX_READ_LIMIT;
       
   158  		b = chunkqueue_get_append_buffer(con->read_queue);
       
   159  		buffer_prepare_copy(b, toread + 1);
       
   160  	}
       
   161 -	len = read(con->fd, b->ptr, b->size - 1);
       
   162 +
       
   163 +	read_offset = (b->used == 0) ? 0 : b->used - 1;
       
   164 +	len = read(con->fd, b->ptr + read_offset, b->size - 1 - read_offset);
       
   165  #endif
       
   166  
       
   167  	if (len < 0) {
       
   168 @@ -374,7 +386,8 @@
       
   169  		con->is_readable = 0;
       
   170  	}
       
   171  
       
   172 -	b->used = len;
       
   173 +	if (b->used > 0) b->used--;
       
   174 +	b->used += len;
       
   175  	b->ptr[b->used++] = '\0';
       
   176  
       
   177  	con->bytes_read += len;
       
   178 @@ -841,13 +854,6 @@
       
   179  	/* The cond_cache gets reset in response.c */
       
   180  	/* config_cond_cache_reset(srv, con); */
       
   181  
       
   182 -#ifdef USE_OPENSSL
       
   183 -	if (con->ssl_error_want_reuse_buffer) {
       
   184 -		buffer_free(con->ssl_error_want_reuse_buffer);
       
   185 -		con->ssl_error_want_reuse_buffer = NULL;
       
   186 -	}
       
   187 -#endif
       
   188 -
       
   189  	con->header_len = 0;
       
   190  	con->in_error_handler = 0;
       
   191  
       
   192 @@ -1131,8 +1137,15 @@
       
   193  			} else {
       
   194  				buffer *b;
       
   195  
       
   196 -				b = chunkqueue_get_append_buffer(dst_cq);
       
   197 -				buffer_copy_string_len(b, c->mem->ptr + c->offset, toRead);
       
   198 +				if (dst_cq->last &&
       
   199 +				    dst_cq->last->type == MEM_CHUNK) {
       
   200 +					b = dst_cq->last->mem;
       
   201 +				} else {
       
   202 +					b = chunkqueue_get_append_buffer(dst_cq);
       
   203 +					/* prepare buffer size for remaining POST data; is < 64kb */
       
   204 +					buffer_prepare_copy(b, con->request.content_length - dst_cq->bytes_in + 1);
       
   205 +				}
       
   206 +				buffer_append_string_len(b, c->mem->ptr + c->offset, toRead);
       
   207  			}
       
   208  
       
   209  			c->offset += toRead;