netlink_packet_audit/rules/
syscalls.rs1use netlink_packet_core::{parse_u32, DecodeError};
4
5use crate::constants::*;
6
7#[derive(Debug, PartialEq, Eq, Clone)]
8#[non_exhaustive]
9pub struct RuleSyscalls(pub(crate) Vec<u32>);
10
11const BITMASK_BYTE_LEN: usize = AUDIT_BITMASK_SIZE * 4;
12const BITMASK_BIT_LEN: u32 = AUDIT_BITMASK_SIZE as u32 * 32;
13
14impl RuleSyscalls {
16 pub fn from_slice(slice: &[u8]) -> Result<Self, DecodeError> {
18 if slice.len() != BITMASK_BYTE_LEN {
19 return Err(DecodeError::from(format!(
20 "invalid bitmask size: expected {} bytes got {}",
21 BITMASK_BYTE_LEN,
22 slice.len()
23 )));
24 }
25 let mut mask = RuleSyscalls::new_zeroed();
26 let mut word = 0;
27 while word < AUDIT_BITMASK_SIZE {
28 mask.0[word] = parse_u32(&slice[word * 4..word * 4 + 4]).unwrap();
29 word += 1;
30 }
31 Ok(mask)
32 }
33
34 pub fn new_zeroed() -> Self {
35 RuleSyscalls(vec![0; AUDIT_BITMASK_SIZE])
36 }
37
38 pub fn new_maxed() -> Self {
39 RuleSyscalls(vec![0xffff_ffff; AUDIT_BITMASK_SIZE])
40 }
41
42 pub fn unset_all(&mut self) -> &mut Self {
44 self.0 = vec![0; AUDIT_BITMASK_SIZE];
45 self
46 }
47
48 pub fn is_all(&self) -> bool {
50 for i in 0..AUDIT_BITMASK_SIZE {
51 if self.0[i] != 0xffff_ffff {
52 return false;
53 }
54 }
55 true
56 }
57
58 pub fn set_all(&mut self) -> &mut Self {
60 self.0 = vec![0xffff_ffff; AUDIT_BITMASK_SIZE];
61 self
62 }
63
64 pub fn unset(&mut self, syscall: u32) -> &mut Self {
66 let (word, mask) = Self::syscall_coordinates(syscall);
67 self.0[word] &= !mask;
68 self
69 }
70
71 pub fn set(&mut self, syscall: u32) -> &mut Self {
73 let (word, mask) = Self::syscall_coordinates(syscall);
74 self.0[word] |= mask;
75 self
76 }
77
78 pub fn has(&self, syscall: u32) -> bool {
80 let (word, mask) = Self::syscall_coordinates(syscall);
81 self.0[word] & mask == mask
82 }
83
84 fn syscall_coordinates(syscall: u32) -> (usize, u32) {
85 let word_index = syscall / 32;
86 let mask = 0x0000_0001 << (syscall - word_index * 32);
87 (word_index as usize, mask)
88 }
89}
90
91#[non_exhaustive]
95pub struct RuleSyscallsIter<T> {
96 index: u32,
97 syscalls: T,
98}
99
100impl IntoIterator for RuleSyscalls {
101 type Item = u32;
102 type IntoIter = RuleSyscallsIter<RuleSyscalls>;
103
104 fn into_iter(self) -> Self::IntoIter {
105 RuleSyscallsIter {
106 index: 0,
107 syscalls: self,
108 }
109 }
110}
111
112impl Iterator for RuleSyscallsIter<RuleSyscalls> {
113 type Item = u32;
114 fn next(&mut self) -> Option<Self::Item> {
115 while self.index < BITMASK_BIT_LEN {
116 let index = self.index;
117 self.index += 1;
118 if self.syscalls.has(index) {
119 return Some(index);
120 }
121 }
122 None
123 }
124}
125
126impl<'a> IntoIterator for &'a RuleSyscalls {
127 type Item = u32;
128 type IntoIter = RuleSyscallsIter<&'a RuleSyscalls>;
129
130 fn into_iter(self) -> Self::IntoIter {
131 RuleSyscallsIter {
132 index: 0,
133 syscalls: self,
134 }
135 }
136}
137
138impl Iterator for RuleSyscallsIter<&RuleSyscalls> {
139 type Item = u32;
140 fn next(&mut self) -> Option<Self::Item> {
141 while self.index < BITMASK_BIT_LEN {
142 let index = self.index;
143 self.index += 1;
144 if self.syscalls.has(index) {
145 return Some(index);
146 }
147 }
148 None
149 }
150}
151
152impl<'a> IntoIterator for &'a mut RuleSyscalls {
153 type Item = u32;
154 type IntoIter = RuleSyscallsIter<&'a mut RuleSyscalls>;
155
156 fn into_iter(self) -> Self::IntoIter {
157 RuleSyscallsIter {
158 index: 0,
159 syscalls: self,
160 }
161 }
162}
163
164impl Iterator for RuleSyscallsIter<&mut RuleSyscalls> {
165 type Item = u32;
166 fn next(&mut self) -> Option<Self::Item> {
167 while self.index < BITMASK_BIT_LEN {
168 let index = self.index;
169 self.index += 1;
170 if self.syscalls.has(index) {
171 return Some(index);
172 }
173 }
174 None
175 }
176}
177
178#[cfg(test)]
179mod test {
180 use super::*;
181 #[test]
182 fn test_from_slice() {
183 let s: Vec<u8> = vec![0xff; BITMASK_BYTE_LEN];
184 let syscalls = RuleSyscalls::from_slice(&s[..]).unwrap();
185 assert_eq!(syscalls.0, vec![0xffff_ffff; AUDIT_BITMASK_SIZE]);
186
187 let s: Vec<u8> = vec![0; BITMASK_BYTE_LEN];
188 let syscalls = RuleSyscalls::from_slice(&s[..]).unwrap();
189 assert_eq!(syscalls.0, vec![0; AUDIT_BITMASK_SIZE]);
190 }
191
192 #[test]
193 fn test_iter() {
194 let s: Vec<u8> = vec![0xff; BITMASK_BYTE_LEN];
195 let syscalls = RuleSyscalls::from_slice(&s[..]).unwrap();
196 let mut iter = syscalls.into_iter();
197 for i in 0..BITMASK_BIT_LEN {
198 assert_eq!(i, iter.next().unwrap());
199 }
200 assert!(iter.next().is_none());
201
202 let s: Vec<u8> = vec![0; BITMASK_BYTE_LEN];
203 let syscalls = RuleSyscalls::from_slice(&s[..]).unwrap();
204 let mut iter = syscalls.into_iter();
205 assert!(iter.next().is_none());
206 }
207
208 #[test]
209 fn test_set_unset() {
210 let mut syscalls = RuleSyscalls::new_zeroed();
211 for i in 0..BITMASK_BIT_LEN {
212 syscalls.set(i);
213 }
214 assert_eq!(syscalls.0, vec![0xffff_ffff; AUDIT_BITMASK_SIZE]);
215 for i in 0..BITMASK_BIT_LEN {
216 syscalls.unset(BITMASK_BIT_LEN - 1 - i);
217 }
218 assert_eq!(syscalls.0, vec![0; AUDIT_BITMASK_SIZE]);
219 }
220}