Merge pull request #2661 from cgwalters/port-cap-std
This commit is contained in:
commit
e527cdc582
|
|
@ -11,6 +11,7 @@ name = "ostree-test"
|
||||||
path = "src/insttestmain.rs"
|
path = "src/insttestmain.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
cap-std-ext = "0.25"
|
||||||
clap = "2.32.0"
|
clap = "2.32.0"
|
||||||
structopt = "0.3"
|
structopt = "0.3"
|
||||||
serde = "1.0.111"
|
serde = "1.0.111"
|
||||||
|
|
@ -33,8 +34,6 @@ procspawn = "0.8"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
strum = "0.18.0"
|
strum = "0.18.0"
|
||||||
strum_macros = "0.18.0"
|
strum_macros = "0.18.0"
|
||||||
openat = "0.1.19"
|
|
||||||
openat-ext = "0.1.4"
|
|
||||||
nix = "0.23.0"
|
nix = "0.23.0"
|
||||||
# See discussion in https://github.com/coreos/rpm-ostree/pull/2569#issuecomment-780569188
|
# See discussion in https://github.com/coreos/rpm-ostree/pull/2569#issuecomment-780569188
|
||||||
rpmostree-client = { git = "https://github.com/coreos/rpm-ostree", tag = "v2021.3" }
|
rpmostree-client = { git = "https://github.com/coreos/rpm-ostree", tag = "v2021.3" }
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use openat_ext::{FileExt, OpenatDirExt};
|
use cap_std::fs::Dir;
|
||||||
|
use cap_std_ext::cap_std;
|
||||||
|
use cap_std_ext::dirext::*;
|
||||||
|
use cap_std_ext::rustix::fs::MetadataExt;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use sh_inline::bash;
|
use sh_inline::bash;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
|
@ -52,40 +55,36 @@ pub(crate) fn is_elf(f: &mut File) -> Result<bool> {
|
||||||
pub(crate) fn mutate_one_executable_to(
|
pub(crate) fn mutate_one_executable_to(
|
||||||
f: &mut File,
|
f: &mut File,
|
||||||
name: &std::ffi::OsStr,
|
name: &std::ffi::OsStr,
|
||||||
dest: &openat::Dir,
|
dest: &Dir,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut destf = dest
|
let perms = f.metadata()?.permissions();
|
||||||
.write_file(name, 0o755)
|
dest.atomic_replace_with(name, |w| {
|
||||||
.context("Failed to open for write")?;
|
std::io::copy(f, w)?;
|
||||||
f.copy_to(&destf).context("Failed to copy")?;
|
|
||||||
// ELF is OK with us just appending some junk
|
// ELF is OK with us just appending some junk
|
||||||
let extra = rand::thread_rng()
|
let extra = rand::thread_rng()
|
||||||
.sample_iter(&rand::distributions::Alphanumeric)
|
.sample_iter(&rand::distributions::Alphanumeric)
|
||||||
.take(10)
|
.take(10)
|
||||||
.collect::<Vec<u8>>();
|
.collect::<Vec<u8>>();
|
||||||
destf
|
w.write_all(&extra).context("Failed to append extra data")?;
|
||||||
.write_all(&extra)
|
w.get_mut()
|
||||||
.context("Failed to append extra data")?;
|
.as_file_mut()
|
||||||
Ok(())
|
.set_permissions(cap_std::fs::Permissions::from_std(perms))?;
|
||||||
|
Ok::<_, anyhow::Error>(())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find ELF files in the srcdir, write new copies to dest (only percentage)
|
/// Find ELF files in the srcdir, write new copies to dest (only percentage)
|
||||||
pub(crate) fn mutate_executables_to(
|
pub(crate) fn mutate_executables_to(src: &Dir, dest: &Dir, percentage: u32) -> Result<u32> {
|
||||||
src: &openat::Dir,
|
|
||||||
dest: &openat::Dir,
|
|
||||||
percentage: u32,
|
|
||||||
) -> Result<u32> {
|
|
||||||
use nix::sys::stat::Mode as NixMode;
|
use nix::sys::stat::Mode as NixMode;
|
||||||
assert!(percentage > 0 && percentage <= 100);
|
assert!(percentage > 0 && percentage <= 100);
|
||||||
let mut mutated = 0;
|
let mut mutated = 0;
|
||||||
for entry in src.list_dir(".")? {
|
for entry in src.entries()? {
|
||||||
let entry = entry?;
|
let entry = entry?;
|
||||||
if src.get_file_type(&entry)? != openat::SimpleType::File {
|
if entry.file_type()? != cap_std::fs::FileType::file() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let meta = src.metadata(entry.file_name())?;
|
let meta = entry.metadata()?;
|
||||||
let st = meta.stat();
|
let mode = NixMode::from_bits_truncate(meta.mode());
|
||||||
let mode = NixMode::from_bits_truncate(st.st_mode);
|
|
||||||
// Must be executable
|
// Must be executable
|
||||||
if !mode.intersects(NixMode::S_IXUSR | NixMode::S_IXGRP | NixMode::S_IXOTH) {
|
if !mode.intersects(NixMode::S_IXUSR | NixMode::S_IXGRP | NixMode::S_IXOTH) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -95,17 +94,17 @@ pub(crate) fn mutate_executables_to(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Greater than 1k in size
|
// Greater than 1k in size
|
||||||
if st.st_size < 1024 {
|
if meta.size() < 1024 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let mut f = src.open_file(entry.file_name())?;
|
let mut f = entry.open()?.into_std();
|
||||||
if !is_elf(&mut f)? {
|
if !is_elf(&mut f)? {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if !rand::thread_rng().gen_ratio(percentage, 100) {
|
if !rand::thread_rng().gen_ratio(percentage, 100) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
mutate_one_executable_to(&mut f, entry.file_name(), dest)
|
mutate_one_executable_to(&mut f, &entry.file_name(), dest)
|
||||||
.with_context(|| format!("Failed updating {:?}", entry.file_name()))?;
|
.with_context(|| format!("Failed updating {:?}", entry.file_name()))?;
|
||||||
mutated += 1;
|
mutated += 1;
|
||||||
}
|
}
|
||||||
|
|
@ -124,15 +123,14 @@ pub(crate) fn update_os_tree<P: AsRef<Path>>(
|
||||||
let tempdir = tempfile::tempdir_in(repo_path.join("tmp"))?;
|
let tempdir = tempfile::tempdir_in(repo_path.join("tmp"))?;
|
||||||
let mut mutated = 0;
|
let mut mutated = 0;
|
||||||
{
|
{
|
||||||
let tempdir = openat::Dir::open(tempdir.path())?;
|
let tempdir = Dir::open_ambient_dir(tempdir.path(), cap_std::ambient_authority())?;
|
||||||
let binary_dirs = &["usr/bin", "usr/sbin", "usr/lib", "usr/lib64"];
|
let binary_dirs = &["usr/bin", "usr/sbin", "usr/lib", "usr/lib64"];
|
||||||
let rootfs = openat::Dir::open("/")?;
|
let rootfs = Dir::open_ambient_dir("/", cap_std::ambient_authority())?;
|
||||||
for v in binary_dirs {
|
for v in binary_dirs {
|
||||||
let v = *v;
|
let v = *v;
|
||||||
if let Some(src) = rootfs.sub_dir_optional(v)? {
|
if let Some(src) = rootfs.open_dir_optional(v)? {
|
||||||
tempdir.ensure_dir("usr", 0o755)?;
|
tempdir.create_dir_all(v)?;
|
||||||
tempdir.ensure_dir(v, 0o755)?;
|
let dest = tempdir.open_dir(v)?;
|
||||||
let dest = tempdir.sub_dir(v)?;
|
|
||||||
mutated += mutate_executables_to(&src, &dest, percentage)
|
mutated += mutate_executables_to(&src, &dest, percentage)
|
||||||
.with_context(|| format!("Replacing binaries in {v}"))?;
|
.with_context(|| format!("Replacing binaries in {v}"))?;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue