blob: 3b2ca09775132d29c0897904cf6ef756c398d6f8 [file] [log] [blame]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use std::env;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
fn rewrite_policies(seccomp_policy_path: &Path, rewrote_policy_folder: &Path) {
for entry in fs::read_dir(seccomp_policy_path).unwrap() {
let policy_file = entry.unwrap();
let policy_file_content = fs::read_to_string(policy_file.path()).unwrap();
let policy_file_content_rewrote =
policy_file_content.replace("/usr/share/policy/crosvm", ".");
fs::write(
rewrote_policy_folder.join(policy_file.file_name()),
policy_file_content_rewrote,
)
.unwrap();
}
}
fn compile_policies(out_dir: &Path, rewrote_policy_folder: &Path, compile_seccomp_policy: &Path) {
let compiled_policy_folder = out_dir.join("policy_output");
fs::create_dir_all(&compiled_policy_folder).unwrap();
let mut include_all_bytes = String::from("std::collections::HashMap::from([\n");
for entry in fs::read_dir(rewrote_policy_folder).unwrap() {
let policy_file = entry.unwrap();
if policy_file.path().extension().unwrap() == "policy" {
let output_file_path = compiled_policy_folder.join(
policy_file
.path()
.with_extension("bpf")
.file_name()
.unwrap(),
);
let status = Command::new(compile_seccomp_policy)
.arg("--arch-json")
.arg(rewrote_policy_folder.join("constants.json"))
.arg("--default-action")
.arg("trap")
.arg(policy_file.path())
.arg(&output_file_path)
.spawn()
.unwrap()
.wait()
.expect("Spawning the bpf compiler failed");
if !status.success() {
panic!("Compile bpf failed");
}
let s = format!(
r#"("{}", include_bytes!("{}").to_vec()),"#,
policy_file.path().file_stem().unwrap().to_str().unwrap(),
output_file_path.to_str().unwrap()
);
include_all_bytes += s.as_str();
}
}
include_all_bytes += "])";
fs::write(out_dir.join("bpf_includes.in"), include_all_bytes).unwrap();
}
fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=seccomp");
if env::var("CARGO_CFG_TARGET_FAMILY").unwrap() != "unix" {
return;
}
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let src_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
let compile_seccomp_policy = if let Ok(path) = which::which("compile_seccomp_policy") {
// If `compile_seccomp_policy` exists in the path (e.g. ChromeOS builds), use it.
path
} else {
// Otherwise, use compile_seccomp_policy.py from the minijail submodule.
let minijail_dir = if let Ok(minijail_dir_env) = env::var("MINIJAIL_DIR") {
PathBuf::from(minijail_dir_env)
} else {
src_dir.join("third_party/minijail")
};
minijail_dir.join("tools/compile_seccomp_policy.py")
};
// check policies exist for target architecuture
let seccomp_arch_name = match env::var("CARGO_CFG_TARGET_ARCH").unwrap().as_str() {
"armv7" => "arm".to_owned(),
x => x.to_owned(),
};
let seccomp_policy_path = src_dir.join("seccomp").join(&seccomp_arch_name);
assert!(
seccomp_policy_path.is_dir(),
"Seccomp policy dir doesn't exist"
);
let rewrote_policy_folder = out_dir.join("policy_input");
fs::create_dir_all(&rewrote_policy_folder).unwrap();
rewrite_policies(&seccomp_policy_path, &rewrote_policy_folder);
compile_policies(&out_dir, &rewrote_policy_folder, &compile_seccomp_policy);
}