use super::Stage; use std::collections::BTreeMap; use std::fs; use std::os::unix::fs::MetadataExt; #[allow(dead_code)] #[path = "support/native_elf.rs"] mod elf; fn prepared(files: &BTreeMap, bool)>) -> Stage { let stage = Stage::new().unwrap(); for (path, (bytes, executable)) in files { stage .write(&format!("input/{path}"), bytes, *executable) .unwrap(); } stage } #[test] fn signed_tool_libraries_share_bytes_without_replacing_host_glibc() { let names = [ "libbfd.so", "libstdc++.so.6", "libgcc_s.so.1", "libc.so.6", "libm.so.6", "libmvec.so.1", "libanl.so.1", "libdl.so.2", "libpthread.so.0", "librt.so.1", "libutil.so.1", "libresolv.so.2", "ld-linux-x86-64.so.2", "ld-linux-aarch64.so.1", ]; let files = names .into_iter() .map(|name| { ( format!("rootfs/usr/lib/fixture/{name}"), (elf::library(name, &[]), false), ) }) .collect(); let stage = prepared(&files); stage.link_tool_libraries(&files).unwrap(); for name in names { let destination = stage.0.join("input/lib").join(name); if matches!(name, "libbfd.so" | "libstdc++.so.6" | "libgcc_s.so.1") { let source = stage.0.join("input/rootfs/usr/lib/fixture").join(name); assert_eq!( fs::metadata(&source).unwrap().ino(), fs::metadata(&destination).unwrap().ino() ); assert_eq!(fs::read(source).unwrap(), fs::read(destination).unwrap()); } else { assert!(!destination.exists()); } } } #[test] fn duplicate_sonames_require_identical_signed_bytes() { let original = elf::library("libfixture.so", &[]); let mut files = BTreeMap::from([ ("rootfs/usr/lib/first.so".into(), (original.clone(), false)), ("rootfs/usr/lib/second.so".into(), (original, false)), ]); let stage = prepared(&files); stage.link_tool_libraries(&files).unwrap(); files.get_mut("rootfs/usr/lib/second.so").unwrap().0 = elf::library("libfixture.so", &["libc.so.6"]); let stage = prepared(&files); assert!( stage .link_tool_libraries(&files) .unwrap_err() .contains("conflicting SONAMEs") ); } #[test] fn tool_library_names_cannot_escape_the_owned_search_directory() { for name in ["../escape.so", "/escape.so", "nested/escape.so"] { let files = BTreeMap::from([( "rootfs/usr/lib/fixture.so".into(), (elf::library(name, &[]), false), )]); let stage = prepared(&files); assert!(stage.link_tool_libraries(&files).is_err()); assert!(!stage.0.join("input/escape.so").exists()); } }