Currently _send() in stream.py[L#415] converts the string buffer to bytes in
case the caller passes it a string buffer.

This becomes a problem when retrying this send call (say due to EAGAIN errors)
with SSLStream and underlying OpenSSL implementation.
Converting the buffer from string to bytes effectively changes the buffer
address (even though its content might be same).
But the OpenSSL implementation expects that the buffer contents and address
to remain same when retrying send/ssl_write on retryable errors such
as EAGAIN.

Following is the sample stacktrace seen when stream.send() return EAGAIN error
and the call is retried by jsonrpc.run():

```
File "/usr/local/lib/python3.9/site-packages/ovs/db/idl.py", line 1652,
in commit_block
    self.idl.run()
  File "/usr/local/lib/python3.9/site-packages/ovs/db/idl.py", line 240,
in run
    self._session.run()
  File "/usr/local/lib/python3.9/site-packages/ovs/jsonrpc.py", line
503, in run
    self.rpc.run()
  File "/usr/local/lib/python3.9/site-packages/ovs/jsonrpc.py", line
202, in run
    retval = self.stream.send(self.output)
  File "/usr/local/lib/python3.9/site-packages/ovs/stream.py", line 831,
in send
    return super(SSLStream, self).send(buf)
  File "/usr/local/lib/python3.9/site-packages/ovs/stream.py", line 413,
in send
    return self.socket.send(buf)
  File "/usr/local/lib/python3.9/site-packages/OpenSSL/SSL.py", line
1652, in send
    self._raise_ssl_error(self._ssl, result)
  File "/usr/local/lib/python3.9/site-packages/OpenSSL/SSL.py", line
1566, in _raise_ssl_error
    _raise_current_error()
  File "/usr/local/lib/python3.9/site-packages/OpenSSL/_util.py", line
57, in exception_from_error_queue
    raise exception_type(errors)
OpenSSL.SSL.Error: [('SSL routines', 'ssl3_write_pending', 'bad write
retry')]
```

This patch fixes it by maintaining the data to be sent as bytes instead
of string in jsonrpc.py so that on retries buffer remains unchanged.

Signed-off-by: Priyankar Jain <[email protected]>
---
 python/ovs/jsonrpc.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/python/ovs/jsonrpc.py b/python/ovs/jsonrpc.py
index d5127268a..60c631874 100644
--- a/python/ovs/jsonrpc.py
+++ b/python/ovs/jsonrpc.py
@@ -186,7 +186,7 @@ class Connection(object):
         self.stream = stream
         self.status = 0
         self.input = ""
-        self.output = ""
+        self.output = b''
         self.parser = None
         self.received_bytes = 0
 
@@ -238,7 +238,7 @@ class Connection(object):
         self.__log_msg("send", msg)
 
         was_empty = len(self.output) == 0
-        self.output += ovs.json.to_string(msg.to_json())
+        self.output += ovs.json.to_string(msg.to_json()).encode("utf-8")
         if was_empty:
             self.run()
         return self.status
@@ -365,7 +365,7 @@ class Connection(object):
         if self.status == 0:
             self.status = error
             self.stream.close()
-            self.output = ""
+            self.output = b''
 
 
 class Session(object):
-- 
2.22.3

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to