use super::TargetArch;
pub type BpfProgram = Vec<sock_filter>;
pub type BpfProgramRef<'a> = &'a [sock_filter];
pub const ARG_NUMBER_MAX: u8 = 5;
pub const CONDITION_MAX_LEN: u8 = 6;
pub const BPF_MAX_LEN: usize = 4096;
pub const SECCOMP_DATA_NR_OFFSET: u8 = 0;
const SECCOMP_DATA_ARCH_OFFSET: u8 = 4;
pub const SECCOMP_DATA_ARGS_OFFSET: u8 = 16;
pub const SECCOMP_DATA_ARG_SIZE: u8 = 8;
#[inline(always)]
pub(crate) fn bpf_jump(code: u16, k: u32, jt: u8, jf: u8) -> sock_filter {
sock_filter { code, jt, jf, k }
}
#[inline(always)]
pub(crate) fn bpf_stmt(code: u16, k: u32) -> sock_filter {
sock_filter {
code,
jt: 0,
jf: 0,
k,
}
}
#[inline(always)]
pub(crate) fn build_arch_validation_sequence(target_arch: TargetArch) -> Vec<sock_filter> {
let audit_arch_value = target_arch.get_audit_value();
vec![
bpf_stmt(BPF_LD | BPF_W | BPF_ABS, SECCOMP_DATA_ARCH_OFFSET as u32),
bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, audit_arch_value, 1, 0),
bpf_stmt(BPF_RET | BPF_K, SECCOMP_RET_KILL_PROCESS),
]
}
pub const BPF_LD: u16 = 0x00;
pub const BPF_ALU: u16 = 0x04;
pub const BPF_JMP: u16 = 0x05;
pub const BPF_RET: u16 = 0x06;
pub const BPF_W: u16 = 0x00;
pub const BPF_ABS: u16 = 0x20;
pub const BPF_AND: u16 = 0x50;
pub const BPF_JA: u16 = 0x00;
pub const BPF_JEQ: u16 = 0x10;
pub const BPF_JGT: u16 = 0x20;
pub const BPF_JGE: u16 = 0x30;
pub const BPF_K: u16 = 0x00;
pub const SECCOMP_RET_ALLOW: u32 = 0x7fff_0000;
pub const SECCOMP_RET_ERRNO: u32 = 0x0005_0000;
pub const SECCOMP_RET_KILL_THREAD: u32 = 0x0000_0000;
pub const SECCOMP_RET_KILL_PROCESS: u32 = 0x8000_0000;
pub const SECCOMP_RET_LOG: u32 = 0x7ffc_0000;
pub const SECCOMP_RET_TRACE: u32 = 0x7ff0_0000;
pub const SECCOMP_RET_TRAP: u32 = 0x0003_0000;
pub const SECCOMP_RET_MASK: u32 = 0x0000_ffff;
pub const AUDIT_ARCH_X86_64: u32 = 62 | 0x8000_0000 | 0x4000_0000;
pub const AUDIT_ARCH_AARCH64: u32 = 183 | 0x8000_0000 | 0x4000_0000;
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct sock_filter {
pub code: ::std::os::raw::c_ushort,
pub jt: ::std::os::raw::c_uchar,
pub jf: ::std::os::raw::c_uchar,
pub k: ::std::os::raw::c_uint,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bpf_functions() {
assert_eq!(
bpf_stmt(BPF_LD | BPF_W | BPF_ABS, 16),
sock_filter {
code: 0x20,
jt: 0,
jf: 0,
k: 16,
}
);
assert_eq!(
bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 10, 2, 5),
sock_filter {
code: 0x15,
jt: 2,
jf: 5,
k: 10,
}
);
}
}