]>
Commit | Line | Data |
---|---|---|
9cffeac4 WB |
1 | //! Low level seccomp module |
2 | //! | |
3 | //! Mostly provides data structures. | |
4 | ||
9cffeac4 | 5 | use std::os::raw::c_int; |
571dbe03 | 6 | use std::{io, mem}; |
9cffeac4 WB |
7 | |
8 | /// Contains syscall data. | |
9 | #[repr(C)] | |
10 | pub struct SeccompData { | |
11 | pub nr: c_int, | |
12 | pub arch: u32, | |
13 | pub instruction_pointer: u64, | |
14 | pub args: [u64; 6], | |
15 | } | |
16 | ||
17 | /// Seccomp syscall notification data. | |
18 | /// | |
19 | /// Sent by the kernel when a seccomp filter returns `SECCOMP_RET_USER_NOTIF` for a syscall. | |
20 | #[repr(C)] | |
21 | pub struct SeccompNotif { | |
22 | pub id: u64, | |
23 | pub pid: u32, | |
24 | pub flags: u32, | |
25 | pub data: SeccompData, | |
26 | } | |
27 | ||
28 | /// Seccomp syscall response data. | |
29 | /// | |
30 | /// This is sent as a reply to `SeccompNotif`. | |
31 | #[repr(C)] | |
32 | pub struct SeccompNotifResp { | |
33 | pub id: u64, | |
34 | pub val: i64, | |
35 | pub error: i32, | |
36 | pub flags: u32, | |
37 | } | |
38 | ||
39 | /// Information about the actual sizes of `SeccompNotif`, and `SeccompNotifResp` and `SeccompData`. | |
40 | /// | |
41 | /// If the sizes mismatch it is likely that the kernel has an incompatible view of these data | |
42 | /// structures. | |
43 | #[derive(Clone)] | |
44 | #[repr(C)] | |
45 | pub struct SeccompNotifSizes { | |
46 | pub notif: u16, | |
47 | pub notif_resp: u16, | |
48 | pub data: u16, | |
49 | } | |
50 | ||
51 | impl SeccompNotifSizes { | |
52 | /// Query the kernel for its data structure sizes. | |
53 | pub fn get() -> io::Result<Self> { | |
54 | const SECCOMP_GET_NOTIF_SIZES: c_int = 3; | |
55 | ||
56 | let mut this = Self { | |
57 | notif: 0, | |
58 | notif_resp: 0, | |
59 | data: 0, | |
60 | }; | |
61 | ||
62 | let rc = unsafe { | |
63 | libc::syscall( | |
64 | libc::SYS_seccomp, | |
65 | SECCOMP_GET_NOTIF_SIZES, | |
66 | 0, | |
67 | &mut this as *mut _, | |
68 | ) | |
69 | }; | |
70 | if rc == 0 { | |
71 | Ok(this) | |
72 | } else { | |
73 | Err(io::Error::last_os_error()) | |
74 | } | |
75 | } | |
571dbe03 WB |
76 | |
77 | /// Check whether the kernel's data structure sizes match the one this | |
78 | /// crate was compiled with. | |
79 | pub fn check(&self) -> io::Result<()> { | |
80 | if usize::from(self.notif) != mem::size_of::<SeccompNotif>() | |
81 | || usize::from(self.notif_resp) != mem::size_of::<SeccompNotifResp>() | |
82 | || usize::from(self.data) != mem::size_of::<SeccompData>() | |
83 | { | |
84 | Err(io::Error::new( | |
85 | io::ErrorKind::Other, | |
86 | "seccomp data structure size mismatch", | |
87 | )) | |
88 | } else { | |
89 | Ok(()) | |
90 | } | |
91 | } | |
92 | ||
93 | /// Query the kernel for its data structure sizes and check whether they | |
94 | /// match this ones this crate was compiled with. | |
95 | pub fn get_checked() -> io::Result<Self> { | |
96 | let this = Self::get()?; | |
97 | this.check()?; | |
98 | Ok(this) | |
99 | } | |
9cffeac4 | 100 | } |