]>
Commit | Line | Data |
---|---|---|
c95be5f6 | 1 | use std::ffi::CString; |
f6a483ad | 2 | use std::os::raw::c_int; |
c95be5f6 | 3 | |
8150a439 | 4 | use anyhow::Error; |
c95be5f6 WB |
5 | use nix::errno::Errno; |
6 | ||
7 | use crate::lxcseccomp::ProxyMessageBuffer; | |
8 | use crate::tools::vec; | |
9 | ||
bd05b957 WB |
10 | const AUDIT_ARCH_X86_64: u32 = 0xc000_003e; |
11 | const AUDIT_ARCH_I386: u32 = 0x4000_0003; | |
f6a483ad | 12 | |
c95be5f6 WB |
13 | pub enum SyscallStatus { |
14 | Ok(i64), | |
15 | Err(i32), | |
16 | } | |
17 | ||
f4b5a72f WB |
18 | impl From<Errno> for SyscallStatus { |
19 | fn from(errno: Errno) -> Self { | |
20 | SyscallStatus::Err(errno as i32) | |
21 | } | |
22 | } | |
23 | ||
7470f14b | 24 | #[derive(Debug)] |
f6a483ad WB |
25 | pub enum Syscall { |
26 | Mknod, | |
27 | MknodAt, | |
d0e7b466 | 28 | Quotactl, |
f6a483ad WB |
29 | } |
30 | ||
31 | pub struct SyscallArch { | |
32 | arch: u32, | |
33 | mknod: i32, | |
34 | mknodat: i32, | |
d0e7b466 | 35 | quotactl: i32, |
f6a483ad WB |
36 | } |
37 | ||
bd05b957 | 38 | const SYSCALL_TABLE: &[SyscallArch] = &[ |
f6a483ad WB |
39 | SyscallArch { |
40 | arch: AUDIT_ARCH_X86_64, | |
41 | mknod: 133, | |
42 | mknodat: 259, | |
d0e7b466 | 43 | quotactl: 179, |
f6a483ad WB |
44 | }, |
45 | SyscallArch { | |
46 | arch: AUDIT_ARCH_I386, | |
47 | mknod: 14, | |
48 | mknodat: 297, | |
d0e7b466 | 49 | quotactl: 131, |
f6a483ad WB |
50 | }, |
51 | ]; | |
52 | ||
53 | pub fn translate_syscall(arch: u32, nr: c_int) -> Option<Syscall> { | |
54 | if nr == -1 { | |
55 | // so we don't hit a -1 in SYSCALL_TABLE by accident... | |
56 | return None; | |
57 | } | |
58 | ||
59 | for sc in SYSCALL_TABLE { | |
60 | if sc.arch == arch { | |
61 | if nr == sc.mknod { | |
62 | return Some(Syscall::Mknod); | |
63 | } else if nr == sc.mknodat { | |
64 | return Some(Syscall::MknodAt); | |
d0e7b466 WB |
65 | } else if nr == sc.quotactl { |
66 | return Some(Syscall::Quotactl); | |
f6a483ad WB |
67 | } |
68 | } | |
69 | } | |
70 | None | |
71 | } | |
72 | ||
c95be5f6 | 73 | pub fn get_c_string(msg: &ProxyMessageBuffer, offset: u64) -> Result<CString, Error> { |
937921aa | 74 | let mut data = unsafe { vec::uninitialized(4096) }; |
c95be5f6 WB |
75 | let got = msg.mem_fd().read_at(&mut data, offset)?; |
76 | ||
77 | let len = unsafe { libc::strnlen(data.as_ptr() as *const _, got) }; | |
78 | if len >= got { | |
b8cb8723 | 79 | Err(Errno::EINVAL.into()) |
c95be5f6 WB |
80 | } else { |
81 | unsafe { | |
82 | data.set_len(len); | |
83 | } | |
84 | // We used strlen, so the only Error in CString::new() cannot happen at this point: | |
85 | Ok(CString::new(data).unwrap()) | |
86 | } | |
87 | } | |
3bb4df0b WB |
88 | |
89 | #[macro_export] | |
90 | macro_rules! sc_libc_try { | |
91 | ($expr:expr) => {{ | |
92 | let res = $expr; | |
93 | if res == -1 { | |
512f780a WB |
94 | return Ok($crate::syscall::SyscallStatus::Err( |
95 | ::nix::errno::errno() as _ | |
96 | )); | |
3bb4df0b WB |
97 | } else { |
98 | res | |
99 | } | |
100 | }}; | |
101 | } |