@@ -3,60 +3,121 @@ use std::collections::HashMap;
33use std:: ffi:: { c_long, c_ulonglong} ;
44use std:: fmt:: { Debug , Formatter } ;
55
6+ use crate :: CatBoxError ;
67use nix:: libc:: {
7- user_regs_struct, SYS_accept , SYS_accept4 , SYS_bind , SYS_clone , SYS_connect , SYS_execve ,
8- SYS_execveat , SYS_fork , SYS_getpeername , SYS_getsockname , SYS_getsockopt , SYS_listen ,
8+ user_regs_struct, SYS_accept , SYS_accept4 , SYS_bind , SYS_clone , SYS_clone3 , SYS_connect ,
9+ SYS_execve , SYS_execveat , SYS_fork , SYS_getpeername , SYS_getsockname , SYS_getsockopt , SYS_listen ,
910 SYS_setsockopt , SYS_shutdown , SYS_socket , SYS_socketpair , SYS_vfork ,
1011} ;
1112use nix:: unistd:: Pid ;
1213
1314type SyscallId = c_ulonglong ;
1415
15- /// 禁止系统调用
16- /// 允许有限次系统调用
16+ /// Syscall permission
1717#[ derive( Clone ) ]
1818pub enum SyscallPerm {
19+ /// Forbid all
1920 Forbid ,
21+ /// Use a filter function to check whether it is ok
2022 FilterFn ( fn ( pid : & Pid , regs : & user_regs_struct ) -> bool ) ,
23+ /// Allow a few times
2124 Allow ( i32 ) ,
2225}
2326
24- /// 系统调用过滤器
25- /// 黑名单过滤,若不在映射内,则允许;否则,禁止或者允许有限次
27+ /// Syscall filter
28+ /// It is a black list filter, and it supports forbid syscall or allow a few times
2629#[ derive( Debug , Clone ) ]
2730pub struct SyscallFilter {
2831 map : HashMap < SyscallId , SyscallPerm > ,
2932}
3033
34+ /// Syscall filter preset category
35+ #[ derive( Debug , Copy , Clone ) ]
36+ pub enum RestrictedSyscall {
37+ Net ,
38+ Process ,
39+ Thread ,
40+ }
41+
3142impl SyscallFilter {
32- pub fn default ( ) -> Self {
33- let mut filter = SyscallFilter {
43+ /// Create an empty syscall filter
44+ pub fn new ( ) -> Self {
45+ let filter = SyscallFilter {
3446 map : HashMap :: new ( ) ,
3547 } ;
36- // 禁用网络
3748 filter
38- . forbid ( SYS_socket )
39- . forbid ( SYS_socketpair )
40- . forbid ( SYS_setsockopt )
41- . forbid ( SYS_getsockopt )
42- . forbid ( SYS_getsockname )
43- . forbid ( SYS_getpeername )
44- . forbid ( SYS_bind )
45- . forbid ( SYS_listen )
46- . forbid ( SYS_accept )
47- . forbid ( SYS_accept4 )
48- . forbid ( SYS_connect )
49- . forbid ( SYS_shutdown ) ;
50- // 禁用进程相关
49+ }
50+
51+ /// Create a default syscall filter with all the presets open
52+ pub fn default ( ) -> Self {
53+ let mut filter = Self :: new ( ) ;
5154 filter
52- . allow ( SYS_execve , 1 )
53- . allow ( SYS_execveat , 1 )
54- . forbid ( SYS_fork )
55- . forbid ( SYS_vfork )
56- . forbid ( SYS_clone ) ;
55+ . enable ( RestrictedSyscall :: Net )
56+ . enable ( RestrictedSyscall :: Process ) ;
5757 filter
5858 }
5959
60+ /// Enable preset
61+ pub fn enable ( self : & mut Self , feature : RestrictedSyscall ) -> & mut Self {
62+ match feature {
63+ RestrictedSyscall :: Net => {
64+ self
65+ . forbid ( SYS_socket )
66+ . forbid ( SYS_socketpair )
67+ . forbid ( SYS_setsockopt )
68+ . forbid ( SYS_getsockopt )
69+ . forbid ( SYS_getsockname )
70+ . forbid ( SYS_getpeername )
71+ . forbid ( SYS_bind )
72+ . forbid ( SYS_listen )
73+ . forbid ( SYS_accept )
74+ . forbid ( SYS_accept4 )
75+ . forbid ( SYS_connect )
76+ . forbid ( SYS_shutdown ) ;
77+ }
78+ RestrictedSyscall :: Process => {
79+ self
80+ . allow ( SYS_execve , 1 )
81+ . allow ( SYS_execveat , 1 )
82+ . forbid ( SYS_fork )
83+ . forbid ( SYS_vfork )
84+ . forbid ( SYS_clone )
85+ . forbid ( SYS_clone3 ) ;
86+ }
87+ RestrictedSyscall :: Thread => { }
88+ } ;
89+ self
90+ }
91+
92+ /// Try parsing presets string
93+ pub fn parse_presets ( presets : Vec < String > ) -> Result < Option < Self > , CatBoxError > {
94+ let mut filter = Self :: new ( ) ;
95+ let presets = presets
96+ . into_iter ( )
97+ . flat_map ( |str| str. split ( " " ) . map ( str:: to_owned) . collect :: < Vec < _ > > ( ) )
98+ . map ( |p| p. trim ( ) . to_ascii_lowercase ( ) )
99+ . filter ( |p| p. len ( ) > 0 )
100+ . collect :: < Vec < String > > ( ) ;
101+ for preset in presets {
102+ match preset. as_str ( ) {
103+ "none" => return Ok ( None ) ,
104+ "net" | "network" => {
105+ filter. enable ( RestrictedSyscall :: Net ) ;
106+ }
107+ "process" => {
108+ filter. enable ( RestrictedSyscall :: Process ) ;
109+ }
110+ "all" => {
111+ filter
112+ . enable ( RestrictedSyscall :: Net )
113+ . enable ( RestrictedSyscall :: Process ) ;
114+ }
115+ _ => return Err ( CatBoxError :: cli ( "Parse ptrace syscall filter string fails" ) ) ,
116+ } ;
117+ }
118+ Ok ( Some ( filter) )
119+ }
120+
60121 pub fn forbid ( self : & mut Self , id : c_long ) -> & mut Self {
61122 self . map . insert ( id as SyscallId , SyscallPerm :: forbid ( ) ) ;
62123 self
0 commit comments