From f56412c324af5a60e1547a4dc23d440cc46f67f4 Mon Sep 17 00:00:00 2001 From: mattsu Date: Wed, 3 Dec 2025 20:47:51 +0900 Subject: [PATCH 01/14] feat(chmod): use dirfd for recursive subdirectory traversal - Update chmod recursive logic to use directory file descriptors instead of full paths for subdirectories - Improves performance, avoids path length issues, and ensures dirfd-relative openat calls - Add test to verify strace output shows no AT_FDCWD with multi-component paths --- src/uu/chmod/src/chmod.rs | 19 ++++++++++++++++-- tests/by-util/test_chmod.rs | 40 +++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/uu/chmod/src/chmod.rs b/src/uu/chmod/src/chmod.rs index c782ad429a4..15b608af6b2 100644 --- a/src/uu/chmod/src/chmod.rs +++ b/src/uu/chmod/src/chmod.rs @@ -522,9 +522,24 @@ impl Chmoder { .safe_chmod_file(&entry_path, dir_fd, &entry_name, meta.mode() & 0o7777) .and(r); - // Recurse into subdirectories + // Recurse into subdirectories using the existing directory fd if meta.is_dir() { - r = self.walk_dir_with_context(&entry_path, false).and(r); + match dir_fd.open_subdir(&entry_name) { + Ok(child_dir_fd) => { + r = self.safe_traverse_dir(&child_dir_fd, &entry_path).and(r); + } + Err(err) => { + let error = if err.kind() == std::io::ErrorKind::PermissionDenied { + ChmodError::PermissionDenied( + entry_path.to_string_lossy().to_string(), + ) + .into() + } else { + err.into() + }; + r = r.and(Err(error)); + } + } } } } diff --git a/tests/by-util/test_chmod.rs b/tests/by-util/test_chmod.rs index 1378aab00d2..a5a49d71574 100644 --- a/tests/by-util/test_chmod.rs +++ b/tests/by-util/test_chmod.rs @@ -1280,6 +1280,46 @@ fn test_chmod_non_utf8_paths() { ); } +#[cfg(all(target_os = "linux", feature = "chmod"))] +#[test] +fn test_chmod_recursive_uses_dirfd_for_subdirs() { + use std::process::Command; + use uutests::get_tests_binary; + + // Skip test if strace is not available + if Command::new("strace").arg("-V").output().is_err() { + eprintln!("strace not found; skipping test_chmod_recursive_uses_dirfd_for_subdirs"); + return; + } + + let (at, _ucmd) = at_and_ucmd!(); + at.mkdir("x"); + at.mkdir("x/y"); + at.mkdir("x/y/z"); + + let log_path = at.plus_as_string("strace.log"); + + let status = Command::new("strace") + .arg("-e") + .arg("openat") + .arg("-o") + .arg(&log_path) + .arg(get_tests_binary!()) + .args(["chmod", "-R", "+x", "x"]) + .current_dir(&at.subdir) + .status() + .expect("failed to run strace"); + assert!(status.success(), "strace run failed"); + + let log = at.read("strace.log"); + + // Regression guard: ensure recursion uses dirfd-relative openat instead of AT_FDCWD with a multi-component path + assert!( + !log.contains("openat(AT_FDCWD, \"x/y"), + "chmod recursed using AT_FDCWD with a multi-component path; expected dirfd-relative openat" + ); +} + #[test] fn test_chmod_colored_output() { // Test colored help message From 2ab13b5012f8e027129c034902aadcffa32b964d Mon Sep 17 00:00:00 2001 From: mattsu Date: Wed, 3 Dec 2025 20:55:06 +0900 Subject: [PATCH 02/14] test(chmod): add spell-check ignore for dirfd, subdirs, openat, FDCWD Added a spell-checker ignore directive in the chmod test file to suppress false positives for legitimate technical terms used in Unix API calls. --- tests/by-util/test_chmod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/by-util/test_chmod.rs b/tests/by-util/test_chmod.rs index a5a49d71574..08ef83ce79a 100644 --- a/tests/by-util/test_chmod.rs +++ b/tests/by-util/test_chmod.rs @@ -2,6 +2,7 @@ // // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. +// spell-checker:ignore (words) dirfd subdirs openat FDCWD use std::fs::{OpenOptions, Permissions, metadata, set_permissions}; use std::os::unix::fs::{OpenOptionsExt, PermissionsExt}; From 232ad2725bf6517d17286959d5653168d08b3c6b Mon Sep 17 00:00:00 2001 From: mattsu Date: Fri, 5 Dec 2025 10:52:33 +0900 Subject: [PATCH 03/14] test(chmod): enforce strace requirement in recursive test, fail fast instead of skip Previously, the test_chmod_recursive_uses_dirfd_for_subdirs test skipped gracefully if strace was unavailable, without failing. This change enforces the strace dependency by failing the test immediately if strace is not installed or runnable, ensuring the test runs reliably in environments where it is expected to pass, and preventing silent skips. --- tests/by-util/test_chmod.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/by-util/test_chmod.rs b/tests/by-util/test_chmod.rs index 08ef83ce79a..351fdf77f6c 100644 --- a/tests/by-util/test_chmod.rs +++ b/tests/by-util/test_chmod.rs @@ -1287,11 +1287,15 @@ fn test_chmod_recursive_uses_dirfd_for_subdirs() { use std::process::Command; use uutests::get_tests_binary; - // Skip test if strace is not available - if Command::new("strace").arg("-V").output().is_err() { - eprintln!("strace not found; skipping test_chmod_recursive_uses_dirfd_for_subdirs"); - return; - } + // strace is required; fail fast if it is missing or not runnable + let output = Command::new("strace") + .arg("-V") + .output() + .expect("strace not found; install strace to run this test"); + assert!( + output.status.success(), + "strace -V failed; ensure strace is installed and usable" + ); let (at, _ucmd) = at_and_ucmd!(); at.mkdir("x"); From 3335055635e0a18e19c63cfb83b10a61772dbfed Mon Sep 17 00:00:00 2001 From: mattsu Date: Fri, 5 Dec 2025 13:17:19 +0900 Subject: [PATCH 04/14] ci: install strace in Ubuntu CI jobs for debugging system calls Add installation of strace tool on Ubuntu runners in both individual build/test and feature build/test jobs. This enables tracing system calls during execution, aiding in debugging and performance analysis within the CI/CD pipeline. Updated existing apt-get commands and added conditional steps for Linux-only installations. --- .github/workflows/CICD.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index d3e3161b11c..05c4be69a36 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -1099,7 +1099,7 @@ jobs: case '${{ matrix.job.os }}' in ubuntu-latest) - sudo apt-get -y update ; sudo apt-get -y install libselinux1-dev + sudo apt-get -y update ; sudo apt-get -y install libselinux1-dev strace # pinky is a tool to show logged-in users from utmp, and gecos fields from /etc/passwd. # In GitHub Action *nix VMs, no accounts log in, even the "runner" account that runs the commands, and "system boot" entry is missing. # The account also has empty gecos fields. @@ -1162,6 +1162,9 @@ jobs: persist-credentials: false - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 + - name: Install strace (Linux only) + if: matrix.job.os == 'ubuntu-latest' + run: sudo apt-get update && sudo apt-get install -y strace - name: build and test all programs individually shell: bash run: | @@ -1189,6 +1192,9 @@ jobs: persist-credentials: false - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 + - name: Install strace (Linux only) + if: matrix.job.os == 'ubuntu-latest' + run: sudo apt-get update && sudo apt-get install -y strace - name: build and test all features individually shell: bash run: | From 41cc13ef56d3935d73b610d6ec85083e4cb48ca2 Mon Sep 17 00:00:00 2001 From: mattsu Date: Fri, 5 Dec 2025 13:47:21 +0900 Subject: [PATCH 05/14] ci: Add strace installation to Ubuntu-based CI workflows Install strace on ubuntu-latest runners across multiple jobs to enable system call tracing for testing purposes, ensuring compatibility with tests that require this debugging tool. This includes updating package lists in existing installation steps. --- .github/workflows/CICD.yml | 14 ++++++++++++-- .github/workflows/l10n.yml | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 05c4be69a36..32b9dba3d17 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -202,7 +202,7 @@ jobs: shell: bash run: | # Install a package for one of the tests - sudo apt-get -y update ; sudo apt-get -y install attr + sudo apt-get -y update ; sudo apt-get -y install attr strace - name: Info shell: bash run: | @@ -276,6 +276,10 @@ jobs: # Test build on the system missing libselinux (don't install libselinux1-dev at here) - name: Run sccache-cache uses: mozilla-actions/sccache-action@v0.0.9 + - name: Install strace (Linux only) + if: matrix.job.os == 'ubuntu-latest' + shell: bash + run: sudo apt-get update && sudo apt-get install -y strace - name: "`make build`" # Also check that target/CACHEDIR.TAG is created on a fresh checkout shell: bash @@ -406,6 +410,9 @@ jobs: - uses: Swatinem/rust-cache@v2 - name: Run sccache-cache uses: mozilla-actions/sccache-action@v0.0.9 + - name: Install strace (Linux only) + if: matrix.job.os == 'ubuntu-latest' + run: sudo apt-get update && sudo apt-get install -y strace - name: Test run: cargo nextest run --hide-progress-bar --profile ci --features ${{ matrix.job.features }} env: @@ -435,6 +442,9 @@ jobs: - uses: Swatinem/rust-cache@v2 - name: Run sccache-cache uses: mozilla-actions/sccache-action@v0.0.9 + - name: Install strace (Linux only) + if: matrix.job.os == 'ubuntu-latest' + run: sudo apt-get update && sudo apt-get install -y strace - name: Test run: cargo nextest run --hide-progress-bar --profile ci --features ${{ matrix.job.features }} env: @@ -738,7 +748,7 @@ jobs: ubuntu-*) # selinux and systemd headers needed to build tests sudo apt-get -y update - sudo apt-get -y install libselinux1-dev libsystemd-dev + sudo apt-get -y install libselinux1-dev libsystemd-dev strace # pinky is a tool to show logged-in users from utmp, and gecos fields from /etc/passwd. # In GitHub Action *nix VMs, no accounts log in, even the "runner" account that runs the commands, and "system boot" entry is missing. # The account also has empty gecos fields. diff --git a/.github/workflows/l10n.yml b/.github/workflows/l10n.yml index c7154f49066..6721f0d1f62 100644 --- a/.github/workflows/l10n.yml +++ b/.github/workflows/l10n.yml @@ -51,7 +51,7 @@ jobs: case '${{ matrix.job.os }}' in ubuntu-*) # selinux headers needed for testing - sudo apt-get -y update ; sudo apt-get -y install libselinux1-dev + sudo apt-get -y update ; sudo apt-get -y install libselinux1-dev strace ;; macos-*) # needed for testing From ce63d1da3f77462fa4223a471d3a6e33c1bff8e1 Mon Sep 17 00:00:00 2001 From: mattsu Date: Fri, 5 Dec 2025 15:22:35 +0900 Subject: [PATCH 06/14] chore(build): install strace and prevent apt prompts in Cross.toml pre-build Modified the pre-build command to install strace utility for debugging and added -y flag to apt-get install to skip prompts, ensuring non-interactive builds. --- Cross.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cross.toml b/Cross.toml index 52f5bad21dd..7e6b0b674c6 100644 --- a/Cross.toml +++ b/Cross.toml @@ -1,7 +1,7 @@ # spell-checker:ignore (misc) dpkg noninteractive tzdata [build] pre-build = [ - "apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install tzdata", + "apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata strace", ] [build.env] passthrough = ["CI", "RUST_BACKTRACE", "CARGO_TERM_COLOR"] From d0cda8de61ca97575e39b9bd50ace53de634f604 Mon Sep 17 00:00:00 2001 From: mattsu Date: Fri, 5 Dec 2025 15:38:12 +0900 Subject: [PATCH 07/14] feat(build): support Alpine-based cross images in pre-build Detect package manager (apt vs apk) to install tzdata and strace in both Debian/Ubuntu and Alpine *-musl targets. Added fallback warning for unsupported managers. This ensures strace is available for targets using Alpine, which doesn't have apt-get. --- Cross.toml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Cross.toml b/Cross.toml index 7e6b0b674c6..49e096c420e 100644 --- a/Cross.toml +++ b/Cross.toml @@ -1,7 +1,15 @@ # spell-checker:ignore (misc) dpkg noninteractive tzdata [build] pre-build = [ - "apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata strace", + # Install tzdata and strace in both Debian/Ubuntu-based and Alpine-based cross images. + # Some cross targets (e.g., *-musl) use Alpine, which lacks apt-get. + "if command -v apt-get >/dev/null 2>&1; then \ + apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata strace; \ + elif command -v apk >/dev/null 2>&1; then \ + apk update && apk add --no-cache tzdata strace; \ + else \ + echo 'WARNING: unknown package manager; strace not installed'; \ + fi", ] [build.env] passthrough = ["CI", "RUST_BACKTRACE", "CARGO_TERM_COLOR"] From 266cdd8531c7846842b669428f5319448774c0f2 Mon Sep 17 00:00:00 2001 From: mattsu Date: Fri, 5 Dec 2025 15:50:01 +0900 Subject: [PATCH 08/14] refactor(build): improve pre-build script readability by using multi-line strings Replace escaped multi-line string with triple-quoted string for better readability in Cross.toml. --- Cross.toml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Cross.toml b/Cross.toml index 49e096c420e..e99d69488d1 100644 --- a/Cross.toml +++ b/Cross.toml @@ -3,13 +3,15 @@ pre-build = [ # Install tzdata and strace in both Debian/Ubuntu-based and Alpine-based cross images. # Some cross targets (e.g., *-musl) use Alpine, which lacks apt-get. - "if command -v apt-get >/dev/null 2>&1; then \ - apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata strace; \ - elif command -v apk >/dev/null 2>&1; then \ - apk update && apk add --no-cache tzdata strace; \ - else \ - echo 'WARNING: unknown package manager; strace not installed'; \ - fi", + """ + if command -v apt-get >/dev/null 2>&1; then + apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata strace; + elif command -v apk >/dev/null 2>&1; then + apk update && apk add --no-cache tzdata strace; + else + echo 'WARNING: unknown package manager; strace not installed'; + fi + """, ] [build.env] passthrough = ["CI", "RUST_BACKTRACE", "CARGO_TERM_COLOR"] From 1e1d982c6e34112862281a633fafc8e45b607e18 Mon Sep 17 00:00:00 2001 From: mattsu Date: Fri, 5 Dec 2025 16:15:47 +0900 Subject: [PATCH 09/14] feat(ci): install strace in WSL2 GitHub Actions workflow Install strace utility in the WSL2 environment to support tracing system calls during testing. Minor update to Cross.toml spell-checker ignore list for consistency with change. --- .github/workflows/wsl2.yml | 5 +++++ Cross.toml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/wsl2.yml b/.github/workflows/wsl2.yml index 1764a03fcd7..de5f67e4c18 100644 --- a/.github/workflows/wsl2.yml +++ b/.github/workflows/wsl2.yml @@ -57,6 +57,11 @@ jobs: curl https://sh.rustup.rs -sSf --output rustup.sh sh rustup.sh -y --profile=minimal curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C "$HOME/.cargo/bin" + - name: Install strace in WSL2 + shell: wsl-bash {0} + run: | + sudo apt-get update + sudo apt-get install -y strace - name: Test shell: wsl-bash {0} run: | diff --git a/Cross.toml b/Cross.toml index e99d69488d1..2be7575a69e 100644 --- a/Cross.toml +++ b/Cross.toml @@ -1,4 +1,4 @@ -# spell-checker:ignore (misc) dpkg noninteractive tzdata +# spell-checker:ignore (misc) dpkg noninteractive tzdata elif [build] pre-build = [ # Install tzdata and strace in both Debian/Ubuntu-based and Alpine-based cross images. From 91246f653c014884fd5ff4713e8fcfdca07a9e5f Mon Sep 17 00:00:00 2001 From: mattsu Date: Fri, 5 Dec 2025 16:56:00 +0900 Subject: [PATCH 10/14] ci(wsl2): install strace as root with non-interactive apt-get Updated the WSL2 workflow step to use root shell (wsl-bash-root) for installing strace, removing sudo calls and adding DEBIAN_FRONTEND=noninteractive to prevent prompts. This improves CI reliability by ensuring direct root access and automated, interrupt-free package installation. --- .github/workflows/wsl2.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/wsl2.yml b/.github/workflows/wsl2.yml index de5f67e4c18..5b1e700312f 100644 --- a/.github/workflows/wsl2.yml +++ b/.github/workflows/wsl2.yml @@ -57,11 +57,11 @@ jobs: curl https://sh.rustup.rs -sSf --output rustup.sh sh rustup.sh -y --profile=minimal curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C "$HOME/.cargo/bin" - - name: Install strace in WSL2 - shell: wsl-bash {0} + - name: Install strace in WSL2 (root) + shell: wsl-bash-root {0} run: | - sudo apt-get update - sudo apt-get install -y strace + apt-get update + DEBIAN_FRONTEND=noninteractive apt-get install -y strace - name: Test shell: wsl-bash {0} run: | From 57520c04a643817da41c06042de2c81cda937c64 Mon Sep 17 00:00:00 2001 From: mattsu Date: Fri, 5 Dec 2025 17:00:53 +0900 Subject: [PATCH 11/14] ci: Move strace installation to user shell and update spell ignore Fix WSL2 GitHub Actions workflow by installing strace as the user instead of root for better permission handling, and add "noninteractive" to the spell-checker ignore comment for consistency with the new apt-get command. This ensures the tool is available in the testing environment without unnecessary privilege escalation. --- .github/workflows/wsl2.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/wsl2.yml b/.github/workflows/wsl2.yml index 5b1e700312f..f96cc9acbe8 100644 --- a/.github/workflows/wsl2.yml +++ b/.github/workflows/wsl2.yml @@ -1,6 +1,6 @@ name: WSL2 -# spell-checker:ignore nextest noprofile norc +# spell-checker:ignore nextest noprofile norc noninteractive on: pull_request: @@ -37,6 +37,11 @@ jobs: distribution: ${{ matrix.job.distribution }} use-cache: 'true' wsl-version: 2 + - name: Install strace in WSL2 + shell: wsl-bash {0} + run: | + apt-get update + DEBIAN_FRONTEND=noninteractive apt-get install -y strace - name: Set up WSL2 user shell: wsl-bash {0} run: | @@ -57,11 +62,6 @@ jobs: curl https://sh.rustup.rs -sSf --output rustup.sh sh rustup.sh -y --profile=minimal curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C "$HOME/.cargo/bin" - - name: Install strace in WSL2 (root) - shell: wsl-bash-root {0} - run: | - apt-get update - DEBIAN_FRONTEND=noninteractive apt-get install -y strace - name: Test shell: wsl-bash {0} run: | From 09dae13fcfdc81ebabc38c1e80ac22f8fbfa5c15 Mon Sep 17 00:00:00 2001 From: mattsu Date: Fri, 5 Dec 2025 17:26:59 +0900 Subject: [PATCH 12/14] chore: ci: remove unused strace installation from CI workflows Remove strace package installation from multiple GitHub Actions workflow files (CICD.yml, l10n.yml, wsl2.yml). Strace was historically installed in Ubuntu jobs for debugging system calls, but it's no longer required for the tests and builds, reducing CI setup time and dependencies. --- .github/workflows/CICD.yml | 24 +++--------------------- .github/workflows/l10n.yml | 2 +- .github/workflows/wsl2.yml | 5 ----- Cross.toml | 12 +----------- 4 files changed, 5 insertions(+), 38 deletions(-) diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 32b9dba3d17..5543cc81e7a 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -202,7 +202,7 @@ jobs: shell: bash run: | # Install a package for one of the tests - sudo apt-get -y update ; sudo apt-get -y install attr strace + sudo apt-get -y update ; sudo apt-get -y install attr - name: Info shell: bash run: | @@ -276,10 +276,6 @@ jobs: # Test build on the system missing libselinux (don't install libselinux1-dev at here) - name: Run sccache-cache uses: mozilla-actions/sccache-action@v0.0.9 - - name: Install strace (Linux only) - if: matrix.job.os == 'ubuntu-latest' - shell: bash - run: sudo apt-get update && sudo apt-get install -y strace - name: "`make build`" # Also check that target/CACHEDIR.TAG is created on a fresh checkout shell: bash @@ -410,9 +406,6 @@ jobs: - uses: Swatinem/rust-cache@v2 - name: Run sccache-cache uses: mozilla-actions/sccache-action@v0.0.9 - - name: Install strace (Linux only) - if: matrix.job.os == 'ubuntu-latest' - run: sudo apt-get update && sudo apt-get install -y strace - name: Test run: cargo nextest run --hide-progress-bar --profile ci --features ${{ matrix.job.features }} env: @@ -442,9 +435,6 @@ jobs: - uses: Swatinem/rust-cache@v2 - name: Run sccache-cache uses: mozilla-actions/sccache-action@v0.0.9 - - name: Install strace (Linux only) - if: matrix.job.os == 'ubuntu-latest' - run: sudo apt-get update && sudo apt-get install -y strace - name: Test run: cargo nextest run --hide-progress-bar --profile ci --features ${{ matrix.job.features }} env: @@ -748,7 +738,7 @@ jobs: ubuntu-*) # selinux and systemd headers needed to build tests sudo apt-get -y update - sudo apt-get -y install libselinux1-dev libsystemd-dev strace + sudo apt-get -y install libselinux1-dev libsystemd-dev # pinky is a tool to show logged-in users from utmp, and gecos fields from /etc/passwd. # In GitHub Action *nix VMs, no accounts log in, even the "runner" account that runs the commands, and "system boot" entry is missing. # The account also has empty gecos fields. @@ -1109,7 +1099,7 @@ jobs: case '${{ matrix.job.os }}' in ubuntu-latest) - sudo apt-get -y update ; sudo apt-get -y install libselinux1-dev strace + sudo apt-get -y update ; sudo apt-get -y install libselinux1-dev # pinky is a tool to show logged-in users from utmp, and gecos fields from /etc/passwd. # In GitHub Action *nix VMs, no accounts log in, even the "runner" account that runs the commands, and "system boot" entry is missing. # The account also has empty gecos fields. @@ -1172,9 +1162,6 @@ jobs: persist-credentials: false - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - - name: Install strace (Linux only) - if: matrix.job.os == 'ubuntu-latest' - run: sudo apt-get update && sudo apt-get install -y strace - name: build and test all programs individually shell: bash run: | @@ -1202,9 +1189,6 @@ jobs: persist-credentials: false - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - - name: Install strace (Linux only) - if: matrix.job.os == 'ubuntu-latest' - run: sudo apt-get update && sudo apt-get install -y strace - name: build and test all features individually shell: bash run: | @@ -1289,8 +1273,6 @@ jobs: persist-credentials: false - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - - name: Install strace - run: sudo apt-get update && sudo apt-get install -y strace - name: Build utilities with safe traversal run: cargo build --release -p uu_rm -p uu_chmod -p uu_chown -p uu_chgrp -p uu_mv -p uu_du - name: Run safe traversal verification diff --git a/.github/workflows/l10n.yml b/.github/workflows/l10n.yml index 6721f0d1f62..c7154f49066 100644 --- a/.github/workflows/l10n.yml +++ b/.github/workflows/l10n.yml @@ -51,7 +51,7 @@ jobs: case '${{ matrix.job.os }}' in ubuntu-*) # selinux headers needed for testing - sudo apt-get -y update ; sudo apt-get -y install libselinux1-dev strace + sudo apt-get -y update ; sudo apt-get -y install libselinux1-dev ;; macos-*) # needed for testing diff --git a/.github/workflows/wsl2.yml b/.github/workflows/wsl2.yml index f96cc9acbe8..3caec357cfb 100644 --- a/.github/workflows/wsl2.yml +++ b/.github/workflows/wsl2.yml @@ -37,11 +37,6 @@ jobs: distribution: ${{ matrix.job.distribution }} use-cache: 'true' wsl-version: 2 - - name: Install strace in WSL2 - shell: wsl-bash {0} - run: | - apt-get update - DEBIAN_FRONTEND=noninteractive apt-get install -y strace - name: Set up WSL2 user shell: wsl-bash {0} run: | diff --git a/Cross.toml b/Cross.toml index 2be7575a69e..42f28a80e84 100644 --- a/Cross.toml +++ b/Cross.toml @@ -1,17 +1,7 @@ # spell-checker:ignore (misc) dpkg noninteractive tzdata elif [build] pre-build = [ - # Install tzdata and strace in both Debian/Ubuntu-based and Alpine-based cross images. - # Some cross targets (e.g., *-musl) use Alpine, which lacks apt-get. - """ - if command -v apt-get >/dev/null 2>&1; then - apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata strace; - elif command -v apk >/dev/null 2>&1; then - apk update && apk add --no-cache tzdata strace; - else - echo 'WARNING: unknown package manager; strace not installed'; - fi - """, + "apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install tzdata", ] [build.env] passthrough = ["CI", "RUST_BACKTRACE", "CARGO_TERM_COLOR"] From 4ce6cd19a2a919433af2b1ae71e26b1e1b777ce0 Mon Sep 17 00:00:00 2001 From: mattsu Date: Fri, 5 Dec 2025 17:31:21 +0900 Subject: [PATCH 13/14] ci: add strace installation and fix spell-checker comments in CI files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Install strace package in CICD workflow to support safe traversal verification for utilities like rm, chmod, chown, chgrp, mv, and du, enabling syscall tracing for testing. - Clean up spell-checker ignore comments in wsl2.yml and Cross.toml by removing misplaced flags.第二个测试产品**ci: add strace installation and fix spell-checker comments in CI files** - Install strace package in CICD workflow to support safe traversal verification for utilities like rm, chmod, chown, chgrp, mv, and du, enabling syscall tracing for testing. - Clean up spell-checker ignore comments in wsl2.yml and Cross.toml by removing misplaced flags. --- .github/workflows/CICD.yml | 2 ++ .github/workflows/wsl2.yml | 2 +- Cross.toml | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 5543cc81e7a..d3e3161b11c 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -1273,6 +1273,8 @@ jobs: persist-credentials: false - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 + - name: Install strace + run: sudo apt-get update && sudo apt-get install -y strace - name: Build utilities with safe traversal run: cargo build --release -p uu_rm -p uu_chmod -p uu_chown -p uu_chgrp -p uu_mv -p uu_du - name: Run safe traversal verification diff --git a/.github/workflows/wsl2.yml b/.github/workflows/wsl2.yml index 3caec357cfb..1764a03fcd7 100644 --- a/.github/workflows/wsl2.yml +++ b/.github/workflows/wsl2.yml @@ -1,6 +1,6 @@ name: WSL2 -# spell-checker:ignore nextest noprofile norc noninteractive +# spell-checker:ignore nextest noprofile norc on: pull_request: diff --git a/Cross.toml b/Cross.toml index 42f28a80e84..52f5bad21dd 100644 --- a/Cross.toml +++ b/Cross.toml @@ -1,4 +1,4 @@ -# spell-checker:ignore (misc) dpkg noninteractive tzdata elif +# spell-checker:ignore (misc) dpkg noninteractive tzdata [build] pre-build = [ "apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install tzdata", From 6ce14f12184790f8f6afe038f7fc53f014c78d1a Mon Sep 17 00:00:00 2001 From: mattsu Date: Fri, 5 Dec 2025 18:12:36 +0900 Subject: [PATCH 14/14] test: add regression guard for recursive chmod dirfd-relative traversal Add a check in check-safe-traversal.sh to ensure recursive chmod operations use dirfd-relative openat calls instead of AT_FDCWD with multi-component paths, preventing potential race conditions. Ignore the corresponding Rust test as it is now covered by this shell script guard. --- tests/by-util/test_chmod.rs | 1 + util/check-safe-traversal.sh | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/tests/by-util/test_chmod.rs b/tests/by-util/test_chmod.rs index 351fdf77f6c..e4d4b028474 100644 --- a/tests/by-util/test_chmod.rs +++ b/tests/by-util/test_chmod.rs @@ -1283,6 +1283,7 @@ fn test_chmod_non_utf8_paths() { #[cfg(all(target_os = "linux", feature = "chmod"))] #[test] +#[ignore = "covered by util/check-safe-traversal.sh"] fn test_chmod_recursive_uses_dirfd_for_subdirs() { use std::process::Command; use uutests::get_tests_binary; diff --git a/util/check-safe-traversal.sh b/util/check-safe-traversal.sh index ed3c5a78eff..8dc9b04cf52 100755 --- a/util/check-safe-traversal.sh +++ b/util/check-safe-traversal.sh @@ -173,6 +173,11 @@ fi if echo "$AVAILABLE_UTILS" | grep -q "chmod"; then cp -r test_dir test_chmod check_utility "chmod" "openat,fchmodat,newfstatat,chmod" "openat fchmodat" "-R 755 test_chmod" "recursive_chmod" + + # Additional regression guard: ensure recursion uses dirfd-relative openat, not AT_FDCWD with a multi-component path + if grep -q 'openat(AT_FDCWD, "test_chmod/' strace_chmod_recursive_chmod.log; then + fail_immediately "chmod recursed using AT_FDCWD with a multi-component path; expected dirfd-relative openat" + fi fi # Test chown - should use openat, fchownat, newfstatat