Skip to content

Commit 2b52e66

Browse files
happyCoder92copybara-github
authored andcommitted
Split out seccomp unotify handling
PiperOrigin-RevId: 734060661 Change-Id: Ib5646f991cb3a030c492f3af4283c6cc73178a63
1 parent f9eb70f commit 2b52e66

11 files changed

+535
-91
lines changed

sandboxed_api/sandbox2/BUILD

+1-1
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ cc_library(
479479
"@com_google_absl//absl/synchronization",
480480
"@com_google_absl//absl/time",
481481
"@com_google_absl//absl/types:span",
482-
"@com_google_sandboxed_api//sandboxed_api:config",
482+
"@com_google_sandboxed_api//sandboxed_api/sandbox2/util:seccomp_unotify",
483483
"@com_google_sandboxed_api//sandboxed_api/util:fileops",
484484
"@com_google_sandboxed_api//sandboxed_api/util:status",
485485
"@com_google_sandboxed_api//sandboxed_api/util:thread",

sandboxed_api/sandbox2/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ target_link_libraries(sandbox2_monitor_unotify
487487
sandbox2::bpf_evaluator
488488
sandbox2::client
489489
sandbox2::forkserver_proto
490-
sapi::config
490+
sandbox2::seccomp_unotify
491491
sapi::status
492492
PUBLIC sandbox2::executor
493493
sandbox2::monitor_base

sandboxed_api/sandbox2/monitor_unotify.cc

+22-81
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
#include "sandboxed_api/sandbox2/monitor_unotify.h"
22

3-
#include <linux/audit.h>
43
#include <linux/seccomp.h>
54
#include <poll.h>
65
#include <sys/eventfd.h>
7-
#include <sys/ioctl.h>
86
#include <sys/ptrace.h>
97
#include <sys/resource.h>
108
#include <sys/sysinfo.h>
@@ -17,8 +15,6 @@
1715
#include <atomic>
1816
#include <cerrno>
1917
#include <cstdint>
20-
#include <cstdlib>
21-
#include <cstring>
2218
#include <memory>
2319
#include <string>
2420
#include <utility>
@@ -36,7 +32,6 @@
3632
#include "absl/time/clock.h"
3733
#include "absl/time/time.h"
3834
#include "absl/types/span.h"
39-
#include "sandboxed_api/config.h"
4035
#include "sandboxed_api/sandbox2/bpf_evaluator.h"
4136
#include "sandboxed_api/sandbox2/client.h"
4237
#include "sandboxed_api/sandbox2/executor.h"
@@ -45,6 +40,7 @@
4540
#include "sandboxed_api/sandbox2/notify.h"
4641
#include "sandboxed_api/sandbox2/policy.h"
4742
#include "sandboxed_api/sandbox2/result.h"
43+
#include "sandboxed_api/sandbox2/util/seccomp_unotify.h"
4844
#include "sandboxed_api/util/fileops.h"
4945
#include "sandboxed_api/util/status_macros.h"
5046
#include "sandboxed_api/util/thread.h"
@@ -53,34 +49,8 @@
5349
#define SECCOMP_RET_USER_NOTIF 0x7fc00000U /* notifies userspace */
5450
#endif
5551

56-
#ifndef SECCOMP_USER_NOTIF_FLAG_CONTINUE
57-
#define SECCOMP_USER_NOTIF_FLAG_CONTINUE 1
58-
#endif
59-
6052
#define DO_USER_NOTIF BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_USER_NOTIF)
6153

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-
8454
namespace sandbox2 {
8555

8656
namespace {
@@ -91,23 +61,6 @@ int seccomp(unsigned int operation, unsigned int flags, void* args) {
9161
return syscall(SYS_seccomp, operation, flags, args);
9262
}
9363

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-
11164
absl::Status WaitForFdReadable(int fd, absl::Time deadline) {
11265
pollfd pfds[] = {
11366
{.fd = fd, .events = POLLIN},
@@ -202,53 +155,47 @@ void UnotifyMonitor::HandleViolation(const Syscall& syscall) {
202155
: ViolationType::kArchitectureSwitch;
203156
LogSyscallViolation(syscall);
204157
notify_->EventSyscallViolation(syscall, violation_type);
205-
MaybeGetStackTrace(req_->pid, Result::VIOLATION);
158+
MaybeGetStackTrace(syscall.pid(), Result::VIOLATION);
206159
SetExitStatusCode(Result::VIOLATION, syscall.nr());
207160
notify_->EventSyscallViolation(syscall, violation_type);
208161
result_.SetSyscall(std::make_unique<Syscall>(syscall));
209162
KillSandboxee();
210163
}
211164

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)) {
221175
VLOG(1) << "Unotify send failed with ENOENT";
222176
} else {
223-
LOG_IF(ERROR, errno == EINVAL)
224-
<< "Unotify send failed with EINVAL. Likely "
225-
"SECCOMP_USER_NOTIF_FLAG_CONTINUE unsupported by the kernel.";
226177
SetExitStatusCode(Result::INTERNAL_ERROR, Result::FAILED_NOTIFY);
227178
}
228179
}
229180
}
230181

231182
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())) {
236186
VLOG(1) << "Unotify recv failed with ENOENT";
237187
} else {
238188
SetExitStatusCode(Result::INTERNAL_ERROR, Result::FAILED_NOTIFY);
189+
return;
239190
}
240-
return;
241191
}
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);
246192
absl::StatusOr<uint32_t> policy_ret =
247-
bpf::Evaluate(original_policy_, req_->data);
193+
bpf::Evaluate(original_policy_, req_data->data);
248194
if (!policy_ret.ok()) {
249195
LOG(ERROR) << "Failed to evaluate policy: " << policy_ret.status();
250196
SetExitStatusCode(Result::INTERNAL_ERROR, Result::FAILED_NOTIFY);
251197
}
198+
Syscall syscall(*req_data);
252199
const sock_filter trace_action = SANDBOX2_TRACE;
253200
bool should_trace = *policy_ret == trace_action.k;
254201
Notify::TraceAction trace_response = Notify::TraceAction::kDeny;
@@ -257,7 +204,7 @@ void UnotifyMonitor::HandleUnotify() {
257204
}
258205
switch (trace_response) {
259206
case Notify::TraceAction::kAllow:
260-
AllowSyscallViaUnotify();
207+
AllowSyscallViaUnotify(*req_data);
261208
return;
262209
case Notify::TraceAction::kDeny:
263210
HandleViolation(syscall);
@@ -290,7 +237,7 @@ void UnotifyMonitor::Run() {
290237

291238
pollfd pfds[] = {
292239
{.fd = process_.status_fd.get(), .events = POLLIN},
293-
{.fd = seccomp_notify_fd_.get(), .events = POLLIN},
240+
{.fd = seccomp_unotify_.GetFd(), .events = POLLIN},
294241
{.fd = monitor_notify_fd_.get(), .events = POLLIN},
295242
};
296243
while (result_.final_status() == Result::UNSET) {
@@ -405,16 +352,10 @@ bool UnotifyMonitor::InitSetupUnotify() {
405352
LOG(ERROR) << "Couldn't recv unotify fd";
406353
return false;
407354
}
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;
412357
return false;
413358
}
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_)));
418359
return true;
419360
}
420361

sandboxed_api/sandbox2/monitor_unotify.h

+3-7
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include <atomic>
1111
#include <cstdint>
1212
#include <cstdlib>
13-
#include <memory>
1413
#include <string>
1514
#include <vector>
1615

@@ -25,6 +24,7 @@
2524
#include "sandboxed_api/sandbox2/notify.h"
2625
#include "sandboxed_api/sandbox2/policy.h"
2726
#include "sandboxed_api/sandbox2/result.h"
27+
#include "sandboxed_api/sandbox2/util/seccomp_unotify.h"
2828
#include "sandboxed_api/util/fileops.h"
2929
#include "sandboxed_api/util/thread.h"
3030

@@ -96,7 +96,7 @@ class UnotifyMonitor : public MonitorBase {
9696
bool KillSandboxee();
9797
void KillInit();
9898

99-
void AllowSyscallViaUnotify();
99+
void AllowSyscallViaUnotify(seccomp_notif req);
100100
void HandleViolation(const Syscall& syscall);
101101
void HandleUnotify();
102102
void SetExitStatusFromStatusPipe();
@@ -108,7 +108,6 @@ class UnotifyMonitor : public MonitorBase {
108108
void NotifyMonitor();
109109

110110
absl::Notification setup_notification_;
111-
sapi::file_util::fileops::FDCloser seccomp_notify_fd_;
112111
sapi::file_util::fileops::FDCloser monitor_notify_fd_;
113112
// Original policy as configured by the user.
114113
std::vector<sock_filter> original_policy_;
@@ -132,10 +131,7 @@ class UnotifyMonitor : public MonitorBase {
132131
// Synchronizes monitor thread deletion and notifying the monitor.
133132
absl::Mutex notify_mutex_;
134133

135-
size_t req_size_;
136-
std::unique_ptr<seccomp_notif, StdFreeDeleter> req_;
137-
size_t resp_size_;
138-
std::unique_ptr<seccomp_notif_resp, StdFreeDeleter> resp_;
134+
util::SeccompUnotify seccomp_unotify_;
139135
};
140136

141137
} // namespace sandbox2

sandboxed_api/sandbox2/syscall.cc

+29
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "sandboxed_api/sandbox2/syscall.h"
1616

1717
#include <linux/audit.h>
18+
#include <linux/seccomp.h>
1819

1920
#include <cstdint>
2021
#include <string>
@@ -31,6 +32,34 @@
3132
#endif
3233

3334
namespace sandbox2 {
35+
namespace {
36+
37+
sapi::cpu::Architecture AuditArchToCPUArch(uint32_t arch) {
38+
switch (arch) {
39+
case AUDIT_ARCH_AARCH64:
40+
return sapi::cpu::Architecture::kArm64;
41+
case AUDIT_ARCH_ARM:
42+
return sapi::cpu::Architecture::kArm;
43+
case AUDIT_ARCH_X86_64:
44+
return sapi::cpu::Architecture::kX8664;
45+
case AUDIT_ARCH_I386:
46+
return sapi::cpu::Architecture::kX86;
47+
case AUDIT_ARCH_PPC64LE:
48+
return sapi::cpu::Architecture::kPPC64LE;
49+
default:
50+
return sapi::cpu::Architecture::kUnknown;
51+
}
52+
}
53+
} // namespace
54+
55+
Syscall::Syscall(const seccomp_notif& req)
56+
: arch_(AuditArchToCPUArch(req.data.arch)),
57+
nr_(req.data.nr),
58+
args_({req.data.args[0], req.data.args[1], req.data.args[2],
59+
req.data.args[3], req.data.args[4], req.data.args[5]}),
60+
pid_(req.pid),
61+
sp_(0),
62+
ip_(req.data.instruction_pointer) {}
3463

3564
std::string Syscall::GetArchDescription(sapi::cpu::Architecture arch) {
3665
switch (arch) {

sandboxed_api/sandbox2/syscall.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#ifndef SANDBOXED_API_SANDBOX2_SYSCALL_H__
1919
#define SANDBOXED_API_SANDBOX2_SYSCALL_H__
2020

21+
#include <linux/seccomp.h>
2122
#include <sys/types.h>
2223

2324
#include <array>
@@ -30,6 +31,10 @@
3031
#include "sandboxed_api/sandbox2/syscall_defs.h"
3132

3233
namespace sandbox2 {
34+
class Regs;
35+
namespace util {
36+
class SeccompUnotify;
37+
}
3338

3439
class Syscall {
3540
public:
@@ -49,6 +54,7 @@ class Syscall {
4954
static std::string GetArchDescription(sapi::cpu::Architecture arch);
5055

5156
Syscall() = default;
57+
Syscall(const seccomp_notif& req);
5258
Syscall(sapi::cpu::Architecture arch, uint64_t nr, Args args = {})
5359
: arch_(arch), nr_(nr), args_(args) {}
5460

@@ -66,7 +72,6 @@ class Syscall {
6672

6773
private:
6874
friend class Regs;
69-
friend class UnotifyMonitor;
7075

7176
explicit Syscall(pid_t pid) : pid_(pid) {}
7277
Syscall(sapi::cpu::Architecture arch, uint64_t nr, Args args, pid_t pid,

sandboxed_api/sandbox2/util/BUILD

+33
Original file line numberDiff line numberDiff line change
@@ -177,3 +177,36 @@ cc_test(
177177
"@com_google_sandboxed_api//sandboxed_api/util:thread",
178178
],
179179
)
180+
181+
cc_library(
182+
name = "seccomp_unotify",
183+
srcs = ["seccomp_unotify.cc"],
184+
hdrs = ["seccomp_unotify.h"],
185+
copts = sapi_platform_copts(),
186+
deps = [
187+
":bpf_helper",
188+
"@com_google_absl//absl/cleanup",
189+
"@com_google_absl//absl/log",
190+
"@com_google_absl//absl/status",
191+
"@com_google_absl//absl/status:statusor",
192+
"@com_google_absl//absl/synchronization",
193+
"@com_google_sandboxed_api//sandboxed_api/sandbox2:syscall",
194+
"@com_google_sandboxed_api//sandboxed_api/sandbox2:util",
195+
"@com_google_sandboxed_api//sandboxed_api/util:fileops",
196+
"@com_google_sandboxed_api//sandboxed_api/util:strerror",
197+
"@com_google_sandboxed_api//sandboxed_api/util:thread",
198+
],
199+
)
200+
201+
cc_test(
202+
name = "seccomp_unotify_test",
203+
srcs = ["seccomp_unotify_test.cc"],
204+
copts = sapi_platform_copts(),
205+
deps = [
206+
":seccomp_unotify",
207+
"@com_google_absl//absl/status:statusor",
208+
"@com_google_googletest//:gtest_main",
209+
"@com_google_sandboxed_api//sandboxed_api/util:fileops",
210+
"@com_google_sandboxed_api//sandboxed_api/util:status_matchers",
211+
],
212+
)

0 commit comments

Comments
 (0)