From 629473e2df95744e1267f267e1fb92bce064026c Mon Sep 17 00:00:00 2001 From: Acts1631 Date: Fri, 3 Jul 2026 19:33:57 -0400 Subject: [PATCH] path: bound directory-walk recursion depth to prevent stack overflow walk_path_recursive() recursed once per directory level with no depth limit. A remote SFTP server (malicious or compromised) can present an arbitrarily deep directory hierarchy, causing the client to recurse until the thread stack is exhausted and the process crashes (SIGSEGV), aborting the transfer. Reproduced locally: a 400-level-deep local directory tree crashes the unpatched walk_src_path() with a segmentation fault (stack overflow). With this patch, the same tree is rejected cleanly with a 'directory nesting too deep' error and no crash. Add a depth counter threaded through walk_path_recursive(), bailing out at 256 levels -- deep enough for any realistic directory layout while keeping stack usage to roughly 1-2MB, well within the default 8MB thread stack. --- src/path.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/path.c b/src/path.c index 1c7ab67..583bb88 100644 --- a/src/path.c +++ b/src/path.c @@ -207,8 +207,10 @@ static bool check_path_should_skip(const char *path) return false; } +#define WALK_PATH_MAX_DEPTH 256 + static int walk_path_recursive(sftp_session sftp, const char *path, - struct path_resolve_args *a) + struct path_resolve_args *a, unsigned int depth) { char next_path[PATH_MAX + 1]; struct dirent *e; @@ -216,6 +218,12 @@ static int walk_path_recursive(sftp_session sftp, const char *path, MDIR *d; int ret; + if (depth > WALK_PATH_MAX_DEPTH) { + pr_err("directory nesting too deep (>%d): %s", + WALK_PATH_MAX_DEPTH, path); + return -1; + } + if (mscp_stat(path, &st, sftp) < 0) { pr_err("stat: %s: %s", path, strerrno()); return -1; @@ -245,7 +253,7 @@ static int walk_path_recursive(sftp_session sftp, const char *path, continue; } - walk_path_recursive(sftp, next_path, a); + walk_path_recursive(sftp, next_path, a, depth + 1); /* do not stop even when walk_path_recursive returns * -1 due to an unreadable file. go to a next * file. Thus, do not pass error messages via @@ -262,7 +270,7 @@ static int walk_path_recursive(sftp_session sftp, const char *path, int walk_src_path(sftp_session src_sftp, const char *src_path, struct path_resolve_args *a) { - return walk_path_recursive(src_sftp, src_path, a); + return walk_path_recursive(src_sftp, src_path, a, 0); } /* based on