Confine package ownership changes to private mounts
This commit is contained in:
parent
2c420012bd
commit
8334fd379f
3 changed files with 402 additions and 25 deletions
|
|
@ -275,8 +275,23 @@ impl IgnoredWorkspace {
|
|||
let stat = match backing {
|
||||
Classification::Host => host,
|
||||
Classification::Isolated => isolated,
|
||||
}
|
||||
.ok_or_else(|| io::Error::from_raw_os_error(libc::ENOENT))?;
|
||||
};
|
||||
let (backing, stat) = if let Some(stat) = stat {
|
||||
(backing, stat)
|
||||
} else if backing == Classification::Isolated
|
||||
&& host.as_ref().is_some_and(|stat| {
|
||||
stat.st_mode & libc::S_IFMT == libc::S_IFDIR
|
||||
&& self
|
||||
.provenance
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.matches(path, &crate::migration::ObjectStamp::from_stat(stat))
|
||||
})
|
||||
{
|
||||
(Classification::Host, host.expect("checked host directory"))
|
||||
} else {
|
||||
return Err(io::Error::from_raw_os_error(libc::ENOENT));
|
||||
};
|
||||
Ok(ResolvedEntry {
|
||||
path: path.to_path_buf(),
|
||||
backing,
|
||||
|
|
|
|||
|
|
@ -81,6 +81,63 @@ fn disabled_isolation_routes_ignored_paths_to_the_host_backing() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn newly_ignored_created_directory_remains_a_safe_traversal_shell() {
|
||||
let fixture = Fixture::new();
|
||||
repository(&fixture.workspace);
|
||||
let filesystem = IgnoredWorkspace::open(&fixture.workspace, &fixture.isolated, None).unwrap();
|
||||
for path in ["environment", "environment/bin"] {
|
||||
fs::create_dir(fixture.workspace.join(path)).unwrap();
|
||||
filesystem
|
||||
.record_created(Classification::Host, std::path::Path::new(path))
|
||||
.unwrap();
|
||||
}
|
||||
fs::write(fixture.workspace.join("environment/.gitignore"), b"*\n").unwrap();
|
||||
filesystem
|
||||
.record_created(
|
||||
Classification::Host,
|
||||
std::path::Path::new("environment/.gitignore"),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let path = std::path::Path::new("environment/bin");
|
||||
let snapshot = filesystem.classifier.snapshot_for(path);
|
||||
let entry = filesystem.resolve(&snapshot, path).unwrap();
|
||||
assert_eq!(entry.backing, Classification::Host);
|
||||
assert_eq!(
|
||||
filesystem.classify(&snapshot, &path.join("python3"), false),
|
||||
Classification::Isolated
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ignored_host_directory_requires_current_creation_provenance() {
|
||||
let fixture = Fixture::new();
|
||||
repository(&fixture.workspace);
|
||||
fs::write(fixture.workspace.join(".gitignore"), b"hidden/\nchanged/\n").unwrap();
|
||||
fs::create_dir(fixture.workspace.join("hidden")).unwrap();
|
||||
fs::create_dir(fixture.workspace.join("changed")).unwrap();
|
||||
let filesystem = IgnoredWorkspace::open(&fixture.workspace, &fixture.isolated, None).unwrap();
|
||||
|
||||
let hidden = std::path::Path::new("hidden");
|
||||
let snapshot = filesystem.classifier.snapshot_for(hidden);
|
||||
let Err(error) = filesystem.resolve(&snapshot, hidden) else {
|
||||
panic!("unproven host directory became visible");
|
||||
};
|
||||
assert_eq!(error.raw_os_error(), Some(libc::ENOENT));
|
||||
|
||||
filesystem
|
||||
.record_created(Classification::Host, std::path::Path::new("changed"))
|
||||
.unwrap();
|
||||
fs::write(fixture.workspace.join("changed/external"), b"outside").unwrap();
|
||||
let changed = std::path::Path::new("changed");
|
||||
let snapshot = filesystem.classifier.snapshot_for(changed);
|
||||
let Err(error) = filesystem.resolve(&snapshot, changed) else {
|
||||
panic!("changed host directory retained creation provenance");
|
||||
};
|
||||
assert_eq!(error.raw_os_error(), Some(libc::ENOENT));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires a usable host FUSE device"]
|
||||
fn physical_router_preserves_lock_domains_across_transition() {
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ impl Provenance {
|
|||
self.objects.extend(moved);
|
||||
}
|
||||
|
||||
fn matches(&self, path: &Path, stamp: &ObjectStamp) -> bool {
|
||||
pub(crate) fn matches(&self, path: &Path, stamp: &ObjectStamp) -> bool {
|
||||
self.objects.get(path) == Some(stamp)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue