summaryrefslogtreecommitdiffstats
path: root/Modules/_ssl.c
diff options
context:
space:
mode:
authorNeal Norwitz <nnorwitz@gmail.com>2006-02-07 07:04:46 (GMT)
committerNeal Norwitz <nnorwitz@gmail.com>2006-02-07 07:04:46 (GMT)
commit082b2df33f4a916392dca2260fdcdd1cbe3a8329 (patch)
tree74534a40daa21d4ca98584ce15a602cf9ef4d260 /Modules/_ssl.c
parent19cbcad20e3672ffe42e5710843f0df3de3f3b8c (diff)
downloadcpython-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.c14
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;