Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Three final findings, including critical and moderate issues, remain unresolved.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Hardens sort temporary storage so scratch files are private to the owner on Unix.
Changes:
- Enables
uucoresafe-copy support. - Uses restrictive
0700directory and0600file permissions. - Adds Unix permission tests.
File summaries
| File | Summary |
|---|---|
src/uucore/Cargo.toml |
Enables the safe-copy feature. |
src/uu/sort/Cargo.toml |
Activates uucore/safe-copy. |
src/uu/sort/src/tmp_dir.rs |
Restricts temporary storage and adds tests. Final findings: critical (2 votes) for using &PathBuf instead of &Path; moderate (3 votes) for unsafe process-wide umask handling; nit (2 votes) for the unversioned GNU behavior claim. |
Review details
Suppressed comments (1)
src/uu/sort/src/tmp_dir.rs:35
- The non-Unix overload has the same
&PathBufparameter and will trigger the sameptr_argwarning when that configuration is linted. Take&std::path::Pathhere as well.
fn create_tmp_file(path: &PathBuf) -> std::io::Result<File> {
- Files reviewed: 3/3 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
4c1c092 to
b07e3f2
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical permission regression and moderate test-coverage issue must be addressed.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (1)
src/uu/sort/src/tmp_dir.rs:159
create_dest_restrictivepasses0o600toopen, so a valid umask such as0o777can still create a mode-000file. The initial descriptor works, but the laterFile::opencalls inmerge.rsthen fail withEACCES; applyset_permissions/fchmodto the returned descriptor before exposing the path (or make the helper do so).
let file = uucore::safe_copy::create_dest_restrictive(&path, true);
- Files reviewed: 3/3 changed files
- Comments generated: 2
- Review effort level: Lite
| // exist at the path yet: a symlink there is hostile, not something to | ||
| // write through. | ||
| #[cfg(unix)] | ||
| let file = uucore::safe_copy::create_dest_restrictive(&path, true); |
|
GNU testsuite comparison: |
b07e3f2 to
f4c28df
Compare
When the input does not fit in memory, sort spills sorted chunks to files under TMPDIR. The temporary directory was created by tempfile's TempDir (0777 & ~umask) and the chunks by File::create (0666 & ~umask), so under the usual 022 umask they came out 0755 and 0644: every local user could read the input being sorted, in sorted pieces, for as long as the sort ran. GNU sort (9.11) creates its temporaries 0600 whatever the umask. Create the directory 0700, and the chunks through the existing uucore::safe_copy::create_dest_restrictive, which opens 0600 with O_NOFOLLOW and O_CLOEXEC. Nothing should exist at a chunk path yet, so a symlink there is hostile rather than something to write through. The files are restricted as well as the directory so that a directory whose mode is later relaxed does not expose the data. The output-is-input path needs the same care: it took a temporary file from next_file and then overwrote it with fs::copy, which carries the source's permission bits across and put a 0644 output file's mode back on the copy. Write through the descriptor next_file already opened. safe_copy uses rustix::fs but the safe-copy feature did not declare it; it built only because every current user also enables uucore's "fs". Declare it so sort is not the second one relying on that.
f4c28df to
7c61f67
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Two moderate correctness issues and one safety-documentation nit remain unresolved.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (2)
src/uu/sort/src/tmp_dir.rs:159
create_dest_restrictivepasses0o600toopen(2), but that mode is still masked by umask. For example, underumask 0o777the chunk can be created as0o000, and the laterFile::opencalls used during merging will fail withEACCES. Set the returned descriptor's permissions to0o600before returning/using it, and add a restrictive-umask test.
let file = uucore::safe_copy::create_dest_restrictive(&path, true);
src/uu/sort/src/tmp_dir.rs:236
- Please add a
// SAFETY:justification for this separatelibc::umaskcall; the existing comment only documents the unsafe block inset, while this block is another FFI call.
unsafe { libc::umask(self.0) };
- Files reviewed: 4/4 changed files
- Comments generated: 2
- Review effort level: Lite
| let mut source = File::open(&output_path) | ||
| .map_err(|error| SortError::OpenTmpFileFailed { error })?; |
| #[cfg(unix)] | ||
| builder.permissions(Permissions::from_mode(0o700)); | ||
| self.temp_dir = Some(builder.tempdir_in(&self.parent_path).map_err(|_| { | ||
| SortError::TmpFileCreationFailed { | ||
| path: self.parent_path.clone(), | ||
| } | ||
| })?); |
No description provided.