Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/firecracker
Path: blob/main/src/vmm/build.rs
1956 views
1
// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
// SPDX-License-Identifier: Apache-2.0
3
4
use std::env;
5
use std::fs;
6
use std::path::{Path, PathBuf};
7
use std::process::Command;
8
9
const ADVANCED_BINARY_FILTER_FILE_NAME: &str = "seccomp_filter.bpf";
10
const BASIC_BINARY_FILTER_FILE_NAME: &str = "basic_seccomp_filter.bpf";
11
12
const JSON_DIR: &str = "../../resources/seccomp";
13
const SECCOMPILER_BUILD_DIR: &str = "../../build/seccompiler";
14
const SECCOMPILER_SRC_DIR: &str = "../seccompiler/src";
15
16
// This script is run on every modification in the target-specific JSON file in `resources/seccomp`.
17
// It compiles the JSON seccomp policies into a serializable BPF format, using seccompiler-bin.
18
// The generated binary code will get included in Firecracker's code, at compile-time.
19
fn main() {
20
let target = env::var("TARGET").expect("Missing target.");
21
let out_dir = env::var("OUT_DIR").expect("Missing build-level OUT_DIR.");
22
23
// Path to the JSON seccomp policy.
24
let mut json_path = PathBuf::from(JSON_DIR);
25
json_path.push(format!("{}.json", target));
26
27
// If the current target doesn't have a default filter, use a default, empty filter.
28
// This is to make sure that Firecracker builds even with libc toolchains for which we don't provide
29
// a default filter. For example, GNU libc.
30
if !json_path.exists() {
31
json_path.pop();
32
json_path.push("unimplemented.json");
33
34
println!(
35
"cargo:warning=No default seccomp policy for target: {}. \
36
Defaulting to `resources/seccomp/unimplemented.json`.",
37
target
38
);
39
}
40
41
// Retrigger the build script if the JSON file has changed.
42
let json_path = json_path.to_str().expect("Invalid bytes");
43
println!("cargo:rerun-if-changed={}", json_path);
44
45
// Also retrigger the build script on any seccompiler source code change.
46
register_seccompiler_src_watchlist(Path::new(SECCOMPILER_SRC_DIR));
47
48
// Run seccompiler-bin, getting the default, advanced filter.
49
let mut bpf_out_path = PathBuf::from(&out_dir);
50
bpf_out_path.push(ADVANCED_BINARY_FILTER_FILE_NAME);
51
run_seccompiler_bin(
52
&target,
53
json_path,
54
bpf_out_path.to_str().expect("Invalid bytes."),
55
false,
56
);
57
58
// Run seccompiler-bin with the `--basic` flag, getting the filter for `--seccomp-level 1`.
59
let mut bpf_out_path = PathBuf::from(&out_dir);
60
bpf_out_path.push(BASIC_BINARY_FILTER_FILE_NAME);
61
run_seccompiler_bin(
62
&target,
63
json_path,
64
bpf_out_path.to_str().expect("Invalid bytes."),
65
true,
66
);
67
}
68
69
// Run seccompiler with the given arguments.
70
fn run_seccompiler_bin(cargo_target: &str, json_path: &str, out_path: &str, basic: bool) {
71
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").expect("Missing target arch.");
72
73
// Command for running seccompiler-bin
74
let mut command = Command::new("cargo");
75
command.args(&[
76
"run",
77
"-p",
78
"seccompiler",
79
"--verbose",
80
"--target",
81
&cargo_target,
82
// We need to specify a separate build directory for seccompiler-bin. Otherwise, cargo will
83
// deadlock waiting to acquire a lock on the build folder that the parent cargo process is
84
// holding.
85
"--target-dir",
86
SECCOMPILER_BUILD_DIR,
87
"--",
88
"--input-file",
89
&json_path,
90
"--target-arch",
91
&target_arch,
92
"--output-file",
93
out_path,
94
]);
95
96
if basic {
97
command.arg("--basic");
98
}
99
100
match command.output() {
101
Err(error) => panic!("\nSeccompiler-bin error: {:?}\n", error),
102
Ok(result) if !result.status.success() => {
103
panic!(
104
"\nSeccompiler-bin returned non-zero exit code:\nstderr: {}\nstdout: {}\n",
105
String::from_utf8(result.stderr).unwrap(),
106
String::from_utf8(result.stdout).unwrap(),
107
);
108
}
109
Ok(_) => {}
110
}
111
}
112
113
// Recursively traverse the entire seccompiler source folder and trigger a re-run of this build
114
// script on any modification of these files.
115
fn register_seccompiler_src_watchlist(src_dir: &Path) {
116
let contents = fs::read_dir(src_dir).expect("Unable to read folder contents.");
117
for entry in contents {
118
let path = entry.unwrap().path();
119
let metadata = fs::metadata(&path).expect("Unable to read file/folder metadata.");
120
121
if metadata.is_file() {
122
// Watch all source files.
123
println!(
124
"cargo:rerun-if-changed={}",
125
path.to_str().expect("Invalid unicode bytes.")
126
);
127
} else if metadata.is_dir() {
128
// If is a folder, recurse.
129
register_seccompiler_src_watchlist(&path);
130
}
131
}
132
}
133
134