Rebased the debdiff for stonking onto current archive version
0.12.0-1ubuntu2:
- stonking: rust-coreutils_0.12.0-1ubuntu3_stonking.debdiff (attached to this
comment)
- resolute: 0.10.0-1ubuntu2~26.04.2 (attached in previous comment)
The patch applies cleanly on top of 0.12.0-1ubuntu2, all crate test
suites pass with 0 regressions, and directory traversal on deep trees
executes without SIGSEGV.
Returning bug status to Confirmed for sponsorship review.
** Description changed:
[ Impact ]
In Ubuntu Resolute and Stonking, rust-coreutils provides the core utilities
du, chmod, chown, and chgrp. When operating on deeply nested directory trees
(depths of ~2000 levels or more), all four utilities crash with Segmentation
fault (core dumped) (SIGSEGV).
The root cause is that directory traversal in du (safe_du), chmod
(safe_traverse_dir), and perms (safe_traverse_dir for chown and chgrp)
was implemented using recursive function calls. Because each stack frame
holds directory descriptors, stat structures, path buffers, and entry
lists, deep trees quickly exceed the Linux default thread stack limit of
8MB (ulimit -s 8192).
This is a functional regression compared to GNU coreutils, which
processes deep directory hierarchies without crashing. Any automated
build system, cache tree, or container environment with deep directory
structures triggers this crash.
[ Fix ]
Replace recursive directory traversal with an iterative heap-allocated stack
across all four affected utilities:
- src/uu/du/src/du.rs: Replaced recursive safe_du with an iterative traversal
using a heap-allocated Vec<DuFrame> stack (post-order DFS to correctly
aggregate subdirectory sizes).
- src/uu/chmod/src/chmod.rs: Replaced recursive safe_traverse_dir in Chmoder
with an iterative traversal using a heap-allocated Vec<ChmodFrame> stack
(pre-order DFS, preserving cycle detection via ancestors set).
- src/uucore/src/lib/features/perms.rs: Replaced recursive safe_traverse_dir
in PerRequest with an iterative traversal using a heap-allocated
Vec<PermsFrame> stack (pre-order DFS, preserving cycle detection via ancestors
set).
This keeps CPU call stack usage strictly O(1) regardless of directory
depth, avoiding stack exhaustion.
[ Test Plan ]
1. Reproduce on unpatched rust-coreutils (0.10.0-1ubuntu2~26.04.1 in
resolute, 0.12.0-1ubuntu1 in stonking):
Create a deep directory tree (depth 2000 or more) using openat/mkdirat
helpers or gnumkdir:
$ du a
Segmentation fault (core dumped)
$ chmod -R 777 a
Segmentation fault (core dumped)
$ chown -R root:root a
Segmentation fault (core dumped)
$ chgrp -R root a
Segmentation fault (core dumped)
- 2. Verify with patched rust-coreutils (0.10.0-1ubuntu2~26.04.2 in resolute,
0.12.0-1ubuntu2 in stonking):
+ 2. Verify with patched rust-coreutils (0.10.0-1ubuntu2~26.04.2 in resolute,
0.12.0-1ubuntu3 in stonking):
Run the same commands on deep directory trees (tested up to depth 4000):
$ du a
(prints size and directory entries without crash, exit code 0)
$ chmod -R 777 a
(completes without crash, exit code 0)
$ chown -R root:root a
(completes without crash, exit code 0)
$ chgrp -R root a
(completes without crash, exit code 0)
3. Run package test suites:
cargo test -p uu_du
cargo test -p uu_chmod
cargo test -p uu_chown
cargo test -p uu_chgrp
All tests pass with 0 regressions.
[ Where problems could occur ]
The change replaces the call stack with a heap stack for directory traversal.
- File descriptor leaks: Each directory frame maintains its DirFd and closes
it when popped from the heap stack.
- Infinite loops / symlink loops: Cycle detection in chmod and perms
(chown/chgrp) uses ancestors tracking (HashSet<FileInformation>), which is
preserved across push and pop operations on the stack.
- Traversal order: du maintains post-order traversal (children before
parents) to aggregate block sizes correctly; chmod and chown/chgrp maintain
pre-order traversal (parents before children).
[ Other Info ]
- Upstream PR: https://github.com/uutils/coreutils/pull/14887 (fixes upstream
issue #10173). Pre-commit CI is passing.
- - Development series (stonking): Addressed in 0.12.0-1ubuntu2. Debdiff
attached to this bug to fulfill SRU development release policy.
+ - Development series (stonking): Addressed in 0.12.0-1ubuntu3. Rebased
debdiff attached to this bug to fulfill SRU development release policy.
- Stable release (resolute): Target SRU debdiff package version is
0.10.0-1ubuntu2~26.04.2. Debdiff attached to this bug.
- Both debdiffs pass all crate test suites and deep directory traversal
verification with 0 regressions.
--- [ Original Report ]
```
$ podman run --rm -it ubuntu:26.04
$ apt update -y; apt upgrade -y
$ ulimit -n
1048576
$ gnumkdir -p $(yes a/ | head -n $((32 * 1024)) | tr -d '\n')
$ chown -R root:root a
Segmentation fault (core dumped) chown -R root:root a
$ chmod -R 777 a
Segmentation fault (core dumped) chmod -R 777 a
$ chgrp -R root a
Segmentation fault (core dumped) chgrp -R root a
$ du a
Segmentation fault (core dumped) du a
-
````
All of the GNU programs work fine:
```
$ gnuchown -R root:root a; echo $?
0
$ gnuchmod -R 777 a; echo $?
0
$ gnuchgrp -R 777 a; echo $?
0
$ gnudu a | wc -l
32768
```
** Changed in: rust-coreutils (Ubuntu)
Status: Incomplete => Confirmed
** Patch added: "rust-coreutils 0.12.0-1ubuntu3 debdiff for stonking"
https://bugs.launchpad.net/ubuntu/+source/rust-coreutils/+bug/2167204/+attachment/6006642/+files/rust-coreutils_0.12.0-1ubuntu3_stonking.debdiff
--
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2167204
Title:
chown, chmod, chgrp, and du segfault due to recursive calls
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/rust-coreutils/+bug/2167204/+subscriptions
--
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs