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 Seccomp = 7,
14 SeccompFilterIoctl = 8,
15 SeccompFilterAppendOnly = 9,
16 SeccompSendFd = 10,
17 SeccompWaitFd = 11,
18 SetSid = 12,
19 SetPty = 13,
20 DupPty = 14,
21 SetPgrp = 15,
22 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
23 SetTSC = 16,
24}
25
26#[derive(Debug)]
32pub enum Error {
33 NixError(i32), UnknownError,
41 CapSet(i32),
43 Exec(i32),
45 ParentDeathSignal(i32),
47 BeforeUnfreeze(Box<dyn ::std::error::Error + Send + Sync + 'static>),
49 PreExec(i32),
51 ProcessStop(i32),
53 ResetSignal(i32),
55 Seccomp(i32),
57 SeccompFilterIoctl(i32),
59 SeccompFilterAppendOnly(i32),
61 SeccompSendFd(i32),
63 SeccompWaitFd(i32),
65 SetSid(i32),
67 SetPty(i32),
69 DupPty(i32),
71 SetPgrp(i32),
73 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
75 SetTSC(i32),
76}
77
78impl std::error::Error for Error {}
79
80impl Error {
81 pub fn raw_os_error(&self) -> Option<i32> {
83 use self::Error::*;
84 match *self {
85 UnknownError => None,
86 NixError(x) => Some(x),
87 CapSet(x) => Some(x),
88 Exec(x) => Some(x),
89 ParentDeathSignal(x) => Some(x),
90 BeforeUnfreeze(..) => None,
91 PreExec(x) => Some(x),
92 ProcessStop(x) => Some(x),
93 ResetSignal(x) => Some(x),
94 Seccomp(x) => Some(x),
95 SeccompFilterIoctl(x) => Some(x),
96 SeccompFilterAppendOnly(x) => Some(x),
97 SeccompSendFd(x) => Some(x),
98 SeccompWaitFd(x) => Some(x),
99 SetSid(x) => Some(x),
100 SetPty(x) => Some(x),
101 DupPty(x) => Some(x),
102 SetPgrp(x) => Some(x),
103 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
104 SetTSC(x) => Some(x),
105 }
106 }
107}
108
109impl Error {
110 fn title(&self) -> &'static str {
111 use self::Error::*;
112 match *self {
113 UnknownError => "unexpected value received via signal pipe",
114 NixError(_) => "some unknown nix error",
115 CapSet(_) => "error when setting capabilities",
116 Exec(_) => "error when executing",
117 ParentDeathSignal(_) => "error when death signal",
118 BeforeUnfreeze(_) => "error in before_unfreeze callback",
119 PreExec(_) => "error in pre_exec callback",
120 ProcessStop(_) => "error stopping process",
121 ResetSignal(_) => "error resetting signals",
122 Seccomp(_) => "error in seccomp filter load",
123 SeccompFilterIoctl(_) => "error filtering ioctl requests with seccomp",
124 SeccompFilterAppendOnly(_) => "error filtering pwritev2 requests with seccomp",
125 SeccompSendFd(_) => "error sending seccomp file descriptor",
126 SeccompWaitFd(_) => "error waiting for parent to receive the seccomp file descriptor",
127 SetSid(_) => "error calling setsid",
128 SetPty(_) => "error setting pty as controlling terminal",
129 DupPty(_) => "error duplicating pty onto stdio fds",
130 SetPgrp(_) => "error setting foreground process group",
131 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
132 SetTSC(_) => "error setting timestamp counter prctl",
133 }
134 }
135}
136
137impl fmt::Display for Error {
138 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
139 use crate::unshare::Error::*;
140 if let Some(code) = self.raw_os_error() {
141 let errno = Errno::from_raw(code);
142 if let nix::errno::Errno::UnknownErrno = errno {
143 write!(
145 fmt,
146 "{}: {}",
147 self.title(),
148 io::Error::from_raw_os_error(code)
149 )
150 } else {
151 write!(
153 fmt,
154 "{}: {} (os error {})",
155 self.title(),
156 errno.desc(),
157 code
158 )
159 }
160 } else {
161 match self {
162 BeforeUnfreeze(err) => {
163 write!(fmt, "{}: {}", self.title(), err)
164 }
165 _ => write!(fmt, "{}", self.title()),
166 }
167 }
168 }
169}