Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/firecracker
Path: blob/main/tests/integration_tests/security/test_custom_seccomp.py
1958 views
1
# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
# SPDX-License-Identifier: Apache-2.0
3
"""Tests that the --seccomp-filter parameter works as expected."""
4
5
import os
6
import platform
7
import json
8
import tempfile
9
import time
10
import psutil
11
import pytest
12
import requests
13
import framework.utils as utils
14
import host_tools.logging as log_tools
15
16
from host_tools.cargo_build import run_seccompiler_bin
17
18
19
def _custom_filter_setup(test_microvm, json_filter):
20
json_temp = tempfile.NamedTemporaryFile(delete=False)
21
json_temp.write(json_filter)
22
json_temp.flush()
23
24
bpf_path = os.path.join(test_microvm.path, 'bpf.out')
25
26
run_seccompiler_bin(bpf_path=bpf_path, json_path=json_temp.name)
27
28
os.unlink(json_temp.name)
29
test_microvm.create_jailed_resource(bpf_path)
30
test_microvm.jailer.extra_args.update({"seccomp-filter": 'bpf.out'})
31
32
33
def _config_file_setup(test_microvm, vm_config_file):
34
test_microvm.create_jailed_resource(test_microvm.kernel_file,
35
create_jail=True)
36
test_microvm.create_jailed_resource(test_microvm.rootfs_file,
37
create_jail=True)
38
39
vm_config_path = os.path.join(test_microvm.path,
40
os.path.basename(vm_config_file))
41
with open(vm_config_file) as f1:
42
with open(vm_config_path, "w") as f2:
43
for line in f1:
44
f2.write(line)
45
test_microvm.create_jailed_resource(vm_config_path, create_jail=True)
46
test_microvm.jailer.extra_args = {'config-file': os.path.basename(
47
vm_config_file)}
48
49
test_microvm.jailer.extra_args.update({'no-api': None})
50
51
52
def test_allow_all(test_microvm_with_api):
53
"""Test --seccomp-filter, allowing all syscalls."""
54
test_microvm = test_microvm_with_api
55
56
_custom_filter_setup(test_microvm, """{
57
"Vmm": {
58
"default_action": "allow",
59
"filter_action": "trap",
60
"filter": []
61
},
62
"Api": {
63
"default_action": "allow",
64
"filter_action": "trap",
65
"filter": []
66
},
67
"Vcpu": {
68
"default_action": "allow",
69
"filter_action": "trap",
70
"filter": []
71
}
72
}""".encode('utf-8'))
73
74
test_microvm.spawn()
75
76
test_microvm.basic_config()
77
78
test_microvm.start()
79
80
utils.assert_seccomp_level(test_microvm.jailer_clone_pid, "2")
81
82
83
def test_working_filter(test_microvm_with_api):
84
"""Test --seccomp-filter, rejecting some dangerous syscalls."""
85
test_microvm = test_microvm_with_api
86
87
_custom_filter_setup(test_microvm, """{
88
"Vmm": {
89
"default_action": "allow",
90
"filter_action": "kill_process",
91
"filter": [
92
{
93
"syscall": "clone"
94
},
95
{
96
"syscall": "execve"
97
}
98
]
99
},
100
"Api": {
101
"default_action": "allow",
102
"filter_action": "kill_process",
103
"filter": [
104
{
105
"syscall": "clone"
106
},
107
{
108
"syscall": "execve"
109
}
110
]
111
},
112
"Vcpu": {
113
"default_action": "allow",
114
"filter_action": "kill_process",
115
"filter": [
116
{
117
"syscall": "clone"
118
},
119
{
120
"syscall": "execve",
121
"comment": "sample comment"
122
}
123
]
124
}
125
}""".encode("utf-8"))
126
127
test_microvm.spawn()
128
129
test_microvm.basic_config()
130
131
test_microvm.start()
132
133
# seccomp-level should be 2, with no additional errors
134
utils.assert_seccomp_level(test_microvm.jailer_clone_pid, "2")
135
136
137
def test_failing_filter(test_microvm_with_api):
138
"""Test --seccomp-filter, denying some needed syscalls."""
139
test_microvm = test_microvm_with_api
140
141
_custom_filter_setup(test_microvm, """{
142
"Vmm": {
143
"default_action": "allow",
144
"filter_action": "trap",
145
"filter": []
146
},
147
"Api": {
148
"default_action": "allow",
149
"filter_action": "trap",
150
"filter": []
151
},
152
"Vcpu": {
153
"default_action": "allow",
154
"filter_action": "trap",
155
"filter": [
156
{
157
"syscall": "ioctl"
158
}
159
]
160
}
161
}""".encode('utf-8'))
162
163
test_microvm.spawn()
164
165
test_microvm.basic_config(vcpu_count=1)
166
167
metrics_fifo_path = os.path.join(test_microvm.path, 'metrics_fifo')
168
metrics_fifo = log_tools.Fifo(metrics_fifo_path)
169
response = test_microvm.metrics.put(
170
metrics_path=test_microvm.create_jailed_resource(metrics_fifo.path)
171
)
172
assert test_microvm.api_session.is_status_no_content(response.status_code)
173
174
# Try to start the VM with error checking off, because it will fail.
175
try:
176
test_microvm.start(check=False)
177
except requests.exceptions.ConnectionError:
178
pass
179
180
# Give time for the process to get killed
181
time.sleep(1)
182
183
test_microvm.expect_kill_by_signal = True
184
# Check the logger output
185
ioctl_num = 16 if platform.machine() == "x86_64" else 29
186
assert "Shutting down VM after intercepting a bad syscall ({})".format(
187
str(ioctl_num)) in test_microvm.log_data
188
189
# Check the metrics
190
lines = metrics_fifo.sequential_reader(100)
191
192
num_faults = 0
193
for line in lines:
194
num_faults += json.loads(line)["seccomp"]["num_faults"]
195
196
assert num_faults == 1
197
198
# assert that the process was killed
199
assert not psutil.pid_exists(test_microvm.jailer_clone_pid)
200
201
202
@pytest.mark.parametrize(
203
"vm_config_file",
204
["framework/vm_config.json"]
205
)
206
def test_invalid_bpf(test_microvm_with_ssh, vm_config_file):
207
"""Test that FC does not start, given an invalid binary filter."""
208
test_microvm = test_microvm_with_ssh
209
210
# Configure VM from JSON. Otherwise, the test will error because
211
# the process will be killed before configuring the API socket.
212
_config_file_setup(test_microvm_with_ssh, vm_config_file)
213
214
bpf_path = os.path.join(test_microvm.path, 'bpf.out')
215
file = open(bpf_path, "w")
216
file.write("Invalid BPF!")
217
file.close()
218
219
test_microvm.create_jailed_resource(bpf_path)
220
test_microvm.jailer.extra_args.update({"seccomp-filter": 'bpf.out'})
221
222
test_microvm.spawn()
223
224
# give time for the process to get killed
225
time.sleep(1)
226
227
# assert that the process was killed
228
assert not psutil.pid_exists(test_microvm.jailer_clone_pid)
229
230