diff options
author | Neal Norwitz <nnorwitz@gmail.com> | 2006-02-07 07:04:46 (GMT) |
---|---|---|
committer | Neal Norwitz <nnorwitz@gmail.com> | 2006-02-07 07:04:46 (GMT) |
commit | 082b2df33f4a916392dca2260fdcdd1cbe3a8329 (patch) | |
tree | 74534a40daa21d4ca98584ce15a602cf9ef4d260 /Modules/_ssl.c | |
parent | 19cbcad20e3672ffe42e5710843f0df3de3f3b8c (diff) | |
download | cpython-082b2df33f4a916392dca2260fdcdd1cbe3a8329.zip cpython-082b2df33f4a916392dca2260fdcdd1cbe3a8329.tar.gz cpython-082b2df33f4a916392dca2260fdcdd1cbe3a8329.tar.bz2 |
Bug #876637, prevent stack corruption when socket descriptor
is larger than FD_SETSIZE.
This can only be acheived with ulimit -n SOME_NUMBER_BIGGER_THAN_FD_SETSIZE
which is typically only available to root. Since this wouldn't normally
be run in a test (ie, run as root), it doesn't seem too worthwhile to
add a normal test. The bug report has one version of a test. I've
written another. Not sure what the best thing to do is.
Do the check before calling internal_select() because we can't set
an error in between Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS.
This seemed the clearest solution, ie handle before calling internal_select()
rather than inside. Plus there is at least one place outside
of internal_select() that needed to be handled.
Will backport.
Diffstat (limited to 'Modules/_ssl.c')
-rw-r--r-- | Modules/_ssl.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/Modules/_ssl.c b/Modules/_ssl.c index b8097e1..6448cb0 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -74,6 +74,7 @@ typedef enum { SOCKET_IS_BLOCKING, SOCKET_HAS_TIMED_OUT, SOCKET_HAS_BEEN_CLOSED, + SOCKET_INVALID, SOCKET_OPERATION_OK } timeout_state; @@ -272,6 +273,9 @@ newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file) } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { PyErr_SetString(PySSLErrorObject, "Underlying socket has been closed."); goto fail; + } else if (sockstate == SOCKET_INVALID) { + PyErr_SetString(PySSLErrorObject, "Underlying socket too large for select()."); + goto fail; } else if (sockstate == SOCKET_IS_NONBLOCKING) { break; } @@ -372,6 +376,10 @@ check_socket_and_wait_for_timeout(PySocketSockObject *s, int writing) if (s->sock_fd < 0) return SOCKET_HAS_BEEN_CLOSED; + /* Guard against socket too large for select*/ + if (s->sock_fd >= FD_SETSIZE) + return SOCKET_INVALID; + /* Construct the arguments to select */ tv.tv_sec = (int)s->sock_timeout; tv.tv_usec = (int)((s->sock_timeout - tv.tv_sec) * 1e6); @@ -409,6 +417,9 @@ static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args) } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { PyErr_SetString(PySSLErrorObject, "Underlying socket has been closed."); return NULL; + } else if (sockstate == SOCKET_INVALID) { + PyErr_SetString(PySSLErrorObject, "Underlying socket too large for select()."); + return NULL; } do { err = 0; @@ -467,6 +478,9 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args) PyErr_SetString(PySSLErrorObject, "The read operation timed out"); Py_DECREF(buf); return NULL; + } else if (sockstate == SOCKET_INVALID) { + PyErr_SetString(PySSLErrorObject, "Underlying socket too large for select()."); + return NULL; } do { err = 0; |