Skip to content

Commit 65d71a5

Browse files
author
Brent Cook
committed
Fix rapid7#4625 Reenable channel receive packet requeueing logic
In rapid7#4475, I incorrectly interpreted the role of the 'incomplete' array in monitor_socket, and that change should be reverted. What appears to happen is, we play a kind of 3-card monty with the list of received packets that are waiting for a handler to use them. monitor_socket continually loops between putting the packets on @pqueue, then into backlog[] to sort them, then into incomplete[] to list all of the packets that did not have handlers, finally back into @pqueue again. If packets don't continually get shuffled back into incomplete, they are not copied back into @pqueue to get rescanned again. The only reason anything should really get into incomplete[] is if we receive a packet, but there is nothing to handle it. This scenario sounds like a bug, but it is exactly what happens with the Tcp Client channel - one can open a new channel, and receive a response packet back from the channel before the subsequent read_once code runs to register a handler to actually process it. This would be akin to your OS speculatively accepting data on a TCP socket with no listener, then when you open the socket for the first time, its already there. While it would be nice if the handlers were setup before the data was sent back, rather than relying on a handler being registered some time between connect and PacketTimeout, this needs to get in now to stop the bleeding. The original meterpreter crash issue from rapid7#4475 appears to be gone as well.
1 parent 75e0470 commit 65d71a5

File tree

1 file changed

+8
-2
lines changed

1 file changed

+8
-2
lines changed

lib/rex/post/meterpreter/packet_dispatcher.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,8 +355,14 @@ def monitor_socket
355355

356356
begin
357357
if ! dispatch_inbound_packet(pkt)
358-
# Only requeue packets newer than the timeout
359-
if (::Time.now.to_i - pkt.created_at.to_i > PacketTimeout)
358+
# Keep Packets in the receive queue until a handler is registered
359+
# for them. Packets will live in the receive queue for up to
360+
# PacketTimeout, after which they will be dropped.
361+
#
362+
# A common reason why there would not immediately be a handler for
363+
# a received Packet is in channels, where a connection may
364+
# open and receive data before anything has asked to read.
365+
if (::Time.now.to_i - pkt.created_at.to_i < PacketTimeout)
360366
incomplete << pkt
361367
end
362368
end

0 commit comments

Comments
 (0)