Skip to content

Commit ff53a96

Browse files
dvyukovcopybara-github
authored andcommitted
Prepare for auto-generating syscall policy for cc_sandboxed_library
PiperOrigin-RevId: 809027184 Change-Id: Ibedd9b969ccf78698e3dd50014a33ff6ebeba505
1 parent efac7f9 commit ff53a96

4 files changed

Lines changed: 77 additions & 3 deletions

File tree

sandboxed_api/bazel/sapi.bzl

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -510,10 +510,13 @@ def cc_sandboxed_library(
510510
# in the sandbox, and will deconstruct string_view into the pair of arguments.
511511
# 2. Build cc_library with the sandboxee header and source files
512512
# and dependency on the original library.
513-
# 3. Create a sapi_library for the sandboxee library created at step 2.
513+
# 3. Build fake cc_binary with main function that calls all sandbox entry functions
514+
# (and depends on the sandboxed library).
515+
# 4. Run syscall extractor on the binary to extract the system call policy.
516+
# 5. Create a sapi_library for the sandboxee library created at step 2.
514517
# This library also links in the generated host source file,
515518
# so that it implements the original library interface verbatim.
516-
# 4. Create a transparent replacement rule that pretends to be a cc_library
519+
# 6. Create a transparent replacement rule that pretends to be a cc_library
517520
# by assembling CcInfo from compilation context of the original library
518521
# and linking context of the sapi_library created at step 3.
519522
# Using the compilation context of the original library ensures that during
@@ -562,10 +565,13 @@ def cc_sandboxed_library(
562565
name = "_sapi_" + name,
563566
lib = ":_sapi_sandboxee_" + name,
564567
lib_name = wrapper_name,
565-
srcs = [name + ".sapi.host.cc"],
568+
srcs = [
569+
name + ".sapi.host.cc",
570+
],
566571
generator_version = 2,
567572
deps = [
568573
"//sandboxed_api:lenval_core",
574+
"//sandboxed_api/sandbox2/util:bpf_helper",
569575
"@abseil-cpp//absl/log:check",
570576
],
571577
**common

sandboxed_api/testcases/replaced_library.cc

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,25 @@
1414

1515
#include "sandboxed_api/testcases/replaced_library.h"
1616

17+
#include <err.h>
18+
#include <errno.h>
19+
#include <sys/epoll.h>
20+
#include <sys/syscall.h>
21+
#include <unistd.h>
22+
1723
#include <cstddef>
1824
#include <cstdint>
1925
#include <string>
2026

2127
#include "absl/strings/string_view.h"
2228

29+
bool mylib_is_sandboxed() {
30+
// Magic sandbox2 syscall number.
31+
// Note: we don't use sandbox2::unit::IsRunningInSandbox2 b/c it pulls in
32+
// too many dependencies and disturbs the policy too much.
33+
return syscall(0xff000fdb) == -1 && errno == 0xfdb;
34+
}
35+
2336
void mylib_scalar_types(int a0, float a1, double a2, int64_t a3, char a4,
2437
bool a5, size_t a6) {}
2538

@@ -30,3 +43,38 @@ void mylib_copy(absl::string_view src, std::string& dst) {
3043
}
3144

3245
int mylib_add(int x, int y) { return x + y; }
46+
47+
// Sanitizer instrumentation may break argument value tracking.
48+
// In particular, ASan emits a call to __asan_memset to zero ev.
49+
static __attribute__((noinline, disable_sanitizer_instrumentation)) void
50+
mylib_epoll_ctl(int cmd) {
51+
// Use epoll_ctl as test syscall b/c it's not used otherwise (e.g. by libc)
52+
// and has subcommands. Also uninline it to make allowed command tracking
53+
// a bit more difficult.
54+
epoll_event ev = {};
55+
int ret = syscall(SYS_epoll_ctl, -1, cmd, -1, &ev);
56+
if (ret == 0 || errno != EBADF)
57+
errx(1, "epoll_ctl did not fail as expected: ret=%d, errno=%d", ret, errno);
58+
}
59+
60+
void mylib_expected_syscall1() { mylib_epoll_ctl(EPOLL_CTL_ADD); }
61+
62+
void mylib_expected_syscall2() { mylib_epoll_ctl(EPOLL_CTL_DEL); }
63+
64+
void mylib_unexpected_syscall1() {
65+
epoll_event ev = {};
66+
// Hide the syscall number via a volatile access, syscall extractor won't
67+
// discover it since it does not track memory accesses. So EPOLL_CTL_MOD
68+
// should end up being prohibited (while ADD/DEL should be allowed).
69+
static volatile int nr = SYS_epoll_ctl;
70+
int ret = syscall(nr, -1, EPOLL_CTL_MOD, -1, &ev);
71+
if (ret == 0 || errno != EBADF)
72+
errx(1, "epoll_ctl did not fail as expected: ret=%d, errno=%d", ret, errno);
73+
}
74+
75+
void mylib_unexpected_syscall2() {
76+
// This syscall should be prohibited (nothing else in the binary should use
77+
// this esoteric syscall).
78+
static volatile int nr = SYS_ioprio_get;
79+
if (syscall(nr, 1, 0)) errx(1, "ioprio_get failed");
80+
}

sandboxed_api/testcases/replaced_library.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,17 @@
2626

2727
#include "absl/strings/string_view.h"
2828

29+
bool mylib_is_sandboxed();
30+
2931
void mylib_scalar_types(int a0, float a1, double a2, int64_t a3, char a4,
3032
bool a5, size_t a6);
3133
int mylib_add(int x, int y);
3234
std::string mylib_copy(const std::string& src);
3335
void mylib_copy(absl::string_view src, std::string& dst);
3436

37+
void mylib_expected_syscall1();
38+
void mylib_expected_syscall2();
39+
void mylib_unexpected_syscall1();
40+
void mylib_unexpected_syscall2();
41+
3542
#endif // SANDBOXED_API_SANDBOX2_TESTCASES_REPLACED_LIBRARY_H_

sandboxed_api/tools/clang_generator/sandboxed_library_emitter.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,18 @@ constexpr absl::string_view kHeaderHeader =
7777
)";
7878

7979
constexpr absl::string_view kHostHeader = R"(
80+
#include <memory>
81+
8082
#include "$0absl/log/check.h"
8183
#include "$0sandboxed_api/vars.h"
8284
#include "$0sandboxed_api/sandbox.h"
8385
86+
__attribute__((weak))
87+
std::unique_ptr<sandbox2::Policy> $1SandboxModifyPolicy(
88+
sandbox2::PolicyBuilder* builder) {
89+
return builder->BuildOrDie();
90+
}
91+
8492
struct $1SandboxImpl : public $1Sandbox {
8593
static $1SandboxImpl* Instance() {
8694
static $1SandboxImpl instance;
@@ -92,6 +100,11 @@ struct $1SandboxImpl : public $1Sandbox {
92100
void Check(const absl::Status& status) {
93101
CHECK_OK(status) << "SAPI sandbox $1 failed";
94102
}
103+
104+
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
105+
sandbox2::PolicyBuilder* builder) override {
106+
return $1SandboxModifyPolicy(builder);
107+
}
95108
};
96109
97110
)";

0 commit comments

Comments
 (0)