diff options
author | Aaron Plattner <aplattner@nvidia.com> | 2017-02-14 15:47:10 +0000 |
---|---|---|
committer | Mike Gabriel <mike.gabriel@das-netzwerkteam.de> | 2017-03-20 10:50:57 +0100 |
commit | 2ecd2a006866bd7053536c04b195319a548c6ca2 (patch) | |
tree | 9b5fbfef6d0f26b691603fea0dff3bcaffd6c12c /nx-X11 | |
parent | cbc2d300b984d7ebc789deac0642104f223c2920 (diff) | |
download | nx-libs-2ecd2a006866bd7053536c04b195319a548c6ca2.tar.gz nx-libs-2ecd2a006866bd7053536c04b195319a548c6ca2.tar.bz2 nx-libs-2ecd2a006866bd7053536c04b195319a548c6ca2.zip |
os: Return BadLength instead of disconnecting BigReq clients (#4565)
Backported from X.org:
commit 67c66606c760c263d7a4c2d1bba43ed6225a4e7c
Author: Robert Morell <rmorell@nvidia.com>
Date: Thu May 9 13:09:02 2013 -0700
os: Reset input buffer's 'ignoreBytes' field
If a client sends a request larger than maxBigRequestSize, the server is
supposed to ignore it.
Before commit cf88363d, the server would simply disconnect the client. After
that commit, it attempts to gracefully ignore the request by remembering how
long the client specified the request to be, and ignoring that many bytes.
However, if a client sends a BigReq header with a large size and disconnects
before actually sending the rest of the specified request, the server will
reuse the ConnectionInput buffer without resetting the ignoreBytes field. This
makes the server ignore new X clients' requests.
This fixes that behavior by resetting the ignoreBytes field when putting the
ConnectionInput buffer back on the FreeInputs list.
Signed-off-by: Robert Morell <rmorell@nvidia.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
commit c80c41767eb101e9dbd8393d8cca7764b4e248a4
Author: Aaron Plattner <aplattner@nvidia.com>
Date: Mon Oct 25 22:01:32 2010 -0700
os: Fix BigReq ignoring when another request is pending
Commit cf88363db0ebb42df7cc286b85d30d7898aea840 fixed the handling of
BigReq requests that are way too large and handles the case where the
read() syscall returns a short read. However, it neglected to handle
the case where it returns a long read, which happens when the client
has another request in the queue after the bogus large one.
Handle the long read case by subtracting the smaller of 'needed' and
'gotnow' from oci->ignoreBytes. If needed < gotnow, simply subtract
the two, leaving gotnow equal to the number of extra bytes read.
Since the code immediately following the (oci->ignoreBytes > 0) block
tries to handle the next request, advance oci->bufptr immediately
instead of setting oci->lenLastReq and letting the next call to
ReadRequestFromClient do it.
Fixes the XTS pChangeKeyboardMapping-3 test.
CASES TESTS PASS UNSUP UNTST NOTIU WARN FIP FAIL UNRES UNIN ABORT
-Xproto 122 389 367 2 19 0 0 0 1 0 0 0
+Xproto 122 389 368 2 19 0 0 0 0 0 0 0
Signed-off-by: Aaron Plattner <aplattner@nvidia.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
commit cf88363db0ebb42df7cc286b85d30d7898aea840
Author: Aaron Plattner <aplattner@nvidia.com>
Date: Fri Aug 27 10:20:29 2010 -0700
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>
Backported-to-NX-by: Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
Diffstat (limited to 'nx-X11')
-rw-r--r-- | nx-X11/programs/Xserver/os/io.c | 43 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/os/osdep.h | 1 |
2 files changed, 41 insertions, 3 deletions
diff --git a/nx-X11/programs/Xserver/os/io.c b/nx-X11/programs/Xserver/os/io.c index 4dc1e7a34..78f450b63 100644 --- a/nx-X11/programs/Xserver/os/io.c +++ b/nx-X11/programs/Xserver/os/io.c @@ -252,7 +252,14 @@ ReadRequestFromClient(ClientPtr client) move_header = FALSE; #endif 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. @@ -297,8 +304,13 @@ ReadRequestFromClient(ClientPtr client) if (needed > MAXBUFSIZE) { /* 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)) @@ -405,6 +417,29 @@ ReadRequestFromClient(ClientPtr client) #endif needed = sizeof(xReq); } + + /* 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; + /* + * The _XSERVTransRead call above may return more or fewer bytes than we + * want to ignore. Ignore the smaller of the two sizes. + */ + if (gotnow < needed) { + oci->ignoreBytes -= gotnow; + oci->bufptr += gotnow; + gotnow = 0; + } else { + oci->ignoreBytes -= needed; + oci->bufptr += needed; + gotnow -= needed; + } + needed = 0; + } + oci->lenLastReq = needed; /* @@ -1178,6 +1213,7 @@ AllocateInputBuffer(void) oci->bufptr = oci->buffer; oci->bufcnt = 0; oci->lenLastReq = 0; + oci->ignoreBytes = 0; return oci; } @@ -1222,6 +1258,7 @@ FreeOsBuffers(OsCommPtr oc) oci->bufptr = oci->buffer; oci->bufcnt = 0; oci->lenLastReq = 0; + oci->ignoreBytes = 0; } } if ((oco = oc->output)) diff --git a/nx-X11/programs/Xserver/os/osdep.h b/nx-X11/programs/Xserver/os/osdep.h index 6ac9d860e..dc66649dc 100644 --- a/nx-X11/programs/Xserver/os/osdep.h +++ b/nx-X11/programs/Xserver/os/osdep.h @@ -129,6 +129,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 { |