1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
use core::fmt; use core::convert::TryInto; use crate::abi::*; use crate::bpf::*; use crate::seccomp; #[derive(Clone, Eq, PartialEq)] pub struct ProgramBuffer { len: u16, array: [SockFilter; BPF_MAXINSNS], } impl ProgramBuffer { pub fn new() -> Self { const EMPTY: SockFilter = SockFilter { code: 0, k: 0, jt: 0, jf: 0 }; ProgramBuffer { len: 0, array: [ EMPTY; BPF_MAXINSNS ] } } pub fn instructions(&self) -> &[SockFilter] { &self.array[.. self.len as usize] } pub fn activate(&self) { let prog = SockFilterProg::new(self.instructions()); if let Err(result) = seccomp::activate(&prog) { panic!("seccomp setup error ({})", result); } } pub fn block(&mut self, block: &[SockFilter]) { for instruction in block { self.inst(*instruction); } } pub fn inst(&mut self, instruction: SockFilter) { if self.len as usize == BPF_MAXINSNS { panic!("filter program exceeding size limit"); } self.array[self.len as usize] = instruction; self.len += 1; } pub fn if_eq(&mut self, k: usize, block: &[SockFilter]) { let to_end_of_block: u8 = block.len().try_into().unwrap(); self.inst(jump( BPF_JMP+BPF_JEQ+BPF_K, k as u32, 0, to_end_of_block )); self.block(block); } pub fn if_any_eq(&mut self, k_list: &[usize], block: &[SockFilter]) { let mut to_block: u8 = k_list.len().try_into().unwrap(); for k in k_list { self.inst(jump( BPF_JMP+BPF_JEQ+BPF_K, *k as u32, to_block, 0 )); to_block -= 1; } self.inst(jump_always(block.len().try_into().unwrap())); self.block(block); } } impl fmt::Debug for ProgramBuffer { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { for index in 0 .. self.len { write!(f, "{:04} {:?}\n", index, self.array[index as usize])?; } Ok(()) } }