extrasafe_multiarch/
macros.rs

1//! Macros for extrasafe
2
3// Heavily inspired by the libseccomp-rs macros, but written from scratch.
4
5/// A macro to easily create [`crate::SeccompArgumentFilter`]s. Note that because internally it uses a
6/// helper macro, to use this macro you should just `use extrasafe::*` if possible.
7/// Usage:
8/// ```
9/// use extrasafe::*;
10/// // usage: `seccomp_arg_filter!(<argN> <operator> <value>);`
11/// // or `seccomp_arg_filter!(<argN> & <mask> == <value>);`
12/// // arg0 through arg5 are supported
13/// // operations <=, <, >=, >, ==, != are supported
14/// let argfilter = seccomp_arg_filter!(arg0 < 5);
15/// // Masked equality is also supported to check specific bits are set.
16/// // The following checks the second bit of the syscall's 4th argument is set.
17/// let argfilter = seccomp_arg_filter!(arg4 & 0b10 == 0b10);
18/// ```
19#[macro_export]
20macro_rules! seccomp_arg_filter {
21    ($argno:ident <= $value:expr) => {
22        $crate::SeccompArgumentFilter::new(match_argno!($argno), $crate::SeccompilerComparator::Le, $value)
23    };
24    ($argno:ident < $value:expr) => {
25        $crate::SeccompArgumentFilter::new(match_argno!($argno), $crate::SeccompilerComparator::Lt, $value)
26    };
27    ($argno:ident >= $value:expr) => {
28        $crate::SeccompArgumentFilter::new(match_argno!($argno), $crate::SeccompilerComparator::Ge, $value)
29    };
30    ($argno:ident > $value:expr) => {
31        $crate::SeccompArgumentFilter::new(match_argno!($argno), $crate::SeccompilerComparator::Gt, $value)
32    };
33    ($argno:ident == $value:expr) => {
34        $crate::SeccompArgumentFilter::new(match_argno!($argno), $crate::SeccompilerComparator::Eq, $value)
35    };
36    ($argno:ident != $value:expr) => {
37        $crate::SeccompArgumentFilter::new(match_argno!($argno), $crate::SeccompilerComparator::Ne, $value)
38    };
39    ($argno:ident & $mask:tt == $value:expr) => {
40        $crate::SeccompArgumentFilter::new(match_argno!($argno), $crate::SeccompilerComparator::MaskedEq($mask), $value)
41    };
42    ($_other:expr) => {compile_error!("usage: `arg[0-5] {<=, <, >=, >, ==, !=} <value>` or `arg[0-5] & <mask> == <value>`")};
43}
44
45#[doc(hidden)]
46#[macro_export]
47/// Internal macro for `seccomp_arg_filter!`
48macro_rules! match_argno {
49    (arg0) => {0};
50    (arg1) => {1};
51    (arg2) => {2};
52    (arg3) => {3};
53    (arg4) => {4};
54    (arg5) => {5};
55    ($_other:expr) => {compile_error!("Seccomp argument filters must start with argX where X is 0-5")};
56}
57
58/// These tests just test that the macro expands correctly, not that the comparators do what they
59/// say they do in seccompiler.
60#[cfg(test)]
61mod tests {
62    use crate::*;
63
64    #[test]
65    fn test_comparison_le() {
66        let cmp = seccomp_arg_filter!(arg0 <= 10);
67        assert_eq!(
68            cmp,
69            SeccompArgumentFilter::new(0, SeccompilerComparator::Le, 10)
70        );
71    }
72
73    #[test]
74    fn test_comparison_lt() {
75        let cmp = seccomp_arg_filter!(arg1 < 10);
76        assert_eq!(
77            cmp,
78            SeccompArgumentFilter::new(1, SeccompilerComparator::Lt, 10)
79        );
80    }
81
82    #[test]
83    fn test_comparison_ge() {
84        let cmp = seccomp_arg_filter!(arg2 >= 5);
85        assert_eq!(
86            cmp,
87            SeccompArgumentFilter::new(2, SeccompilerComparator::Ge, 5)
88        );
89    }
90
91    #[test]
92    fn test_comparison_gt() {
93        let cmp = seccomp_arg_filter!(arg3 > 200);
94        assert_eq!(
95            cmp,
96            SeccompArgumentFilter::new(3, SeccompilerComparator::Gt, 200)
97        );
98    }
99
100    #[test]
101    fn test_comparison_eq() {
102        let cmp = seccomp_arg_filter!(arg4 == 0);
103        assert_eq!(
104            cmp,
105            SeccompArgumentFilter::new(4, SeccompilerComparator::Eq, 0)
106        );
107    }
108
109    #[test]
110    fn test_comparison_ne() {
111        let cmp = seccomp_arg_filter!(arg5 != 80);
112        assert_eq!(
113            cmp,
114            SeccompArgumentFilter::new(5, SeccompilerComparator::Ne, 80)
115        );
116    }
117
118    #[test]
119    fn test_comparison_mask() {
120        let cmp = seccomp_arg_filter!(arg2 & 0x1337 == 0x37);
121        assert_eq!(
122            cmp,
123            SeccompArgumentFilter::new(2, SeccompilerComparator::MaskedEq(0x1337), 0x37)
124        );
125    }
126}