[Spice-devel] [PATCH 05/13] server/reds: RFC: improve ssl_{read, write} return values

Marc-André Lureau marcandre.lureau at redhat.com
Tue Feb 22 08:08:59 PST 2011


There is no known bug related to this patch, it might cause more harm
than good.

The implementation of ssl_writev() looks incorrect: it never returned
an error (return_code is always >= 0). But, it should return the
number of bytes written before it reached EAGAIN, otherwise, we risk
of sending corrupted data.

Finally, since the SSL usage is hidden from the reader/writter, and it
assumes it is a fd-kind/libc of API (checking ERRNO), we should make
sure errno is set to a correct value in that case (EAGAIN for instance).

Note: we should be careful with the polling of SSL fd, since
SSL_read() or SSL_write() both can return WANT_READ or WANT_WRITE.  We
should poll both IN and OUT, not sure how it's handled now.
---
 server/reds.c |   31 +++++++++++++++++++------------
 1 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/server/reds.c b/server/reds.c
index 45e4964..2aefe31 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -319,6 +319,13 @@ static ssize_t stream_read_cb(RedsStream *s, void *buf, size_t size)
     return read(s->socket, buf, size);
 }
 
+static void ssl_error_eagain(int error)
+{
+    /* can this help? */
+    if (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE)
+        errno = EAGAIN;
+}
+
 static ssize_t stream_ssl_write_cb(RedsStream *s, const void *buf, size_t size)
 {
     int return_code;
@@ -326,8 +333,10 @@ static ssize_t stream_ssl_write_cb(RedsStream *s, const void *buf, size_t size)
 
     return_code = SSL_write(s->ssl, buf, size);
 
-    if (return_code < 0)
+    if (return_code < 0) {
         ssl_error = SSL_get_error(s->ssl, return_code);
+        ssl_error_eagain(ssl_error); /* just to be sure */
+    }
 
     return return_code;
 }
@@ -339,8 +348,10 @@ static ssize_t stream_ssl_read_cb(RedsStream *s, void *buf, size_t size)
 
     return_code = SSL_read(s->ssl, buf, size);
 
-    if (return_code < 0)
+    if (return_code < 0) {
         ssl_error = SSL_get_error(s->ssl, return_code);
+        ssl_error_eagain(ssl_error); /* just to be sure */
+    }
 
     return return_code;
 }
@@ -349,24 +360,20 @@ static ssize_t stream_ssl_writev_cb(RedsStream *s, const struct iovec *vector, i
 {
     int i;
     int n;
-    ssize_t return_code = 0;
+    ssize_t ret = 0;
     int ssl_error;
 
     for (i = 0; i < count; ++i) {
         n = SSL_write(s->ssl, vector[i].iov_base, vector[i].iov_len);
         if (n <= 0) {
             ssl_error = SSL_get_error(s->ssl, n);
-            if (return_code <= 0) {
-                return n;
-            } else {
-                break;
-            }
-        } else {
-            return_code += n;
-        }
+            ssl_error_eagain(ssl_error); /* just to be sure we have EAGAIN */
+            return ret == 0 ? n : ret;
+        } else
+            ret += n;
     }
 
-    return return_code;
+    return ret;
 }
 
 static void reds_stream_remove_watch(RedsStream* s)
-- 
1.7.4



More information about the Spice-devel mailing list