-
-
Notifications
You must be signed in to change notification settings - Fork 14.8k
Fix for CVE-2022-21658 is unsafe on some file systems #94335
Copy link
Copy link
Closed
Labels
A-ioArea: `std::io`, `std::fs`, `std::net` and `std::path`Area: `std::io`, `std::fs`, `std::net` and `std::path`C-bugCategory: This is a bug.Category: This is a bug.O-solarisOperating system: SolarisOperating system: SolarisO-unixOperating system: Unix-likeOperating system: Unix-likeP-criticalCritical priorityCritical priorityT-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.Performance or correctness regression from one stable version to another.
Metadata
Metadata
Assignees
Labels
A-ioArea: `std::io`, `std::fs`, `std::net` and `std::path`Area: `std::io`, `std::fs`, `std::net` and `std::path`C-bugCategory: This is a bug.Category: This is a bug.O-solarisOperating system: SolarisOperating system: SolarisO-unixOperating system: Unix-likeOperating system: Unix-likeP-criticalCritical priorityCritical priorityT-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.Performance or correctness regression from one stable version to another.
Type
Fields
Give feedbackNo fields configured for issues without a type.
The fix for CVE-2022-21658 (#93112, 54e22eb) appears to have introduced a regression that can cause file system corruption on some UNIX systems.
The new code will attempt to use unlinkat(2) in any case where it does not know what type of file a directory entry represents. Some systems do not provide that information along with the entry names returned while reading a directory, and even on systems which provide a type hint, that hint may be
DT_UNKNOWN. In cases where we do not know the type of the entry, the code tries first to unlink it as if it were something other than a directory:rust/library/std/src/sys/unix/fs.rs
Lines 1700 to 1712 in 4b043fa
The code assumes that
unlinkat()on a directory will fail withEPERM, or on Linux with the non-standardEISDIR, but this is not always the case. POSIX does suggestsEPERMas a failure in some, but not all cases:(See unlink in The Open Group Base Specifications Issue 7, 2018 edition)
Implementations are not required to prohibit
unlink()on directories, and indeed UFS file systems on present day illumos and presumably at least some Solaris systems allowunlink()of a directory if the user has sufficient privileges. Other platforms may as well.Unfortunately unlinking a directory on UFS causes a sort of file system corruption that requires an unmount and a trip through
fsckto correct. Any code that usesstd::fs::remove_dir_all()on UFS has since started causing that kind of corruption, which took a bit of work to track down.I think the fix is probably relatively simple, and has the benefit of not touching the code path where we believe we know what sort of entry we are removing:
In short, we should try to
rmdir()first, rather thanunlink()first, as that always fails in a safe way that we can detect.