v0.2.14 : correction install binaire - detection des archives par magic bytes (un zip renomme n est plus copie tel quel), preference des archives sur les setup/installers, validation de l executable (MZ/ELF/Mach-O) avec erreur claire avant le premier start
This commit is contained in:
@@ -76,6 +76,9 @@ pub fn install(
|
||||
format!("cannot copy {} to {}", tmpfile.display(), dest_bin.display())
|
||||
})?;
|
||||
}
|
||||
// Guard against installing something that is not an executable for this
|
||||
// platform (wrong architecture, an unextracted archive, ...).
|
||||
verify_executable(&dest_bin)?;
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
@@ -88,6 +91,49 @@ pub fn install(
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn verify_executable_accepts_pe_and_rejects_elf() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let pe = dir.path().join("a.exe");
|
||||
std::fs::write(&pe, b"MZwhatever").unwrap();
|
||||
assert!(verify_executable(&pe).is_ok());
|
||||
let elf = dir.path().join("b");
|
||||
std::fs::write(&elf, b"ELF").unwrap();
|
||||
let err = verify_executable(&elf).unwrap_err();
|
||||
assert!(err.to_string().contains("not a"), "{err}");
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that the downloaded file is an executable of this platform.
|
||||
/// Detects the classic Windows "not compatible" (error 216) and Linux
|
||||
/// "exec format error" failures before the agent is ever started.
|
||||
fn verify_executable(path: &std::path::Path) -> Result<()> {
|
||||
let mut head = [0u8; 4];
|
||||
let n = std::fs::File::open(path)
|
||||
.and_then(|mut f| std::io::Read::read(&mut f, &mut head))
|
||||
.unwrap_or(0);
|
||||
#[cfg(windows)]
|
||||
let ok = n >= 2 && &head[0..2] == b"MZ";
|
||||
#[cfg(target_os = "macos")]
|
||||
let ok = (n >= 4 && (&head[0..4] == b"\xcf\xfa\xed\xfe" || &head[0..4] == b"\xfe\xed\xfa\xcf"))
|
||||
|| (n >= 4 && &head[0..4] == b"\xca\xfe\xba\xbe");
|
||||
#[cfg(all(unix, not(target_os = "macos")))]
|
||||
let ok = n >= 4 && &head[0..4] == b"\x7fELF";
|
||||
if ok {
|
||||
return Ok(());
|
||||
}
|
||||
bail!(
|
||||
"downloaded file {} is not a {} executable (magic bytes {:02x?}) — the release asset is probably for another platform or is an installer/archive",
|
||||
path.display(),
|
||||
std::env::consts::OS,
|
||||
&head[..n]
|
||||
)
|
||||
}
|
||||
|
||||
/// Latest release tag (without the leading "v").
|
||||
pub fn latest(
|
||||
_app: &App,
|
||||
|
||||
Reference in New Issue
Block a user