This mirrors the solution in commit f3728a162d22 ("erofs-utils: dump:
fix stack-overflow due to directory loops").Reported-by: Tristan <[email protected]> Fixes: 5a9ac8e057cf ("erofs-utils: dump: convert readdir to use erofs_iterate_dir()") Closes: https://lore.kernel.org/r/CAA1XrhPMekMqAnRkC-jV9rTsO4LHjzh=kxn6zqkmgbrqfrn...@mail.gmail.com/6-dump-erofs-recursion.txt Signed-off-by: Gao Xiang <[email protected]> --- dump/main.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/dump/main.c b/dump/main.c index 6c7258a5db40..9eebcb8a3e3f 100644 --- a/dump/main.c +++ b/dump/main.c @@ -17,7 +17,13 @@ #include "../lib/liberofs_private.h" #include "../lib/liberofs_uuid.h" +struct erofsdump_dirstack { + erofs_nid_t dirs[PATH_MAX]; + int top; +}; + struct erofsdump_cfg { + struct erofsdump_dirstack dirstack; unsigned int totalshow; bool show_inode; bool show_extent; @@ -359,7 +365,6 @@ static int erofsdump_readdir(struct erofs_dir_context *ctx) update_file_size_statistics(occupied_size, false); } - /* XXXX: the dir depth should be restricted in order to avoid loops */ if (S_ISDIR(vi.i_mode)) { struct erofs_dir_context nctx = { .flags = ctx->dir ? EROFS_READDIR_VALID_PNID : 0, @@ -367,8 +372,18 @@ static int erofsdump_readdir(struct erofs_dir_context *ctx) .dir = &vi, .cb = erofsdump_dirent_iter, }; - - return erofs_iterate_dir(&nctx, false); + int i, ret; + + /* XXX: support the deeper cases later */ + if (dumpcfg.dirstack.top >= ARRAY_SIZE(dumpcfg.dirstack.dirs)) + return -ENAMETOOLONG; + for (i = 0; i < dumpcfg.dirstack.top; ++i) + if (vi.nid == dumpcfg.dirstack.dirs[i]) + return -ELOOP; + dumpcfg.dirstack.dirs[dumpcfg.dirstack.top++] = nctx.pnid; + ret = erofs_iterate_dir(&nctx, false); + --dumpcfg.dirstack.top; + return ret; } return 0; } -- 2.43.5
