first commit
This commit is contained in:
16
x2t-sandbox-rulegen/Cargo.toml
Normal file
16
x2t-sandbox-rulegen/Cargo.toml
Normal file
@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "x2t-sandbox-rulegen"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1"
|
||||
quote = "1"
|
||||
nix = "0.27.1"
|
||||
regex = "1.10.2"
|
||||
|
63
x2t-sandbox-rulegen/src/lib.rs
Normal file
63
x2t-sandbox-rulegen/src/lib.rs
Normal file
@ -0,0 +1,63 @@
|
||||
use std::{collections::HashSet, str::FromStr};
|
||||
|
||||
use proc_macro::*;
|
||||
use quote::{quote, format_ident, TokenStreamExt};
|
||||
|
||||
#[proc_macro]
|
||||
pub fn generate(input: TokenStream) -> TokenStream {
|
||||
let wd = std::path::PathBuf::from_str(&std::env::var("CARGO_MANIFEST_DIR").unwrap()).unwrap();
|
||||
|
||||
let syscall_filepath =
|
||||
wd.join(std::env::var("X2T_SYSCALLS_FILE").unwrap_or("x2t-syscalls.txt".to_string()));
|
||||
|
||||
if let Some(syscalls) = option_env!("X2T_SYSCALLS") {
|
||||
generate_from(input.clone(), syscalls.to_lowercase(), ":").into()
|
||||
} else if let Ok(syscalls) = std::fs::read_to_string(&syscall_filepath) {
|
||||
generate_from(input.clone(), syscalls, "\n").into()
|
||||
} else {
|
||||
panic!("either specify a X2T_SYSCALLS environment variable with values seperated by colon or write the allowed syscalls line by line into {}", syscall_filepath.to_string_lossy());
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_from(input: proc_macro::TokenStream, buf: String, sep: &str) -> proc_macro2::TokenStream {
|
||||
// TODO: improve generate rules to restrict arguments
|
||||
let mut tokens = Vec::new();
|
||||
let mut syscalls = HashSet::new();
|
||||
|
||||
let raw_syscall_pattern = regex::Regex::new("^\\s*([a-z_][a-z0-9_]*)").unwrap();
|
||||
let strace_pattern = regex::Regex::new("^\\d+ ([a-z_][a-z0-9_]*)").unwrap();
|
||||
for s in buf.split(sep) {
|
||||
// s can be a
|
||||
// - a name matched by [[:space:]]*(?P<syscall>[a-z_][a-z0-9_]*)
|
||||
// - strace line matched by [[:digit:]] (?P<syscall>[a-z_][a-z0-9_]*)
|
||||
for pattern in [&raw_syscall_pattern, &strace_pattern] {
|
||||
if let Some(capture) = pattern.captures(s) {
|
||||
let (_, [syscall_name]) = capture.extract();
|
||||
syscalls.insert(syscall_name.to_string());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut syscalls: Vec<String> = syscalls.iter().map(|s| s.to_owned()).collect();
|
||||
syscalls.sort();
|
||||
|
||||
let hook: proc_macro2::TokenStream = input.into();
|
||||
|
||||
for syscall_name in syscalls {
|
||||
let libc_name = format_ident!("SYS_{}", syscall_name);
|
||||
tokens.push(
|
||||
quote! {
|
||||
{
|
||||
let syscall_nr = nix::libc::#libc_name;
|
||||
let syscall_name = #syscall_name;
|
||||
filter.add_rule_conditional(ScmpAction::Allow, syscall_nr as i32, &[])?;
|
||||
#hook
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
quote! {
|
||||
#(#tokens);*
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user