feat: publish Dever core with project scaffolding and versioned AI skills
This commit is contained in:
1 parent
70fa73cdc2
commit
ac458ffa7f
960 files changed
+221319
-1163
No files matched your search
@@ -0,0 +1,140 @@
|
||||
//! Trust-chain regression checks touch only an explicitly owned target subtree.
|
||||
use super::*;
|
||||
use std::fs;
|
||||
use std::os::unix::fs::{PermissionsExt, chown, symlink};
|
||||
|
||||
#[path = "../dever-tests/tests/support/temp.rs"]
|
||||
mod temp;
|
||||
|
||||
#[test]
|
||||
fn restricted_hosts_require_strict_profile_transitions_before_helper_selection() {
|
||||
use std::io::{Error, ErrorKind};
|
||||
for userns in [None, Some("0\n")] {
|
||||
assert!(
|
||||
!host_policy(|path| {
|
||||
assert!(
|
||||
path.ends_with("apparmor_restrict_unprivileged_userns"),
|
||||
"unrestricted hosts must not read the strict flag"
|
||||
);
|
||||
userns
|
||||
.map(str::to_owned)
|
||||
.ok_or_else(|| Error::from(ErrorKind::NotFound))
|
||||
})
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
for strict in [None, Some("0\n"), Some("1\n")] {
|
||||
let result = host_policy(|path| {
|
||||
if path.ends_with("apparmor_restrict_unprivileged_userns") {
|
||||
return Ok("1\n".into());
|
||||
}
|
||||
assert!(path.ends_with("apparmor_restrict_unprivileged_unconfined"));
|
||||
strict
|
||||
.map(str::to_owned)
|
||||
.ok_or_else(|| Error::from(ErrorKind::NotFound))
|
||||
});
|
||||
if strict == Some("1\n") {
|
||||
assert!(result.unwrap());
|
||||
} else {
|
||||
assert!(
|
||||
result
|
||||
.unwrap_err()
|
||||
.contains("kernel.apparmor_restrict_unprivileged_unconfined=1")
|
||||
);
|
||||
}
|
||||
}
|
||||
for failure in [ErrorKind::PermissionDenied, ErrorKind::InvalidData] {
|
||||
assert!(
|
||||
host_policy(|_| Err(Error::from(failure)))
|
||||
.unwrap_err()
|
||||
.contains("cannot inspect")
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
host_policy(|_| Ok("2\n".into()))
|
||||
.unwrap_err()
|
||||
.contains("invalid AppArmor kernel flag")
|
||||
);
|
||||
assert!(
|
||||
host_policy(
|
||||
|path| if path.ends_with("apparmor_restrict_unprivileged_userns") {
|
||||
Ok("1".into())
|
||||
} else {
|
||||
Err(Error::from(ErrorKind::PermissionDenied))
|
||||
}
|
||||
)
|
||||
.unwrap_err()
|
||||
.contains("cannot inspect")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires root and the prepared static author bwrap; touches only owned target files"]
|
||||
fn rejects_untrusted_helper_paths_bytes_modes_owners_and_capabilities() {
|
||||
assert_eq!(rustix::process::geteuid().as_raw(), 0);
|
||||
let target = Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("../../target")
|
||||
.canonicalize()
|
||||
.unwrap();
|
||||
let root = temp::TemporaryDirectory::new_in(&target);
|
||||
let bytes = fs::read(target.join("sandbox-inputs/assets/bin/bwrap")).unwrap();
|
||||
let hash = crate::validate_bwrap(&bytes).unwrap();
|
||||
let directory = root.path().join(&hash);
|
||||
fs::create_dir(&directory).unwrap();
|
||||
let helper = directory.join("bwrap");
|
||||
assert!(
|
||||
verify_helper(&helper, &hash)
|
||||
.unwrap_err()
|
||||
.contains("missing")
|
||||
);
|
||||
fs::write(&helper, &bytes).unwrap();
|
||||
fs::set_permissions(&helper, fs::Permissions::from_mode(0o755)).unwrap();
|
||||
verify_helper(&helper, &hash).unwrap();
|
||||
assert!(
|
||||
verify_helper(&helper, &"0".repeat(64))
|
||||
.unwrap_err()
|
||||
.contains("differs")
|
||||
);
|
||||
for mode in [0o775, 0o4755, 0o2755, 0o644] {
|
||||
fs::set_permissions(&helper, fs::Permissions::from_mode(mode)).unwrap();
|
||||
assert!(verify_helper(&helper, &hash).is_err());
|
||||
}
|
||||
fs::set_permissions(&helper, fs::Permissions::from_mode(0o755)).unwrap();
|
||||
chown(&helper, Some(65534), Some(65534)).unwrap();
|
||||
assert!(verify_helper(&helper, &hash).is_err());
|
||||
chown(&helper, Some(0), Some(0)).unwrap();
|
||||
fs::set_permissions(&directory, fs::Permissions::from_mode(0o777)).unwrap();
|
||||
assert!(verify_helper(&helper, &hash).is_err());
|
||||
fs::set_permissions(&directory, fs::Permissions::from_mode(0o755)).unwrap();
|
||||
let renamed = root.path().join("retained");
|
||||
fs::rename(&directory, &renamed).unwrap();
|
||||
symlink(&renamed, &directory).unwrap();
|
||||
assert!(verify_helper(&helper, &hash).is_err());
|
||||
fs::remove_file(&directory).unwrap();
|
||||
fs::rename(&renamed, &directory).unwrap();
|
||||
// VFS_CAP_REVISION_2 with only CAP_NET_ADMIN permitted; never execute it.
|
||||
let mut capability = [0u8; 20];
|
||||
capability[..4].copy_from_slice(&0x0200_0001u32.to_le_bytes());
|
||||
capability[4..8].copy_from_slice(&(1u32 << 12).to_le_bytes());
|
||||
rustix::fs::setxattr(
|
||||
&helper,
|
||||
"security.capability",
|
||||
&capability,
|
||||
rustix::fs::XattrFlags::empty(),
|
||||
)
|
||||
.unwrap();
|
||||
assert!(
|
||||
verify_helper(&helper, &hash)
|
||||
.unwrap_err()
|
||||
.contains("file capabilities")
|
||||
);
|
||||
rustix::fs::removexattr(&helper, "security.capability").unwrap();
|
||||
verify_helper(&helper, &hash).unwrap();
|
||||
// A sticky /tmp ancestor is acceptable for installer image fixtures, but
|
||||
// cannot be part of the runtime's administrator-controlled attachment path.
|
||||
let shared_ancestor = temp::TemporaryDirectory::new();
|
||||
let shared_helper = shared_ancestor.path().join("bwrap");
|
||||
fs::write(&shared_helper, &bytes).unwrap();
|
||||
fs::set_permissions(&shared_helper, fs::Permissions::from_mode(0o755)).unwrap();
|
||||
assert!(verify_helper(&shared_helper, &hash).is_err());
|
||||
}
|
||||
Reference in new issue
Block a user