security(lensdb): refuse a non-regular *.xml before opening it (opening a FIFO blocks)

The pathname is checked before File::open as well as the opened file after it: File::open on a FIFO blocks until a writer appears, so the post-open check alone never ran for one. Adds a unix regression test that hung before the fix.
This commit is contained in:
FredApps
2026-11-04 11:58:39 +01:00
parent 0a5a53c1da
commit 1c1eec5179
2 changed files with 23 additions and 1 deletions
+5 -1
View File
@@ -280,7 +280,11 @@ fn exif_focal_range(exif: &[String]) -> Option<(f64, f64)> {
fn read_capped(path: &Path) -> Result<String, Error> {
use std::io::Read;
let io = |e: std::io::Error| Error::Io(e.to_string());
// the opened file is checked, not the pathname: a link or FIFO swapped in after a pathname check is refused too
// the pathname is checked before opening (opening a FIFO for reading blocks until a writer appears), then the
// opened file again: a link or FIFO swapped in after the pathname check is refused too
if !std::fs::metadata(path).map_err(io)?.is_file() {
return Err(Error::Io(format!("{}: not a regular file", path.display())));
}
let file = std::fs::File::open(path).map_err(io)?;
let meta = file.metadata().map_err(io)?;
if !meta.is_file() {
+18
View File
@@ -417,3 +417,21 @@ fn load_dir_refuses_a_non_regular_xml_entry() {
assert!(db.is_empty());
assert_eq!(errs.len(), 1, "{errs:?}");
}
/// A FIFO named `*.xml` is refused without opening it: opening a FIFO for reading blocks until a writer appears.
#[cfg(unix)]
#[test]
fn load_dir_refuses_a_fifo_without_blocking() {
let dir = std::env::temp_dir().join(format!("lensdb-test-fifo-{}", std::process::id()));
std::fs::create_dir(&dir).unwrap();
let fifo = dir.join("f.xml");
let made = std::process::Command::new("mkfifo").arg(&fifo).status().is_ok_and(|s| s.success());
if !made {
std::fs::remove_dir_all(&dir).unwrap();
return;
}
let (db, errs) = LensDb::load_dir(&dir).unwrap();
std::fs::remove_dir_all(&dir).unwrap();
assert!(db.is_empty());
assert_eq!(errs.len(), 1, "{errs:?}");
}