22# SPDX-License-Identifier: Apache-2.0
33"""Tests that the --seccomp-filter parameter works as expected."""
44
5- import os
65import platform
7- import tempfile
86import time
7+ from pathlib import Path
98
10- import pytest
119import requests
1210
1311from framework import utils
14- from host_tools .cargo_build import run_seccompiler_bin
1512
1613
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 } )
2118
22- bpf_path = os .path .join (test_microvm .path , "bpf.out" )
2319
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+ }
2526
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 )
5028 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 )
7530 test_microvm .spawn ()
76-
7731 test_microvm .basic_config ()
78-
7932 test_microvm .start ()
80-
8133 utils .assert_seccomp_level (test_microvm .firecracker_pid , "2" )
8234
8335
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."""
8938
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 : {
11841 "default_action" : "allow" ,
11942 "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" }],
12944 }
130- }""" .encode (
131- "utf-8"
132- ),
133- )
45+ for thread in ["vmm" , "api" , "vcpu" ]
46+ }
13447
48+ bpf_path = seccompiler .compile (seccomp_filter )
49+ test_microvm = uvm_plain
50+ install_filter (test_microvm , bpf_path )
13551 test_microvm .spawn ()
136-
13752 test_microvm .basic_config ()
138-
13953 test_microvm .start ()
14054
14155 # level should be 2, with no additional errors
14256 utils .assert_seccomp_level (test_microvm .firecracker_pid , "2" )
14357
14458
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."""
15061
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 " : {
15566 "default_action" : "allow" ,
15667 "filter_action" : "trap" ,
157- "filter": []
68+ "filter" : [{ "syscall" : "ioctl" }],
15869 },
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+ }
17771
72+ bpf_path = seccompiler .compile (seccomp_filter )
73+ test_microvm = uvm_plain
74+ install_filter (test_microvm , bpf_path )
17875 test_microvm .spawn ()
17976 test_microvm .basic_config (vcpu_count = 1 )
18077
@@ -190,8 +87,7 @@ def test_failing_filter(uvm_plain):
19087 # Check the logger output
19188 ioctl_num = 16 if platform .machine () == "x86_64" else 29
19289 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 } )"
19591 )
19692
19793 # Check the metrics
@@ -208,28 +104,28 @@ def test_failing_filter(uvm_plain):
208104 test_microvm .mark_killed ()
209105
210106
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."""
216109 test_microvm = uvm_plain
217110
218111 # Configure VM from JSON. Otherwise, the test will error because
219112 # 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 )
221115
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 } )
226120
121+ bpf_path = Path (test_microvm .path ) / "bpf.out"
122+ bpf_path .write_bytes (b"Invalid BPF!" )
227123 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 })
229125
230126 test_microvm .spawn ()
231-
232127 # give time for the process to get killed
233128 time .sleep (1 )
129+ assert "Seccomp error: Filter deserialization failed" in test_microvm .log_data
234130
235131 test_microvm .mark_killed ()
0 commit comments