2
2
# SPDX-License-Identifier: Apache-2.0
3
3
"""Tests that the --seccomp-filter parameter works as expected."""
4
4
5
- import os
6
5
import platform
7
- import tempfile
8
6
import time
7
+ from pathlib import Path
9
8
10
- import pytest
11
9
import requests
12
10
13
11
from framework import utils
14
- from host_tools .cargo_build import run_seccompiler_bin
15
12
16
13
17
- def _custom_filter_setup ( test_microvm , json_filter ):
18
- json_temp = tempfile . NamedTemporaryFile ( delete = False )
19
- json_temp . write ( json_filter )
20
- json_temp . flush ( )
14
+ def install_filter ( microvm , bpf_path ):
15
+ """Install seccomp filter in microvm."""
16
+ microvm . create_jailed_resource ( bpf_path )
17
+ microvm . jailer . extra_args . update ({ "seccomp-filter" : bpf_path . name } )
21
18
22
- bpf_path = os .path .join (test_microvm .path , "bpf.out" )
23
19
24
- run_seccompiler_bin (bpf_path = bpf_path , json_path = json_temp .name )
20
+ def test_allow_all (uvm_plain , seccompiler ):
21
+ """Test --seccomp-filter, allowing all syscalls."""
22
+ seccomp_filter = {
23
+ thread : {"default_action" : "allow" , "filter_action" : "trap" , "filter" : []}
24
+ for thread in ["vmm" , "api" , "vcpu" ]
25
+ }
25
26
26
- os .unlink (json_temp .name )
27
- test_microvm .create_jailed_resource (bpf_path )
28
- test_microvm .jailer .extra_args .update ({"seccomp-filter" : "bpf.out" })
29
-
30
-
31
- def _config_file_setup (test_microvm , vm_config_file ):
32
- test_microvm .create_jailed_resource (test_microvm .kernel_file )
33
- test_microvm .create_jailed_resource (test_microvm .rootfs_file )
34
-
35
- vm_config_path = os .path .join (test_microvm .path , os .path .basename (vm_config_file ))
36
- with open (vm_config_file , encoding = "utf-8" ) as f1 :
37
- with open (vm_config_path , "w" , encoding = "utf-8" ) as f2 :
38
- for line in f1 :
39
- f2 .write (line )
40
- test_microvm .create_jailed_resource (vm_config_path )
41
- test_microvm .jailer .extra_args = {"config-file" : os .path .basename (vm_config_file )}
42
-
43
- test_microvm .jailer .extra_args .update ({"no-api" : None })
44
-
45
-
46
- def test_allow_all (uvm_plain ):
47
- """
48
- Test --seccomp-filter, allowing all syscalls.
49
- """
27
+ bpf_path = seccompiler .compile (seccomp_filter )
50
28
test_microvm = uvm_plain
51
-
52
- _custom_filter_setup (
53
- test_microvm ,
54
- """{
55
- "Vmm": {
56
- "default_action": "allow",
57
- "filter_action": "trap",
58
- "filter": []
59
- },
60
- "Api": {
61
- "default_action": "allow",
62
- "filter_action": "trap",
63
- "filter": []
64
- },
65
- "Vcpu": {
66
- "default_action": "allow",
67
- "filter_action": "trap",
68
- "filter": []
69
- }
70
- }""" .encode (
71
- "utf-8"
72
- ),
73
- )
74
-
29
+ install_filter (test_microvm , bpf_path )
75
30
test_microvm .spawn ()
76
-
77
31
test_microvm .basic_config ()
78
-
79
32
test_microvm .start ()
80
-
81
33
utils .assert_seccomp_level (test_microvm .firecracker_pid , "2" )
82
34
83
35
84
- def test_working_filter (uvm_plain ):
85
- """
86
- Test --seccomp-filter, rejecting some dangerous syscalls.
87
- """
88
- test_microvm = uvm_plain
36
+ def test_working_filter (uvm_plain , seccompiler ):
37
+ """Test --seccomp-filter, rejecting some dangerous syscalls."""
89
38
90
- _custom_filter_setup (
91
- test_microvm ,
92
- """{
93
- "Vmm": {
94
- "default_action": "allow",
95
- "filter_action": "kill_process",
96
- "filter": [
97
- {
98
- "syscall": "clone"
99
- },
100
- {
101
- "syscall": "execve"
102
- }
103
- ]
104
- },
105
- "Api": {
106
- "default_action": "allow",
107
- "filter_action": "kill_process",
108
- "filter": [
109
- {
110
- "syscall": "clone"
111
- },
112
- {
113
- "syscall": "execve"
114
- }
115
- ]
116
- },
117
- "Vcpu": {
39
+ seccomp_filter = {
40
+ thread : {
118
41
"default_action" : "allow" ,
119
42
"filter_action" : "kill_process" ,
120
- "filter": [
121
- {
122
- "syscall": "clone"
123
- },
124
- {
125
- "syscall": "execve",
126
- "comment": "sample comment"
127
- }
128
- ]
43
+ "filter" : [{"syscall" : "clone" }, {"syscall" : "execve" }],
129
44
}
130
- }""" .encode (
131
- "utf-8"
132
- ),
133
- )
45
+ for thread in ["vmm" , "api" , "vcpu" ]
46
+ }
134
47
48
+ bpf_path = seccompiler .compile (seccomp_filter )
49
+ test_microvm = uvm_plain
50
+ install_filter (test_microvm , bpf_path )
135
51
test_microvm .spawn ()
136
-
137
52
test_microvm .basic_config ()
138
-
139
53
test_microvm .start ()
140
54
141
55
# level should be 2, with no additional errors
142
56
utils .assert_seccomp_level (test_microvm .firecracker_pid , "2" )
143
57
144
58
145
- def test_failing_filter (uvm_plain ):
146
- """
147
- Test --seccomp-filter, denying some needed syscalls.
148
- """
149
- test_microvm = uvm_plain
59
+ def test_failing_filter (uvm_plain , seccompiler ):
60
+ """Test --seccomp-filter, denying some needed syscalls."""
150
61
151
- _custom_filter_setup (
152
- test_microvm ,
153
- """{
154
- "Vmm ": {
62
+ seccomp_filter = {
63
+ "vmm" : { "default_action" : "allow" , "filter_action" : "trap" , "filter" : []} ,
64
+ "api" : { "default_action" : "allow" , "filter_action" : "trap" , "filter" : []},
65
+ "vcpu " : {
155
66
"default_action" : "allow" ,
156
67
"filter_action" : "trap" ,
157
- "filter": []
68
+ "filter" : [{ "syscall" : "ioctl" }],
158
69
},
159
- "Api": {
160
- "default_action": "allow",
161
- "filter_action": "trap",
162
- "filter": []
163
- },
164
- "Vcpu": {
165
- "default_action": "allow",
166
- "filter_action": "trap",
167
- "filter": [
168
- {
169
- "syscall": "ioctl"
170
- }
171
- ]
172
- }
173
- }""" .encode (
174
- "utf-8"
175
- ),
176
- )
70
+ }
177
71
72
+ bpf_path = seccompiler .compile (seccomp_filter )
73
+ test_microvm = uvm_plain
74
+ install_filter (test_microvm , bpf_path )
178
75
test_microvm .spawn ()
179
76
test_microvm .basic_config (vcpu_count = 1 )
180
77
@@ -190,8 +87,7 @@ def test_failing_filter(uvm_plain):
190
87
# Check the logger output
191
88
ioctl_num = 16 if platform .machine () == "x86_64" else 29
192
89
test_microvm .check_log_message (
193
- "Shutting down VM after intercepting a bad"
194
- " syscall ({})" .format (str (ioctl_num ))
90
+ f"Shutting down VM after intercepting a bad syscall ({ ioctl_num } )"
195
91
)
196
92
197
93
# Check the metrics
@@ -208,28 +104,28 @@ def test_failing_filter(uvm_plain):
208
104
test_microvm .mark_killed ()
209
105
210
106
211
- @pytest .mark .parametrize ("vm_config_file" , ["framework/vm_config.json" ])
212
- def test_invalid_bpf (uvm_plain , vm_config_file ):
213
- """
214
- Test that FC does not start, given an invalid binary filter.
215
- """
107
+ def test_invalid_bpf (uvm_plain ):
108
+ """Test that FC does not start, given an invalid binary filter."""
216
109
test_microvm = uvm_plain
217
110
218
111
# Configure VM from JSON. Otherwise, the test will error because
219
112
# the process will be killed before configuring the API socket.
220
- _config_file_setup (uvm_plain , vm_config_file )
113
+ test_microvm .create_jailed_resource (test_microvm .kernel_file )
114
+ test_microvm .create_jailed_resource (test_microvm .rootfs_file )
221
115
222
- bpf_path = os . path . join ( test_microvm . path , "bpf.out " )
223
- file = open ( bpf_path , "w" , encoding = "utf-8" )
224
- file . write ( "Invalid BPF!" )
225
- file . close ( )
116
+ vm_config_file = Path ( "framework/vm_config.json " )
117
+ test_microvm . create_jailed_resource ( vm_config_file )
118
+ test_microvm . jailer . extra_args = { "config-file" : vm_config_file . name }
119
+ test_microvm . jailer . extra_args . update ({ "no-api" : None } )
226
120
121
+ bpf_path = Path (test_microvm .path ) / "bpf.out"
122
+ bpf_path .write_bytes (b"Invalid BPF!" )
227
123
test_microvm .create_jailed_resource (bpf_path )
228
- test_microvm .jailer .extra_args .update ({"seccomp-filter" : "bpf.out" })
124
+ test_microvm .jailer .extra_args .update ({"seccomp-filter" : bpf_path . name })
229
125
230
126
test_microvm .spawn ()
231
-
232
127
# give time for the process to get killed
233
128
time .sleep (1 )
129
+ assert "Seccomp error: Filter deserialization failed" in test_microvm .log_data
234
130
235
131
test_microvm .mark_killed ()
0 commit comments