Skip to content

Commit 52c6734

Browse files
committed
Add option to set argument matchtype
1 parent 3aa8719 commit 52c6734

4 files changed

Lines changed: 88 additions & 19 deletions

File tree

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,18 @@ syscalls:
2828
arg0: 3
2929
arg0_char: false
3030
```
31+
In the case, that the argument is a char pointer, it can be specified how the argument should be matched, possible options are "full", "begins" and "contains":
32+
```
33+
log_file: /some/random/path
34+
syscalls:
35+
- umount2
36+
log: true
37+
block: true
38+
arg0: "/some/path"
39+
arg0_char: true
40+
arg0_matchtype: "begins"
41+
```
42+
In this example, syscall interceptor checks if the argument in the syscall begins with "/some/path", meaning that trying to call `umount2` on `/some/path` or `/some/path/nested` would be blocked.
3143

3244
In the future an extra tool may be developed to either fully generate or at least assist with the generation of a configuration file.
3345

config.yml

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
log_file: ./log.txt
22
syscalls:
3-
- umount2:
3+
- openat:
44
log: true
55
block: true
6-
arg0: "/usr"
7-
arg0_char: true
8-
arg1: 1
9-
arg1_char: false
6+
arg1: "/usr"
7+
arg1_char: true
8+
arg1_matchtype: "begins"
109
- umount2:
1110
log: false
1211
block: true
1312
arg0: "/home/xen/Projects/syscall-interceptor/test"
1413
arg0_char: true
15-
arg1: 2
16-
arg1_char: false
14+
arg0_matchtype: "full"
1715
- getdents64:
1816
log: true
1917
block: false

parse_config.py

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,26 @@
2222
bool block;
2323
char *arg0;
2424
long arg0_long;
25+
int arg0_matchtype;
2526
char *arg1;
2627
long arg1_long;
28+
int arg1_matchtype;
2729
char *arg2;
2830
long arg2_long;
31+
int arg2_matchtype;
2932
char *arg3;
3033
long arg3_long;
34+
int arg3_matchtype;
3135
char *arg4;
3236
long arg4_long;
37+
int arg4_matchtype;
3338
char *arg5;
3439
long arg5_long;
40+
int arg5_matchtype;
3541
3642
struct syscall *next;
3743
struct syscall *prev;
38-
}} syscall_default = {{NULL, -1, false, false, NULL, -1, NULL, -1, NULL, -1, NULL, -1, NULL, -1, NULL, -1, NULL, NULL}};
44+
}} syscall_default = {{NULL, -1, false, false, NULL, -1, 0, NULL, -1, 0, NULL, -1, 0, NULL, -1, 0, NULL, -1, 0, NULL, -1, 0, NULL, NULL}};
3945
4046
typedef struct syscall syscall;
4147
@@ -53,6 +59,7 @@
5359
"set_block": "{varname}->block = {block};\n",
5460
"set_arg_char": '{varname}->{argname} = (char *) malloc(strlen("{arg}")+1);\nstrcpy({varname}->{argname}, "{arg}");\n',
5561
"set_arg_long": '{varname}->{argname}_long = {arg};\n',
62+
"set_arg_matchtype": '{varname}->{argname}_matchtype = {matchtype};\n',
5663
"set_next": "{varname}->next = {nextcall};\n",
5764
"set_prev": "{varname}->prev = {prevcall};\n",
5865
}
@@ -63,17 +70,23 @@ class Syscall:
6370
log: bool
6471
block: bool
6572
arg0: str = ""
66-
arg_char: bool = True
73+
arg0_char: bool = True
74+
arg0_matchtype: str = "full"
6775
arg1: str = ""
6876
arg1_char: bool = True
77+
arg1_matchtype: str = "full"
6978
arg2: str = ""
7079
arg2_char: bool = True
80+
arg2_matchtype: str = "full"
7181
arg3: str = ""
7282
arg3_char: bool = True
83+
arg3_matchtype: str = "full"
7384
arg4: str = ""
7485
arg4_char: bool = True
86+
arg4_matchtype: str = "full"
7587
arg5: str = ""
7688
arg5_char: bool = True
89+
arg5_matchtype: str = "full"
7790

7891
def __init__(
7992
self,
@@ -82,32 +95,44 @@ def __init__(
8295
block: bool,
8396
arg0: str = "",
8497
arg0_char: bool = True,
98+
arg0_matchtype: str = "full",
8599
arg1: str = "",
86100
arg1_char: bool = True,
101+
arg1_matchtype: str = "full",
87102
arg2: str = "",
88103
arg2_char: bool = True,
104+
arg2_matchtype: str = "full",
89105
arg3: str = "",
90106
arg3_char: bool = True,
107+
arg3_matchtype: str = "full",
91108
arg4: str = "",
92109
arg4_char: bool = True,
110+
arg4_matchtype: str = "full",
93111
arg5: str = "",
94112
arg5_char: bool = True,
113+
arg5_matchtype: str = "full",
95114
):
96115
self.name = name
97116
self.log = log
98117
self.block = block
99118
self.arg0 = arg0
100119
self.arg0_char = arg0_char
120+
self.arg0_matchtype = arg0_matchtype
101121
self.arg1 = arg1
102122
self.arg1_char = arg1_char
123+
self.arg1_matchtype = arg1_matchtype
103124
self.arg2 = arg2
104125
self.arg2_char = arg2_char
126+
self.arg2_matchtype = arg2_matchtype
105127
self.arg3 = arg3
106128
self.arg3_char = arg3_char
129+
self.arg3_matchtype = arg3_matchtype
107130
self.arg4 = arg4
108131
self.arg4_char = arg4_char
132+
self.arg4_matchtype = arg4_matchtype
109133
self.arg5 = arg5
110134
self.arg5_char = arg5_char
135+
self.arg5_matchtype = arg5_matchtype
111136

112137
def build_c_code(self, varname: str) -> str:
113138
c_code = structbuild_template["var_define"].format(varname=varname)
@@ -132,16 +157,21 @@ def build_c_code(self, varname: str) -> str:
132157
c_code = c_code + structbuild_template["set_arg_char"].format(
133158
varname=varname, argname="arg0", arg=self.arg0
134159
)
160+
c_code = c_code + structbuild_template["set_arg_matchtype"].format(
161+
varname=varname, argname="arg0", matchtype=0 if self.arg0_matchtype == "full" else -1 if self.arg0_matchtype == "begins" else 1
162+
)
135163
else:
136164
c_code = c_code + structbuild_template["set_arg_long"].format(
137165
varname=varname, argname="arg0", arg=self.arg0
138166
)
139-
140167
if self.arg1 != "":
141168
if self.arg1_char:
142169
c_code = c_code + structbuild_template["set_arg_char"].format(
143170
varname=varname, argname="arg1", arg=self.arg1
144171
)
172+
c_code = c_code + structbuild_template["set_arg_matchtype"].format(
173+
varname=varname, argname="arg1", matchtype=0 if self.arg1_matchtype == "full" else -1 if self.arg1_matchtype == "begins" else 1
174+
)
145175
else:
146176
c_code = c_code + structbuild_template["set_arg_long"].format(
147177
varname=varname, argname="arg1", arg=self.arg1
@@ -152,6 +182,9 @@ def build_c_code(self, varname: str) -> str:
152182
c_code = c_code + structbuild_template["set_arg_char"].format(
153183
varname=varname, argname="arg2", arg=self.arg2
154184
)
185+
c_code = c_code + structbuild_template["set_arg_matchtype"].format(
186+
varname=varname, argname="arg2", matchtype=0 if self.arg2_matchtype == "full" else -1 if self.arg2_matchtype == "begins" else 1
187+
)
155188
else:
156189
c_code = c_code + structbuild_template["set_arg_long"].format(
157190
varname=varname, argname="arg2", arg=self.arg2
@@ -163,6 +196,9 @@ def build_c_code(self, varname: str) -> str:
163196
c_code = c_code + structbuild_template["set_arg_char"].format(
164197
varname=varname, argname="arg3", arg=self.arg3
165198
)
199+
c_code = c_code + structbuild_template["set_arg_matchtype"].format(
200+
varname=varname, argname="arg3", matchtype=0 if self.arg3_matchtype == "full" else -1 if self.arg3_matchtype == "begins" else 1
201+
)
166202
else:
167203
c_code = c_code + structbuild_template["set_arg_long"].format(
168204
varname=varname, argname="arg3", arg=self.arg3
@@ -173,6 +209,9 @@ def build_c_code(self, varname: str) -> str:
173209
c_code = c_code + structbuild_template["set_arg_char"].format(
174210
varname=varname, argname="arg4", arg=self.arg4
175211
)
212+
c_code = c_code + structbuild_template["set_arg_matchtype"].format(
213+
varname=varname, argname="arg4", matchtype=0 if self.arg4_matchtype == "full" else -1 if self.arg4_matchtype == "begins" else 1
214+
)
176215
else:
177216
c_code = c_code + structbuild_template["set_arg_long"].format(
178217
varname=varname, argname="arg4", arg=self.arg4
@@ -183,6 +222,9 @@ def build_c_code(self, varname: str) -> str:
183222
c_code = c_code + structbuild_template["set_arg_char"].format(
184223
varname=varname, argname="arg5", arg=self.arg5
185224
)
225+
c_code = c_code + structbuild_template["set_arg_matchtype"].format(
226+
varname=varname, argname="arg5", matchtype=0 if self.arg5_matchtype == "full" else -1 if self.arg5_matchtype == "begins" else 1
227+
)
186228
else:
187229
c_code = c_code + structbuild_template["set_arg_long"].format(
188230
varname=varname, argname="arg5", arg=self.arg5
@@ -200,21 +242,27 @@ def init_from_dict(parsed: dict):
200242
if parsed.get("arg0") is not None:
201243
call.arg0 = str(parsed.get("arg0"))
202244
call.arg0_char = bool(parsed.get("arg0_char"))
245+
call.arg0_matchtype = str(parsed.get("arg0_matchtype"))
203246
if parsed.get("arg1") is not None:
204247
call.arg1 = str(parsed.get("arg1"))
205248
call.arg1_char = bool(parsed.get("arg1_char"))
249+
call.arg1_matchtype = str(parsed.get("arg1_matchtype"))
206250
if parsed.get("arg2") is not None:
207251
call.arg2 = str(parsed.get("arg2"))
208252
call.arg2_char = bool(parsed.get("arg2_char"))
253+
call.arg2_matchtype = str(parsed.get("arg2_matchtype"))
209254
if parsed.get("arg3") is not None:
210255
call.arg3 = str(parsed.get("arg3"))
211256
call.arg3_char = bool(parsed.get("arg3_char"))
257+
call.arg3_matchtype = str(parsed.get("arg3_matchtype"))
212258
if parsed.get("arg4") is not None:
213259
call.arg4 = str(parsed.get("arg4"))
214260
call.arg4_char = bool(parsed.get("arg4_char"))
261+
call.arg4_matchtype = str(parsed.get("arg4_matchtype"))
215262
if parsed.get("arg5") is not None:
216263
call.arg5 = str(parsed.get("arg5"))
217264
call.arg5_char = bool(parsed.get("arg5_char"))
265+
call.arg5_matchtype = str(parsed.get("arg5_matchtype"))
218266
return call
219267

220268

src/main.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,23 @@ has_flag(long search_flag, long all_flags) {
1515
}
1616

1717
bool
18-
argcmp(long config_arg_long, char *config_arg_char, long sys_arg) {
18+
argcmp(int matchtype, long config_arg_long, char *config_arg_char, long sys_arg) {
1919
if (!config_arg_char && config_arg_long != -1) {
2020
return has_flag(config_arg_long, sys_arg);
2121
} else if (config_arg_char) {
22-
if (strcmp((char *)sys_arg, config_arg_char) == 0) {
23-
return true;
22+
switch (matchtype) {
23+
case -1:
24+
return strncmp(config_arg_char, (char*)sys_arg, strlen(config_arg_char)) == 0;
25+
case 0:
26+
if (strcmp((char *)sys_arg, config_arg_char) == 0)
27+
return true;
28+
break;
29+
case 1:
30+
if (strstr((char *)sys_arg, config_arg_char) != NULL)
31+
return true;
32+
break;
33+
default:
34+
return false;
2435
}
2536
}
2637
return false;
@@ -30,22 +41,22 @@ bool
3041
match_args(syscall *call, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5) {
3142
bool arg0_match = true, arg1_match = true, arg2_match = true, arg3_match = true, arg4_match = true, arg5_match = true;
3243
if (call->arg0 || call->arg0_long != -1) {
33-
arg0_match = argcmp(call->arg0_long, call->arg0, arg0);
44+
arg0_match = argcmp(call->arg0_matchtype, call->arg0_long, call->arg0, arg0);
3445
}
3546
if (call->arg1 || call->arg1_long != -1) {
36-
arg1_match = argcmp(call->arg1_long, call->arg1, arg1);
47+
arg1_match = argcmp(call->arg1_matchtype, call->arg1_long, call->arg1, arg1);
3748
}
3849
if (call->arg2 || call->arg2_long != -1) {
39-
arg2_match = argcmp(call->arg2_long, call->arg2, arg2);
50+
arg2_match = argcmp(call->arg2_matchtype, call->arg2_long, call->arg2, arg2);
4051
}
4152
if (call->arg3 || call->arg3_long != -1) {
42-
arg3_match = argcmp(call->arg3_long, call->arg3, arg3);
53+
arg3_match = argcmp(call->arg3_matchtype, call->arg3_long, call->arg3, arg3);
4354
}
4455
if (call->arg4 || call->arg4_long != -1) {
45-
arg4_match = argcmp(call->arg4_long, call->arg4, arg4);
56+
arg4_match = argcmp(call->arg4_matchtype, call->arg4_long, call->arg4, arg4);
4657
}
4758
if (call->arg5 || call->arg5_long != -1) {
48-
arg5_match = argcmp(call->arg5_long, call->arg5, arg5);
59+
arg5_match = argcmp(call->arg5_matchtype, call->arg5_long, call->arg5, arg5);
4960
}
5061

5162
return arg0_match && arg1_match && arg2_match && arg3_match && arg4_match && arg5_match;

0 commit comments

Comments
 (0)