]>
Commit | Line | Data |
---|---|---|
e420f6f9 WB |
1 | use std::sync::Arc; |
2 | ||
8150a439 | 3 | use anyhow::Error; |
f4b5a72f | 4 | use nix::errno::Errno; |
e420f6f9 | 5 | |
8dd26985 | 6 | use crate::io::seq_packet::SeqPacketSocket; |
e420f6f9 | 7 | use crate::lxcseccomp::ProxyMessageBuffer; |
f4b5a72f | 8 | use crate::syscall::{self, Syscall, SyscallStatus}; |
e420f6f9 WB |
9 | |
10 | pub struct Client { | |
9aa2a15a | 11 | socket: SeqPacketSocket, |
e420f6f9 WB |
12 | } |
13 | ||
14 | impl Client { | |
9aa2a15a | 15 | pub fn new(socket: SeqPacketSocket) -> Arc<Self> { |
e420f6f9 WB |
16 | Arc::new(Self { socket }) |
17 | } | |
18 | ||
0e2d0fa2 | 19 | /// Wrap futures returning a `Result` so if they fail we `shutdown()` the socket to drop the |
e420f6f9 WB |
20 | /// client. |
21 | async fn wrap_error<F>(self: Arc<Self>, fut: F) | |
22 | where | |
23 | F: std::future::Future<Output = Result<(), Error>>, | |
24 | { | |
25 | if let Err(err) = fut.await { | |
26 | eprintln!("client error, dropping connection: {}", err); | |
27 | if let Err(err) = self.socket.shutdown(nix::sys::socket::Shutdown::Both) { | |
28 | eprintln!(" (error shutting down client socket: {})", err); | |
29 | } | |
30 | } | |
31 | } | |
32 | ||
33 | pub async fn main(self: Arc<Self>) { | |
34 | self.clone().wrap_error(self.main_do()).await | |
35 | } | |
36 | ||
37 | async fn main_do(self: Arc<Self>) -> Result<(), Error> { | |
7b37bdac | 38 | let mut msg = ProxyMessageBuffer::new(64); |
e420f6f9 | 39 | loop { |
41214ae2 | 40 | if !msg.recv(&self.socket).await? { |
41214ae2 WB |
41 | break Ok(()); |
42 | } | |
e420f6f9 | 43 | |
7b37bdac | 44 | self.handle_syscall(&mut msg).await?; |
e420f6f9 WB |
45 | } |
46 | } | |
47 | ||
7b37bdac | 48 | async fn handle_syscall(&self, msg: &mut ProxyMessageBuffer) -> Result<(), Error> { |
a03af34b | 49 | let result = match Self::handle_syscall_do(msg).await { |
c95be5f6 WB |
50 | Ok(r) => r, |
51 | Err(err) => { | |
7b37bdac | 52 | // handle the various kinds of errors we may get: |
b8cb8723 | 53 | if let Some(errno) = err.downcast_ref::<nix::Error>() { |
c95be5f6 WB |
54 | SyscallStatus::Err(*errno as _) |
55 | } else if let Some(ioerr) = err.downcast_ref::<std::io::Error>() { | |
56 | if let Some(errno) = ioerr.raw_os_error() { | |
57 | SyscallStatus::Err(errno) | |
58 | } else { | |
59 | return Err(err); | |
60 | } | |
61 | } else { | |
62 | return Err(err); | |
63 | } | |
64 | } | |
65 | }; | |
e420f6f9 WB |
66 | |
67 | let resp = msg.response_mut(); | |
68 | match result { | |
69 | SyscallStatus::Ok(val) => { | |
70 | resp.val = val; | |
71 | resp.error = 0; | |
72 | } | |
73 | SyscallStatus::Err(err) => { | |
74 | resp.val = -1; | |
75 | resp.error = -err; | |
76 | } | |
77 | } | |
78 | ||
0e2d0fa2 | 79 | msg.respond(&self.socket).await.map_err(Error::from) |
e420f6f9 WB |
80 | } |
81 | ||
7b37bdac | 82 | async fn handle_syscall_do(msg: &ProxyMessageBuffer) -> Result<SyscallStatus, Error> { |
f4b5a72f WB |
83 | let (arch, sysnr) = (msg.request().data.arch, msg.request().data.nr); |
84 | ||
85 | let syscall_nr = match syscall::translate_syscall(arch, sysnr) { | |
86 | Some(nr) => nr, | |
87 | None => return Ok(Errno::ENOSYS.into()), | |
88 | }; | |
89 | ||
90 | match syscall_nr { | |
91 | Syscall::Mknod => crate::sys_mknod::mknod(msg).await, | |
92 | Syscall::MknodAt => crate::sys_mknod::mknodat(msg).await, | |
d0e7b466 | 93 | Syscall::Quotactl => crate::sys_quotactl::quotactl(msg).await, |
e420f6f9 WB |
94 | } |
95 | } | |
96 | } |