Skip to content

Prevent file descriptor leaks in user input handling#21569

Open
dwelch-r7 wants to merge 1 commit into
rapid7:masterfrom
dwelch-r7:fix-fd-leak
Open

Prevent file descriptor leaks in user input handling#21569
dwelch-r7 wants to merge 1 commit into
rapid7:masterfrom
dwelch-r7:fix-fd-leak

Conversation

@dwelch-r7

@dwelch-r7 dwelch-r7 commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Description

fixes leaking file descriptors

Related Issue: #21553

Breaking Changes

None

Verification Steps

Automated Tests

bundle exec rspec spec/lib/rex/ui/subscriber_spec.rb

All 40 examples should pass. The "FD stability with real Input::Buffer instances" test directly validates that repeated init_ui calls with socket-backed buffers do not leak file descriptors.

Manual Verification — FD Leak over RPC
Reproduces the issue from #21553 using a meterpreter bind payload in Docker.

  • Generate a meterpreter bind payload
    ./msfvenom -p linux/x64/meterpreter/bind_tcp LPORT=4444 -f elf -o /tmp/mbind

  • Run it in a Docker container
    docker run --rm -d --name msf-target -p 4444:4444 -v /tmp/mbind:/mbind debian:bookworm-slim bash -c "chmod +x /mbind && /mbind"

  • Start msfrpcd (no SSL, foreground)
    ./msfrpcd -P test -S -f -a 127.0.0.1

  • Connect to the bind payload via msfrpc
    ./msfrpc -a 127.0.0.1 -S -P test -U msf
    In the IRB shell:

rpc.call('module.execute', 'exploit', 'multi/handler', {'PAYLOAD' => 'linux/x64/meterpreter/bind_tcp', 'RHOST' => '127.0.0.1', 'LPORT' => '4444'})
Wait a few seconds, confirm the session:

rpc.call('session.list')

  • Record baseline FD count (separate terminal)
    lsof -p $(pgrep -f msfrpcd) | wc -l

  • Run repeated RPC interactions with pymetasploit3
    pip install pymetasploit3

from pymetasploit3.msfrpc import MsfRpcClient
client = MsfRpcClient('test', ssl=False)
sid = list(client.sessions.list.keys())[0]
for i in range(20):
    shell = client.sessions.session(sid)
    shell.write('id')
    shell.read()
    print(f'Cycle {i+1}')
  • Check FD count
    lsof -p $(pgrep -f msfrpcd) | wc -l
    Expected (with fix): FD count remains stable (no growth after initial settling).

Before fix: FD count grows by ~4 per cycle (2 TCP sockets + 2 FIFO pipes leaked each time).

  • Cleanup
    docker rm -f msf-target

Test Evidence

~/dev/rex-socket on  fix-fd-leak! ⌚ 13:34:58
$ lsof -p $(pgrep -f msfrpcd) | wc -l                                                   ‹ruby-3.4.5›

     119
     
~/dev/metasploit-framework on  fix-fd-leak! ⌚ 13:36:45
$ python3 -c "                                                     ‹ruby-3.3.8@metasploit-framework›
from pymetasploit3.msfrpc import MsfRpcClient
client = MsfRpcClient('test', ssl=False)
sid = list(client.sessions.list.keys())[0]
for i in range(20):
    shell = client.sessions.session(sid)
    shell.write('id')
    shell.read()
    print(f'Cycle {i+1}')
"
Cycle 1
Cycle 2
Cycle 3
Cycle 4
Cycle 5
Cycle 6
Cycle 7
Cycle 8
Cycle 9
Cycle 10
Cycle 11
Cycle 12
Cycle 13
Cycle 14
Cycle 15
Cycle 16
Cycle 17
Cycle 18
Cycle 19
Cycle 20

~/dev/rex-socket on  fix-fd-leak! ⌚ 13:36:46
$ lsof -p $(pgrep -f msfrpcd) | wc -l                                                   ‹ruby-3.4.5›

     119
     

Environment

Field Details
Operating System macOS 26.5.1
Ruby Version 3.3.8

AI Usage Disclosure

Kiro

Pre-Submission Checklist

  • Ran rubocop on new files with no new offenses (net new files only)
  • Ran msftidy on changed module files with no new offenses (modules only)
  • Ran msftidy_docs on changed documentation files with no new offenses (documentation files only)
  • Included a corresponding documentation markdown file in documentation/modules (new modules only)
  • No sensitive information (IP addresses, credentials, API keys, hashes) in code or documentation
  • Tested on the target environment specified in the Environment section above
  • Included RSpec tests for library changes (encouraged for lib/ changes)
  • Read the CONTRIBUTING.md and module acceptance guidelines

@github-actions

Copy link
Copy Markdown

Thanks for your pull request! As part of our landing process, we manually verify that all modules work as expected.

We've added the additional-testing-required label to indicate that additional testing is required before this pull request can be merged.
For maintainers, this means visiting here.

@dwelch-r7 dwelch-r7 changed the title [WIP] prevent file descriptor leaks in user input handling Prevent file descriptor leaks in user input handling Jun 15, 2026
@dwelch-r7 dwelch-r7 added the rn-fix release notes fix label Jun 15, 2026
@jenkins-eks-metasploit

Copy link
Copy Markdown

Additional test pipeline started ⌛
Note: build results only accessible to maintainers.

@jenkins-eks-metasploit

Copy link
Copy Markdown

Pipeline results available

Slice summary:

No test slices found.

Note: build results only accessible to maintainers.

@jenkins-eks-metasploit

Copy link
Copy Markdown

Additional test pipeline started ⌛
Note: build results only accessible to maintainers.

@jenkins-eks-metasploit

Copy link
Copy Markdown

Pipeline results available

Slice summary:

  • Test slice 2 - 🟢
  • Test slice 3 - 🟢

Note: build results only accessible to maintainers.

@jenkins-eks-metasploit

Copy link
Copy Markdown

Additional test pipeline started ⌛
Note: build results only accessible to maintainers.

@jenkins-eks-metasploit

Copy link
Copy Markdown

Pipeline results available

Slice summary:

  • Test slice 1 - 🟢
  • Test slice 2 - 🟢
  • Test slice 3 - 🟢
  • Test slice 4 - 🟢

Note: build results only accessible to maintainers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

2 participants