1
1
#include " sandboxed_api/sandbox2/monitor_unotify.h"
2
2
3
- #include < linux/audit.h>
4
3
#include < linux/seccomp.h>
5
4
#include < poll.h>
6
5
#include < sys/eventfd.h>
7
- #include < sys/ioctl.h>
8
6
#include < sys/ptrace.h>
9
7
#include < sys/resource.h>
10
8
#include < sys/sysinfo.h>
17
15
#include < atomic>
18
16
#include < cerrno>
19
17
#include < cstdint>
20
- #include < cstdlib>
21
- #include < cstring>
22
18
#include < memory>
23
19
#include < string>
24
20
#include < utility>
36
32
#include " absl/time/clock.h"
37
33
#include " absl/time/time.h"
38
34
#include " absl/types/span.h"
39
- #include " sandboxed_api/config.h"
40
35
#include " sandboxed_api/sandbox2/bpf_evaluator.h"
41
36
#include " sandboxed_api/sandbox2/client.h"
42
37
#include " sandboxed_api/sandbox2/executor.h"
45
40
#include " sandboxed_api/sandbox2/notify.h"
46
41
#include " sandboxed_api/sandbox2/policy.h"
47
42
#include " sandboxed_api/sandbox2/result.h"
43
+ #include " sandboxed_api/sandbox2/util/seccomp_unotify.h"
48
44
#include " sandboxed_api/util/fileops.h"
49
45
#include " sandboxed_api/util/status_macros.h"
50
46
#include " sandboxed_api/util/thread.h"
53
49
#define SECCOMP_RET_USER_NOTIF 0x7fc00000U /* notifies userspace */
54
50
#endif
55
51
56
- #ifndef SECCOMP_USER_NOTIF_FLAG_CONTINUE
57
- #define SECCOMP_USER_NOTIF_FLAG_CONTINUE 1
58
- #endif
59
-
60
52
#define DO_USER_NOTIF BPF_STMT (BPF_RET + BPF_K, SECCOMP_RET_USER_NOTIF)
61
53
62
- #ifndef SECCOMP_GET_NOTIF_SIZES
63
- #define SECCOMP_GET_NOTIF_SIZES 3
64
-
65
- struct seccomp_notif_sizes {
66
- __u16 seccomp_notif;
67
- __u16 seccomp_notif_resp;
68
- __u16 seccomp_data;
69
- };
70
- #endif
71
-
72
- #ifndef SECCOMP_IOCTL_NOTIF_RECV
73
- #ifndef SECCOMP_IOWR
74
- #define SECCOMP_IOC_MAGIC ' !'
75
- #define SECCOMP_IO (nr ) _IO(SECCOMP_IOC_MAGIC, nr)
76
- #define SECCOMP_IOWR (nr, type ) _IOWR(SECCOMP_IOC_MAGIC, nr, type)
77
- #endif
78
-
79
- // Flags for seccomp notification fd ioctl.
80
- #define SECCOMP_IOCTL_NOTIF_RECV SECCOMP_IOWR (0 , struct seccomp_notif )
81
- #define SECCOMP_IOCTL_NOTIF_SEND SECCOMP_IOWR (1 , struct seccomp_notif_resp )
82
- #endif
83
-
84
54
namespace sandbox2 {
85
55
86
56
namespace {
@@ -91,23 +61,6 @@ int seccomp(unsigned int operation, unsigned int flags, void* args) {
91
61
return syscall (SYS_seccomp, operation, flags, args);
92
62
}
93
63
94
- sapi::cpu::Architecture AuditArchToCPUArch (uint32_t arch) {
95
- switch (arch) {
96
- case AUDIT_ARCH_AARCH64:
97
- return sapi::cpu::Architecture::kArm64 ;
98
- case AUDIT_ARCH_ARM:
99
- return sapi::cpu::Architecture::kArm ;
100
- case AUDIT_ARCH_X86_64:
101
- return sapi::cpu::Architecture::kX8664 ;
102
- case AUDIT_ARCH_I386:
103
- return sapi::cpu::Architecture::kX86 ;
104
- case AUDIT_ARCH_PPC64LE:
105
- return sapi::cpu::Architecture::kPPC64LE ;
106
- default :
107
- return sapi::cpu::Architecture::kUnknown ;
108
- }
109
- }
110
-
111
64
absl::Status WaitForFdReadable (int fd, absl::Time deadline) {
112
65
pollfd pfds[] = {
113
66
{.fd = fd, .events = POLLIN},
@@ -202,53 +155,47 @@ void UnotifyMonitor::HandleViolation(const Syscall& syscall) {
202
155
: ViolationType::kArchitectureSwitch ;
203
156
LogSyscallViolation (syscall );
204
157
notify_->EventSyscallViolation (syscall , violation_type);
205
- MaybeGetStackTrace (req_-> pid , Result::VIOLATION);
158
+ MaybeGetStackTrace (syscall . pid () , Result::VIOLATION);
206
159
SetExitStatusCode (Result::VIOLATION, syscall .nr ());
207
160
notify_->EventSyscallViolation (syscall , violation_type);
208
161
result_.SetSyscall (std::make_unique<Syscall>(syscall ));
209
162
KillSandboxee ();
210
163
}
211
164
212
- void UnotifyMonitor::AllowSyscallViaUnotify () {
213
- memset (resp_.get (), 0 , resp_size_);
214
- resp_->id = req_->id ;
215
- resp_->val = 0 ;
216
- resp_->error = 0 ;
217
- resp_->flags = SECCOMP_USER_NOTIF_FLAG_CONTINUE;
218
- if (ioctl (seccomp_notify_fd_.get (), SECCOMP_IOCTL_NOTIF_SEND, resp_.get ()) !=
219
- 0 ) {
220
- if (errno == ENOENT) {
165
+ void UnotifyMonitor::AllowSyscallViaUnotify (seccomp_notif req) {
166
+ if (!util::SeccompUnotify::IsContinueSupported ()) {
167
+ LOG (ERROR)
168
+ << " SECCOMP_USER_NOTIF_FLAG_CONTINUE not supported by the kernel." ;
169
+ SetExitStatusCode (Result::INTERNAL_ERROR, Result::FAILED_NOTIFY);
170
+ return ;
171
+ }
172
+ if (absl::Status status = seccomp_unotify_.RespondContinue (req);
173
+ !status.ok ()) {
174
+ if (absl::IsNotFound (status)) {
221
175
VLOG (1 ) << " Unotify send failed with ENOENT" ;
222
176
} else {
223
- LOG_IF (ERROR, errno == EINVAL)
224
- << " Unotify send failed with EINVAL. Likely "
225
- " SECCOMP_USER_NOTIF_FLAG_CONTINUE unsupported by the kernel." ;
226
177
SetExitStatusCode (Result::INTERNAL_ERROR, Result::FAILED_NOTIFY);
227
178
}
228
179
}
229
180
}
230
181
231
182
void UnotifyMonitor::HandleUnotify () {
232
- memset (req_.get (), 0 , req_size_);
233
- if (ioctl (seccomp_notify_fd_.get (), SECCOMP_IOCTL_NOTIF_RECV, req_.get ()) !=
234
- 0 ) {
235
- if (errno == ENOENT) {
183
+ absl::StatusOr<seccomp_notif> req_data = seccomp_unotify_.Receive ();
184
+ if (!req_data.ok ()) {
185
+ if (absl::IsNotFound (req_data.status ())) {
236
186
VLOG (1 ) << " Unotify recv failed with ENOENT" ;
237
187
} else {
238
188
SetExitStatusCode (Result::INTERNAL_ERROR, Result::FAILED_NOTIFY);
189
+ return ;
239
190
}
240
- return ;
241
191
}
242
- Syscall syscall (AuditArchToCPUArch (req_->data .arch ), req_->data .nr ,
243
- {req_->data .args [0 ], req_->data .args [1 ], req_->data .args [2 ],
244
- req_->data .args [3 ], req_->data .args [4 ], req_->data .args [5 ]},
245
- req_->pid , 0 , req_->data .instruction_pointer );
246
192
absl::StatusOr<uint32_t > policy_ret =
247
- bpf::Evaluate (original_policy_, req_ ->data );
193
+ bpf::Evaluate (original_policy_, req_data ->data );
248
194
if (!policy_ret.ok ()) {
249
195
LOG (ERROR) << " Failed to evaluate policy: " << policy_ret.status ();
250
196
SetExitStatusCode (Result::INTERNAL_ERROR, Result::FAILED_NOTIFY);
251
197
}
198
+ Syscall syscall (*req_data);
252
199
const sock_filter trace_action = SANDBOX2_TRACE;
253
200
bool should_trace = *policy_ret == trace_action.k ;
254
201
Notify::TraceAction trace_response = Notify::TraceAction::kDeny ;
@@ -257,7 +204,7 @@ void UnotifyMonitor::HandleUnotify() {
257
204
}
258
205
switch (trace_response) {
259
206
case Notify::TraceAction::kAllow :
260
- AllowSyscallViaUnotify ();
207
+ AllowSyscallViaUnotify (*req_data );
261
208
return ;
262
209
case Notify::TraceAction::kDeny :
263
210
HandleViolation (syscall );
@@ -290,7 +237,7 @@ void UnotifyMonitor::Run() {
290
237
291
238
pollfd pfds[] = {
292
239
{.fd = process_.status_fd .get (), .events = POLLIN},
293
- {.fd = seccomp_notify_fd_. get (), .events = POLLIN},
240
+ {.fd = seccomp_unotify_. GetFd (), .events = POLLIN},
294
241
{.fd = monitor_notify_fd_.get (), .events = POLLIN},
295
242
};
296
243
while (result_.final_status () == Result::UNSET) {
@@ -405,16 +352,10 @@ bool UnotifyMonitor::InitSetupUnotify() {
405
352
LOG (ERROR) << " Couldn't recv unotify fd" ;
406
353
return false ;
407
354
}
408
- seccomp_notify_fd_ = FDCloser (fd);
409
- struct seccomp_notif_sizes sizes = {};
410
- if (seccomp (SECCOMP_GET_NOTIF_SIZES, 0 , &sizes) == -1 ) {
411
- LOG (ERROR) << " Couldn't get seccomp_notif_sizes" ;
355
+ if (absl::Status status = seccomp_unotify_.Init (FDCloser (fd)); !status.ok ()) {
356
+ LOG (ERROR) << " Could not init seccomp_unotify: " << status;
412
357
return false ;
413
358
}
414
- req_size_ = sizes.seccomp_notif ;
415
- req_.reset (static_cast <seccomp_notif*>(malloc (req_size_)));
416
- resp_size_ = sizes.seccomp_notif_resp ;
417
- resp_.reset (static_cast <seccomp_notif_resp*>(malloc (resp_size_)));
418
359
return true ;
419
360
}
420
361
0 commit comments