1use std::{fmt, io};
2
3use nix::errno::Errno;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum ErrorCode {
7 Exec = 1,
8 CapSet = 2,
9 ParentDeathSignal = 3,
10 PreExec = 4,
11 ProcessStop = 5,
12 ResetSignal = 6,
13 SetResourceLimits = 7,
14 LandlockFilterScopedSignals = 8,
15 Seccomp = 9,
16 SeccompFilterIoctl = 10,
17 SeccompFilterAppendOnly = 11,
18 SeccompFilterKptr = 12,
19 SeccompSendFd = 13,
20 SeccompWaitFd = 14,
21 SetDumpable = 15,
22 SetSid = 16,
23 SetPty = 17,
24 DupPty = 18,
25 SetPgrp = 19,
26 SetTSC = 20,
27}
28
29#[derive(Debug)]
35pub enum Error {
36 NixError(i32), UnknownError,
44 CapSet(i32),
46 Exec(i32),
48 ParentDeathSignal(i32),
50 BeforeUnfreeze(Box<dyn ::std::error::Error + Send + Sync + 'static>),
52 PreExec(i32),
54 ProcessStop(i32),
56 ResetSignal(i32),
58 SetResourceLimits(i32),
60 LandlockFilterScopedSignals(i32),
62 Seccomp(i32),
64 SeccompFilterIoctl(i32),
66 SeccompFilterAppendOnly(i32),
68 SeccompFilterKptr(i32),
70 SeccompSendFd(i32),
72 SeccompWaitFd(i32),
74 SetDumpable(i32),
76 SetSid(i32),
78 SetPty(i32),
80 DupPty(i32),
82 SetPgrp(i32),
84 SetTSC(i32),
86}
87
88impl std::error::Error for Error {}
89
90impl Error {
91 pub fn raw_os_error(&self) -> Option<i32> {
93 use self::Error::*;
94 match *self {
95 UnknownError => None,
96 NixError(x) => Some(x),
97 CapSet(x) => Some(x),
98 Exec(x) => Some(x),
99 ParentDeathSignal(x) => Some(x),
100 BeforeUnfreeze(..) => None,
101 PreExec(x) => Some(x),
102 ProcessStop(x) => Some(x),
103 ResetSignal(x) => Some(x),
104 SetResourceLimits(x) => Some(x),
105 LandlockFilterScopedSignals(x) => Some(x),
106 Seccomp(x) => Some(x),
107 SeccompFilterIoctl(x) => Some(x),
108 SeccompFilterAppendOnly(x) => Some(x),
109 SeccompFilterKptr(x) => Some(x),
110 SeccompSendFd(x) => Some(x),
111 SeccompWaitFd(x) => Some(x),
112 SetDumpable(x) => Some(x),
113 SetSid(x) => Some(x),
114 SetPty(x) => Some(x),
115 DupPty(x) => Some(x),
116 SetPgrp(x) => Some(x),
117 SetTSC(x) => Some(x),
118 }
119 }
120}
121
122impl Error {
123 fn title(&self) -> &'static str {
124 use self::Error::*;
125 match *self {
126 UnknownError => "unexpected value received via signal pipe",
127 NixError(_) => "some unknown nix error",
128 CapSet(_) => "error when setting capabilities",
129 Exec(_) => "error when executing",
130 ParentDeathSignal(_) => "error when death signal",
131 BeforeUnfreeze(_) => "error in before_unfreeze callback",
132 PreExec(_) => "error in pre_exec callback",
133 ProcessStop(_) => "error stopping process",
134 ResetSignal(_) => "error resetting signals",
135 SetResourceLimits(_) => "error setting resource limits",
136 LandlockFilterScopedSignals(_) => "error scoping signals with landlock",
137 Seccomp(_) => "error in seccomp filter load",
138 SeccompFilterIoctl(_) => "error filtering ioctl requests with seccomp",
139 SeccompFilterAppendOnly(_) => "error filtering pwritev2 requests with seccomp",
140 SeccompFilterKptr(_) => {
141 "error filtering kernel pointers in syscall arguments with seccomp"
142 }
143 SeccompSendFd(_) => "error sending seccomp file descriptor",
144 SeccompWaitFd(_) => "error waiting for parent to receive the seccomp file descriptor",
145 SetDumpable(_) => "error resetting process dumpable attribute",
146 SetSid(_) => "error calling setsid",
147 SetPty(_) => "error setting pty as controlling terminal",
148 DupPty(_) => "error duplicating pty onto stdio fds",
149 SetPgrp(_) => "error setting foreground process group",
150 SetTSC(_) => "error setting timestamp counter prctl",
151 }
152 }
153}
154
155impl fmt::Display for Error {
156 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
157 use crate::unshare::Error::*;
158 if let Some(code) = self.raw_os_error() {
159 let errno = Errno::from_raw(code);
160 if let nix::errno::Errno::UnknownErrno = errno {
161 write!(
163 fmt,
164 "{}: {}",
165 self.title(),
166 io::Error::from_raw_os_error(code)
167 )
168 } else {
169 write!(
171 fmt,
172 "{}: {} (os error {})",
173 self.title(),
174 errno.desc(),
175 code
176 )
177 }
178 } else {
179 match self {
180 BeforeUnfreeze(err) => {
181 write!(fmt, "{}: {}", self.title(), err)
182 }
183 _ => write!(fmt, "{}", self.title()),
184 }
185 }
186 }
187}