summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2010-08-27 10:20:29 -0700
committerAaron Plattner <aplattner@nvidia.com>2010-09-30 16:23:13 -0700
commit0ca9f07f7349afc41bdb68a8956c24be1d7d779e (patch)
tree985382c5de726bb787a44194dd8633928b277ec5
parent3336e1f7f3d7a0e37cc75f7edd96524dd6cf228a (diff)
os: Return BadLength instead of disconnecting BigReq clients (#4565)
If a client sends a big request that's too big (i.e. bigger than maxBigRequestSize << 2 bytes), the server just disconnects it. This makes the client receive SIGPIPE the next time it tries to send something. The X Test Suite sends requests that are too big when the test specifies the TOO_LONG test type. When the client receives SIGPIPE, XTS marks it as UNRESOLVED, which counts as a failure. Instead, remember how long the request is supposed to be and then return that size. Dispatch() checks the length and sends BadLength to the client. Then, whenever oci->ignoreBytes is nonzero, ignore the data read instead of trying to process it as a request. Signed-off-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Keith Packard <keithp@keithp.com> (cherry picked from commit cf88363db0ebb42df7cc286b85d30d7898aea840)
-rw-r--r--os/io.c27
-rw-r--r--os/osdep.h1
2 files changed, 25 insertions, 3 deletions
diff --git a/os/io.c b/os/io.c
index 64b64ae75..923509a68 100644
--- a/os/io.c
+++ b/os/io.c
@@ -251,7 +251,14 @@ ReadRequestFromClient(ClientPtr client)
need_header = FALSE;
move_header = FALSE;
gotnow = oci->bufcnt + oci->buffer - oci->bufptr;
- if (gotnow < sizeof(xReq))
+
+ if (oci->ignoreBytes > 0) {
+ if (oci->ignoreBytes > oci->size)
+ needed = oci->size;
+ else
+ needed = oci->ignoreBytes;
+ }
+ else if (gotnow < sizeof(xReq))
{
/* We don't have an entire xReq yet. Can't tell how big
* the request will be until we get the whole xReq.
@@ -294,8 +301,13 @@ ReadRequestFromClient(ClientPtr client)
if (needed > maxBigRequestSize << 2)
{
/* request is too big for us to handle */
- YieldControlDeath();
- return -1;
+ /*
+ * Mark the rest of it as needing to be ignored, and then return
+ * the full size. Dispatch() will turn it into a BadLength error.
+ */
+ oci->ignoreBytes = needed - gotnow;
+ oci->lenLastReq = gotnow;
+ return needed;
}
if ((gotnow == 0) ||
((oci->bufptr - oci->buffer + needed) > oci->size))
@@ -400,6 +412,14 @@ ReadRequestFromClient(ClientPtr client)
}
oci->lenLastReq = needed;
+ /* If there are bytes to ignore, ignore them now. */
+
+ if (oci->ignoreBytes > 0) {
+ assert(needed == oci->ignoreBytes || needed == oci->size);
+ oci->ignoreBytes -= gotnow;
+ needed = gotnow = 0;
+ }
+
/*
* Check to see if client has at least one whole request in the
* buffer beyond the request we're returning to the caller.
@@ -1024,6 +1044,7 @@ AllocateInputBuffer(void)
oci->bufptr = oci->buffer;
oci->bufcnt = 0;
oci->lenLastReq = 0;
+ oci->ignoreBytes = 0;
return oci;
}
diff --git a/os/osdep.h b/os/osdep.h
index 3d75bbaab..a0411ecf9 100644
--- a/os/osdep.h
+++ b/os/osdep.h
@@ -124,6 +124,7 @@ typedef struct _connectionInput {
int bufcnt; /* count of bytes in buffer */
int lenLastReq;
int size;
+ unsigned int ignoreBytes; /* bytes to ignore before the next request */
} ConnectionInput, *ConnectionInputPtr;
typedef struct _connectionOutput {