daemonStreamHandleWrite() snapshots status from msg->header.status
before dispatching to the per-type handler, then reuses that stale
snapshot afterwards to decide whether to send a fake release reply.
A stale snapshot lets it send that reply twice for the same 'msg',
linking the message to itself and deadlooping the event loop thread
in virNetMessageQueuePush()'s tail-walk loop.

Remove the 'status' variable and read msg->header.status directly
at the point of use instead. Commit 411cbe7199c ("remote: fix
stream use-after-free") introduced it alongside its real fix: it
also moved virNetMessageQueueServe() to dequeue 'msg' from
stream->rx before dispatch instead of after, which is what actually
prevents corrupting stream->rx's linkage and remains unchanged
here. The variable itself was never load-bearing: no dispatch
handler frees 'msg' on the path that reaches this check, so reading
msg->header.status straight from 'msg' cannot go stale.

Fixes: 411cbe7199ce ("remote: fix stream use-after-free")
Signed-off-by: Denis V. Lunev <[email protected]>
---
 src/remote/remote_daemon_stream.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/src/remote/remote_daemon_stream.c 
b/src/remote/remote_daemon_stream.c
index 3777c8e684..437cec374f 100644
--- a/src/remote/remote_daemon_stream.c
+++ b/src/remote/remote_daemon_stream.c
@@ -736,7 +736,6 @@ static int
 daemonStreamHandleWrite(virNetServerClient *client,
                         daemonClientStream *stream)
 {
-    virNetMessageStatus status = VIR_NET_OK;
     VIR_DEBUG("client=%p, stream=%p", client, stream);
 
     while (stream->rx && !stream->closed) {
@@ -748,10 +747,8 @@ daemonStreamHandleWrite(virNetServerClient *client,
              * Otherwise just carry on with processing stream
              * data. */
             ret = daemonStreamHandleHole(client, stream, msg);
-            status = msg->header.status;
         } else if (msg->header.type == VIR_NET_STREAM) {
-            status = msg->header.status;
-            switch (status) {
+            switch (msg->header.status) {
             case VIR_NET_OK:
                 ret = daemonStreamHandleFinish(client, stream, msg);
                 break;
@@ -791,7 +788,7 @@ daemonStreamHandleWrite(virNetServerClient *client,
          * onto the wire, but this causes the client to reset
          * its active request count / throttling
          */
-        if (status == VIR_NET_CONTINUE) {
+        if (msg->header.status == VIR_NET_CONTINUE) {
             virNetMessageClear(msg);
             msg->header.type = VIR_NET_REPLY;
             if (virNetServerClientSendMessage(client, msg) < 0) {
-- 
2.53.0

Reply via email to