Skip to content

Cap open SFTP handles per session - #1135

Merged
philljj merged 2 commits into
wolfSSL:masterfrom
ejohnstown:handles-cap
Jul 31, 2026
Merged

Cap open SFTP handles per session#1135
philljj merged 2 commits into
wolfSSL:masterfrom
ejohnstown:handles-cap

Conversation

@ejohnstown

Copy link
Copy Markdown
Contributor

Bounds the per-session SFTP handle lists, which an authenticated peer could previously grow without limit by looping on OPEN/OPENDIR until allocation failed. Also bounds the linear handle lookup those lists feed.

  • Caps both lists at WOLFSSH_MAX_SFTP_HANDLES (default 64, #ifndef-overridable). ssh->fileList and ssh->dirList are separate lists with separate insert paths, so each is checked independently — worst case per session is twice the macro.
  • Refuses before acquiring the resource. The cap is checked after path resolution and before WOPEN/WOPENDIR, in both the POSIX and Windows branches. This matters for files: the open flags may carry O_CREAT|O_TRUNC, so refusing after the open would truncate the target on a request the peer is told failed — a plain sftp put would zero the destination and then report failure.
  • Refusal is visible to the client as SSH_FX_FAILURE with "Too Many Open File/Directory Handles", rather than a dropped reply or a generic internal error.
  • Tests (tests/regress.c): fill to the cap, confirm the next request is refused and the list does not grow, confirm the reply is an FXP_STATUS carrying the right code and request id, confirm a refused open leaves a pre-seeded file untouched, then free one slot and confirm a fresh open succeeds — so the cap tracks the live count rather than latching shut.

Supersedes #1017, which targeted SFTP_AddHandleNode/ssh->handleList, removed from master when the handle tracking moved to ssh->fileList. Thank you to @loganaden, for the bug report and the original fix.

An authenticated peer could open SFTP file handles without limit,
growing ssh->fileList until allocation failed and making the linear
handle lookup progressively more expensive.

- Limit tracked file handles per session to WOLFSSH_MAX_SFTP_HANDLES
  (default 64), bounding memory and the linear-lookup DoS surface.
- Check the cap in SFTP_FileHandleCapped() from both RecvOpen branches
  after the path is resolved and before the file is opened. The open
  flags derived from the request may carry O_CREAT and O_TRUNC, so
  refusing after the open would create or truncate the target on a
  request the peer is told failed. SFTP_AddFileHandle() keeps the check
  as a backstop.
- Refuse with FTP_FAILURE "Too Many Open File Handles" so the peer can
  tell a resource limit from a server malfunction.
- Add a regress test via wolfSSH_SFTP_TestFileHandleCount() covering the
  cap, the refusal status reply, and that a refused open leaves the
  target file untouched.
Directory handles are tracked on ssh->dirList, a separate list from the
file handles, so the SFTP_AddFileHandle cap does not reach them. A peer
could loop on OPENDIR and grow that list until allocation failed.

- Add SFTP_DirHandleCapped() and check it in both RecvOpenDir branches
  before the directory is opened or the name buffer allocated, so the
  rejection has nothing to unwind. Refusal sends an SFTP status like the
  existing permission-denied path rather than dropping the request.
- Reuse WOLFSSH_MAX_SFTP_HANDLES, so each list is bounded separately.
- Add wolfSSH_SFTP_TestDirHandleCount() and a regress test.
Copilot AI review requested due to automatic review settings July 29, 2026 19:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #1135

Scan targets checked: wolfssh-bugs, wolfssh-src

No new issues found in the changed files. ✅

@philljj
philljj self-requested a review July 31, 2026 19:33
@philljj philljj self-assigned this Jul 31, 2026
@philljj
philljj requested a review from Copilot July 31, 2026 20:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Suppressed comments (1)

wolfssh/internal.h:900

  • The macro comment says "0 yields a cap of one handle per list", but the preprocessor check below rejects any value < 1, so 0 will not compile. This is misleading documentation for anyone trying to tune the cap.
/* Maximum number of open handles tracked per session, applied separately to
 * the file list and the directory list, so the worst case for one session is
 * twice this value. Bounds memory use and keeps the linear handle lookup from
 * becoming a CPU DoS vector. Must be at least 1; there is no "unlimited"
 * setting, and 0 yields a cap of one handle per list. */

@philljj
philljj merged commit 70eef07 into wolfSSL:master Jul 31, 2026
148 checks passed
@ejohnstown
ejohnstown deleted the handles-cap branch July 31, 2026 21:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants