Conversation
On 32-bit Linux the libc open()/openat() bindings do not add O_LARGEFILE the way glibc's large-file entry points do, so the kernel rejects a directory whose metadata overflows the 32-bit ranges with EOVERFLOW. du then failed with "Value too large for defined data type" on any directory traversal. Add the flag to the directory opens in DirFd, and to open_file_at() so a destination file over 2 GiB does not hit the same wall. It is defined as 0 on 64-bit, so no cfg gating is needed beyond Linux/Android, and the opens stay on nix: this module deliberately goes through libc so LD_PRELOAD tools (fakeroot, fakechroot, pseudo) can interpose them. Fixes uutils#11848
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Pull request overview
Fixes du failures on 32-bit Linux by switching safe directory opens to rustix::fs::openat, which injects O_LARGEFILE to avoid EOVERFLOW when traversing large directories.
Changes:
- Replace
nix::fcntl::open/openatwithrustix::fs::openatinDirFd::openandDirFd::open_subdir. - Update open flags from
nix::fcntl::OFlagtorustix::fs::OFlagsand adjust error conversion. - Add
rustix/fsto thesafe-traversalfeature dependencies.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/uucore/src/lib/features/safe_traversal.rs | Uses rustix::fs::openat for directory opens to ensure O_LARGEFILE behavior on 32-bit Linux. |
| src/uucore/Cargo.toml | Enables rustix/fs under the safe-traversal feature. |
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
GNU testsuite comparison: |
Merging this PR will not alter performance
Comparing Footnotes
|
c6c706f to
4dfce47
Compare
There was a problem hiding this comment.
🔵 Needs a closer look
Both rustix openat paths bypass required LD_PRELOAD interposition and need an interposable large-file-safe alternative.
Review details
Suppressed comments (2)
src/uucore/src/lib/features/safe_traversal.rs:185
- The subdirectory path has the same regression: rustix's Linux-raw
openatbypasses theLD_PRELOADwrappers that this module explicitly supports for fakeroot/fakechroot/pseudo. Keep this operation libc-interposable, or provide an equivalent large-file-safe libc path on 32-bit Linux.
let fd = rustix_openat(
&self.fd,
name_cstr.as_c_str(),
flags,
rustix::fs::Mode::empty(),
)
.map_err(|e| SafeTraversalError::OpenFailed {
path: name.into(),
source: io::Error::from_raw_os_error(e.raw_os_error()),
src/uucore/src/lib/features/safe_traversal.rs:156
- This changes
DirFd::openfrom libc-backednix::opento rustix's Linux-raw syscall, so fakeroot/fakechroot/pseudoLD_PRELOADwrappers cannot see or emulate this path. The same module deliberately keepschmod_aton nix for this reason (lines 303-326); preserve interposition here while still arrangingO_LARGEFILEfor 32-bit Linux.
let fd = rustix_openat(rustix::fs::CWD, path, flags, rustix::fs::Mode::empty()).map_err(
|e| SafeTraversalError::OpenFailed {
path: path.into(),
source: io::Error::from_raw_os_error(e.raw_os_error()),
},
)?;
- Files reviewed: 2/2 changed files
- Comments generated: 0 new
- Review effort level: Lite
4dfce47 to
80e10f0
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Two moderate test-coverage issues and one implementation/description mismatch remain unresolved.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (2)
src/uucore/src/lib/features/safe_traversal.rs:1050
- This regression test is in
uucore's unit-test module, but the i686 CI jobs runcargo test -p coreutilswhile only selected jobs add--workspace; it therefore is not executed on the 32-bit target whereO_LARGEFILEis nonzero. Add a target-run regression (or run the uucore tests for i686) so removing this flag cannot pass CI.
#[test]
#[cfg(any(target_os = "linux", target_os = "android"))]
fn test_dirfd_open_status_flags_match_std() {
src/uucore/src/lib/features/safe_traversal.rs:482
- The new
LARGEFILEbehavior foropen_file_atis not covered bytest_dirfd_open_status_flags_match_std, which only inspects directory descriptors. Add a correspondingopen_file_atflag/behavior assertion on 32-bit Linux, or drop this extra hunk if large destination files are not part of this fix.
| OFlag::O_NOFOLLOW
| LARGEFILE;
- Files reviewed: 1/1 changed files
- Comments generated: 1
- Review effort level: Lite
| #[cfg(any(target_os = "linux", target_os = "android"))] | ||
| const LARGEFILE: OFlag = OFlag::O_LARGEFILE; | ||
| #[cfg(not(any(target_os = "linux", target_os = "android")))] | ||
| const LARGEFILE: OFlag = OFlag::empty(); |
On 32-bit Linux, open(2) without O_LARGEFILE returns EOVERFLOW when directory metadata (inode numbers, sizes) exceed 32-bit off_t limits. This caused du to fail with "Value too large for defined data type" on any directory traversal.
Switch DirFd::open() and DirFd::open_subdir() from nix::fcntl::open/ openat to rustix::fs::openat. The rustix linux_raw backend automatically injects O_LARGEFILE into every open call, fixing the 32-bit overflow without any platform-specific cfg gates.
Add rustix/fs to the safe-traversal feature dependencies.
Fixes #11848