tr1pd/sandbox/
seccomp.rs

1use seccomp_sys::*;
2
3use sandbox::syscalls::Syscall;
4
5mod errors {
6    error_chain! {
7        errors {
8            FFI
9        }
10    }
11}
12pub use self::errors::{Result, Error, ErrorKind};
13
14
15pub struct Context {
16    ctx: *mut scmp_filter_ctx,
17}
18
19impl Context {
20    fn init() -> Result<Context> {
21        let ctx = unsafe { seccomp_init(SCMP_ACT_KILL) };
22
23        if ctx.is_null() {
24            return Err(ErrorKind::FFI.into());
25        }
26
27        Ok(Context {
28            ctx,
29        })
30    }
31
32    fn allow_syscall(&mut self, syscall: Syscall) -> Result<()> {
33        debug!("seccomp: allowing syscall={:?}", syscall);
34        let ret = unsafe { seccomp_rule_add(self.ctx, SCMP_ACT_ALLOW, syscall.as_i32(), 0) };
35
36        if ret != 0 {
37            Err(ErrorKind::FFI.into())
38        } else {
39            Ok(())
40        }
41    }
42
43    fn load(&self) -> Result<()> {
44        let ret = unsafe { seccomp_load(self.ctx) };
45
46        if ret != 0 {
47            Err(ErrorKind::FFI.into())
48        } else {
49            Ok(())
50        }
51    }
52}
53
54impl Drop for Context {
55    fn drop(&mut self) {
56        unsafe {
57            seccomp_release(self.ctx)
58        };
59    }
60}
61
62pub fn activate_stage1() -> Result<()> {
63    let mut ctx = Context::init()?;
64
65    ctx.allow_syscall(Syscall::read)?;
66    ctx.allow_syscall(Syscall::write)?;
67    ctx.allow_syscall(Syscall::mmap)?;
68    ctx.allow_syscall(Syscall::mprotect)?;
69    ctx.allow_syscall(Syscall::getrandom)?;
70    ctx.allow_syscall(Syscall::futex)?;
71    ctx.allow_syscall(Syscall::openat)?;
72    #[cfg(not(target_arch = "aarch64"))]
73    ctx.allow_syscall(Syscall::open)?;
74    ctx.allow_syscall(Syscall::ioctl)?;
75    ctx.allow_syscall(Syscall::close)?;
76    #[cfg(not(target_arch = "aarch64"))]
77    ctx.allow_syscall(Syscall::readlink)?;
78    ctx.allow_syscall(Syscall::readlinkat)?;
79    #[cfg(not(target_arch = "aarch64"))]
80    ctx.allow_syscall(Syscall::mkdir)?;
81    ctx.allow_syscall(Syscall::mkdirat)?;
82    #[cfg(not(target_arch = "aarch64"))]
83    ctx.allow_syscall(Syscall::lstat)?;
84    ctx.allow_syscall(Syscall::fstat)?;
85    ctx.allow_syscall(Syscall::newfstatat)?;
86    #[cfg(not(target_arch = "aarch64"))]
87    ctx.allow_syscall(Syscall::unlink)?;
88    ctx.allow_syscall(Syscall::unlinkat)?;
89    #[cfg(not(target_arch = "aarch64"))]
90    ctx.allow_syscall(Syscall::symlink)?;
91    ctx.allow_syscall(Syscall::symlinkat)?;
92    ctx.allow_syscall(Syscall::getdents)?;
93    ctx.allow_syscall(Syscall::getpid)?;
94    ctx.allow_syscall(Syscall::getuid)?;
95    ctx.allow_syscall(Syscall::readv)?;
96    ctx.allow_syscall(Syscall::lseek)?;
97    ctx.allow_syscall(Syscall::eventfd2)?;
98    ctx.allow_syscall(Syscall::sched_getparam)?;
99    ctx.allow_syscall(Syscall::sched_getscheduler)?;
100    ctx.allow_syscall(Syscall::sched_setscheduler)?;
101    ctx.allow_syscall(Syscall::poll)?;
102    ctx.allow_syscall(Syscall::getsockname)?;
103    ctx.allow_syscall(Syscall::getsockopt)?;
104    ctx.allow_syscall(Syscall::getpeername)?;
105    ctx.allow_syscall(Syscall::sendto)?;
106    ctx.allow_syscall(Syscall::clone)?;
107    ctx.allow_syscall(Syscall::set_robust_list)?;
108    ctx.allow_syscall(Syscall::sigaltstack)?;
109    ctx.allow_syscall(Syscall::munmap)?;
110    ctx.allow_syscall(Syscall::sched_getaffinity)?;
111    ctx.allow_syscall(Syscall::pipe2)?;
112    ctx.allow_syscall(Syscall::epoll_create1)?;
113    ctx.allow_syscall(Syscall::epoll_ctl)?;
114    ctx.allow_syscall(Syscall::epoll_pwait)?;
115    #[cfg(not(target_arch = "aarch64"))]
116    ctx.allow_syscall(Syscall::epoll_wait)?;
117    #[cfg(not(target_arch = "aarch64"))]
118    ctx.allow_syscall(Syscall::stat)?;
119    ctx.allow_syscall(Syscall::socket)?;
120    ctx.allow_syscall(Syscall::bind)?;
121    ctx.allow_syscall(Syscall::listen)?;
122    #[cfg(not(target_arch = "aarch64"))]
123    ctx.allow_syscall(Syscall::chmod)?;
124    ctx.allow_syscall(Syscall::fchmodat)?;
125    ctx.allow_syscall(Syscall::accept4)?;
126    ctx.allow_syscall(Syscall::recvfrom)?;
127    ctx.allow_syscall(Syscall::shutdown)?;
128    ctx.allow_syscall(Syscall::connect)?;
129    ctx.allow_syscall(Syscall::nanosleep)?;
130    ctx.allow_syscall(Syscall::sched_yield)?;
131    ctx.allow_syscall(Syscall::madvise)?;
132    ctx.allow_syscall(Syscall::exit_group)?;
133    ctx.allow_syscall(Syscall::exit)?;
134    ctx.allow_syscall(Syscall::wait4)?;
135    ctx.allow_syscall(Syscall::fcntl)?;
136    ctx.allow_syscall(Syscall::brk)?;
137    ctx.allow_syscall(Syscall::rt_sigprocmask)?;
138    ctx.allow_syscall(Syscall::clock_gettime)?;
139    ctx.allow_syscall(Syscall::gettimeofday)?;
140    ctx.allow_syscall(Syscall::prctl)?; // needed for stage2
141    ctx.allow_syscall(Syscall::seccomp)?; // needed for stage2
142    ctx.allow_syscall(Syscall::capget)?; // needed for stage2
143    ctx.allow_syscall(Syscall::capset)?; // needed for stage2
144    ctx.allow_syscall(Syscall::chroot)?; // needed for stage2
145    ctx.allow_syscall(Syscall::chdir)?; // needed for stage2
146
147    ctx.load()?;
148
149    info!("stage 1/1 is active");
150
151    Ok(())
152}
153
154pub fn activate_tr1pd_stage2() -> Result<()> {
155    let mut ctx = Context::init()?;
156
157    ctx.allow_syscall(Syscall::read)?;
158    ctx.allow_syscall(Syscall::write)?;
159    ctx.allow_syscall(Syscall::mmap)?;
160    ctx.allow_syscall(Syscall::mprotect)?;
161    ctx.allow_syscall(Syscall::getrandom)?;
162    ctx.allow_syscall(Syscall::futex)?;
163    ctx.allow_syscall(Syscall::openat)?;
164    #[cfg(not(target_arch = "aarch64"))]
165    ctx.allow_syscall(Syscall::open)?;
166    ctx.allow_syscall(Syscall::ioctl)?;
167    ctx.allow_syscall(Syscall::close)?;
168    #[cfg(not(target_arch = "aarch64"))]
169    ctx.allow_syscall(Syscall::readlink)?;
170    ctx.allow_syscall(Syscall::readlinkat)?;
171    #[cfg(not(target_arch = "aarch64"))]
172    ctx.allow_syscall(Syscall::mkdir)?;
173    ctx.allow_syscall(Syscall::mkdirat)?;
174    #[cfg(not(target_arch = "aarch64"))]
175    ctx.allow_syscall(Syscall::lstat)?;
176    ctx.allow_syscall(Syscall::newfstatat)?;
177    #[cfg(not(target_arch = "aarch64"))]
178    ctx.allow_syscall(Syscall::unlink)?;
179    ctx.allow_syscall(Syscall::unlinkat)?;
180    #[cfg(not(target_arch = "aarch64"))]
181    ctx.allow_syscall(Syscall::symlink)?;
182    ctx.allow_syscall(Syscall::symlinkat)?;
183    ctx.allow_syscall(Syscall::sched_getparam)?;
184    ctx.allow_syscall(Syscall::sched_getscheduler)?;
185    ctx.allow_syscall(Syscall::sched_setscheduler)?;
186    ctx.allow_syscall(Syscall::getpeername)?;
187    ctx.allow_syscall(Syscall::eventfd2)?;
188    ctx.allow_syscall(Syscall::getpid)?;
189    ctx.allow_syscall(Syscall::poll)?;
190    ctx.allow_syscall(Syscall::sendto)?;
191    ctx.allow_syscall(Syscall::clone)?;
192    ctx.allow_syscall(Syscall::set_robust_list)?;
193    ctx.allow_syscall(Syscall::sigaltstack)?;
194    ctx.allow_syscall(Syscall::munmap)?;
195    ctx.allow_syscall(Syscall::sched_getaffinity)?;
196    ctx.allow_syscall(Syscall::pipe2)?;
197    ctx.allow_syscall(Syscall::epoll_create1)?;
198    ctx.allow_syscall(Syscall::epoll_ctl)?;
199    ctx.allow_syscall(Syscall::epoll_pwait)?;
200    #[cfg(not(target_arch = "aarch64"))]
201    ctx.allow_syscall(Syscall::epoll_wait)?;
202    #[cfg(not(target_arch = "aarch64"))]
203    ctx.allow_syscall(Syscall::stat)?;
204    ctx.allow_syscall(Syscall::socket)?;
205    ctx.allow_syscall(Syscall::bind)?;
206    ctx.allow_syscall(Syscall::listen)?;
207    #[cfg(not(target_arch = "aarch64"))]
208    ctx.allow_syscall(Syscall::chmod)?;
209    ctx.allow_syscall(Syscall::fchmodat)?;
210    ctx.allow_syscall(Syscall::accept4)?;
211    ctx.allow_syscall(Syscall::recvfrom)?;
212    ctx.allow_syscall(Syscall::shutdown)?;
213    ctx.allow_syscall(Syscall::connect)?;
214    ctx.allow_syscall(Syscall::nanosleep)?;
215    ctx.allow_syscall(Syscall::sched_yield)?;
216    ctx.allow_syscall(Syscall::madvise)?;
217    ctx.allow_syscall(Syscall::exit_group)?;
218    ctx.allow_syscall(Syscall::exit)?;
219    ctx.allow_syscall(Syscall::wait4)?;
220    ctx.allow_syscall(Syscall::fcntl)?;
221    ctx.allow_syscall(Syscall::brk)?;
222    ctx.allow_syscall(Syscall::clock_gettime)?;
223    // ctx.allow_syscall(Syscall::prctl)?; // needed for stage2
224    // ctx.allow_syscall(Syscall::seccomp)?; // needed for stage2
225    // ctx.allow_syscall(Syscall::capget)?; // needed for stage2 TODO
226    // ctx.allow_syscall(Syscall::capset)?; // needed for stage2 TODO
227    // ctx.allow_syscall(Syscall::chroot)?; // needed for stage2 TODO
228    // ctx.allow_syscall(Syscall::chdir)?; // needed for stage2 TODO
229
230    ctx.load()?;
231
232    info!("stage 2/2 is active");
233
234    Ok(())
235}