]> git.proxmox.com Git - pve-lxc-syscalld.git/blob - src/syscall.rs
update nix dependency
[pve-lxc-syscalld.git] / src / syscall.rs
1 use std::ffi::CString;
2 use std::os::raw::c_int;
3
4 use anyhow::Error;
5 use nix::errno::Errno;
6
7 use crate::lxcseccomp::ProxyMessageBuffer;
8 use crate::tools::vec;
9
10 const AUDIT_ARCH_X86_64: u32 = 0xc000_003e;
11 const AUDIT_ARCH_I386: u32 = 0x4000_0003;
12
13 pub enum SyscallStatus {
14 Ok(i64),
15 Err(i32),
16 }
17
18 impl From<Errno> for SyscallStatus {
19 fn from(errno: Errno) -> Self {
20 SyscallStatus::Err(errno as i32)
21 }
22 }
23
24 #[derive(Debug)]
25 pub enum Syscall {
26 Mknod,
27 MknodAt,
28 Quotactl,
29 }
30
31 pub struct SyscallArch {
32 arch: u32,
33 mknod: i32,
34 mknodat: i32,
35 quotactl: i32,
36 }
37
38 const SYSCALL_TABLE: &[SyscallArch] = &[
39 SyscallArch {
40 arch: AUDIT_ARCH_X86_64,
41 mknod: 133,
42 mknodat: 259,
43 quotactl: 179,
44 },
45 SyscallArch {
46 arch: AUDIT_ARCH_I386,
47 mknod: 14,
48 mknodat: 297,
49 quotactl: 131,
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);
65 } else if nr == sc.quotactl {
66 return Some(Syscall::Quotactl);
67 }
68 }
69 }
70 None
71 }
72
73 pub fn get_c_string(msg: &ProxyMessageBuffer, offset: u64) -> Result<CString, Error> {
74 let mut data = unsafe { vec::uninitialized(4096) };
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 {
79 Err(nix::Error::Sys(Errno::EINVAL).into())
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 }
88
89 #[macro_export]
90 macro_rules! sc_libc_try {
91 ($expr:expr) => {{
92 let res = $expr;
93 if res == -1 {
94 return Ok($crate::syscall::SyscallStatus::Err(
95 ::nix::errno::errno() as _
96 ));
97 } else {
98 res
99 }
100 }};
101 }