Normalize inactive State Anchor work storage
This commit is contained in:
parent
7cd8a90af0
commit
42e197510e
1 changed files with 133 additions and 11 deletions
|
|
@ -18,6 +18,7 @@ use lazaret_state_anchor::{
|
|||
ProtectedRuntimeFiles, RuntimeStateAnchorAuthority, RuntimeStateAnchorInherited,
|
||||
StateAnchorLaunchAuthority, StateAnchorLayout, StateAnchorResetScope,
|
||||
};
|
||||
use rustix::fs::{XattrFlags, fsetxattr};
|
||||
|
||||
static SEQUENCE: AtomicU64 = AtomicU64::new(0);
|
||||
|
||||
|
|
@ -33,6 +34,40 @@ fn maintenance_accepts_exact_empty_fuse_overlayfs_work_shape() {
|
|||
layout.inspect_state().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inactive_normalization_removes_exact_opaque_fuse_overlayfs_residue() {
|
||||
let tree = TestTree::new();
|
||||
let configuration = configuration(&tree);
|
||||
let layout = StateAnchorLayout::create(&configuration).unwrap();
|
||||
let nested = domain_path(&configuration).join("state-anchor/work/work");
|
||||
fs::create_dir(&nested).unwrap();
|
||||
fs::set_permissions(&nested, fs::Permissions::from_mode(0o700)).unwrap();
|
||||
create_opaque_work_residue(&nested, "4");
|
||||
create_opaque_work_residue(&nested, "12");
|
||||
|
||||
assert!(layout.inspect_state().is_err());
|
||||
layout.normalize_inactive_work_directory().unwrap();
|
||||
layout.inspect_state().unwrap();
|
||||
let work = domain_path(&configuration).join("state-anchor/work");
|
||||
assert!(work.read_dir().unwrap().next().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inactive_normalization_unlinks_work_symlinks_without_following_them() {
|
||||
let tree = TestTree::new();
|
||||
let configuration = configuration(&tree);
|
||||
let layout = StateAnchorLayout::create(&configuration).unwrap();
|
||||
let work = domain_path(&configuration).join("state-anchor/work");
|
||||
let foreign = tree.path.join("foreign-work");
|
||||
fs::create_dir(&foreign).unwrap();
|
||||
fs::write(foreign.join("value"), b"foreign").unwrap();
|
||||
std::os::unix::fs::symlink(&foreign, work.join("residue")).unwrap();
|
||||
|
||||
layout.normalize_inactive_work_directory().unwrap();
|
||||
assert!(!work.join("residue").exists());
|
||||
assert_eq!(fs::read(foreign.join("value")).unwrap(), b"foreign");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn maintenance_refuses_mutated_fuse_overlayfs_work_shapes() {
|
||||
let tree = TestTree::new();
|
||||
|
|
@ -60,6 +95,26 @@ fn maintenance_refuses_mutated_fuse_overlayfs_work_shapes() {
|
|||
assert!(layout.inspect_state().is_err());
|
||||
}
|
||||
|
||||
fn create_opaque_work_residue(nested: &Path, name: &str) {
|
||||
let residue = nested.join(name);
|
||||
fs::create_dir(&residue).unwrap();
|
||||
fs::set_permissions(&residue, fs::Permissions::from_mode(0o755)).unwrap();
|
||||
fs::write(residue.join(".wh..wh..opq"), b"").unwrap();
|
||||
fs::set_permissions(
|
||||
residue.join(".wh..wh..opq"),
|
||||
fs::Permissions::from_mode(0o700),
|
||||
)
|
||||
.unwrap();
|
||||
let residue = File::open(residue).unwrap();
|
||||
fsetxattr(
|
||||
&residue,
|
||||
"user.fuseoverlayfs.opaque",
|
||||
b"y",
|
||||
XattrFlags::empty(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn selected_reset_removes_exact_state_and_whiteout_without_touching_siblings() {
|
||||
let tree = TestTree::new();
|
||||
|
|
|
|||
Loading…
Reference in a new issue