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