aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-02-28 21:12:08 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-02-28 21:12:08 +0000
commitde52c92466a958191403bea1b6cedf5d1b88ef8b (patch)
treea4ebe56fe319047144b94bf8290bca25bb6c4bd3
parent5e25d68ae73c8df54a81fe828274c67cd5e4f562 (diff)
parentbbaabc5ab384b910d474223313e866d75b3bfcec (diff)
downloadsandboxed-api-simpleperf-release.tar.gz
Snap for 11510257 from bbaabc5ab384b910d474223313e866d75b3bfcec to simpleperf-releasesimpleperf-release
Change-Id: I9c5bf3b9da480d9bbc4cb958672aa6f4e1786726
-rw-r--r--.github/workflows/fedora-cmake.yml4
-rw-r--r--.github/workflows/ubuntu-cmake-contrib.yml4
-rw-r--r--contrib/zopfli/sandboxed.h2
-rw-r--r--oss-internship-2020/curl/sandbox.h2
-rw-r--r--oss-internship-2020/libpng/sandboxed.h2
-rw-r--r--oss-internship-2020/libuv/examples/uvcat.cc2
-rw-r--r--oss-internship-2020/libuv/tests/test_os.cc2
-rw-r--r--sandboxed_api/bazel/sapi.bzl4
-rw-r--r--sandboxed_api/rpcchannel.cc10
-rw-r--r--sandboxed_api/sandbox.cc52
-rw-r--r--sandboxed_api/sandbox.h2
-rw-r--r--sandboxed_api/sandbox2/BUILD.bazel28
-rw-r--r--sandboxed_api/sandbox2/CMakeLists.txt14
-rw-r--r--sandboxed_api/sandbox2/examples/network/network_sandbox.cc2
-rw-r--r--sandboxed_api/sandbox2/examples/network_proxy/networkproxy_sandbox.cc3
-rw-r--r--sandboxed_api/sandbox2/fork_client.cc7
-rw-r--r--sandboxed_api/sandbox2/fork_client.h9
-rw-r--r--sandboxed_api/sandbox2/forkserver.cc24
-rw-r--r--sandboxed_api/sandbox2/global_forkclient.cc2
-rw-r--r--sandboxed_api/sandbox2/global_forkclient.h2
-rw-r--r--sandboxed_api/sandbox2/logserver.proto3
-rw-r--r--sandboxed_api/sandbox2/monitor_base.cc2
-rw-r--r--sandboxed_api/sandbox2/mounts.cc10
-rw-r--r--sandboxed_api/sandbox2/notify.h1
-rw-r--r--sandboxed_api/sandbox2/notify_test.cc17
-rw-r--r--sandboxed_api/sandbox2/policy.cc5
-rw-r--r--sandboxed_api/sandbox2/policybuilder.cc38
-rw-r--r--sandboxed_api/sandbox2/policybuilder.h52
-rw-r--r--sandboxed_api/sandbox2/sandbox2_test.cc19
-rw-r--r--sandboxed_api/sandbox2/stack_trace.cc2
-rw-r--r--sandboxed_api/sandbox2/syscall_defs.cc249
-rw-r--r--sandboxed_api/sandbox2/syscall_defs.h50
-rw-r--r--sandboxed_api/sandbox2/testcases/BUILD.bazel13
-rw-r--r--sandboxed_api/sandbox2/testcases/CMakeLists.txt16
-rw-r--r--sandboxed_api/sandbox2/testcases/custom_fork.cc34
-rw-r--r--sandboxed_api/sandbox2/testcases/starve.cc2
-rw-r--r--sandboxed_api/sandbox2/trace_all_syscalls.h27
-rw-r--r--sandboxed_api/sandbox2/util/BUILD.bazel2
-rw-r--r--sandboxed_api/sapi_test.cc19
-rw-r--r--sandboxed_api/tools/generator2/code_test.py2
-rw-r--r--sandboxed_api/var_ptr.h5
41 files changed, 587 insertions, 158 deletions
diff --git a/.github/workflows/fedora-cmake.yml b/.github/workflows/fedora-cmake.yml
index e2a4bb8..9157dd5 100644
--- a/.github/workflows/fedora-cmake.yml
+++ b/.github/workflows/fedora-cmake.yml
@@ -11,7 +11,7 @@ jobs:
fail-fast: false
matrix:
include:
- - container: fedora:35
+ - container: fedora:38
compiler: gcc
compiler-version: 11 # Only used in cache action so far
ignore-errors: true # Stack trace test fails on Fedora (issue #118)
@@ -56,7 +56,7 @@ jobs:
- name: Create Build Environment
run: |
- $RUN_CMD pip3 install --progress-bar=off absl-py clang
+ $RUN_CMD pip3 install --progress-bar=off absl-py 'clang>=13,<14'
$RUN_CMD cmake -E make_directory $GITHUB_WORKSPACE/build
- name: Configure CMake
diff --git a/.github/workflows/ubuntu-cmake-contrib.yml b/.github/workflows/ubuntu-cmake-contrib.yml
index 193b97d..8d67218 100644
--- a/.github/workflows/ubuntu-cmake-contrib.yml
+++ b/.github/workflows/ubuntu-cmake-contrib.yml
@@ -10,7 +10,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- os: [ubuntu-20.04]
+ os: [ubuntu-22.04]
contrib:
- brotli
- c-blosc
@@ -78,7 +78,7 @@ jobs:
- name: Create Build Environment
run: |
- pip3 install absl-py clang
+ pip3 install absl-py 'clang>=14,<15'
cmake -E make_directory $GITHUB_WORKSPACE/build
- name: Configure CMake
diff --git a/contrib/zopfli/sandboxed.h b/contrib/zopfli/sandboxed.h
index 80442e3..7f25069 100644
--- a/contrib/zopfli/sandboxed.h
+++ b/contrib/zopfli/sandboxed.h
@@ -31,7 +31,7 @@ class ZopfliSapiSandbox : public ZopfliSandbox {
.AllowDynamicStartup()
.AllowWrite()
.AllowExit()
- .AllowMmap()
+ .AllowMmapWithoutExec()
.AllowSystemMalloc()
.AllowSyscalls({
__NR_recvmsg,
diff --git a/oss-internship-2020/curl/sandbox.h b/oss-internship-2020/curl/sandbox.h
index 29bbbc2..49cf7ad 100644
--- a/oss-internship-2020/curl/sandbox.h
+++ b/oss-internship-2020/curl/sandbox.h
@@ -38,7 +38,7 @@ class CurlSapiSandbox : public curl::CurlSandbox {
.AllowFutexOp(FUTEX_WAIT_PRIVATE)
.AllowFutexOp(FUTEX_WAKE_PRIVATE)
.AllowFutexOp(FUTEX_REQUEUE_PRIVATE)
- .AllowMmap()
+ .AllowMmapWithoutExec()
.AllowOpen()
.AllowSafeFcntl()
.AllowWrite()
diff --git a/oss-internship-2020/libpng/sandboxed.h b/oss-internship-2020/libpng/sandboxed.h
index c811ddc..d55247e 100644
--- a/oss-internship-2020/libpng/sandboxed.h
+++ b/oss-internship-2020/libpng/sandboxed.h
@@ -38,7 +38,7 @@ class LibPNGSapiSandbox : public LibPNGSandbox {
.AllowOpen()
.AllowExit()
.AllowStat()
- .AllowMmap()
+ .AllowMmapWithoutExec()
.AllowSystemMalloc()
.AllowSyscalls({
__NR_futex,
diff --git a/oss-internship-2020/libuv/examples/uvcat.cc b/oss-internship-2020/libuv/examples/uvcat.cc
index 7b54f76..cc930fa 100644
--- a/oss-internship-2020/libuv/examples/uvcat.cc
+++ b/oss-internship-2020/libuv/examples/uvcat.cc
@@ -37,7 +37,7 @@ class UVSapiUVCatSandbox : public uv::UVSandbox {
.AllowFork()
.AllowFutexOp(FUTEX_WAKE_PRIVATE)
.AllowFutexOp(FUTEX_WAIT_PRIVATE)
- .AllowMmap()
+ .AllowMmapWithoutExec()
.AllowOpen()
.AllowEpoll()
.AllowSyscall(__NR_eventfd2)
diff --git a/oss-internship-2020/libuv/tests/test_os.cc b/oss-internship-2020/libuv/tests/test_os.cc
index 1e5da3b..a96a5ce 100644
--- a/oss-internship-2020/libuv/tests/test_os.cc
+++ b/oss-internship-2020/libuv/tests/test_os.cc
@@ -32,7 +32,7 @@ class UVTestOSSapiSandbox : public uv::UVSandbox {
.AllowExit()
.AllowFutexOp(FUTEX_WAKE_PRIVATE)
.AllowGetIDs()
- .AllowMmap()
+ .AllowMmapWithoutExec()
.AllowOpen()
.AllowWrite()
.AllowSyscalls({__NR_connect, __NR_socket})
diff --git a/sandboxed_api/bazel/sapi.bzl b/sandboxed_api/bazel/sapi.bzl
index 4b79e41..386c32b 100644
--- a/sandboxed_api/bazel/sapi.bzl
+++ b/sandboxed_api/bazel/sapi.bzl
@@ -146,10 +146,10 @@ def _sapi_interface_impl(ctx):
# Disable warnings in parsed code
extra_flags.append("--extra-arg=-Wno-everything")
- extra_flags += ["--extra-arg=-isystem{}".format(d) for d in cpp_toolchain.built_in_include_directories]
extra_flags += ["--extra-arg=-D{}".format(d) for d in cc_ctx.defines.to_list()]
extra_flags += ["--extra-arg=-isystem{}".format(i) for i in cc_ctx.system_includes.to_list()]
extra_flags += ["--extra-arg=-iquote{}".format(i) for i in quote_includes]
+ extra_flags += ["--extra-arg=-isystem{}".format(d) for d in cpp_toolchain.built_in_include_directories]
else:
append_all(extra_flags, "-D", cc_ctx.defines.to_list())
append_all(extra_flags, "-isystem", cc_ctx.system_includes.to_list())
@@ -236,6 +236,7 @@ def sapi_library(
name,
lib,
lib_name,
+ malloc = "@bazel_tools//tools/cpp:malloc",
namespace = "",
api_version = 1,
embed = True,
@@ -355,6 +356,7 @@ def sapi_library(
# The sandboxing client must have access to all
"-Wl,-E", # symbols used in the sandboxed library, so these
] + exported_funcs, # must be both referenced, and exported
+ malloc = malloc,
deps = [
":" + name + ".lib",
"//sandboxed_api:client",
diff --git a/sandboxed_api/rpcchannel.cc b/sandboxed_api/rpcchannel.cc
index 7eeb447..7e76b05 100644
--- a/sandboxed_api/rpcchannel.cc
+++ b/sandboxed_api/rpcchannel.cc
@@ -140,16 +140,6 @@ absl::Status RPCChannel::Exit() {
// Try the RPC exit sequence. But, the only thing that matters as a success
// indicator is whether the Comms channel had been closed
comms_->SendTLV(comms::kMsgExit, 0, nullptr);
- bool unused;
- comms_->RecvBool(&unused);
-
- if (!comms_->IsTerminated()) {
- LOG(ERROR) << "Comms channel not terminated in Exit()";
- // TODO(hamacher): Better error code
- return absl::FailedPreconditionError(
- "Comms channel not terminated in Exit()");
- }
-
return absl::OkStatus();
}
diff --git a/sandboxed_api/sandbox.cc b/sandboxed_api/sandbox.cc
index b134ac9..88b2696 100644
--- a/sandboxed_api/sandbox.cc
+++ b/sandboxed_api/sandbox.cc
@@ -40,6 +40,7 @@
#include "sandboxed_api/sandbox2/executor.h"
#include "sandboxed_api/sandbox2/policy.h"
#include "sandboxed_api/sandbox2/policybuilder.h"
+#include "sandboxed_api/sandbox2/result.h"
#include "sandboxed_api/sandbox2/sandbox2.h"
#include "sandboxed_api/sandbox2/util/bpf_helper.h"
#include "sandboxed_api/util/fileops.h"
@@ -75,6 +76,7 @@ void InitDefaultPolicyBuilder(sandbox2::PolicyBuilder* builder) {
.AllowGetPIDs()
.AllowSleep()
.AllowReadlink()
+ .AllowAccess()
.AllowSyscalls({
__NR_recvmsg,
__NR_sendmsg,
@@ -105,20 +107,31 @@ void Sandbox::Terminate(bool attempt_graceful_exit) {
return;
}
+ absl::StatusOr<sandbox2::Result> result;
if (attempt_graceful_exit) {
- // Gracefully ask it to exit (with 1 second limit) first, then kill it.
- Exit();
- } else {
- // Kill it straight away
+ if (absl::Status requested_exit = rpc_channel_->Exit();
+ !requested_exit.ok()) {
+ LOG(WARNING)
+ << "rpc_channel->Exit() failed, calling AwaitResultWithTimeout(1) "
+ << requested_exit;
+ }
+ result = s2_->AwaitResultWithTimeout(absl::Seconds(1));
+ if (!result.ok()) {
+ LOG(WARNING) << "s2_->AwaitResultWithTimeout failed, status: "
+ << result.status() << " Killing PID: " << pid();
+ }
+ }
+
+ if (!attempt_graceful_exit || !result.ok()) {
s2_->Kill();
+ result = s2_->AwaitResult();
}
- const auto& result = AwaitResult();
- if (result.final_status() == sandbox2::Result::OK &&
- result.reason_code() == 0) {
- VLOG(2) << "Sandbox2 finished with: " << result.ToString();
+ if (result->final_status() == sandbox2::Result::OK &&
+ result->reason_code() == 0) {
+ VLOG(2) << "Sandbox2 finished with: " << result->ToString();
} else {
- LOG(WARNING) << "Sandbox2 finished with: " << result.ToString();
+ LOG(WARNING) << "Sandbox2 finished with: " << result->ToString();
}
}
@@ -127,7 +140,7 @@ static std::string PathToSAPILib(const std::string& lib_path) {
: GetDataDependencyFilePath(lib_path);
}
-absl::Status Sandbox::Init() {
+absl::Status Sandbox::Init(bool use_unotify_monitor) {
// It's already initialized
if (is_active()) {
return absl::OkStatus();
@@ -176,6 +189,9 @@ absl::Status Sandbox::Init() {
sandbox2::PolicyBuilder policy_builder;
InitDefaultPolicyBuilder(&policy_builder);
+ if (use_unotify_monitor) {
+ policy_builder.CollectStacktracesOnSignal(false);
+ }
auto s2p = ModifyPolicy(&policy_builder);
// Spawn new process from the forkserver.
@@ -196,6 +212,9 @@ absl::Status Sandbox::Init() {
s2_ = std::make_unique<sandbox2::Sandbox2>(std::move(executor),
std::move(s2p), CreateNotifier());
+ if (use_unotify_monitor) {
+ SAPI_RETURN_IF_ERROR(s2_->EnableUnotifyMonitor());
+ }
s2_awaited_ = false;
auto res = s2_->RunAsync();
@@ -306,6 +325,14 @@ absl::Status Sandbox::Call(const std::string& func, v::Callable* ret,
// Copy all arguments into rfcall.
int i = 0;
for (auto* arg : args) {
+ if (arg == nullptr) {
+ rfcall.arg_type[i] = v::Type::kPointer;
+ rfcall.arg_size[i] = sizeof(void*);
+ rfcall.args[i].arg_int = 0;
+ VLOG(1) << "CALL ARG: (" << i << "): nullptr";
+ ++i;
+ continue;
+ }
rfcall.arg_size[i] = arg->GetSize();
rfcall.arg_type[i] = arg->GetType();
@@ -339,7 +366,6 @@ absl::Status Sandbox::Call(const std::string& func, v::Callable* ret,
}
rfcall.args[i].arg_int = fd->GetRemoteFd();
}
-
VLOG(1) << "CALL ARG: (" << i << "), Type: " << arg->GetTypeString()
<< ", Size: " << arg->GetSize() << ", Val: " << arg->ToString();
++i;
@@ -364,7 +390,9 @@ absl::Status Sandbox::Call(const std::string& func, v::Callable* ret,
// Synchronize all pointers after the call if it's needed.
for (auto* arg : args) {
- SAPI_RETURN_IF_ERROR(SynchronizePtrAfter(arg));
+ if (arg != nullptr) {
+ SAPI_RETURN_IF_ERROR(SynchronizePtrAfter(arg));
+ }
}
VLOG(1) << "CALL EXIT: Type: " << ret->GetTypeString()
diff --git a/sandboxed_api/sandbox.h b/sandboxed_api/sandbox.h
index 577144e..b691e08 100644
--- a/sandboxed_api/sandbox.h
+++ b/sandboxed_api/sandbox.h
@@ -52,7 +52,7 @@ class Sandbox {
virtual ~Sandbox();
// Initializes a new sandboxing session.
- absl::Status Init();
+ absl::Status Init(bool use_unotify_monitor = false);
// Returns whether the current sandboxing session is active.
bool is_active() const;
diff --git a/sandboxed_api/sandbox2/BUILD.bazel b/sandboxed_api/sandbox2/BUILD.bazel
index 9e0ade3..3b08b55 100644
--- a/sandboxed_api/sandbox2/BUILD.bazel
+++ b/sandboxed_api/sandbox2/BUILD.bazel
@@ -41,6 +41,23 @@ cc_library(
)
cc_library(
+ name = "trace_all_syscalls",
+ hdrs = ["trace_all_syscalls.h"],
+ copts = sapi_platform_copts(),
+ visibility = [
+ "//sandboxed_api/sandbox2:__pkg__",
+ ],
+)
+
+cc_library(
+ name = "testonly_trace_all_syscalls",
+ testonly = True,
+ hdrs = ["trace_all_syscalls.h"],
+ copts = sapi_platform_copts(),
+ visibility = ["//visibility:public"],
+)
+
+cc_library(
name = "allow_unrestricted_networking",
hdrs = ["allow_unrestricted_networking.h"],
copts = sapi_platform_copts(),
@@ -109,15 +126,18 @@ cc_library(
srcs = [
"syscall.cc",
"syscall_defs.cc",
+ ],
+ hdrs = [
+ "syscall.h",
"syscall_defs.h",
],
- hdrs = ["syscall.h"],
copts = sapi_platform_copts(),
visibility = ["//visibility:public"],
deps = [
":util",
"//sandboxed_api:config",
"@com_google_absl//absl/algorithm:container",
+ "@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
@@ -237,7 +257,6 @@ cc_library(
":result",
":syscall",
":util",
- "//sandboxed_api:config",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/log",
],
@@ -529,6 +548,7 @@ cc_library(
":stack_trace",
":syscall",
":util",
+ "//sandboxed_api/sandbox2/network_proxy:client",
"//sandboxed_api/sandbox2/network_proxy:server",
"//sandboxed_api/util:file_helpers",
"//sandboxed_api/util:raw_logging",
@@ -560,6 +580,7 @@ cc_library(
":namespace",
":policy",
":syscall",
+ ":trace_all_syscalls",
":violation_cc_proto",
"//sandboxed_api:config",
"//sandboxed_api/sandbox2/network_proxy:filtering",
@@ -921,6 +942,7 @@ cc_test(
deps = [
":comms",
":sandbox2",
+ ":trace_all_syscalls",
"//sandboxed_api:testing",
"@com_google_absl//absl/log",
"@com_google_absl//absl/strings",
@@ -957,6 +979,7 @@ cc_test(
copts = sapi_platform_copts(),
data = [
"//sandboxed_api/sandbox2/testcases:abort",
+ "//sandboxed_api/sandbox2/testcases:custom_fork",
"//sandboxed_api/sandbox2/testcases:minimal",
"//sandboxed_api/sandbox2/testcases:sleep",
"//sandboxed_api/sandbox2/testcases:starve",
@@ -967,6 +990,7 @@ cc_test(
"no_qemu_user_mode",
],
deps = [
+ ":fork_client",
":sandbox2",
"//sandboxed_api:config",
"//sandboxed_api:testing",
diff --git a/sandboxed_api/sandbox2/CMakeLists.txt b/sandboxed_api/sandbox2/CMakeLists.txt
index 116f609..b01c4d9 100644
--- a/sandboxed_api/sandbox2/CMakeLists.txt
+++ b/sandboxed_api/sandbox2/CMakeLists.txt
@@ -26,6 +26,15 @@ target_link_libraries(sandbox2_allow_all_syscalls PRIVATE
sapi::base
)
+# sandboxed_api/sandbox2:trace_all_syscalls
+add_library(sandbox2_trace_all_syscalls ${SAPI_LIB_TYPE}
+ trace_all_syscalls.h
+)
+add_library(sandbox2::trace_all_syscalls ALIAS sandbox2_trace_all_syscalls)
+target_link_libraries(sandbox2_trace_all_syscalls PRIVATE
+ sapi::base
+)
+
# sandboxed_api/sandbox2:allow_unrestricted_networking
add_library(sandbox2_allow_unrestricted_networking ${SAPI_LIB_TYPE}
allow_unrestricted_networking.h
@@ -194,7 +203,6 @@ target_link_libraries(sandbox2_notify
sandbox2::syscall
sandbox2::util
PRIVATE sapi::base
- sapi::config
)
# sandboxed_api/sandbox2:limits
@@ -422,6 +430,7 @@ target_link_libraries(sandbox2_monitor_base
sandbox2::executor
sandbox2::fork_client
sandbox2::ipc
+ sandbox2::network_proxy_client
sandbox2::network_proxy_server
sandbox2::notify
sandbox2::policy
@@ -994,6 +1003,7 @@ if(BUILD_TESTING AND SAPI_BUILD_TESTING)
sandbox2::comms
sandbox2::regs
sandbox2::sandbox2
+ sandbox2::trace_all_syscalls
sapi::testing
sapi::test_main
)
@@ -1039,6 +1049,7 @@ if(BUILD_TESTING AND SAPI_BUILD_TESTING)
)
add_dependencies(sandbox2_sandbox2_test
sandbox2::testcase_abort
+ sandbox2::testcase_custom_fork
sandbox2::testcase_minimal
sandbox2::testcase_sleep
sandbox2::testcase_tsync
@@ -1050,6 +1061,7 @@ if(BUILD_TESTING AND SAPI_BUILD_TESTING)
absl::synchronization
absl::time
sapi::config
+ sandbox2::fork_client
sandbox2::sandbox2
sapi::testing
sapi::status_matchers
diff --git a/sandboxed_api/sandbox2/examples/network/network_sandbox.cc b/sandboxed_api/sandbox2/examples/network/network_sandbox.cc
index 684cbde..7dca5f6 100644
--- a/sandboxed_api/sandbox2/examples/network/network_sandbox.cc
+++ b/sandboxed_api/sandbox2/examples/network/network_sandbox.cc
@@ -49,7 +49,7 @@ namespace {
std::unique_ptr<sandbox2::Policy> GetPolicy(absl::string_view sandboxee_path) {
return sandbox2::PolicyBuilder()
.AllowExit()
- .AllowMmap()
+ .AllowMmapWithoutExec()
.AllowRead()
.AllowWrite()
.AllowSyscall(__NR_close)
diff --git a/sandboxed_api/sandbox2/examples/network_proxy/networkproxy_sandbox.cc b/sandboxed_api/sandbox2/examples/network_proxy/networkproxy_sandbox.cc
index da1c800..76208d1 100644
--- a/sandboxed_api/sandbox2/examples/network_proxy/networkproxy_sandbox.cc
+++ b/sandboxed_api/sandbox2/examples/network_proxy/networkproxy_sandbox.cc
@@ -41,7 +41,7 @@ constexpr char kSandboxeePath[] =
std::unique_ptr<sandbox2::Policy> GetPolicy(absl::string_view sandboxee_path) {
sandbox2::PolicyBuilder builder;
builder.AllowExit()
- .AllowMmap()
+ .AllowMmapWithoutExec()
.AllowRead()
.AllowWrite()
.AllowStat() // printf, puts
@@ -50,6 +50,7 @@ std::unique_ptr<sandbox2::Policy> GetPolicy(absl::string_view sandboxee_path) {
.AllowSyscall(__NR_lseek)
.AllowSyscall(__NR_munmap)
.AllowSyscall(__NR_getpid)
+ .AllowSyscall(__NR_sigaltstack)
.AllowTcMalloc()
.AddLibrariesForBinary(sandboxee_path);
if (absl::GetFlag(FLAGS_connect_with_handler)) {
diff --git a/sandboxed_api/sandbox2/fork_client.cc b/sandboxed_api/sandbox2/fork_client.cc
index 285344e..7ccc22f 100644
--- a/sandboxed_api/sandbox2/fork_client.cc
+++ b/sandboxed_api/sandbox2/fork_client.cc
@@ -27,6 +27,13 @@ namespace sandbox2 {
using ::sapi::file_util::fileops::FDCloser;
+ForkClient::ForkClient(pid_t pid, Comms* comms, bool is_global)
+ : pid_(pid), comms_(comms), is_global_(is_global) {
+}
+
+ForkClient::~ForkClient() {
+}
+
SandboxeeProcess ForkClient::SendRequest(const ForkRequest& request,
int exec_fd, int comms_fd) {
SandboxeeProcess process;
diff --git a/sandboxed_api/sandbox2/fork_client.h b/sandboxed_api/sandbox2/fork_client.h
index 842b152..60d483e 100644
--- a/sandboxed_api/sandbox2/fork_client.h
+++ b/sandboxed_api/sandbox2/fork_client.h
@@ -37,9 +37,10 @@ struct SandboxeeProcess {
class ForkClient {
public:
- ForkClient(pid_t pid, Comms* comms) : pid_(pid), comms_(comms) {}
+ ForkClient(pid_t pid, Comms* comms) : ForkClient(pid, comms, false) {}
ForkClient(const ForkClient&) = delete;
ForkClient& operator=(const ForkClient&) = delete;
+ ~ForkClient();
// Sends the fork request over the supplied Comms channel.
SandboxeeProcess SendRequest(const ForkRequest& request, int exec_fd,
@@ -48,10 +49,16 @@ class ForkClient {
pid_t pid() { return pid_; }
private:
+ friend class GlobalForkClient;
+
+ ForkClient(pid_t pid, Comms* comms, bool is_global);
+
// Pid of the ForkServer.
pid_t pid_;
// Comms channel connecting with the ForkServer. Not owned by the object.
Comms* comms_ ABSL_GUARDED_BY(comms_mutex_);
+ // Is it the global forkserver
+ bool is_global_;
// Mutex locking transactions (requests) over the Comms channel.
absl::Mutex comms_mutex_;
};
diff --git a/sandboxed_api/sandbox2/forkserver.cc b/sandboxed_api/sandbox2/forkserver.cc
index 1106e02..c8b381b 100644
--- a/sandboxed_api/sandbox2/forkserver.cc
+++ b/sandboxed_api/sandbox2/forkserver.cc
@@ -543,16 +543,20 @@ bool ForkServer::Initialize() {
cap_t wanted_caps = cap_init(); // starts as empty set, ie. no caps
SAPI_RAW_CHECK(wanted_caps, "failed to cap_init()");
- for (cap_flag_t flag : {CAP_EFFECTIVE, CAP_PERMITTED}) {
- cap_flag_value_t value;
- int rc = cap_get_flag(have_caps, CAP_SETFCAP, flag, &value);
- SAPI_RAW_CHECK(!rc, "cap_get_flag");
- if (value == CAP_SET) {
- cap_value_t caps_to_set[1] = {
- CAP_SETFCAP,
- };
- rc = cap_set_flag(wanted_caps, flag, 1, caps_to_set, CAP_SET);
- SAPI_RAW_CHECK(!rc, "cap_set_flag");
+ // CAP_SYS_PTRACE appears to be needed for apparmor (or possibly yama)
+ // CAP_SETFCAP is needed on newer kernels (5.10 needs it, 4.15 does not)
+ for (cap_value_t cap : {CAP_SYS_PTRACE, CAP_SETFCAP}) {
+ for (cap_flag_t flag : {CAP_EFFECTIVE, CAP_PERMITTED}) {
+ cap_flag_value_t value;
+ int rc = cap_get_flag(have_caps, cap, flag, &value);
+ SAPI_RAW_CHECK(!rc, "cap_get_flag");
+ if (value == CAP_SET) {
+ cap_value_t caps_to_set[1] = {
+ cap,
+ };
+ rc = cap_set_flag(wanted_caps, flag, 1, caps_to_set, CAP_SET);
+ SAPI_RAW_CHECK(!rc, "cap_set_flag");
+ }
}
}
diff --git a/sandboxed_api/sandbox2/global_forkclient.cc b/sandboxed_api/sandbox2/global_forkclient.cc
index 8a6231e..b014931 100644
--- a/sandboxed_api/sandbox2/global_forkclient.cc
+++ b/sandboxed_api/sandbox2/global_forkclient.cc
@@ -271,7 +271,7 @@ void GlobalForkClient::ForceStart() {
"already running");
absl::StatusOr<std::unique_ptr<GlobalForkClient>> forkserver =
StartGlobalForkServer();
- SAPI_RAW_CHECK(forkserver.ok(), forkserver.status().message().data());
+ SAPI_RAW_CHECK(forkserver.ok(), forkserver.status().ToString().c_str());
instance_ = forkserver->release();
}
diff --git a/sandboxed_api/sandbox2/global_forkclient.h b/sandboxed_api/sandbox2/global_forkclient.h
index 4517c27..13e8ad1 100644
--- a/sandboxed_api/sandbox2/global_forkclient.h
+++ b/sandboxed_api/sandbox2/global_forkclient.h
@@ -43,7 +43,7 @@ enum class GlobalForkserverStartMode {
class GlobalForkClient {
public:
GlobalForkClient(int fd, pid_t pid)
- : comms_(fd), fork_client_(pid, &comms_) {}
+ : comms_(fd), fork_client_(pid, &comms_, /*is_global=*/true) {}
static SandboxeeProcess SendRequest(const ForkRequest& request, int exec_fd,
int comms_fd)
diff --git a/sandboxed_api/sandbox2/logserver.proto b/sandboxed_api/sandbox2/logserver.proto
index 0329c24..a2bf74d 100644
--- a/sandboxed_api/sandbox2/logserver.proto
+++ b/sandboxed_api/sandbox2/logserver.proto
@@ -13,12 +13,13 @@
// limitations under the License.
syntax = "proto3";
+
package sandbox2;
message LogMessage {
optional int32 severity = 1;
optional string path = 2;
optional int32 line = 3;
- optional string message = 4;
+ optional bytes message = 4;
optional int32 pid = 5;
}
diff --git a/sandboxed_api/sandbox2/monitor_base.cc b/sandboxed_api/sandbox2/monitor_base.cc
index 8423415..76978c9 100644
--- a/sandboxed_api/sandbox2/monitor_base.cc
+++ b/sandboxed_api/sandbox2/monitor_base.cc
@@ -50,7 +50,9 @@
#include "sandboxed_api/sandbox2/limits.h"
#include "sandboxed_api/sandbox2/mounts.h"
#include "sandboxed_api/sandbox2/namespace.h"
+#include "sandboxed_api/sandbox2/network_proxy/client.h"
#include "sandboxed_api/sandbox2/network_proxy/server.h"
+#include "sandboxed_api/sandbox2/notify.h"
#include "sandboxed_api/sandbox2/policy.h"
#include "sandboxed_api/sandbox2/result.h"
#include "sandboxed_api/sandbox2/stack_trace.h"
diff --git a/sandboxed_api/sandbox2/mounts.cc b/sandboxed_api/sandbox2/mounts.cc
index 097d53d..227d207 100644
--- a/sandboxed_api/sandbox2/mounts.cc
+++ b/sandboxed_api/sandbox2/mounts.cc
@@ -163,7 +163,7 @@ bool HasSameTarget(const MountTree::Node& n1, const MountTree::Node& n2) {
if (n1.node_case() != n2.node_case()) {
return false;
}
- // Compare proto fileds
+ // Compare proto fields
switch (n1.node_case()) {
case MountTree::Node::kFileNode:
// Check whether files are the same (e.g. symlinks / hardlinks)
@@ -185,7 +185,7 @@ bool IsEquivalentNode(const MountTree::Node& n1, const MountTree::Node& n2) {
return false;
}
- // Compare proto fileds
+ // Compare proto fields
switch (n1.node_case()) {
case MountTree::Node::kFileNode:
return n1.file_node().writable() == n2.file_node().writable();
@@ -309,7 +309,7 @@ absl::Status Mounts::Insert(absl::string_view path,
if (!internal::IsWritable(curtree->node()) &&
internal::IsWritable(new_node)) {
SAPI_RAW_LOG(INFO,
- "Chaning %s to writable, was insterted read-only before",
+ "Changing %s to writable, was inserted read-only before",
std::string(path).c_str());
*curtree->mutable_node() = new_node;
return absl::OkStatus();
@@ -317,7 +317,7 @@ absl::Status Mounts::Insert(absl::string_view path,
if (internal::IsWritable(curtree->node()) &&
!internal::IsWritable(new_node)) {
SAPI_RAW_LOG(INFO,
- "Inserting %s read-only is a nop, as it was insterted "
+ "Inserting %s read-only is a nop, as it was inserted "
"writable before",
std::string(path).c_str());
return absl::OkStatus();
@@ -349,7 +349,7 @@ absl::Status Mounts::AddFileAt(absl::string_view outside,
absl::Status Mounts::AddDirectoryAt(absl::string_view outside,
absl::string_view inside, bool is_ro) {
MountTree::Node node;
- auto dir_node = node.mutable_dir_node();
+ auto* dir_node = node.mutable_dir_node();
dir_node->set_outside(std::string(outside));
dir_node->set_writable(!is_ro);
return Insert(inside, node);
diff --git a/sandboxed_api/sandbox2/notify.h b/sandboxed_api/sandbox2/notify.h
index 8d00a7f..0195428 100644
--- a/sandboxed_api/sandbox2/notify.h
+++ b/sandboxed_api/sandbox2/notify.h
@@ -21,7 +21,6 @@
#include "absl/base/attributes.h"
#include "absl/log/log.h"
-#include "sandboxed_api/config.h"
#include "sandboxed_api/sandbox2/comms.h"
#include "sandboxed_api/sandbox2/result.h"
#include "sandboxed_api/sandbox2/syscall.h"
diff --git a/sandboxed_api/sandbox2/notify_test.cc b/sandboxed_api/sandbox2/notify_test.cc
index ad77dc8..6942f50 100644
--- a/sandboxed_api/sandbox2/notify_test.cc
+++ b/sandboxed_api/sandbox2/notify_test.cc
@@ -33,6 +33,7 @@
#include "sandboxed_api/sandbox2/policybuilder.h"
#include "sandboxed_api/sandbox2/sandbox2.h"
#include "sandboxed_api/sandbox2/syscall.h"
+#include "sandboxed_api/sandbox2/trace_all_syscalls.h"
#include "sandboxed_api/testing.h"
namespace sandbox2 {
@@ -126,5 +127,21 @@ TEST(NotifyTest, PrintPidAndComms) {
EXPECT_THAT(result.reason_code(), Eq(33));
}
+// Test EventSyscallTrap on personality syscall through TraceAllSyscalls
+TEST(NotifyTest, TraceAllAllowPersonality) {
+ const std::string path = GetTestSourcePath("sandbox2/testcases/personality");
+ std::vector<std::string> args = {path};
+ auto policy = CreateDefaultPermissiveTestPolicy(path)
+ .DefaultAction(TraceAllSyscalls())
+ .BuildOrDie();
+ Sandbox2 s2(std::make_unique<Executor>(path, args),
+ NotifyTestcasePolicy(path),
+ std::make_unique<PersonalityNotify>(/*allow=*/true));
+ auto result = s2.Run();
+
+ ASSERT_THAT(result.final_status(), Eq(Result::OK));
+ EXPECT_THAT(result.reason_code(), Eq(22));
+}
+
} // namespace
} // namespace sandbox2
diff --git a/sandboxed_api/sandbox2/policy.cc b/sandboxed_api/sandbox2/policy.cc
index 6a4b2f4..721abcf 100644
--- a/sandboxed_api/sandbox2/policy.cc
+++ b/sandboxed_api/sandbox2/policy.cc
@@ -183,8 +183,9 @@ std::vector<sock_filter> Policy::GetDefaultPolicy(bool user_notif) const {
policy.insert(policy.end(),
{
#ifdef __NR_clone3
- // Disallow clone3
- JEQ32(__NR_clone3, DENY),
+ // Disallow clone3. Errno instead of DENY so that libraries
+ // can fallback to regular clone/clone2.
+ JEQ32(__NR_clone3, ERRNO(ENOSYS)),
#endif
// Disallow clone3 and clone with unsafe flags. This uses
// LOAD_SYSCALL_NR from above.
diff --git a/sandboxed_api/sandbox2/policybuilder.cc b/sandboxed_api/sandbox2/policybuilder.cc
index 80b42d8..6fbda54 100644
--- a/sandboxed_api/sandbox2/policybuilder.cc
+++ b/sandboxed_api/sandbox2/policybuilder.cc
@@ -60,6 +60,7 @@
#include "sandboxed_api/sandbox2/namespace.h"
#include "sandboxed_api/sandbox2/policy.h"
#include "sandboxed_api/sandbox2/syscall.h"
+#include "sandboxed_api/sandbox2/trace_all_syscalls.h"
#include "sandboxed_api/sandbox2/util/bpf_helper.h"
#include "sandboxed_api/sandbox2/violation.pb.h"
#include "sandboxed_api/util/path.h"
@@ -70,6 +71,9 @@
#include <asm/termbits.h> // On PPC, TCGETS macro needs termios
#endif
+#ifndef MAP_FIXED_NOREPLACE
+#define MAP_FIXED_NOREPLACE 0x100000
+#endif
#ifndef PR_SET_VMA
#define PR_SET_VMA 0x53564d41
#endif
@@ -285,6 +289,7 @@ PolicyBuilder& PolicyBuilder::AllowTcMalloc() {
LABEL(&labels, prot_none),
ARG_32(3), // flags
JEQ32(MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, ALLOW),
+ JEQ32(MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE, ALLOW),
JEQ32(MAP_ANONYMOUS | MAP_PRIVATE, ALLOW),
LABEL(&labels, mmap_end),
@@ -329,7 +334,7 @@ PolicyBuilder& PolicyBuilder::AllowLlvmSanitizers() {
// example:
// https://github.com/llvm/llvm-project/blob/596d534ac3524052df210be8d3c01a33b2260a42/compiler-rt/lib/asan/asan_allocator.cpp#L980
// https://github.com/llvm/llvm-project/blob/62ec4ac90738a5f2d209ed28c822223e58aaaeb7/compiler-rt/lib/sanitizer_common/sanitizer_allocator_secondary.h#L98
- AllowMmap();
+ AllowMmapWithoutExec();
AllowSyscall(__NR_munmap);
AllowSyscall(__NR_sched_yield);
@@ -359,7 +364,7 @@ PolicyBuilder& PolicyBuilder::AllowLlvmSanitizers() {
OverridableBlockSyscallWithErrno(__NR_ioctl, EPERM);
// https://github.com/llvm/llvm-project/blob/9aa39481d9eb718e872993791547053a3c1f16d5/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp#L150
// https://sourceware.org/git/?p=glibc.git;a=blob;f=nptl/pthread_getattr_np.c;h=de7edfa0928224eb8375e2fe894d6677570fbb3b;hb=HEAD#l188
- OverridableBlockSyscallWithErrno(__NR_sched_getaffinity, EPERM);
+ AllowSyscall(__NR_sched_getaffinity);
// https://github.com/llvm/llvm-project/blob/02c2b472b510ff55679844c087b66e7837e13dc2/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp#L434
#ifdef __NR_readlink
OverridableBlockSyscallWithErrno(__NR_readlink, ENOENT);
@@ -415,6 +420,14 @@ PolicyBuilder& PolicyBuilder::AllowLimitedMadvise() {
});
}
+PolicyBuilder& PolicyBuilder::AllowMmapWithoutExec() {
+ return AddPolicyOnMmap({
+ ARG_32(2),
+ BPF_JUMP(BPF_JMP | BPF_JSET | BPF_K, PROT_EXEC, 1, 0),
+ ALLOW,
+ });
+}
+
PolicyBuilder& PolicyBuilder::AllowMmap() {
return AllowSyscalls(kMmapSyscalls);
}
@@ -760,11 +773,13 @@ PolicyBuilder& PolicyBuilder::AllowRestartableSequences(
AllowFutexOp(FUTEX_WAKE);
AllowRead();
AllowOpen();
+ AllowPoll();
AllowSyscall(__NR_close);
AddPolicyOnSyscall(__NR_rt_sigprocmask, {
ARG_32(0),
JEQ32(SIG_SETMASK, ALLOW),
});
+ AllowPrctlSetVma();
if (cpu_fence_mode == kAllowSlowFences) {
AllowSyscall(__NR_sched_getaffinity);
AllowSyscall(__NR_sched_setaffinity);
@@ -796,6 +811,9 @@ PolicyBuilder& PolicyBuilder::AllowGetPGIDs() {
}
PolicyBuilder& PolicyBuilder::AllowGetRlimit() {
+#ifdef __NR_prlimit64
+ AddPolicyOnSyscall(__NR_prlimit64, {ARG(2), JEQ64(0, 0, ALLOW)});
+#endif
return AllowSyscalls({
#ifdef __NR_getrlimit
__NR_getrlimit,
@@ -808,6 +826,9 @@ PolicyBuilder& PolicyBuilder::AllowGetRlimit() {
PolicyBuilder& PolicyBuilder::AllowSetRlimit() {
return AllowSyscalls({
+#ifdef __NR_prlimit64
+ __NR_prlimit64,
+#endif
#ifdef __NR_setrlimit
__NR_setrlimit,
#endif
@@ -856,7 +877,7 @@ PolicyBuilder& PolicyBuilder::AllowLogForwarding() {
ARG_32(0),
JEQ32(SIG_BLOCK, ALLOW),
});
- AllowSyscall(__NR_prlimit64);
+ AllowGetRlimit();
// For LOG(FATAL)
return AddPolicyOnSyscall(__NR_kill,
@@ -990,14 +1011,14 @@ PolicyBuilder& PolicyBuilder::AllowStaticStartup() {
OverridableBlockSyscallWithErrno(__NR_readlink, ENOENT);
#endif
-#ifdef __NR_prlimit64
- OverridableBlockSyscallWithErrno(__NR_prlimit64, EPERM);
-#endif
+ AllowGetRlimit();
AddPolicyOnSyscall(__NR_mprotect, {
ARG_32(2),
JEQ32(PROT_READ, ALLOW),
});
+ OverridableBlockSyscallWithErrno(__NR_sigaltstack, ENOSYS);
+
return *this;
}
@@ -1224,6 +1245,11 @@ PolicyBuilder& PolicyBuilder::DefaultAction(AllowAllSyscalls) {
return *this;
}
+PolicyBuilder& PolicyBuilder::DefaultAction(TraceAllSyscalls) {
+ default_action_ = SANDBOX2_TRACE;
+ return *this;
+}
+
absl::StatusOr<std::string> PolicyBuilder::ValidateAbsolutePath(
absl::string_view path) {
if (!file::IsAbsolutePath(path)) {
diff --git a/sandboxed_api/sandbox2/policybuilder.h b/sandboxed_api/sandbox2/policybuilder.h
index c832d00..5485833 100644
--- a/sandboxed_api/sandbox2/policybuilder.h
+++ b/sandboxed_api/sandbox2/policybuilder.h
@@ -43,6 +43,7 @@ struct bpf_labels;
namespace sandbox2 {
class AllowAllSyscalls;
+class TraceAllSyscalls;
class UnrestrictedNetworking;
// PolicyBuilder is a helper class to simplify creation of policies. The builder
@@ -245,20 +246,25 @@ class PolicyBuilder final {
// Appends code to allow mmap. Specifically this allows mmap and mmap2 syscall
// on architectures where this syscalls exist.
+ // Prefer using AllowMmapWithoutExec as allowing mapping executable pages
+ // makes exploitation easier.
PolicyBuilder& AllowMmap();
+ // Appends code to allow mmap calls that don't specify PROT_EXEC.
+ PolicyBuilder& AllowMmapWithoutExec();
+
// Appends code to allow calling futex with the given operation.
PolicyBuilder& AllowFutexOp(int op);
// Appends code to allow opening and possibly creating files or directories.
- // Allows these sycalls:
+ // Allows these syscalls:
// - creat
// - open
// - openat
PolicyBuilder& AllowOpen();
// Appends code to allow calling stat, fstat and lstat.
- // Allows these sycalls:
+ // Allows these syscalls:
// - fstat
// - fstat64
// - fstatat
@@ -313,7 +319,7 @@ class PolicyBuilder final {
PolicyBuilder& AllowChown();
// Appends code to the policy to allow reading from file descriptors.
- // Allows these sycalls:
+ // Allows these syscalls:
// - read
// - readv
// - preadv
@@ -321,7 +327,7 @@ class PolicyBuilder final {
PolicyBuilder& AllowRead();
// Appends code to the policy to allow writing to file descriptors.
- // Allows these sycalls:
+ // Allows these syscalls:
// - write
// - writev
// - pwritev
@@ -329,37 +335,37 @@ class PolicyBuilder final {
PolicyBuilder& AllowWrite();
// Appends code to allow reading directories.
- // Allows these sycalls:
+ // Allows these syscalls:
// - getdents
// - getdents64
PolicyBuilder& AllowReaddir();
// Appends code to allow reading symbolic links.
- // Allows these sycalls:
+ // Allows these syscalls:
// - readlink
// - readlinkat
PolicyBuilder& AllowReadlink();
// Appends code to allow creating links.
- // Allows these sycalls:
+ // Allows these syscalls:
// - link
// - linkat
PolicyBuilder& AllowLink();
// Appends code to allow creating symbolic links.
- // Allows these sycalls:
+ // Allows these syscalls:
// - symlink
// - symlinkat
PolicyBuilder& AllowSymlink();
// Appends code to allow creating directories.
- // Allows these sycalls:
+ // Allows these syscalls:
// - mkdir
// - mkdirat
PolicyBuilder& AllowMkdir();
// Appends code to allow changing file timestamps.
- // Allows these sycalls:
+ // Allows these syscalls:
// - futimens
// - utime
// - utimensat
@@ -367,7 +373,7 @@ class PolicyBuilder final {
PolicyBuilder& AllowUtime();
// Appends code to allow safe calls to fcntl.
- // Allows these sycalls:
+ // Allows these syscalls:
// - fcntl
// - fcntl64 (on architectures where it exists)
//
@@ -377,7 +383,7 @@ class PolicyBuilder final {
PolicyBuilder& AllowSafeFcntl();
// Appends code to allow creating new processes.
- // Allows these sycalls:
+ // Allows these syscalls:
// - fork
// - vfork
// - clone
@@ -388,19 +394,19 @@ class PolicyBuilder final {
PolicyBuilder& AllowFork();
// Appends code to allow waiting for processes.
- // Allows these sycalls:
+ // Allows these syscalls:
// - waitpid (on architectures where it exists)
// - wait4
PolicyBuilder& AllowWait();
// Appends code to allow setting alarms / interval timers.
- // Allows these sycalls:
+ // Allows these syscalls:
// - alarm (on architectures where it exists)
// - setitimer
PolicyBuilder& AllowAlarm();
// Appends code to allow setting up signal handlers, returning from them, etc.
- // Allows these sycalls:
+ // Allows these syscalls:
// - rt_sigaction
// - rt_sigreturn
// - rt_procmask
@@ -411,12 +417,12 @@ class PolicyBuilder final {
PolicyBuilder& AllowHandleSignals();
// Appends code to allow doing the TCGETS ioctl.
- // Allows these sycalls:
+ // Allows these syscalls:
// - ioctl (when the first argument is TCGETS)
PolicyBuilder& AllowTCGETS();
// Appends code to allow to getting the current time.
- // Allows these sycalls:
+ // Allows these syscalls:
// - time
// - gettimeofday
// - clock_gettime
@@ -450,19 +456,19 @@ class PolicyBuilder final {
PolicyBuilder& AllowGetPGIDs();
// Appends code to allow getting the rlimits.
- // Allows these sycalls:
+ // Allows these syscalls:
// - getrlimit
// - ugetrlimit (on architectures where it exist)
PolicyBuilder& AllowGetRlimit();
// Appends code to allow setting the rlimits.
- // Allows these sycalls:
+ // Allows these syscalls:
// - setrlimit
// - usetrlimit (on architectures where it exist)
PolicyBuilder& AllowSetRlimit();
// Appends code to allow reading random bytes.
- // Allows these sycalls:
+ // Allows these syscalls:
// - getrandom (with no flags or GRND_NONBLOCK)
//
PolicyBuilder& AllowGetRandom();
@@ -707,6 +713,12 @@ class PolicyBuilder final {
// sandbox-team@ first if unsure.
PolicyBuilder& DefaultAction(AllowAllSyscalls);
+ // Changes the default action to SANDBOX2_TRACE.
+ // All syscalls not handled explicitly by the policy will be passed off to
+ // the `sandbox2::Notify` implementation given to the `sandbox2::Sandbox2`
+ // instance.
+ PolicyBuilder& DefaultAction(TraceAllSyscalls);
+
ABSL_DEPRECATED("Use DefaultAction(sandbox2::AllowAllSyscalls()) instead")
PolicyBuilder& DangerDefaultAllowAll();
diff --git a/sandboxed_api/sandbox2/sandbox2_test.cc b/sandboxed_api/sandbox2/sandbox2_test.cc
index 8060d06..828803f 100644
--- a/sandboxed_api/sandbox2/sandbox2_test.cc
+++ b/sandboxed_api/sandbox2/sandbox2_test.cc
@@ -35,6 +35,7 @@
#include "absl/time/time.h"
#include "sandboxed_api/config.h"
#include "sandboxed_api/sandbox2/executor.h"
+#include "sandboxed_api/sandbox2/fork_client.h"
#include "sandboxed_api/sandbox2/policy.h"
#include "sandboxed_api/sandbox2/policybuilder.h"
#include "sandboxed_api/sandbox2/result.h"
@@ -51,6 +52,7 @@ using ::testing::Eq;
using ::testing::IsEmpty;
using ::testing::IsTrue;
using ::testing::Lt;
+using ::testing::Ne;
class Sandbox2Test : public ::testing::TestWithParam<bool> {
public:
@@ -195,6 +197,23 @@ TEST_P(Sandbox2Test, SandboxeeNotKilledWhenStartingThreadFinishes) {
EXPECT_EQ(result.final_status(), Result::OK);
}
+TEST_P(Sandbox2Test, CustomForkserverWorks) {
+ const std::string path = GetTestSourcePath("sandbox2/testcases/custom_fork");
+ std::vector<std::string> args = {path};
+ auto fork_executor = std::make_unique<Executor>(path, args);
+ std::unique_ptr<ForkClient> fork_client = fork_executor->StartForkServer();
+ ASSERT_THAT(fork_client.get(), Ne(nullptr));
+
+ SAPI_ASSERT_OK_AND_ASSIGN(auto policy,
+ CreateDefaultTestPolicy(path).TryBuild());
+
+ Sandbox2 sandbox(std::make_unique<Executor>(fork_client.get()),
+ std::move(policy));
+ ASSERT_THAT(SetUpSandbox(&sandbox), IsOk());
+ Result result = sandbox.Run();
+ EXPECT_EQ(result.final_status(), Result::OK);
+}
+
TEST(StarvationTest, MonitorIsNotStarvedByTheSandboxee) {
const std::string path = GetTestSourcePath("sandbox2/testcases/starve");
diff --git a/sandboxed_api/sandbox2/stack_trace.cc b/sandboxed_api/sandbox2/stack_trace.cc
index 2b970ad..11f9b6f 100644
--- a/sandboxed_api/sandbox2/stack_trace.cc
+++ b/sandboxed_api/sandbox2/stack_trace.cc
@@ -145,7 +145,7 @@ absl::StatusOr<std::unique_ptr<Policy>> StackTracePeer::GetPolicy(
.AllowSyscall(__NR_recvmsg)
// libunwind
- .AllowMmap()
+ .AllowMmapWithoutExec()
.AllowStat()
.AllowSyscall(__NR_lseek)
#ifdef __NR__llseek
diff --git a/sandboxed_api/sandbox2/syscall_defs.cc b/sandboxed_api/sandbox2/syscall_defs.cc
index ffbaa36..a7b41ed 100644
--- a/sandboxed_api/sandbox2/syscall_defs.cc
+++ b/sandboxed_api/sandbox2/syscall_defs.cc
@@ -8,6 +8,7 @@
#include <vector>
#include "absl/algorithm/container.h"
+#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
@@ -18,56 +19,15 @@
namespace sandbox2 {
-// Type of a given syscall argument. Used with argument conversion routines.
-enum ArgType {
- kGen = 1,
- kInt,
- kPath,
- kHex,
- kOct,
- kSocketCall,
- kSocketCallPtr,
- kSignal,
- kString,
- kAddressFamily,
- kSockaddr,
- kSockmsghdr,
- kCloneFlag,
-};
-
-// Single syscall definition
-struct SyscallTable::Entry {
- // Returns the number of arguments which given syscall takes.
- int GetNumArgs() const {
- if (num_args < 0 || num_args > syscalls::kMaxArgs) {
- return syscalls::kMaxArgs;
- }
- return num_args;
- }
-
- static std::string GetArgumentDescription(uint64_t value, ArgType type,
- pid_t pid);
-
- static constexpr bool BySyscallNr(const SyscallTable::Entry& a,
- const SyscallTable::Entry& b) {
- return a.nr < b.nr;
- }
-
- int nr;
- absl::string_view name;
- int num_args;
- std::array<ArgType, syscalls::kMaxArgs> arg_types;
-};
-
std::string SyscallTable::Entry::GetArgumentDescription(uint64_t value,
- ArgType type,
+ syscalls::ArgType type,
pid_t pid) {
std::string ret = absl::StrFormat("%#x", value);
switch (type) {
- case kOct:
+ case syscalls::kOct:
absl::StrAppendFormat(&ret, " [\\0%o]", value);
break;
- case kPath:
+ case syscalls::kPath:
if (auto path_or = util::ReadCPathFromPid(pid, value); path_or.ok()) {
absl::StrAppendFormat(&ret, " ['%s']",
absl::CHexEscape(path_or.value()));
@@ -75,7 +35,7 @@ std::string SyscallTable::Entry::GetArgumentDescription(uint64_t value,
absl::StrAppend(&ret, " [unreadable path]");
}
break;
- case kInt:
+ case syscalls::kInt:
absl::StrAppendFormat(&ret, " [%d]", value);
break;
default:
@@ -85,14 +45,11 @@ std::string SyscallTable::Entry::GetArgumentDescription(uint64_t value,
}
absl::string_view SyscallTable::GetName(int syscall) const {
- auto it = absl::c_lower_bound(
- data_, syscall, [](const SyscallTable::Entry& entry, int syscall) {
- return entry.nr < syscall;
- });
- if (it == data_.end() || it->nr != syscall) {
+ auto entry = GetEntry(syscall);
+ if (!entry.ok()) {
return "";
}
- return it->name;
+ return entry->name;
}
namespace {
@@ -108,32 +65,61 @@ constexpr SyscallTable::Entry MakeEntry(int nr, absl::string_view name,
struct UnknownArguments {};
constexpr SyscallTable::Entry MakeEntry(int nr, absl::string_view name,
UnknownArguments) {
- return {nr, name, -1, {kGen, kGen, kGen, kGen, kGen, kGen}};
+ return {nr,
+ name,
+ -1,
+ {syscalls::kGen, syscalls::kGen, syscalls::kGen, syscalls::kGen,
+ syscalls::kGen, syscalls::kGen}};
}
} // namespace
-std::vector<std::string> SyscallTable::GetArgumentsDescription(
- int syscall, const uint64_t values[], pid_t pid) const {
- static SyscallTable::Entry kInvalidEntry =
- MakeEntry(-1, "", UnknownArguments());
+absl::StatusOr<SyscallTable::Entry> SyscallTable::GetEntry(int syscall) const {
auto it = absl::c_lower_bound(
data_, syscall, [](const SyscallTable::Entry& entry, int syscall) {
return entry.nr < syscall;
});
- const auto& entry =
- it != data_.end() && it->nr == syscall ? *it : kInvalidEntry;
+ if (it == data_.end() || it->nr != syscall) {
+ return absl::NotFoundError(absl::StrCat("Syscall not found: ", syscall));
+ }
+ return *it;
+}
+
+absl::StatusOr<SyscallTable::Entry> SyscallTable::GetEntry(
+ absl::string_view name) const {
+ // Note: There's no uniqueness guarantee of syscall names in the table, but
+ // other than typos it's likely safe to assume uniqueness.
+ auto filter = [name](const SyscallTable::Entry& entry) {
+ return entry.name == name;
+ };
+ auto it = absl::c_find_if(data_, filter);
+ if (it != data_.end()) {
+ return *it;
+ } else {
+ return absl::NotFoundError(absl::StrCat("Name not found: ", name));
+ }
+}
+
+std::vector<std::string> SyscallTable::GetArgumentsDescription(
+ int syscall, const uint64_t values[], pid_t pid) const {
+ static SyscallTable::Entry kInvalidEntry =
+ MakeEntry(-1, "", UnknownArguments());
+ auto entry = GetEntry(syscall);
+ if (!entry.ok()) {
+ entry = kInvalidEntry;
+ }
- int num_args = entry.GetNumArgs();
+ int num_args = entry->GetNumArgs();
std::vector<std::string> rv;
rv.reserve(num_args);
for (int i = 0; i < num_args; ++i) {
rv.push_back(SyscallTable::Entry::GetArgumentDescription(
- values[i], entry.arg_types[i], pid));
+ values[i], entry->arg_types[i], pid));
}
return rv;
}
+namespace syscalls {
namespace {
// TODO(C++20) Use std::is_sorted
@@ -494,6 +480,33 @@ constexpr std::array kSyscallDataX8664 = {
MakeEntry(332, "statx", kInt, kPath, kHex, kHex, kHex),
MakeEntry(333, "io_pgetevents", UnknownArguments()),
MakeEntry(334, "rseq", kHex, kInt, kHex, kHex),
+ MakeEntry(435, "clone3", kHex, kInt),
+ MakeEntry(436, "close_range", kInt, kInt, kHex),
+ MakeEntry(437, "openat2", kInt, kPath, kHex, kInt),
+ MakeEntry(438, "pidfd_getfd", UnknownArguments()),
+ MakeEntry(439, "faccessat2", kInt, kPath, kHex, kHex),
+ MakeEntry(440, "process_madvise", UnknownArguments()),
+ MakeEntry(441, "epoll_pwait2", UnknownArguments()),
+ MakeEntry(442, "mount_setattr", UnknownArguments()),
+ MakeEntry(443, "quotactl_fd", UnknownArguments()),
+ MakeEntry(444, "landlock_create_ruleset", UnknownArguments()),
+ MakeEntry(445, "landlock_add_rule", UnknownArguments()),
+ MakeEntry(446, "landlock_restrict_self", UnknownArguments()),
+ MakeEntry(447, "memfd_secret", UnknownArguments()),
+ MakeEntry(448, "process_mrelease", UnknownArguments()),
+ MakeEntry(449, "futex_waitv", UnknownArguments()),
+ MakeEntry(450, "set_mempolicy_home_node", UnknownArguments()),
+ MakeEntry(451, "cachestat", UnknownArguments()),
+ MakeEntry(452, "fchmodat2", kInt, kPath, kHex, kHex),
+ MakeEntry(453, "map_shadow_stack", UnknownArguments()),
+ MakeEntry(454, "futex_wake", UnknownArguments()),
+ MakeEntry(455, "futex_wait", UnknownArguments()),
+ MakeEntry(456, "futex_requeue", UnknownArguments()),
+ MakeEntry(457, "statmount", UnknownArguments()),
+ MakeEntry(458, "listmount", UnknownArguments()),
+ MakeEntry(459, "lsm_get_self_attr", UnknownArguments()),
+ MakeEntry(460, "lsm_set_self_attr", UnknownArguments()),
+ MakeEntry(461, "lsm_list_modules", UnknownArguments()),
// clang-format on
};
@@ -860,6 +873,33 @@ constexpr std::array kSyscallDataX8632 = {
MakeEntry(355, "getrandom", kGen, kInt, kHex),
MakeEntry(356, "memfd_create", kString, kHex),
MakeEntry(357, "bpf", kInt, kHex, kInt),
+ MakeEntry(435, "clone3", kHex, kInt),
+ MakeEntry(436, "close_range", kInt, kInt, kHex),
+ MakeEntry(437, "openat2", kInt, kPath, kHex, kInt),
+ MakeEntry(438, "pidfd_getfd", UnknownArguments()),
+ MakeEntry(439, "faccessat2", kInt, kPath, kHex, kHex),
+ MakeEntry(440, "process_madvise", UnknownArguments()),
+ MakeEntry(441, "epoll_pwait2", UnknownArguments()),
+ MakeEntry(442, "mount_setattr", UnknownArguments()),
+ MakeEntry(443, "quotactl_fd", UnknownArguments()),
+ MakeEntry(444, "landlock_create_ruleset", UnknownArguments()),
+ MakeEntry(445, "landlock_add_rule", UnknownArguments()),
+ MakeEntry(446, "landlock_restrict_self", UnknownArguments()),
+ MakeEntry(447, "memfd_secret", UnknownArguments()),
+ MakeEntry(448, "process_mrelease", UnknownArguments()),
+ MakeEntry(449, "futex_waitv", UnknownArguments()),
+ MakeEntry(450, "set_mempolicy_home_node", UnknownArguments()),
+ MakeEntry(451, "cachestat", UnknownArguments()),
+ MakeEntry(452, "fchmodat2", kInt, kPath, kHex, kHex),
+ MakeEntry(453, "map_shadow_stack", UnknownArguments()),
+ MakeEntry(454, "futex_wake", UnknownArguments()),
+ MakeEntry(455, "futex_wait", UnknownArguments()),
+ MakeEntry(456, "futex_requeue", UnknownArguments()),
+ MakeEntry(457, "statmount", UnknownArguments()),
+ MakeEntry(458, "listmount", UnknownArguments()),
+ MakeEntry(459, "lsm_get_self_attr", UnknownArguments()),
+ MakeEntry(460, "lsm_set_self_attr", UnknownArguments()),
+ MakeEntry(461, "lsm_list_modules", UnknownArguments()),
// clang-format on
};
@@ -1239,6 +1279,32 @@ constexpr std::array kSyscallDataPPC64LE = {
MakeEntry(379, "copy_file_range", kInt, kHex, kInt, kHex, kInt, kHex),
MakeEntry(380, "preadv2", kInt, kHex, kInt, kInt, kInt, kHex),
MakeEntry(381, "pwritev2", kInt, kHex, kInt, kInt, kInt, kHex),
+ MakeEntry(435, "clone3", kHex, kInt),
+ MakeEntry(436, "close_range", kInt, kInt, kHex),
+ MakeEntry(437, "openat2", kInt, kPath, kHex, kInt),
+ MakeEntry(438, "pidfd_getfd", UnknownArguments()),
+ MakeEntry(439, "faccessat2", kInt, kPath, kHex, kHex),
+ MakeEntry(440, "process_madvise", UnknownArguments()),
+ MakeEntry(441, "epoll_pwait2", UnknownArguments()),
+ MakeEntry(442, "mount_setattr", UnknownArguments()),
+ MakeEntry(443, "quotactl_fd", UnknownArguments()),
+ MakeEntry(444, "landlock_create_ruleset", UnknownArguments()),
+ MakeEntry(445, "landlock_add_rule", UnknownArguments()),
+ MakeEntry(446, "landlock_restrict_self", UnknownArguments()),
+ MakeEntry(448, "process_mrelease", UnknownArguments()),
+ MakeEntry(449, "futex_waitv", UnknownArguments()),
+ MakeEntry(450, "set_mempolicy_home_node", UnknownArguments()),
+ MakeEntry(451, "cachestat", UnknownArguments()),
+ MakeEntry(452, "fchmodat2", kInt, kPath, kHex, kHex),
+ MakeEntry(453, "map_shadow_stack", UnknownArguments()),
+ MakeEntry(454, "futex_wake", UnknownArguments()),
+ MakeEntry(455, "futex_wait", UnknownArguments()),
+ MakeEntry(456, "futex_requeue", UnknownArguments()),
+ MakeEntry(457, "statmount", UnknownArguments()),
+ MakeEntry(458, "listmount", UnknownArguments()),
+ MakeEntry(459, "lsm_get_self_attr", UnknownArguments()),
+ MakeEntry(460, "lsm_set_self_attr", UnknownArguments()),
+ MakeEntry(461, "lsm_list_modules", UnknownArguments()),
// clang-format on
};
@@ -1520,6 +1586,32 @@ constexpr std::array kSyscallDataArm64 = {
MakeEntry(285, "copy_file_range", kInt, kHex, kInt, kHex, kInt, kHex),
MakeEntry(286, "preadv2", kInt, kHex, kInt, kInt, kInt, kHex),
MakeEntry(287, "pwritev2", kInt, kHex, kInt, kInt, kInt, kHex),
+ MakeEntry(435, "clone3", kHex, kInt),
+ MakeEntry(436, "close_range", kInt, kInt, kHex),
+ MakeEntry(437, "openat2", kInt, kPath, kHex, kInt),
+ MakeEntry(438, "pidfd_getfd", UnknownArguments()),
+ MakeEntry(439, "faccessat2", kInt, kPath, kHex, kHex),
+ MakeEntry(440, "process_madvise", UnknownArguments()),
+ MakeEntry(441, "epoll_pwait2", UnknownArguments()),
+ MakeEntry(442, "mount_setattr", UnknownArguments()),
+ MakeEntry(443, "quotactl_fd", UnknownArguments()),
+ MakeEntry(444, "landlock_create_ruleset", UnknownArguments()),
+ MakeEntry(445, "landlock_add_rule", UnknownArguments()),
+ MakeEntry(446, "landlock_restrict_self", UnknownArguments()),
+ MakeEntry(448, "process_mrelease", UnknownArguments()),
+ MakeEntry(449, "futex_waitv", UnknownArguments()),
+ MakeEntry(450, "set_mempolicy_home_node", UnknownArguments()),
+ MakeEntry(451, "cachestat", UnknownArguments()),
+ MakeEntry(452, "fchmodat2", kInt, kPath, kHex, kHex),
+ MakeEntry(453, "map_shadow_stack", UnknownArguments()),
+ MakeEntry(454, "futex_wake", UnknownArguments()),
+ MakeEntry(455, "futex_wait", UnknownArguments()),
+ MakeEntry(456, "futex_requeue", UnknownArguments()),
+ MakeEntry(457, "statmount", UnknownArguments()),
+ MakeEntry(458, "listmount", UnknownArguments()),
+ MakeEntry(459, "lsm_get_self_attr", UnknownArguments()),
+ MakeEntry(460, "lsm_set_self_attr", UnknownArguments()),
+ MakeEntry(461, "lsm_list_modules", UnknownArguments()),
// clang-format on
};
@@ -1877,6 +1969,32 @@ constexpr std::array kSyscallDataArm32 = {
MakeEntry(393, "pwritev2", kInt, kHex, kInt, kInt, kInt, kHex),
MakeEntry(400, "migrate_pages", kGen, kGen, kGen, kGen),
MakeEntry(401, "kexec_file_load", kInt, kInt, kInt, kString, kHex),
+ MakeEntry(435, "clone3", kHex, kInt),
+ MakeEntry(436, "close_range", kInt, kInt, kHex),
+ MakeEntry(437, "openat2", kInt, kPath, kHex, kInt),
+ MakeEntry(438, "pidfd_getfd", UnknownArguments()),
+ MakeEntry(439, "faccessat2", kInt, kPath, kHex, kHex),
+ MakeEntry(440, "process_madvise", UnknownArguments()),
+ MakeEntry(441, "epoll_pwait2", UnknownArguments()),
+ MakeEntry(442, "mount_setattr", UnknownArguments()),
+ MakeEntry(443, "quotactl_fd", UnknownArguments()),
+ MakeEntry(444, "landlock_create_ruleset", UnknownArguments()),
+ MakeEntry(445, "landlock_add_rule", UnknownArguments()),
+ MakeEntry(446, "landlock_restrict_self", UnknownArguments()),
+ MakeEntry(448, "process_mrelease", UnknownArguments()),
+ MakeEntry(449, "futex_waitv", UnknownArguments()),
+ MakeEntry(450, "set_mempolicy_home_node", UnknownArguments()),
+ MakeEntry(451, "cachestat", UnknownArguments()),
+ MakeEntry(452, "fchmodat2", kInt, kPath, kHex, kHex),
+ MakeEntry(453, "map_shadow_stack", UnknownArguments()),
+ MakeEntry(454, "futex_wake", UnknownArguments()),
+ MakeEntry(455, "futex_wait", UnknownArguments()),
+ MakeEntry(456, "futex_requeue", UnknownArguments()),
+ MakeEntry(457, "statmount", UnknownArguments()),
+ MakeEntry(458, "listmount", UnknownArguments()),
+ MakeEntry(459, "lsm_get_self_attr", UnknownArguments()),
+ MakeEntry(460, "lsm_set_self_attr", UnknownArguments()),
+ MakeEntry(461, "lsm_list_modules", UnknownArguments()),
MakeEntry(0xf0001, "ARM_breakpoint", kHex, kHex, kHex, kHex),
MakeEntry(0xf0002, "ARM_cacheflush", kHex, kHex, kHex, kHex),
MakeEntry(0xf0003, "ARM_usr26", kHex, kHex, kHex, kHex),
@@ -1889,19 +2007,20 @@ static_assert(IsSorted(kSyscallDataArm32, SyscallTable::Entry::BySyscallNr),
"Syscalls should be sorted");
} // namespace
+} // namespace syscalls
SyscallTable SyscallTable::get(sapi::cpu::Architecture arch) {
switch (arch) {
case sapi::cpu::kX8664:
- return SyscallTable(kSyscallDataX8664);
+ return SyscallTable(syscalls::kSyscallDataX8664);
case sapi::cpu::kX86:
- return SyscallTable(kSyscallDataX8632);
+ return SyscallTable(syscalls::kSyscallDataX8632);
case sapi::cpu::kPPC64LE:
- return SyscallTable(kSyscallDataPPC64LE);
+ return SyscallTable(syscalls::kSyscallDataPPC64LE);
case sapi::cpu::kArm64:
- return SyscallTable(kSyscallDataArm64);
+ return SyscallTable(syscalls::kSyscallDataArm64);
case sapi::cpu::kArm:
- return SyscallTable(kSyscallDataArm32);
+ return SyscallTable(syscalls::kSyscallDataArm32);
default:
return SyscallTable();
}
diff --git a/sandboxed_api/sandbox2/syscall_defs.h b/sandboxed_api/sandbox2/syscall_defs.h
index a5e7fc3..1fbf3dc 100644
--- a/sandboxed_api/sandbox2/syscall_defs.h
+++ b/sandboxed_api/sandbox2/syscall_defs.h
@@ -3,10 +3,12 @@
#include <sys/types.h>
+#include <array>
#include <cstdint>
#include <string>
#include <vector>
+#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "sandboxed_api/config.h"
@@ -17,11 +19,51 @@ namespace syscalls {
constexpr int kMaxArgs = 6;
+// Type of a given syscall argument. Used with argument conversion routines.
+enum ArgType {
+ kGen = 1,
+ kInt,
+ kPath,
+ kHex,
+ kOct,
+ kSocketCall,
+ kSocketCallPtr,
+ kSignal,
+ kString,
+ kAddressFamily,
+ kSockaddr,
+ kSockmsghdr,
+ kCloneFlag,
+};
+
} // namespace syscalls
class SyscallTable {
public:
- struct Entry;
+ // Single syscall definition
+ struct Entry {
+ // Returns the number of arguments which given syscall takes.
+ int GetNumArgs() const {
+ if (num_args < 0 || num_args > syscalls::kMaxArgs) {
+ return syscalls::kMaxArgs;
+ }
+ return num_args;
+ }
+
+ static std::string GetArgumentDescription(uint64_t value,
+ syscalls::ArgType type,
+ pid_t pid);
+
+ static constexpr bool BySyscallNr(const SyscallTable::Entry& a,
+ const SyscallTable::Entry& b) {
+ return a.nr < b.nr;
+ }
+
+ int nr;
+ absl::string_view name;
+ int num_args;
+ std::array<syscalls::ArgType, syscalls::kMaxArgs> arg_types;
+ };
// Returns the syscall table for the architecture.
static SyscallTable get(sapi::cpu::Architecture arch);
@@ -34,6 +76,12 @@ class SyscallTable {
const uint64_t values[],
pid_t pid) const;
+ absl::StatusOr<Entry> GetEntry(int syscall) const;
+ // Returns the first entry matching the provided name.
+ absl::StatusOr<Entry> GetEntry(absl::string_view name) const;
+
+ absl::Span<const Entry> GetEntries() const { return data_; }
+
private:
constexpr SyscallTable() = default;
explicit constexpr SyscallTable(absl::Span<const Entry> data) : data_(data) {}
diff --git a/sandboxed_api/sandbox2/testcases/BUILD.bazel b/sandboxed_api/sandbox2/testcases/BUILD.bazel
index 92cedb8..7ba8141 100644
--- a/sandboxed_api/sandbox2/testcases/BUILD.bazel
+++ b/sandboxed_api/sandbox2/testcases/BUILD.bazel
@@ -261,3 +261,16 @@ cc_binary(
"@com_google_absl//absl/strings:string_view",
],
)
+
+cc_binary(
+ name = "custom_fork",
+ testonly = True,
+ srcs = ["custom_fork.cc"],
+ copts = sapi_platform_copts(),
+ features = ["fully_static_link"],
+ deps = [
+ "//sandboxed_api/sandbox2:comms",
+ "//sandboxed_api/sandbox2:forkingclient",
+ "//sandboxed_api/util:raw_logging",
+ ],
+)
diff --git a/sandboxed_api/sandbox2/testcases/CMakeLists.txt b/sandboxed_api/sandbox2/testcases/CMakeLists.txt
index 3dfd039..43bde70 100644
--- a/sandboxed_api/sandbox2/testcases/CMakeLists.txt
+++ b/sandboxed_api/sandbox2/testcases/CMakeLists.txt
@@ -322,3 +322,19 @@ target_link_libraries(sandbox2_testcase_network_proxy PRIVATE
sapi::status
)
+# sandboxed_api/sandbox2/testcases:custom_fork
+add_executable(sandbox2_testcase_custom_fork
+ custom_fork.cc
+)
+add_executable(sandbox2::testcase_custom_fork ALIAS sandbox2_testcase_custom_fork)
+set_target_properties(sandbox2_testcase_custom_fork PROPERTIES
+ OUTPUT_NAME custom_fork
+)
+target_link_libraries(sandbox2_testcase_custom_fork PRIVATE
+ sandbox2::comms
+ sandbox2::forkingclient
+ sapi::base
+ sapi::raw_logging
+)
+
+
diff --git a/sandboxed_api/sandbox2/testcases/custom_fork.cc b/sandboxed_api/sandbox2/testcases/custom_fork.cc
new file mode 100644
index 0000000..3625229
--- /dev/null
+++ b/sandboxed_api/sandbox2/testcases/custom_fork.cc
@@ -0,0 +1,34 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "sandboxed_api/sandbox2/comms.h"
+#include "sandboxed_api/sandbox2/forkingclient.h"
+#include "sandboxed_api/util/raw_logging.h"
+
+int main(int argc, char* argv[]) {
+ sandbox2::Comms comms(sandbox2::Comms::kDefaultConnection);
+ sandbox2::ForkingClient s2client(&comms);
+
+ for (;;) {
+ pid_t pid = s2client.WaitAndFork();
+ if (pid == -1) {
+ SAPI_RAW_LOG(FATAL, "Could not spawn a new sandboxee");
+ }
+ if (pid == 0) {
+ // Start sandboxing here
+ s2client.SandboxMeHere();
+ return 0;
+ }
+ }
+}
diff --git a/sandboxed_api/sandbox2/testcases/starve.cc b/sandboxed_api/sandbox2/testcases/starve.cc
index 6903c0a..5295e76 100644
--- a/sandboxed_api/sandbox2/testcases/starve.cc
+++ b/sandboxed_api/sandbox2/testcases/starve.cc
@@ -40,7 +40,7 @@ int ChildFunc(void*) {
int main() {
for (int i = 0; i < kProcesses; ++i) {
- int p[2];
+ int p[2] = {0, 0};
char c = ' ';
pipe(p);
g_pids[i] = fork();
diff --git a/sandboxed_api/sandbox2/trace_all_syscalls.h b/sandboxed_api/sandbox2/trace_all_syscalls.h
new file mode 100644
index 0000000..d387cc3
--- /dev/null
+++ b/sandboxed_api/sandbox2/trace_all_syscalls.h
@@ -0,0 +1,27 @@
+// Copyright 2024 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SANDBOXED_API_SANDBOX2_TRACE_ALL_SYSCALLS_H_
+#define SANDBOXED_API_SANDBOX2_TRACE_ALL_SYSCALLS_H_
+
+namespace sandbox2 {
+
+class TraceAllSyscalls {
+ public:
+ explicit TraceAllSyscalls() = default;
+};
+
+} // namespace sandbox2
+
+#endif // SANDBOXED_API_SANDBOX2_ALLOW_ALL_SYSCALLS_H_
diff --git a/sandboxed_api/sandbox2/util/BUILD.bazel b/sandboxed_api/sandbox2/util/BUILD.bazel
index 86cc785..89bc522 100644
--- a/sandboxed_api/sandbox2/util/BUILD.bazel
+++ b/sandboxed_api/sandbox2/util/BUILD.bazel
@@ -32,8 +32,6 @@ cc_library(
name = "bpf_helper",
srcs = ["bpf_helper.c"],
hdrs = ["bpf_helper.h"],
- copts = sapi_platform_copts([
- ]),
visibility = ["//visibility:public"],
)
diff --git a/sandboxed_api/sapi_test.cc b/sandboxed_api/sapi_test.cc
index 5f66f2c..6aa25ab 100644
--- a/sandboxed_api/sapi_test.cc
+++ b/sandboxed_api/sapi_test.cc
@@ -284,5 +284,24 @@ TEST(SandboxTest, NoRaceInConcurrentTerminate) {
EXPECT_THAT(result.final_status(), Eq(sandbox2::Result::EXTERNAL_KILL));
}
+TEST(SandboxTest, UseUnotifyMonitor) {
+ SumSandbox sandbox;
+ ASSERT_THAT(sandbox.Init(/*use_unotify_monitor=*/true), IsOk());
+ SumApi api(&sandbox);
+
+ // Violate the sandbox policy.
+ EXPECT_THAT(api.violate(), StatusIs(absl::StatusCode::kUnavailable));
+ EXPECT_THAT(api.sum(1, 2).status(), StatusIs(absl::StatusCode::kUnavailable));
+ EXPECT_THAT(sandbox.AwaitResult().final_status(),
+ Eq(sandbox2::Result::VIOLATION));
+
+ // Restart the sandbox.
+ ASSERT_THAT(sandbox.Restart(false), IsOk());
+
+ // The sandbox should now be responsive again.
+ SAPI_ASSERT_OK_AND_ASSIGN(int result, api.sum(1, 2));
+ EXPECT_THAT(result, Eq(3));
+}
+
} // namespace
} // namespace sapi
diff --git a/sandboxed_api/tools/generator2/code_test.py b/sandboxed_api/tools/generator2/code_test.py
index de74485..8ef6057 100644
--- a/sandboxed_api/tools/generator2/code_test.py
+++ b/sandboxed_api/tools/generator2/code_test.py
@@ -89,7 +89,7 @@ class CodeAnalysisTest(parameterized.TestCase):
if x.kind != cindex.CursorKind.MACRO_DEFINITION
]
self.assertListEqual(cursor_kinds, [
- cindex.CursorKind.TRANSLATION_UNIT, cindex.CursorKind.UNEXPOSED_DECL,
+ cindex.CursorKind.TRANSLATION_UNIT, cindex.CursorKind.LINKAGE_SPEC,
cindex.CursorKind.FUNCTION_DECL, cindex.CursorKind.PARM_DECL
])
diff --git a/sandboxed_api/var_ptr.h b/sandboxed_api/var_ptr.h
index ad2568c..2c9894f 100644
--- a/sandboxed_api/var_ptr.h
+++ b/sandboxed_api/var_ptr.h
@@ -20,6 +20,7 @@
#include <memory>
#include <string>
+#include "absl/base/attributes.h"
#include "absl/base/macros.h"
#include "absl/strings/str_format.h"
#include "sandboxed_api/var_abstract.h"
@@ -79,7 +80,9 @@ class Ptr : public Reg<Var*> {
};
// Good, old nullptr
-class NullPtr : public Ptr {
+class ABSL_DEPRECATED(
+ "Use regular `nullptr` or `NULL` instead. This class will eventually get "
+ "removed") NullPtr : public Ptr {
public:
NullPtr() : Ptr(&void_obj_, SyncType::kSyncNone) {}