mirror of
https://github.com/containers/youki
synced 2024-11-22 17:02:00 +01:00
seccomp: Update experiment seccomp program (#2946)
Signed-off-by: sat0ken <15720506+sat0ken@users.noreply.github.com>
This commit is contained in:
parent
dc2e09b431
commit
eaaca64fe4
42
experiment/seccomp/Cargo.lock
generated
42
experiment/seccomp/Cargo.lock
generated
@ -266,10 +266,42 @@ dependencies = [
|
||||
"nix 0.27.1",
|
||||
"prctl",
|
||||
"syscall-numbers",
|
||||
"syscalls",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.208"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.208"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_repr"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.2"
|
||||
@ -312,6 +344,16 @@ version = "3.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "084e382bf467cd3381fdec080d883505792ee0d16a004b1b090abf2db5dc2a29"
|
||||
|
||||
[[package]]
|
||||
name = "syscalls"
|
||||
version = "0.6.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43d0e35dc7d73976a53c7e6d7d177ef804a0c0ee774ec77bcc520c2216fd7cbe"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_repr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.58"
|
||||
|
@ -24,3 +24,4 @@ prctl = "1.0.0"
|
||||
anyhow = "1.0"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
syscall-numbers = "3.1.1"
|
||||
syscalls = { version = "0.6.18", features = ["std", "serde", "aarch64", "x86_64"]}
|
@ -1,13 +1,15 @@
|
||||
use crate::instruction::Instruction;
|
||||
use crate::instruction::*;
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum Arch {
|
||||
X86,
|
||||
X86,AArch64
|
||||
}
|
||||
|
||||
pub fn gen_validate(arc: &Arch) -> Vec<Instruction> {
|
||||
let arch = match arc {
|
||||
Arch::X86 => AUDIT_ARCH_X86_64,
|
||||
Arch::AArch64 => AUDIT_ARCH_AARCH64
|
||||
};
|
||||
|
||||
vec![
|
||||
|
@ -1,5 +1,5 @@
|
||||
use seccomp::{
|
||||
instruction::{self, *},
|
||||
instruction::{*},
|
||||
seccomp::{NotifyFd, Seccomp},
|
||||
};
|
||||
|
||||
@ -9,19 +9,18 @@ use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
||||
use std::slice;
|
||||
|
||||
use anyhow::Result;
|
||||
use nix::{
|
||||
libc,
|
||||
sys::{
|
||||
signal::Signal,
|
||||
socket::{
|
||||
self, ControlMessage, ControlMessageOwned, MsgFlags, SockFlag, SockType, UnixAddr,
|
||||
},
|
||||
stat::Mode,
|
||||
wait::{self, WaitStatus},
|
||||
use nix::{libc, sys::{
|
||||
signal::Signal,
|
||||
socket::{
|
||||
self, ControlMessage, ControlMessageOwned, MsgFlags, SockFlag, SockType, UnixAddr,
|
||||
},
|
||||
unistd::{close, mkdir},
|
||||
};
|
||||
stat::Mode,
|
||||
wait::{self, WaitStatus},
|
||||
}, unistd::{close, mkdir}};
|
||||
|
||||
use syscall_numbers::x86_64;
|
||||
use syscalls::syscall_args;
|
||||
use seccomp::seccomp::{InstructionData, Rule};
|
||||
|
||||
fn send_fd<F: AsRawFd>(sock: OwnedFd, fd: &F) -> nix::Result<()> {
|
||||
let fd = fd.as_raw_fd();
|
||||
@ -90,30 +89,16 @@ async fn main() -> Result<()> {
|
||||
)?;
|
||||
|
||||
let _ = prctl::set_no_new_privileges(true);
|
||||
|
||||
let mut bpf_prog = instruction::gen_validate(&Arch::X86);
|
||||
bpf_prog.append(&mut vec![
|
||||
// A: Check if syscall is getcwd
|
||||
Instruction::stmt(BPF_LD | BPF_W | BPF_ABS, 0),
|
||||
Instruction::jump(BPF_JMP | BPF_JEQ | BPF_K, 0, 1, libc::SYS_getcwd as u32), // If false, go to B
|
||||
Instruction::stmt(BPF_RET | BPF_K, SECCOMP_RET_KILL_PROCESS),
|
||||
// B: Check if syscall is write and it is writing to stderr(fd=2)
|
||||
Instruction::stmt(BPF_LD | BPF_W | BPF_ABS, 0),
|
||||
Instruction::jump(BPF_JMP | BPF_JEQ | BPF_K, 0, 3, libc::SYS_write as u32), // If false, go to C
|
||||
// Load the file descriptor
|
||||
Instruction::stmt(BPF_LD | BPF_W | BPF_ABS, seccomp_data_args_offset().into()),
|
||||
// Check if args is stderr
|
||||
Instruction::jump(BPF_JMP | BPF_JEQ | BPF_K, 0, 1, libc::STDERR_FILENO as u32), // If false, go to C
|
||||
Instruction::stmt(BPF_RET | BPF_K, SECCOMP_RET_KILL_PROCESS),
|
||||
// C: Check if syscall is mkdir and if so, return seccomp notify
|
||||
Instruction::stmt(BPF_LD | BPF_W | BPF_ABS, 0),
|
||||
Instruction::jump(BPF_JMP | BPF_JEQ | BPF_K, 0, 1, libc::SYS_mkdir as u32), // If false, go to D
|
||||
Instruction::stmt(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF),
|
||||
// D: Pass
|
||||
Instruction::stmt(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
|
||||
]);
|
||||
|
||||
let seccomp = Seccomp { filters: bpf_prog };
|
||||
let inst_data = InstructionData{
|
||||
arc: Arch::X86,
|
||||
def_action: SECCOMP_RET_KILL_PROCESS,
|
||||
rule_arr: vec![
|
||||
Rule::new("getcwd".parse()?, 0, syscall_args!(),false),
|
||||
Rule::new("write".parse()?,1, syscall_args!(libc::STDERR_FILENO as usize), false),
|
||||
Rule::new("mkdir".parse()?,0, syscall_args!(), true)
|
||||
]
|
||||
};
|
||||
let seccomp = Seccomp {filters: Vec::from(inst_data)};
|
||||
|
||||
tokio::spawn(async move {
|
||||
tokio::signal::ctrl_c()
|
||||
|
@ -7,14 +7,16 @@ use std::{
|
||||
},
|
||||
};
|
||||
|
||||
use std::str::FromStr;
|
||||
use nix::{
|
||||
errno::Errno,
|
||||
ioctl_readwrite, ioctl_write_ptr, libc,
|
||||
libc::{SECCOMP_FILTER_FLAG_NEW_LISTENER, SECCOMP_SET_MODE_FILTER},
|
||||
unistd,
|
||||
};
|
||||
|
||||
use crate::instruction::{Instruction, SECCOMP_IOC_MAGIC};
|
||||
use syscalls::{SyscallArgs};
|
||||
use crate::instruction::{*};
|
||||
use crate::instruction::{Arch, Instruction, SECCOMP_IOC_MAGIC};
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum SeccompError {
|
||||
@ -198,3 +200,77 @@ struct Filters {
|
||||
pub len: c_ushort,
|
||||
pub filter: *const Instruction,
|
||||
}
|
||||
|
||||
fn get_syscall_number(arc: &Arch, name: &str) -> Option<u64> {
|
||||
match arc {
|
||||
Arch::X86 => {
|
||||
match syscalls::x86_64::Sysno::from_str(name) {
|
||||
Ok(syscall) => Some(syscall as u64),
|
||||
Err(_) => None,
|
||||
}
|
||||
},
|
||||
Arch::AArch64 => {
|
||||
match syscalls::aarch64::Sysno::from_str(name) {
|
||||
Ok(syscall) => Some(syscall as u64),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InstructionData {
|
||||
pub arc: Arch,
|
||||
pub def_action: u32,
|
||||
pub rule_arr: Vec<Rule>
|
||||
}
|
||||
|
||||
impl From<InstructionData> for Vec<Instruction> {
|
||||
fn from(inst_data: InstructionData) -> Self {
|
||||
let mut bpf_prog = gen_validate(&inst_data.arc);
|
||||
|
||||
for rule in &inst_data.rule_arr {
|
||||
bpf_prog.append(&mut Rule::to_instruction(&inst_data.arc, inst_data.def_action, rule));
|
||||
}
|
||||
|
||||
bpf_prog.append(&mut vec![Instruction::stmt(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)]);
|
||||
bpf_prog
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Rule {
|
||||
pub syscall: String,
|
||||
pub arg_cnt: u8,
|
||||
pub args: SyscallArgs,
|
||||
pub is_notify: bool
|
||||
}
|
||||
|
||||
impl Rule {
|
||||
pub fn new(syscall: String, arg_cnt: u8, args: SyscallArgs, is_notify: bool) -> Self {
|
||||
Self {
|
||||
syscall,
|
||||
arg_cnt,
|
||||
args,
|
||||
is_notify,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_instruction(arch: &Arch, action: u32, rule: &Rule) -> Vec<Instruction> {
|
||||
let mut bpf_prog = gen_validate(arch);
|
||||
bpf_prog.append(&mut vec![Instruction::stmt(BPF_LD | BPF_W | BPF_ABS, 0)]);
|
||||
bpf_prog.append(&mut vec![Instruction::jump(BPF_JMP | BPF_JEQ | BPF_K, 0, 1,
|
||||
get_syscall_number(arch, &rule.syscall).unwrap() as c_uint)]);
|
||||
if rule.arg_cnt != 0 {
|
||||
bpf_prog.append(&mut vec![Instruction::stmt(BPF_LD | BPF_W | BPF_ABS, seccomp_data_args_offset().into())]);
|
||||
bpf_prog.append(&mut vec![Instruction::jump(BPF_JMP | BPF_JEQ | BPF_K, 0, 1, rule.args.arg0 as c_uint)]);
|
||||
}
|
||||
|
||||
if rule.is_notify {
|
||||
bpf_prog.append(&mut vec![Instruction::stmt(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF)]);
|
||||
} else {
|
||||
bpf_prog.append(&mut vec![Instruction::stmt(BPF_RET | BPF_K, action)]);
|
||||
}
|
||||
bpf_prog
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user