Skip to content

Commit bd9ebee

Browse files
committed
Land rapid7#5851, meterpreter dispatcher queue
2 parents 7ad8adf + c03ff13 commit bd9ebee

File tree

2 files changed

+26
-30
lines changed

2 files changed

+26
-30
lines changed

lib/rex/post/meterpreter/packet_dispatcher.rb

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ def monitor_socket
253253

254254
self.waiters = []
255255

256-
@pqueue = []
256+
@pqueue = ::Queue.new
257257
@finish = false
258258
@last_recvd = Time.now
259259
@ping_sent = false
@@ -318,16 +318,12 @@ def monitor_socket
318318
# Whether we're finished or not is determined by the receiver
319319
# thread above.
320320
while(not @finish)
321-
if(@pqueue.empty?)
322-
::IO.select(nil, nil, nil, 0.10)
323-
next
324-
end
325-
326321
incomplete = []
327322
backlog = []
328323

324+
backlog << @pqueue.pop
329325
while(@pqueue.length > 0)
330-
backlog << @pqueue.shift
326+
backlog << @pqueue.pop
331327
end
332328

333329
#
@@ -393,11 +389,16 @@ def monitor_socket
393389
::IO.select(nil, nil, nil, 0.10)
394390
end
395391

396-
@pqueue.unshift(*incomplete)
392+
while incomplete.length > 0
393+
@pqueue << incomplete.shift
394+
end
397395

398396
if(@pqueue.length > 100)
399-
dlog("Backlog has grown to over 100 in monitor_socket, dropping older packets: #{@pqueue[0 .. 25].map{|x| x.inspect}.join(" - ")}", 'meterpreter', LEV_1)
400-
@pqueue = @pqueue[25 .. 100]
397+
removed = []
398+
(1..25).each {
399+
removed << @pqueue.pop
400+
}
401+
dlog("Backlog has grown to over 100 in monitor_socket, dropping older packets: #{removed.map{|x| x.inspect}.join(" - ")}", 'meterpreter', LEV_1)
401402
end
402403
end
403404
rescue ::Exception => e
@@ -454,15 +455,16 @@ def add_response_waiter(request, completion_routine = nil, completion_param = ni
454455
# if anyone.
455456
#
456457
def notify_response_waiter(response)
458+
handled = false
457459
self.waiters.each() { |waiter|
458460
if (waiter.waiting_for?(response))
459461
waiter.notify(response)
460-
461462
remove_response_waiter(waiter)
462-
463+
handled = true
463464
break
464465
end
465466
}
467+
return handled
466468
end
467469

468470
#

lib/rex/post/meterpreter/packet_response_waiter.rb

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ def initialize(rid, completion_routine = nil, completion_param = nil)
2727
self.completion_routine = completion_routine
2828
self.completion_param = completion_param
2929
else
30-
self.done = false
30+
self.mutex = Mutex.new
31+
self.cond = ConditionVariable.new
3132
end
3233
end
3334

@@ -43,12 +44,14 @@ def waiting_for?(packet)
4344
# Notifies the waiter that the supplied response packet has arrived.
4445
#
4546
def notify(response)
46-
self.response = response
47-
4847
if (self.completion_routine)
48+
self.response = response
4949
self.completion_routine.call(response, self.completion_param)
5050
else
51-
self.done = true
51+
self.mutex.synchronize do
52+
self.response = response
53+
self.cond.signal
54+
end
5255
end
5356
end
5457

@@ -57,25 +60,16 @@ def notify(response)
5760
# If the interval is -1 we can wait forever.
5861
#
5962
def wait(interval)
60-
if( interval and interval == -1 )
61-
while(not self.done)
62-
::IO.select(nil, nil, nil, 0.1)
63-
end
64-
else
65-
begin
66-
Timeout.timeout(interval) {
67-
while(not self.done)
68-
::IO.select(nil, nil, nil, 0.1)
69-
end
70-
}
71-
rescue Timeout::Error
72-
self.response = nil
63+
interval = nil if interval and interval == -1
64+
self.mutex.synchronize do
65+
if self.response.nil?
66+
self.cond.wait(self.mutex, interval)
7367
end
7468
end
7569
return self.response
7670
end
7771

78-
attr_accessor :rid, :done, :response # :nodoc:
72+
attr_accessor :rid, :mutex, :cond, :response # :nodoc:
7973
attr_accessor :completion_routine, :completion_param # :nodoc:
8074
end
8175

0 commit comments

Comments
 (0)