forked from msg555/sjail
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfilter_proc.cpp
119 lines (101 loc) · 2.96 KB
/
filter_proc.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <limits.h>
#include <regex.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include "config.h"
#include "filter.h"
#include "memory.h"
#include "process_state.h"
#include "report.h"
#include "sjail.h"
static int regex_init = false;
static regex_t exec_reg;
exec_filter::exec_filter() : fork_count(0), clone_count(0) {
}
exec_filter::~exec_filter() {
}
static filter_action filter_exec(pid_data& pdata, process_state& st) {
pid_t pid = st.get_pid();
if(!regex_init) {
if(regcomp(&exec_reg, get_exec_match().c_str(),
REG_EXTENDED | REG_NOSUB)) {
log_violation(pid, "could not compile exec match regex");
return FILTER_BLOCK_SYSCALL;
}
regex_init = true;
}
char* filename = (char*)safemem_read_pid_to_null(pdata, st.get_param(0));
if(!filename) {
log_violation(pid, "could not read exec filename");
return FILTER_BLOCK_SYSCALL;
}
if(regexec(&exec_reg, filename, 0, NULL, 0)) {
log_violation(pid, "invalid execve filename " + std::string(filename));
return FILTER_BLOCK_SYSCALL;
}
if(!get_passive()) {
uintptr_t rem_addr = safemem_remote_addr(pdata, filename);
if(!rem_addr) {
log_violation(pid, "cannot allow file op without safe mem installed");
return FILTER_BLOCK_SYSCALL;
}
st.set_param(0, rem_addr);
}
return FILTER_PERMIT_SYSCALL;
}
filter_action exec_filter::filter_syscall_enter(pid_data& pdata, process_state& st) {
bool isfork = false;
switch(st.get_syscall()) {
case sys_execve:
return filter_exec(pdata, st);
case sys_fork:
case sys_vfork:
isfork = true;
case sys_clone:
if(!isfork) {
/* Force CLONE_PTRACE into the flags. */
param_t flags = st.get_param(0);
flags |= CLONE_PTRACE;
flags &= ~CLONE_UNTRACED;
st.set_param(0, flags);
st.save();
/* This is the same rule that ptrace(2) uses to differentiate between a
* fork and a clone. */
isfork = (flags & 0xFF) == SIGCHLD;
}
if(isfork && (get_processes() < 0 ||
fork_count < (size_t)get_processes())) {
++fork_count;
return FILTER_PERMIT_SYSCALL;
} else if(!isfork && (get_threads() < 0 ||
clone_count < (size_t)get_threads())) {
++clone_count;
return FILTER_PERMIT_SYSCALL;
}
return FILTER_BLOCK_SYSCALL;
default:
return FILTER_NO_ACTION;
}
}
filter_action exec_filter::filter_syscall_exit(pid_data& pdata,
process_state& st) {
bool isfork = false;
switch(st.get_syscall()) {
case sys_fork:
case sys_vfork:
isfork = true;
case sys_clone:
if(!isfork) {
isfork = (st.get_param(0) & 0xFF) == SIGCHLD;
}
if(st.is_error_result()) {
--(isfork ? fork_count : clone_count);
}
break;
default: break;
}
return FILTER_NO_ACTION;
}