1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker
5*bb4ee6a4SAndroid Build Coastguard Worker use std::env;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::ffi::OsStr;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::fs;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::path::Path;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::path::PathBuf;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::process::Command;
11*bb4ee6a4SAndroid Build Coastguard Worker
12*bb4ee6a4SAndroid Build Coastguard Worker use rayon::prelude::*;
13*bb4ee6a4SAndroid Build Coastguard Worker
rewrite_policies(seccomp_policy_path: &Path, rewrote_policy_folder: &Path)14*bb4ee6a4SAndroid Build Coastguard Worker fn rewrite_policies(seccomp_policy_path: &Path, rewrote_policy_folder: &Path) {
15*bb4ee6a4SAndroid Build Coastguard Worker for entry in fs::read_dir(seccomp_policy_path).unwrap() {
16*bb4ee6a4SAndroid Build Coastguard Worker let policy_file = entry.unwrap();
17*bb4ee6a4SAndroid Build Coastguard Worker let policy_file_content = fs::read_to_string(policy_file.path()).unwrap();
18*bb4ee6a4SAndroid Build Coastguard Worker let policy_file_content_rewrote =
19*bb4ee6a4SAndroid Build Coastguard Worker policy_file_content.replace("/usr/share/policy/crosvm", ".");
20*bb4ee6a4SAndroid Build Coastguard Worker fs::write(
21*bb4ee6a4SAndroid Build Coastguard Worker rewrote_policy_folder.join(policy_file.file_name()),
22*bb4ee6a4SAndroid Build Coastguard Worker policy_file_content_rewrote,
23*bb4ee6a4SAndroid Build Coastguard Worker )
24*bb4ee6a4SAndroid Build Coastguard Worker .unwrap();
25*bb4ee6a4SAndroid Build Coastguard Worker }
26*bb4ee6a4SAndroid Build Coastguard Worker }
27*bb4ee6a4SAndroid Build Coastguard Worker
compile_policy( compile_script: &Path, compile_policy_folder: &Path, output_folder: &Path, policy_file: &fs::DirEntry, ) -> String28*bb4ee6a4SAndroid Build Coastguard Worker fn compile_policy(
29*bb4ee6a4SAndroid Build Coastguard Worker compile_script: &Path,
30*bb4ee6a4SAndroid Build Coastguard Worker compile_policy_folder: &Path,
31*bb4ee6a4SAndroid Build Coastguard Worker output_folder: &Path,
32*bb4ee6a4SAndroid Build Coastguard Worker policy_file: &fs::DirEntry,
33*bb4ee6a4SAndroid Build Coastguard Worker ) -> String {
34*bb4ee6a4SAndroid Build Coastguard Worker let output_file_path = compile_policy_folder.join(
35*bb4ee6a4SAndroid Build Coastguard Worker policy_file
36*bb4ee6a4SAndroid Build Coastguard Worker .path()
37*bb4ee6a4SAndroid Build Coastguard Worker .with_extension("bpf")
38*bb4ee6a4SAndroid Build Coastguard Worker .file_name()
39*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(),
40*bb4ee6a4SAndroid Build Coastguard Worker );
41*bb4ee6a4SAndroid Build Coastguard Worker let status = Command::new(compile_script)
42*bb4ee6a4SAndroid Build Coastguard Worker .arg("--arch-json")
43*bb4ee6a4SAndroid Build Coastguard Worker .arg(output_folder.join("constants.json"))
44*bb4ee6a4SAndroid Build Coastguard Worker .arg("--default-action")
45*bb4ee6a4SAndroid Build Coastguard Worker .arg("trap")
46*bb4ee6a4SAndroid Build Coastguard Worker .arg(policy_file.path())
47*bb4ee6a4SAndroid Build Coastguard Worker .arg(&output_file_path)
48*bb4ee6a4SAndroid Build Coastguard Worker .spawn()
49*bb4ee6a4SAndroid Build Coastguard Worker .unwrap()
50*bb4ee6a4SAndroid Build Coastguard Worker .wait()
51*bb4ee6a4SAndroid Build Coastguard Worker .expect("Spawning the bpf compiler failed");
52*bb4ee6a4SAndroid Build Coastguard Worker if !status.success() {
53*bb4ee6a4SAndroid Build Coastguard Worker panic!("Compile bpf failed");
54*bb4ee6a4SAndroid Build Coastguard Worker }
55*bb4ee6a4SAndroid Build Coastguard Worker format!(
56*bb4ee6a4SAndroid Build Coastguard Worker r#"("{}", include_bytes!("{}").to_vec()),"#,
57*bb4ee6a4SAndroid Build Coastguard Worker policy_file.path().file_stem().unwrap().to_str().unwrap(),
58*bb4ee6a4SAndroid Build Coastguard Worker output_file_path.to_str().unwrap()
59*bb4ee6a4SAndroid Build Coastguard Worker )
60*bb4ee6a4SAndroid Build Coastguard Worker }
61*bb4ee6a4SAndroid Build Coastguard Worker
compile_policies(out_dir: &Path, rewrote_policy_folder: &Path, compile_seccomp_policy: &Path)62*bb4ee6a4SAndroid Build Coastguard Worker fn compile_policies(out_dir: &Path, rewrote_policy_folder: &Path, compile_seccomp_policy: &Path) {
63*bb4ee6a4SAndroid Build Coastguard Worker let compiled_policy_folder = out_dir.join("policy_output");
64*bb4ee6a4SAndroid Build Coastguard Worker fs::create_dir_all(&compiled_policy_folder).unwrap();
65*bb4ee6a4SAndroid Build Coastguard Worker let mut include_all_bytes = String::from("std::collections::HashMap::from([\n");
66*bb4ee6a4SAndroid Build Coastguard Worker
67*bb4ee6a4SAndroid Build Coastguard Worker let entries = fs::read_dir(rewrote_policy_folder)
68*bb4ee6a4SAndroid Build Coastguard Worker .unwrap()
69*bb4ee6a4SAndroid Build Coastguard Worker .map(|ent| ent.unwrap())
70*bb4ee6a4SAndroid Build Coastguard Worker .collect::<Vec<_>>();
71*bb4ee6a4SAndroid Build Coastguard Worker
72*bb4ee6a4SAndroid Build Coastguard Worker let s = entries
73*bb4ee6a4SAndroid Build Coastguard Worker .par_iter()
74*bb4ee6a4SAndroid Build Coastguard Worker .filter(|ent| ent.path().extension() == Some(OsStr::new("policy")))
75*bb4ee6a4SAndroid Build Coastguard Worker .map(|policy_file| {
76*bb4ee6a4SAndroid Build Coastguard Worker compile_policy(
77*bb4ee6a4SAndroid Build Coastguard Worker compile_seccomp_policy,
78*bb4ee6a4SAndroid Build Coastguard Worker &compiled_policy_folder,
79*bb4ee6a4SAndroid Build Coastguard Worker rewrote_policy_folder,
80*bb4ee6a4SAndroid Build Coastguard Worker policy_file,
81*bb4ee6a4SAndroid Build Coastguard Worker )
82*bb4ee6a4SAndroid Build Coastguard Worker })
83*bb4ee6a4SAndroid Build Coastguard Worker .collect::<Vec<_>>()
84*bb4ee6a4SAndroid Build Coastguard Worker .join("");
85*bb4ee6a4SAndroid Build Coastguard Worker include_all_bytes += &s;
86*bb4ee6a4SAndroid Build Coastguard Worker
87*bb4ee6a4SAndroid Build Coastguard Worker include_all_bytes += "])";
88*bb4ee6a4SAndroid Build Coastguard Worker fs::write(out_dir.join("bpf_includes.in"), include_all_bytes).unwrap();
89*bb4ee6a4SAndroid Build Coastguard Worker }
90*bb4ee6a4SAndroid Build Coastguard Worker
main()91*bb4ee6a4SAndroid Build Coastguard Worker fn main() {
92*bb4ee6a4SAndroid Build Coastguard Worker println!("cargo:rerun-if-changed=build.rs");
93*bb4ee6a4SAndroid Build Coastguard Worker println!("cargo:rerun-if-changed=seccomp");
94*bb4ee6a4SAndroid Build Coastguard Worker
95*bb4ee6a4SAndroid Build Coastguard Worker if env::var("CARGO_CFG_TARGET_FAMILY").unwrap() != "unix" {
96*bb4ee6a4SAndroid Build Coastguard Worker return;
97*bb4ee6a4SAndroid Build Coastguard Worker }
98*bb4ee6a4SAndroid Build Coastguard Worker
99*bb4ee6a4SAndroid Build Coastguard Worker let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
100*bb4ee6a4SAndroid Build Coastguard Worker let src_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
101*bb4ee6a4SAndroid Build Coastguard Worker
102*bb4ee6a4SAndroid Build Coastguard Worker let compile_seccomp_policy = if let Ok(path) = which::which("compile_seccomp_policy") {
103*bb4ee6a4SAndroid Build Coastguard Worker // If `compile_seccomp_policy` exists in the path (e.g. ChromeOS builds), use it.
104*bb4ee6a4SAndroid Build Coastguard Worker path
105*bb4ee6a4SAndroid Build Coastguard Worker } else {
106*bb4ee6a4SAndroid Build Coastguard Worker // Otherwise, use compile_seccomp_policy.py from the minijail submodule.
107*bb4ee6a4SAndroid Build Coastguard Worker let minijail_dir = if let Ok(minijail_dir_env) = env::var("MINIJAIL_DIR") {
108*bb4ee6a4SAndroid Build Coastguard Worker PathBuf::from(minijail_dir_env)
109*bb4ee6a4SAndroid Build Coastguard Worker } else {
110*bb4ee6a4SAndroid Build Coastguard Worker src_dir.join("../third_party/minijail")
111*bb4ee6a4SAndroid Build Coastguard Worker };
112*bb4ee6a4SAndroid Build Coastguard Worker minijail_dir.join("tools/compile_seccomp_policy.py")
113*bb4ee6a4SAndroid Build Coastguard Worker };
114*bb4ee6a4SAndroid Build Coastguard Worker
115*bb4ee6a4SAndroid Build Coastguard Worker // check policies exist for target architecture
116*bb4ee6a4SAndroid Build Coastguard Worker let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
117*bb4ee6a4SAndroid Build Coastguard Worker let seccomp_arch_name = match target_arch.as_str() {
118*bb4ee6a4SAndroid Build Coastguard Worker "armv7" => "arm",
119*bb4ee6a4SAndroid Build Coastguard Worker x => x,
120*bb4ee6a4SAndroid Build Coastguard Worker };
121*bb4ee6a4SAndroid Build Coastguard Worker let seccomp_policy_path = src_dir.join("seccomp").join(seccomp_arch_name);
122*bb4ee6a4SAndroid Build Coastguard Worker assert!(
123*bb4ee6a4SAndroid Build Coastguard Worker seccomp_policy_path.is_dir(),
124*bb4ee6a4SAndroid Build Coastguard Worker "Seccomp policy dir doesn't exist"
125*bb4ee6a4SAndroid Build Coastguard Worker );
126*bb4ee6a4SAndroid Build Coastguard Worker
127*bb4ee6a4SAndroid Build Coastguard Worker let rewrote_policy_folder = out_dir.join("policy_input");
128*bb4ee6a4SAndroid Build Coastguard Worker fs::create_dir_all(&rewrote_policy_folder).unwrap();
129*bb4ee6a4SAndroid Build Coastguard Worker rewrite_policies(&seccomp_policy_path, &rewrote_policy_folder);
130*bb4ee6a4SAndroid Build Coastguard Worker compile_policies(&out_dir, &rewrote_policy_folder, &compile_seccomp_policy);
131*bb4ee6a4SAndroid Build Coastguard Worker }
132