File memcached-1.2.x_garbage_data_dos.patch of Package memcached
This patch contains: d9cd01ede97f4145af9781d448c62a3318952719 and 75cc83685e103bc8ba380a57468c8f04413033f9
From 75cc83685e103bc8ba380a57468c8f04413033f9 Mon Sep 17 00:00:00 2001
From: Trond Norbye <Trond.Norbye@sun.com>
Date: Wed, 28 Oct 2009 11:51:05 +0100
Subject: [PATCH] Issue 102: Piping null to the server will crash it
---
memcached.c | 31 +++++++++++++++++++++++++++++--
testapp.c | 17 +++++++++++++++++
2 files changed, 46 insertions(+), 2 deletions(-)
Index: memcached.c
===================================================================
--- memcached.c.orig 2010-04-09 13:21:06.000000000 +0200
+++ memcached.c 2010-04-09 13:24:35.605185882 +0200
@@ -1861,8 +1861,27 @@ static int try_read_command(conn *c) {
if (c->rbytes == 0)
return 0;
el = memchr(c->rcurr, '\n', c->rbytes);
- if (!el)
+ if (!el) {
+ if (c->rbytes > 1024) {
+ /*
+ * We didn't have a '\n' in the first k. This _has_ to be a
+ * large multiget, if not we should just nuke the connection.
+ */
+ char *ptr = c->rcurr;
+ while (*ptr == ' ') { /* ignore leading whitespaces */
+ ++ptr;
+ }
+
+ if (ptr - c->rcurr > 100 ||
+ (strncmp(ptr, "get ", 4) && strncmp(ptr, "gets ", 5))) {
+
+ conn_set_state(c, conn_closing);
+ return 1;
+ }
+ }
+
return 0;
+ }
cont = el + 1;
if ((el - c->rcurr) > 1 && *(el - 1) == '\r') {
el--;
@@ -1925,11 +1944,17 @@ static int try_read_udp(conn *c) {
* before reading, move the remaining incomplete fragment of a command
* (if any) to the beginning of the buffer.
* return 0 if there's nothing to read on the first read.
+ *
+ * To protect us from someone flooding a connection with bogus data causing
+ * the connection to eat up all available memory, break out and start looking
+ * at the data I've got after a number of reallocs...
+ *
*/
static int try_read_network(conn *c) {
int gotdata = 0;
int res;
+ int num_allocs = 0;
assert(c != NULL);
if (c->rcurr != c->rbuf) {
@@ -1940,6 +1965,10 @@ static int try_read_network(conn *c) {
while (1) {
if (c->rbytes >= c->rsize) {
+ if (num_allocs == 4) {
+ return gotdata;
+ }
+ ++num_allocs;
char *new_rbuf = realloc(c->rbuf, c->rsize * 2);
if (!new_rbuf) {
if (settings.verbose > 0)