A zero return from BIO_read()/BIO_write() could be retryable
authorMatt Caswell <matt@openssl.org>
Fri, 21 Oct 2016 12:25:19 +0000 (13:25 +0100)
committerMatt Caswell <matt@openssl.org>
Fri, 28 Oct 2016 08:17:30 +0000 (09:17 +0100)
A zero return from BIO_read()/BIO_write() could mean that an IO operation
is retryable. A zero return from SSL_read()/SSL_write() means that the
connection has been closed down (either cleanly or not). Therefore we
should not propagate a zero return value from BIO_read()/BIO_write() back
up the stack to SSL_read()/SSL_write(). This could result in a retryable
failure being treated as fatal.

Reviewed-by: Richard Levitte <levitte@openssl.org>
(cherry picked from commit 4880672a9b41a09a0984b55e219f02a2de7ab75e)

ssl/record/rec_layer_s3.c

index 0775095b9a317e30c94928258776d3fa12992dfd..9c8c23c85332b44940233206f82702d49c356c75 100644 (file)
@@ -177,6 +177,12 @@ const char *SSL_rstate_string(const SSL *s)
     }
 }
 
+/*
+ * Return values are as per SSL_read(), i.e.
+ * >0 The number of read bytes
+ *  0 Failure (not retryable)
+ * <0 Failure (may be retryable)
+ */
 int ssl3_read_n(SSL *s, int n, int max, int extend, int clearold)
 {
     /*
@@ -306,7 +312,7 @@ int ssl3_read_n(SSL *s, int n, int max, int extend, int clearold)
             if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s))
                 if (len + left == 0)
                     ssl3_release_read_buffer(s);
-            return (i);
+            return -1;
         }
         left += i;
         /*
@@ -874,7 +880,13 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
     return -1;
 }
 
-/* if s->s3->wbuf.left != 0, we need to call this */
+/* if s->s3->wbuf.left != 0, we need to call this
+ *
+ * Return values are as per SSL_read(), i.e.
+ * >0 The number of read bytes
+ *  0 Failure (not retryable)
+ * <0 Failure (may be retryable)
+ */
 int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
                        unsigned int len)
 {
@@ -924,7 +936,7 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
                  */
                 SSL3_BUFFER_set_left(&wb[currbuf], 0);
             }
-            return (i);
+            return -1;
         }
         SSL3_BUFFER_add_offset(&wb[currbuf], i);
         SSL3_BUFFER_add_left(&wb[currbuf], -i);