mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
Automated rollback of commit 800339d672
.
PiperOrigin-RevId: 294644781 Change-Id: I88ad35abd96468476294039a41b6f2a8234db6ca
This commit is contained in:
parent
800339d672
commit
05280287e0
|
@ -89,7 +89,7 @@ cc_library(
|
||||||
":syscall",
|
":syscall",
|
||||||
":util",
|
":util",
|
||||||
"//sandboxed_api/util:status",
|
"//sandboxed_api/util:status",
|
||||||
"//sandboxed_api/util:statusor",
|
"@com_google_absl//absl/base",
|
||||||
"@com_google_absl//absl/memory",
|
"@com_google_absl//absl/memory",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
],
|
],
|
||||||
|
@ -127,6 +127,36 @@ cc_library(
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "network_proxy_server",
|
||||||
|
srcs = ["network_proxy_server.cc"],
|
||||||
|
hdrs = ["network_proxy_server.h"],
|
||||||
|
copts = sapi_platform_copts(),
|
||||||
|
deps = [
|
||||||
|
":comms",
|
||||||
|
"//sandboxed_api/sandbox2/util:fileops",
|
||||||
|
"@com_google_absl//absl/memory",
|
||||||
|
"@com_google_glog//:glog",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "network_proxy_client",
|
||||||
|
srcs = ["network_proxy_client.cc"],
|
||||||
|
hdrs = ["network_proxy_client.h"],
|
||||||
|
copts = sapi_platform_copts(),
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = [
|
||||||
|
":comms",
|
||||||
|
"//sandboxed_api/sandbox2/util:strerror",
|
||||||
|
"//sandboxed_api/util:status",
|
||||||
|
"@com_google_absl//absl/memory",
|
||||||
|
"@com_google_absl//absl/strings",
|
||||||
|
"@com_google_absl//absl/synchronization",
|
||||||
|
"@com_google_glog//:glog",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "ipc",
|
name = "ipc",
|
||||||
srcs = ["ipc.cc"],
|
srcs = ["ipc.cc"],
|
||||||
|
@ -136,6 +166,8 @@ cc_library(
|
||||||
":comms",
|
":comms",
|
||||||
":logserver",
|
":logserver",
|
||||||
":logsink",
|
":logsink",
|
||||||
|
":network_proxy_client",
|
||||||
|
":network_proxy_server",
|
||||||
"@com_google_absl//absl/base:core_headers",
|
"@com_google_absl//absl/base:core_headers",
|
||||||
"@com_google_absl//absl/memory",
|
"@com_google_absl//absl/memory",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
|
@ -154,7 +186,6 @@ cc_library(
|
||||||
":regs",
|
":regs",
|
||||||
":syscall",
|
":syscall",
|
||||||
":violation_cc_proto",
|
":violation_cc_proto",
|
||||||
"//sandboxed_api/sandbox2/network_proxy:filtering",
|
|
||||||
"//sandboxed_api/sandbox2/util:bpf_helper",
|
"//sandboxed_api/sandbox2/util:bpf_helper",
|
||||||
"//sandboxed_api/util:flags",
|
"//sandboxed_api/util:flags",
|
||||||
"@com_google_absl//absl/base:core_headers",
|
"@com_google_absl//absl/base:core_headers",
|
||||||
|
@ -275,10 +306,10 @@ cc_library(
|
||||||
":client",
|
":client",
|
||||||
":executor",
|
":executor",
|
||||||
":comms",
|
":comms",
|
||||||
":forkserver_cc_proto",
|
|
||||||
":global_forkserver",
|
|
||||||
":violation_cc_proto",
|
":violation_cc_proto",
|
||||||
":forkserver",
|
":forkserver",
|
||||||
|
":forkserver_cc_proto",
|
||||||
|
":global_forkserver",
|
||||||
":ipc",
|
":ipc",
|
||||||
":limits",
|
":limits",
|
||||||
":logsink",
|
":logsink",
|
||||||
|
@ -290,6 +321,7 @@ cc_library(
|
||||||
":result",
|
":result",
|
||||||
":syscall",
|
":syscall",
|
||||||
":util",
|
":util",
|
||||||
|
":network_proxy_client",
|
||||||
"@com_google_absl//absl/base:core_headers",
|
"@com_google_absl//absl/base:core_headers",
|
||||||
"@com_google_absl//absl/container:flat_hash_map",
|
"@com_google_absl//absl/container:flat_hash_map",
|
||||||
"@com_google_absl//absl/container:flat_hash_set",
|
"@com_google_absl//absl/container:flat_hash_set",
|
||||||
|
@ -301,17 +333,12 @@ cc_library(
|
||||||
"@com_google_absl//absl/time",
|
"@com_google_absl//absl/time",
|
||||||
"@com_google_absl//absl/types:optional",
|
"@com_google_absl//absl/types:optional",
|
||||||
"@org_kernel_libcap//:libcap",
|
"@org_kernel_libcap//:libcap",
|
||||||
"//sandboxed_api/sandbox2/network_proxy:client",
|
|
||||||
"//sandboxed_api/sandbox2/network_proxy:filtering",
|
|
||||||
"//sandboxed_api/sandbox2/network_proxy:server",
|
|
||||||
"//sandboxed_api/sandbox2/unwind",
|
"//sandboxed_api/sandbox2/unwind",
|
||||||
"//sandboxed_api/sandbox2/unwind:unwind_cc_proto",
|
"//sandboxed_api/sandbox2/unwind:unwind_cc_proto",
|
||||||
"//sandboxed_api/sandbox2/util:bpf_helper",
|
"//sandboxed_api/sandbox2/util:bpf_helper",
|
||||||
"//sandboxed_api/sandbox2/util:file_base",
|
"//sandboxed_api/sandbox2/util:file_base",
|
||||||
"//sandboxed_api/sandbox2/util:fileops",
|
"//sandboxed_api/sandbox2/util:fileops",
|
||||||
"//sandboxed_api/sandbox2/util:strerror",
|
|
||||||
"//sandboxed_api/util:raw_logging",
|
"//sandboxed_api/util:raw_logging",
|
||||||
"//util/functional",
|
|
||||||
"//sandboxed_api/util:status",
|
"//sandboxed_api/util:status",
|
||||||
"//sandboxed_api/util:statusor",
|
"//sandboxed_api/util:statusor",
|
||||||
|
|
||||||
|
@ -337,7 +364,7 @@ cc_library(
|
||||||
deps = [
|
deps = [
|
||||||
":comms",
|
":comms",
|
||||||
":logsink",
|
":logsink",
|
||||||
"//sandboxed_api/sandbox2/network_proxy:client",
|
":network_proxy_client",
|
||||||
"//sandboxed_api/sandbox2/util:file_helpers",
|
"//sandboxed_api/sandbox2/util:file_helpers",
|
||||||
"//sandboxed_api/sandbox2/util:fileops",
|
"//sandboxed_api/sandbox2/util:fileops",
|
||||||
"//sandboxed_api/sandbox2/util:strerror",
|
"//sandboxed_api/sandbox2/util:strerror",
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
add_subdirectory(examples)
|
add_subdirectory(examples)
|
||||||
add_subdirectory(unwind)
|
add_subdirectory(unwind)
|
||||||
add_subdirectory(util)
|
add_subdirectory(util)
|
||||||
add_subdirectory(network_proxy)
|
|
||||||
|
|
||||||
# sandboxed_api/sandbox2:bpfdisassembler
|
# sandboxed_api/sandbox2:bpfdisassembler
|
||||||
add_library(sandbox2_bpfdisassembler STATIC
|
add_library(sandbox2_bpfdisassembler STATIC
|
||||||
|
@ -122,6 +121,36 @@ target_link_libraries(sandbox2_logsink
|
||||||
PUBLIC glog::glog
|
PUBLIC glog::glog
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# sandboxed_api/sandbox2:network_proxy_server
|
||||||
|
add_library(sandbox2_network_proxy_server STATIC
|
||||||
|
network_proxy_server.cc
|
||||||
|
network_proxy_server.h
|
||||||
|
)
|
||||||
|
add_library(sandbox2::network_proxy_server ALIAS sandbox2_network_proxy_server)
|
||||||
|
target_link_libraries(sandbox2_network_proxy_server PRIVATE
|
||||||
|
absl::memory
|
||||||
|
glog::glog
|
||||||
|
sandbox2::comms
|
||||||
|
sandbox2::fileops
|
||||||
|
sapi::base
|
||||||
|
)
|
||||||
|
|
||||||
|
# sandboxed_api/sandbox2:network_proxy_client
|
||||||
|
add_library(sandbox2_network_proxy_client STATIC
|
||||||
|
network_proxy_client.cc
|
||||||
|
network_proxy_client.h
|
||||||
|
)
|
||||||
|
add_library(sandbox2::network_proxy_client ALIAS sandbox2_network_proxy_client)
|
||||||
|
target_link_libraries(sandbox2_network_proxy_client PRIVATE
|
||||||
|
absl::strings
|
||||||
|
absl::synchronization
|
||||||
|
glog::glog
|
||||||
|
sandbox2::comms
|
||||||
|
sandbox2::strerror
|
||||||
|
sapi::base
|
||||||
|
sapi::status
|
||||||
|
)
|
||||||
|
|
||||||
# sandboxed_api/sandbox2:ipc
|
# sandboxed_api/sandbox2:ipc
|
||||||
add_library(sandbox2_ipc STATIC
|
add_library(sandbox2_ipc STATIC
|
||||||
ipc.cc
|
ipc.cc
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "absl/strings/str_join.h"
|
#include "absl/strings/str_join.h"
|
||||||
#include "absl/strings/str_split.h"
|
#include "absl/strings/str_split.h"
|
||||||
#include "sandboxed_api/sandbox2/comms.h"
|
#include "sandboxed_api/sandbox2/comms.h"
|
||||||
|
#include "sandboxed_api/sandbox2/network_proxy_client.h"
|
||||||
#include "sandboxed_api/sandbox2/sanitizer.h"
|
#include "sandboxed_api/sandbox2/sanitizer.h"
|
||||||
#include "sandboxed_api/sandbox2/util/strerror.h"
|
#include "sandboxed_api/sandbox2/util/strerror.h"
|
||||||
#include "sandboxed_api/util/raw_logging.h"
|
#include "sandboxed_api/util/raw_logging.h"
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
#include "sandboxed_api/sandbox2/comms.h"
|
#include "sandboxed_api/sandbox2/comms.h"
|
||||||
#include "sandboxed_api/sandbox2/logsink.h"
|
#include "sandboxed_api/sandbox2/logsink.h"
|
||||||
#include "sandboxed_api/sandbox2/network_proxy/client.h"
|
#include "sandboxed_api/sandbox2/network_proxy_client.h"
|
||||||
|
|
||||||
namespace sandbox2 {
|
namespace sandbox2 {
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,10 @@
|
||||||
|
|
||||||
# The 'network proxy' example demonstrates how to use network proxy server.
|
# The 'network proxy' example demonstrates how to use network proxy server.
|
||||||
|
|
||||||
load("//sandboxed_api/bazel:build_defs.bzl", "sapi_platform_copts")
|
|
||||||
|
|
||||||
licenses(["notice"])
|
licenses(["notice"])
|
||||||
|
|
||||||
|
load("//sandboxed_api/bazel:build_defs.bzl", "sapi_platform_copts")
|
||||||
|
|
||||||
# Executor
|
# Executor
|
||||||
cc_binary(
|
cc_binary(
|
||||||
name = "networkproxy_sandbox",
|
name = "networkproxy_sandbox",
|
||||||
|
@ -27,7 +27,6 @@ cc_binary(
|
||||||
deps = [
|
deps = [
|
||||||
"//sandboxed_api/sandbox2",
|
"//sandboxed_api/sandbox2",
|
||||||
"//sandboxed_api/sandbox2:comms",
|
"//sandboxed_api/sandbox2:comms",
|
||||||
"//sandboxed_api/sandbox2/network_proxy:filtering",
|
|
||||||
"//sandboxed_api/sandbox2/util:bpf_helper",
|
"//sandboxed_api/sandbox2/util:bpf_helper",
|
||||||
"//sandboxed_api/sandbox2/util:fileops",
|
"//sandboxed_api/sandbox2/util:fileops",
|
||||||
"//sandboxed_api/sandbox2/util:runfiles",
|
"//sandboxed_api/sandbox2/util:runfiles",
|
||||||
|
@ -43,7 +42,7 @@ cc_binary(
|
||||||
deps = [
|
deps = [
|
||||||
"//sandboxed_api/sandbox2:client",
|
"//sandboxed_api/sandbox2:client",
|
||||||
"//sandboxed_api/sandbox2:comms",
|
"//sandboxed_api/sandbox2:comms",
|
||||||
"//sandboxed_api/sandbox2/network_proxy:client",
|
"//sandboxed_api/sandbox2:network_proxy_client",
|
||||||
"//sandboxed_api/sandbox2/util:fileops",
|
"//sandboxed_api/sandbox2/util:fileops",
|
||||||
"@com_google_absl//absl/strings:str_format",
|
"@com_google_absl//absl/strings:str_format",
|
||||||
],
|
],
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include "absl/strings/str_format.h"
|
#include "absl/strings/str_format.h"
|
||||||
#include "sandboxed_api/sandbox2/client.h"
|
#include "sandboxed_api/sandbox2/client.h"
|
||||||
#include "sandboxed_api/sandbox2/comms.h"
|
#include "sandboxed_api/sandbox2/comms.h"
|
||||||
#include "sandboxed_api/sandbox2/network_proxy/client.h"
|
#include "sandboxed_api/sandbox2/network_proxy_client.h"
|
||||||
#include "sandboxed_api/sandbox2/util/fileops.h"
|
#include "sandboxed_api/sandbox2/util/fileops.h"
|
||||||
|
|
||||||
static ssize_t ReadFromFd(int fd, uint8_t* buf, size_t size) {
|
static ssize_t ReadFromFd(int fd, uint8_t* buf, size_t size) {
|
||||||
|
@ -113,6 +113,5 @@ int main(int argc, char** argv) {
|
||||||
if (!CommunicationTest(client.get())) {
|
if (!CommunicationTest(client.get())) {
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,8 +42,6 @@ std::unique_ptr<sandbox2::Policy> GetPolicy(absl::string_view sandboxee_path) {
|
||||||
.AllowSyscall(__NR_munmap)
|
.AllowSyscall(__NR_munmap)
|
||||||
.AllowSyscall(__NR_getpid)
|
.AllowSyscall(__NR_getpid)
|
||||||
.AddNetworkProxyHandlerPolicy()
|
.AddNetworkProxyHandlerPolicy()
|
||||||
.AllowTcMalloc()
|
|
||||||
.AllowIPv6("::1")
|
|
||||||
.AddLibrariesForBinary(sandboxee_path)
|
.AddLibrariesForBinary(sandboxee_path)
|
||||||
.BuildOrDie();
|
.BuildOrDie();
|
||||||
}
|
}
|
||||||
|
@ -131,7 +129,10 @@ int main(int argc, char** argv) {
|
||||||
// is capable of enabling sandboxing on its own).
|
// is capable of enabling sandboxing on its own).
|
||||||
->set_enable_sandbox_before_exec(false)
|
->set_enable_sandbox_before_exec(false)
|
||||||
// Set cwd to / to get rids of warnings connected with file namespace.
|
// Set cwd to / to get rids of warnings connected with file namespace.
|
||||||
.set_cwd("/");
|
.set_cwd("/")
|
||||||
|
// Enable built-in network proxy.
|
||||||
|
.ipc()
|
||||||
|
->EnableNetworkProxyServer();
|
||||||
executor
|
executor
|
||||||
->limits()
|
->limits()
|
||||||
// Remove restrictions on the size of address-space of sandboxed
|
// Remove restrictions on the size of address-space of sandboxed
|
||||||
|
|
|
@ -17,12 +17,16 @@
|
||||||
#include "sandboxed_api/sandbox2/ipc.h"
|
#include "sandboxed_api/sandbox2/ipc.h"
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <thread>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <thread> // NOLINT(build/c++11)
|
||||||
|
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include "absl/memory/memory.h"
|
#include "absl/memory/memory.h"
|
||||||
#include "sandboxed_api/sandbox2/logserver.h"
|
#include "sandboxed_api/sandbox2/logserver.h"
|
||||||
#include "sandboxed_api/sandbox2/logsink.h"
|
#include "sandboxed_api/sandbox2/logsink.h"
|
||||||
|
#include "sandboxed_api/sandbox2/network_proxy_client.h"
|
||||||
|
#include "sandboxed_api/sandbox2/network_proxy_server.h"
|
||||||
|
|
||||||
namespace sandbox2 {
|
namespace sandbox2 {
|
||||||
|
|
||||||
|
@ -99,4 +103,16 @@ void IPC::EnableLogServer() {
|
||||||
log_thread.detach();
|
log_thread.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IPC::EnableNetworkProxyServer() {
|
||||||
|
int fd = ReceiveFd(NetworkProxyClient::kFDName);
|
||||||
|
|
||||||
|
auto proxy_server = [fd]() {
|
||||||
|
NetworkProxyServer network_proxy_server(fd);
|
||||||
|
network_proxy_server.Run();
|
||||||
|
};
|
||||||
|
|
||||||
|
std::thread proxy_thread{proxy_server};
|
||||||
|
proxy_thread.detach();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sandbox2
|
} // namespace sandbox2
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "absl/base/macros.h"
|
||||||
#include "absl/strings/string_view.h"
|
#include "absl/strings/string_view.h"
|
||||||
#include "sandboxed_api/sandbox2/comms.h"
|
#include "sandboxed_api/sandbox2/comms.h"
|
||||||
|
|
||||||
|
@ -59,6 +60,10 @@ class IPC final {
|
||||||
// Client::SendLogsToSupervisor in the sandboxee.
|
// Client::SendLogsToSupervisor in the sandboxee.
|
||||||
void EnableLogServer();
|
void EnableLogServer();
|
||||||
|
|
||||||
|
// Enable network proxy server, this will start a thread in the sandbox
|
||||||
|
// that waits for connection requests from the sandboxee.
|
||||||
|
void EnableNetworkProxyServer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class Executor;
|
friend class Executor;
|
||||||
friend class Monitor;
|
friend class Monitor;
|
||||||
|
|
|
@ -53,7 +53,6 @@
|
||||||
#include "sandboxed_api/sandbox2/limits.h"
|
#include "sandboxed_api/sandbox2/limits.h"
|
||||||
#include "sandboxed_api/sandbox2/mounts.h"
|
#include "sandboxed_api/sandbox2/mounts.h"
|
||||||
#include "sandboxed_api/sandbox2/namespace.h"
|
#include "sandboxed_api/sandbox2/namespace.h"
|
||||||
#include "sandboxed_api/sandbox2/network_proxy/server.h"
|
|
||||||
#include "sandboxed_api/sandbox2/policy.h"
|
#include "sandboxed_api/sandbox2/policy.h"
|
||||||
#include "sandboxed_api/sandbox2/regs.h"
|
#include "sandboxed_api/sandbox2/regs.h"
|
||||||
#include "sandboxed_api/sandbox2/result.h"
|
#include "sandboxed_api/sandbox2/result.h"
|
||||||
|
@ -141,9 +140,6 @@ Monitor::~Monitor() {
|
||||||
if (log_file_) {
|
if (log_file_) {
|
||||||
std::fclose(log_file_);
|
std::fclose(log_file_);
|
||||||
}
|
}
|
||||||
if (network_proxy_server_) {
|
|
||||||
network_proxy_thread_.join();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -202,10 +198,6 @@ void Monitor::Run() {
|
||||||
// sandbox master/monitor, which ptrace_attach'es to the child.
|
// sandbox master/monitor, which ptrace_attach'es to the child.
|
||||||
int clone_flags = CLONE_UNTRACED;
|
int clone_flags = CLONE_UNTRACED;
|
||||||
|
|
||||||
if (policy_->allowed_hosts_) {
|
|
||||||
EnableNetworkProxyServer();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get PID of the sandboxee.
|
// Get PID of the sandboxee.
|
||||||
pid_t init_pid = 0;
|
pid_t init_pid = 0;
|
||||||
Namespace* ns = policy_->GetNamespace();
|
Namespace* ns = policy_->GetNamespace();
|
||||||
|
@ -357,14 +349,6 @@ void Monitor::MainLoop(sigset_t* sset) {
|
||||||
KillSandboxee();
|
KillSandboxee();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (network_proxy_server_ &&
|
|
||||||
network_proxy_server_->violation_occurred_.load(
|
|
||||||
std::memory_order_acquire) &&
|
|
||||||
!network_violation_) {
|
|
||||||
network_violation_ = true;
|
|
||||||
KillSandboxee();
|
|
||||||
}
|
|
||||||
|
|
||||||
// It should be a non-blocking operation (hence WNOHANG), so this function
|
// It should be a non-blocking operation (hence WNOHANG), so this function
|
||||||
// returns quickly if there are no events to be processed.
|
// returns quickly if there are no events to be processed.
|
||||||
// Prioritize main pid to avoid resource starvation
|
// Prioritize main pid to avoid resource starvation
|
||||||
|
@ -417,10 +401,7 @@ void Monitor::MainLoop(sigset_t* sset) {
|
||||||
VLOG(1) << "PID: " << ret << " terminated with signal: "
|
VLOG(1) << "PID: " << ret << " terminated with signal: "
|
||||||
<< util::GetSignalName(WTERMSIG(status));
|
<< util::GetSignalName(WTERMSIG(status));
|
||||||
if (ret == pid_) {
|
if (ret == pid_) {
|
||||||
if (network_violation_) {
|
if (external_kill_) {
|
||||||
SetExitStatusCode(Result::NETWORK_VIOLATION, 0);
|
|
||||||
result_.SetNetworkViolation(network_proxy_server_->violation_msg_);
|
|
||||||
} else if (external_kill_) {
|
|
||||||
SetExitStatusCode(Result::EXTERNAL_KILL, 0);
|
SetExitStatusCode(Result::EXTERNAL_KILL, 0);
|
||||||
} else if (timed_out_) {
|
} else if (timed_out_) {
|
||||||
SetExitStatusCode(Result::TIMEOUT, 0);
|
SetExitStatusCode(Result::TIMEOUT, 0);
|
||||||
|
@ -813,10 +794,7 @@ void Monitor::EventPtraceExit(pid_t pid, int event_msg) {
|
||||||
// 3) Regular signal/other exit cause.
|
// 3) Regular signal/other exit cause.
|
||||||
if (pid == pid_) {
|
if (pid == pid_) {
|
||||||
VLOG(1) << "PID: " << pid << " main special exit";
|
VLOG(1) << "PID: " << pid << " main special exit";
|
||||||
if (network_violation_) {
|
if (external_kill_) {
|
||||||
SetExitStatusCode(Result::NETWORK_VIOLATION, 0);
|
|
||||||
result_.SetNetworkViolation(network_proxy_server_->violation_msg_);
|
|
||||||
} else if (external_kill_) {
|
|
||||||
SetExitStatusCode(Result::EXTERNAL_KILL, 0);
|
SetExitStatusCode(Result::EXTERNAL_KILL, 0);
|
||||||
} else if (timed_out_) {
|
} else if (timed_out_) {
|
||||||
SetExitStatusCode(Result::TIMEOUT, 0);
|
SetExitStatusCode(Result::TIMEOUT, 0);
|
||||||
|
@ -948,14 +926,4 @@ void Monitor::LogSyscallViolationExplanation(const Syscall& syscall) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Monitor::EnableNetworkProxyServer() {
|
|
||||||
int fd = ipc_->ReceiveFd(NetworkProxyClient::kFDName);
|
|
||||||
|
|
||||||
network_proxy_server_ = absl::make_unique<NetworkProxyServer>(
|
|
||||||
fd, &policy_->allowed_hosts_.value(), pthread_self());
|
|
||||||
|
|
||||||
network_proxy_thread_ = std::thread(&NetworkProxyServer::Run,
|
|
||||||
network_proxy_server_.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace sandbox2
|
} // namespace sandbox2
|
||||||
|
|
|
@ -26,13 +26,11 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
#include "absl/synchronization/notification.h"
|
#include "absl/synchronization/notification.h"
|
||||||
#include "sandboxed_api/sandbox2/comms.h"
|
#include "sandboxed_api/sandbox2/comms.h"
|
||||||
#include "sandboxed_api/sandbox2/executor.h"
|
#include "sandboxed_api/sandbox2/executor.h"
|
||||||
#include "sandboxed_api/sandbox2/ipc.h"
|
#include "sandboxed_api/sandbox2/ipc.h"
|
||||||
#include "sandboxed_api/sandbox2/network_proxy/server.h"
|
|
||||||
#include "sandboxed_api/sandbox2/notify.h"
|
#include "sandboxed_api/sandbox2/notify.h"
|
||||||
#include "sandboxed_api/sandbox2/policy.h"
|
#include "sandboxed_api/sandbox2/policy.h"
|
||||||
#include "sandboxed_api/sandbox2/regs.h"
|
#include "sandboxed_api/sandbox2/regs.h"
|
||||||
|
@ -141,10 +139,6 @@ class Monitor final {
|
||||||
// Processes stop path.
|
// Processes stop path.
|
||||||
void EventPtraceStop(pid_t pid, int stopsig);
|
void EventPtraceStop(pid_t pid, int stopsig);
|
||||||
|
|
||||||
// Enable network proxy server, this will start a thread in the sandbox
|
|
||||||
// that waits for connection requests from the sandboxee.
|
|
||||||
void EnableNetworkProxyServer();
|
|
||||||
|
|
||||||
// Internal objects, owned by the Sandbox2 object.
|
// Internal objects, owned by the Sandbox2 object.
|
||||||
Executor* executor_;
|
Executor* executor_;
|
||||||
Notify* notify_;
|
Notify* notify_;
|
||||||
|
@ -174,8 +168,6 @@ class Monitor final {
|
||||||
std::atomic<int64_t> deadline_millis_{0};
|
std::atomic<int64_t> deadline_millis_{0};
|
||||||
// Was external kill sent to the sandboxee
|
// Was external kill sent to the sandboxee
|
||||||
bool external_kill_ = false;
|
bool external_kill_ = false;
|
||||||
// Network violation occurred and process of killing sandboxee started
|
|
||||||
bool network_violation_ = false;
|
|
||||||
// Is the sandboxee timed out
|
// Is the sandboxee timed out
|
||||||
bool timed_out_ = false;
|
bool timed_out_ = false;
|
||||||
// Should we dump the main sandboxed PID's stack?
|
// Should we dump the main sandboxed PID's stack?
|
||||||
|
@ -186,12 +178,6 @@ class Monitor final {
|
||||||
// Log file specified by
|
// Log file specified by
|
||||||
// --sandbox_danger_danger_permit_all_and_log flag.
|
// --sandbox_danger_danger_permit_all_and_log flag.
|
||||||
FILE* log_file_ = nullptr;
|
FILE* log_file_ = nullptr;
|
||||||
|
|
||||||
// Handle to the class responsible for proxying and validating connect()
|
|
||||||
// requests.
|
|
||||||
std::unique_ptr<NetworkProxyServer> network_proxy_server_;
|
|
||||||
|
|
||||||
std::thread network_proxy_thread_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sandbox2
|
} // namespace sandbox2
|
||||||
|
|
217
sandboxed_api/sandbox2/network_proxy_client.cc
Normal file
217
sandboxed_api/sandbox2/network_proxy_client.cc
Normal file
|
@ -0,0 +1,217 @@
|
||||||
|
// Copyright 2019 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
|
||||||
|
//
|
||||||
|
// http://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/network_proxy_client.h"
|
||||||
|
|
||||||
|
#include <linux/net.h>
|
||||||
|
#include <linux/seccomp.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <syscall.h>
|
||||||
|
#include <ucontext.h>
|
||||||
|
|
||||||
|
#include <cerrno>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <glog/logging.h>
|
||||||
|
#include "absl/memory/memory.h"
|
||||||
|
#include "absl/strings/str_cat.h"
|
||||||
|
#include "sandboxed_api/sandbox2/util/strerror.h"
|
||||||
|
#include "sandboxed_api/util/canonical_errors.h"
|
||||||
|
#include "sandboxed_api/util/status.h"
|
||||||
|
#include "sandboxed_api/util/status_macros.h"
|
||||||
|
|
||||||
|
namespace sandbox2 {
|
||||||
|
|
||||||
|
#ifndef SYS_SECCOMP
|
||||||
|
constexpr int SYS_SECCOMP = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
constexpr int kRegResult = REG_RAX;
|
||||||
|
constexpr int kRegSyscall = REG_RAX;
|
||||||
|
constexpr int kRegArg0 = REG_RDI;
|
||||||
|
constexpr int kRegArg1 = REG_RSI;
|
||||||
|
constexpr int kRegArg2 = REG_RDX;
|
||||||
|
#endif
|
||||||
|
#if defined(__powerpc64__)
|
||||||
|
constexpr int kRegResult = 3;
|
||||||
|
constexpr int kRegSyscall = 0;
|
||||||
|
constexpr int kRegArg0 = 3;
|
||||||
|
constexpr int kRegArg1 = 4;
|
||||||
|
constexpr int kRegArg2 = 5;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
constexpr char NetworkProxyClient::kFDName[];
|
||||||
|
|
||||||
|
int NetworkProxyClient::ConnectHandler(int sockfd, const struct sockaddr* addr,
|
||||||
|
socklen_t addrlen) {
|
||||||
|
sapi::Status status = Connect(sockfd, addr, addrlen);
|
||||||
|
if (status.ok()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
LOG(ERROR) << "ConnectHandler() failed: " << status.message();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sapi::Status NetworkProxyClient::Connect(int sockfd,
|
||||||
|
const struct sockaddr* addr,
|
||||||
|
socklen_t addrlen) {
|
||||||
|
absl::MutexLock lock(&mutex_);
|
||||||
|
|
||||||
|
// Check if socket is SOCK_STREAM
|
||||||
|
int type;
|
||||||
|
socklen_t type_size = sizeof(int);
|
||||||
|
int result = getsockopt(sockfd, SOL_SOCKET, SO_TYPE, &type, &type_size);
|
||||||
|
if (result == -1) {
|
||||||
|
return sapi::FailedPreconditionError("Invalid socket FD");
|
||||||
|
}
|
||||||
|
if (type_size != sizeof(int) || type != SOCK_STREAM) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return sapi::InvalidArgumentError(
|
||||||
|
"Invalid socket, only SOCK_STREAM is allowed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send sockaddr struct
|
||||||
|
if (!comms_.SendBytes(reinterpret_cast<const uint8_t*>(addr), addrlen)) {
|
||||||
|
errno = EIO;
|
||||||
|
return sapi::InternalError("Sending data to network proxy failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
SAPI_RETURN_IF_ERROR(ReceiveRemoteResult());
|
||||||
|
|
||||||
|
// Receive new socket
|
||||||
|
int s;
|
||||||
|
if (!comms_.RecvFD(&s)) {
|
||||||
|
errno = EIO;
|
||||||
|
return sapi::InternalError("Receiving data from network proxy failed");
|
||||||
|
}
|
||||||
|
if (dup2(s, sockfd) == -1) {
|
||||||
|
close(s);
|
||||||
|
return sapi::InternalError("Processing data from network proxy failed");
|
||||||
|
}
|
||||||
|
return sapi::OkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
sapi::Status NetworkProxyClient::ReceiveRemoteResult() {
|
||||||
|
int result;
|
||||||
|
if (!comms_.RecvInt32(&result)) {
|
||||||
|
errno = EIO;
|
||||||
|
return sapi::InternalError("Receiving data from the network proxy failed");
|
||||||
|
}
|
||||||
|
if (result != 0) {
|
||||||
|
errno = result;
|
||||||
|
return sapi::InternalError(
|
||||||
|
absl::StrCat("Error in network proxy server: ", StrError(errno)));
|
||||||
|
}
|
||||||
|
return sapi::OkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
static NetworkProxyHandler* g_network_proxy_handler = nullptr;
|
||||||
|
|
||||||
|
void SignalHandler(int nr, siginfo_t* info, void* void_context) {
|
||||||
|
g_network_proxy_handler->ProcessSeccompTrap(nr, info, void_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
sapi::Status NetworkProxyHandler::InstallNetworkProxyHandler(
|
||||||
|
NetworkProxyClient* npc) {
|
||||||
|
if (g_network_proxy_handler) {
|
||||||
|
return sapi::AlreadyExistsError(
|
||||||
|
"Network proxy handler is already installed");
|
||||||
|
}
|
||||||
|
g_network_proxy_handler = new NetworkProxyHandler(npc);
|
||||||
|
return sapi::OkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkProxyHandler::InvokeOldAct(int nr, siginfo_t* info,
|
||||||
|
void* void_context) {
|
||||||
|
if (oldact_.sa_flags & SA_SIGINFO) {
|
||||||
|
if (oldact_.sa_sigaction) {
|
||||||
|
oldact_.sa_sigaction(nr, info, void_context);
|
||||||
|
}
|
||||||
|
} else if (oldact_.sa_handler == SIG_IGN) {
|
||||||
|
return;
|
||||||
|
} else if (oldact_.sa_handler == SIG_DFL) {
|
||||||
|
sigaction(SIGSYS, &oldact_, nullptr);
|
||||||
|
raise(SIGSYS);
|
||||||
|
} else if (oldact_.sa_handler) {
|
||||||
|
oldact_.sa_handler(nr);
|
||||||
|
}
|
||||||
|
} // namespace sandbox2
|
||||||
|
|
||||||
|
void NetworkProxyHandler::ProcessSeccompTrap(int nr, siginfo_t* info,
|
||||||
|
void* void_context) {
|
||||||
|
ucontext_t* ctx = (ucontext_t*)(void_context);
|
||||||
|
if (info->si_code != SYS_SECCOMP) {
|
||||||
|
InvokeOldAct(nr, info, void_context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!ctx) return;
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
auto* registers = ctx->uc_mcontext.gregs;
|
||||||
|
#elif defined(__powerpc64__)
|
||||||
|
auto* registers = ctx->uc_mcontext.gp_regs;
|
||||||
|
using ppc_gpreg_t = std::decay<decltype(registers[0])>::type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int syscall = registers[kRegSyscall];
|
||||||
|
|
||||||
|
int sockfd;
|
||||||
|
const struct sockaddr* addr;
|
||||||
|
socklen_t addrlen;
|
||||||
|
|
||||||
|
if (syscall == __NR_connect) {
|
||||||
|
sockfd = static_cast<int>(registers[kRegArg0]);
|
||||||
|
addr = reinterpret_cast<const struct sockaddr*>(registers[kRegArg1]);
|
||||||
|
addrlen = static_cast<socklen_t>(registers[kRegArg2]);
|
||||||
|
#if defined(__powerpc64__)
|
||||||
|
} else if (syscall == __NR_socketcall &&
|
||||||
|
static_cast<int>(registers[kRegArg0]) == SYS_CONNECT) {
|
||||||
|
ppc_gpreg_t* args = reinterpret_cast<ppc_gpreg_t*>(registers[kRegArg1]);
|
||||||
|
|
||||||
|
sockfd = static_cast<int>(args[0]);
|
||||||
|
addr = reinterpret_cast<const struct sockaddr*>(args[1]);
|
||||||
|
addrlen = static_cast<socklen_t>(args[2]);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
InvokeOldAct(nr, info, void_context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sapi::Status result = network_proxy_client_->Connect(sockfd, addr, addrlen);
|
||||||
|
if (result.ok()) {
|
||||||
|
registers[kRegResult] = 0;
|
||||||
|
} else {
|
||||||
|
registers[kRegResult] = -errno;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkProxyHandler::InstallSeccompTrap() {
|
||||||
|
sigset_t mask;
|
||||||
|
sigemptyset(&mask);
|
||||||
|
sigaddset(&mask, SIGSYS);
|
||||||
|
|
||||||
|
struct sigaction act = {};
|
||||||
|
act.sa_sigaction = &SignalHandler;
|
||||||
|
act.sa_flags = SA_SIGINFO;
|
||||||
|
|
||||||
|
CHECK_EQ(sigaction(SIGSYS, &act, &oldact_), 0);
|
||||||
|
CHECK_EQ(sigprocmask(SIG_UNBLOCK, &mask, nullptr), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sandbox2
|
75
sandboxed_api/sandbox2/network_proxy_client.h
Normal file
75
sandboxed_api/sandbox2/network_proxy_client.h
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
// Copyright 2019 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
|
||||||
|
//
|
||||||
|
// http://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_NETWORK_PROXY_CLIENT_H_
|
||||||
|
#define SANDBOXED_API_SANDBOX2_NETWORK_PROXY_CLIENT_H_
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#include "absl/synchronization/mutex.h"
|
||||||
|
#include "sandboxed_api/sandbox2/comms.h"
|
||||||
|
#include "sandboxed_api/util/status.h"
|
||||||
|
|
||||||
|
namespace sandbox2 {
|
||||||
|
|
||||||
|
class NetworkProxyClient {
|
||||||
|
public:
|
||||||
|
static constexpr char kFDName[] = "sb2_networkproxy";
|
||||||
|
|
||||||
|
explicit NetworkProxyClient(int fd) : comms_(fd) {}
|
||||||
|
|
||||||
|
NetworkProxyClient(const NetworkProxyClient&) = delete;
|
||||||
|
NetworkProxyClient& operator=(const NetworkProxyClient&) = delete;
|
||||||
|
|
||||||
|
// Establishes a new network connection.
|
||||||
|
// Semantic is similar to a regular connect() call.
|
||||||
|
// Arguments are sent to network proxy server, which sends back a connected
|
||||||
|
// socket.
|
||||||
|
sapi::Status Connect(int sockfd, const struct sockaddr* addr,
|
||||||
|
socklen_t addrlen);
|
||||||
|
// Same as Connect, but with same API as regular connect() call.
|
||||||
|
int ConnectHandler(int sockfd, const struct sockaddr* addr,
|
||||||
|
socklen_t addrlen);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Comms comms_;
|
||||||
|
sapi::Status ReceiveRemoteResult();
|
||||||
|
|
||||||
|
// Needed to make the Proxy thread safe.
|
||||||
|
absl::Mutex mutex_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NetworkProxyHandler {
|
||||||
|
public:
|
||||||
|
// Installs the handler that redirects connect() syscalls to the trap
|
||||||
|
// function. This function exchange data with NetworkProxyServer that checks
|
||||||
|
// if this connection is allowed and sends the connected socket to us.
|
||||||
|
// In other words, this function just use NetworkProxyClient class.
|
||||||
|
static sapi::Status InstallNetworkProxyHandler(NetworkProxyClient* npc);
|
||||||
|
void ProcessSeccompTrap(int nr, siginfo_t* info, void* void_context);
|
||||||
|
|
||||||
|
private:
|
||||||
|
NetworkProxyHandler(NetworkProxyClient* npc) : network_proxy_client_(npc) {
|
||||||
|
InstallSeccompTrap();
|
||||||
|
}
|
||||||
|
void InvokeOldAct(int nr, siginfo_t* info, void* void_context);
|
||||||
|
void InstallSeccompTrap();
|
||||||
|
|
||||||
|
struct sigaction oldact_;
|
||||||
|
NetworkProxyClient* network_proxy_client_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sandbox2
|
||||||
|
|
||||||
|
#endif // SANDBOXED_API_SANDBOX2_NETWORK_PROXY_CLIENT_H_
|
95
sandboxed_api/sandbox2/network_proxy_server.cc
Normal file
95
sandboxed_api/sandbox2/network_proxy_server.cc
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
// Copyright 2019 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
|
||||||
|
//
|
||||||
|
// http://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/network_proxy_server.h"
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <syscall.h>
|
||||||
|
#include <cerrno>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <glog/logging.h>
|
||||||
|
#include "absl/memory/memory.h"
|
||||||
|
#include "sandboxed_api/sandbox2/util/fileops.h"
|
||||||
|
|
||||||
|
namespace sandbox2 {
|
||||||
|
|
||||||
|
NetworkProxyServer::NetworkProxyServer(int fd)
|
||||||
|
: comms_{absl::make_unique<Comms>(fd)}, fatal_error_{false} {}
|
||||||
|
|
||||||
|
void NetworkProxyServer::ProcessConnectRequest() {
|
||||||
|
std::vector<uint8_t> addr;
|
||||||
|
if (!comms_->RecvBytes(&addr)) {
|
||||||
|
fatal_error_ = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct sockaddr_in* saddr =
|
||||||
|
reinterpret_cast<const sockaddr_in*>(addr.data());
|
||||||
|
|
||||||
|
// Only IPv4 TCP and IPv6 TCP are supported.
|
||||||
|
if (!((addr.size() == sizeof(sockaddr_in) && saddr->sin_family == AF_INET) ||
|
||||||
|
(addr.size() == sizeof(sockaddr_in6) &&
|
||||||
|
saddr->sin_family == AF_INET6))) {
|
||||||
|
SendError(EINVAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int new_socket = socket(saddr->sin_family, SOCK_STREAM, 0);
|
||||||
|
if (new_socket < 0) {
|
||||||
|
SendError(errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_util::fileops::FDCloser new_socket_closer(new_socket);
|
||||||
|
|
||||||
|
int result = connect(
|
||||||
|
new_socket, reinterpret_cast<const sockaddr*>(addr.data()), addr.size());
|
||||||
|
|
||||||
|
if (result == 0) {
|
||||||
|
NotifySuccess();
|
||||||
|
if (!fatal_error_) {
|
||||||
|
if (!comms_->SendFD(new_socket)) {
|
||||||
|
fatal_error_ = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkProxyServer::Run() {
|
||||||
|
while (!fatal_error_) {
|
||||||
|
ProcessConnectRequest();
|
||||||
|
}
|
||||||
|
LOG(INFO)
|
||||||
|
<< "Clean shutdown or error occurred, shutting down NetworkProxyServer";
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkProxyServer::SendError(int saved_errno) {
|
||||||
|
if (!comms_->SendInt32(saved_errno)) {
|
||||||
|
fatal_error_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkProxyServer::NotifySuccess() {
|
||||||
|
if (!comms_->SendInt32(0)) {
|
||||||
|
fatal_error_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sandbox2
|
53
sandboxed_api/sandbox2/network_proxy_server.h
Normal file
53
sandboxed_api/sandbox2/network_proxy_server.h
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
// Copyright 2019 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
|
||||||
|
//
|
||||||
|
// http://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_NETWORK_PROXY_SERVER_H_
|
||||||
|
#define SANDBOXED_API_SANDBOX2_NETWORK_PROXY_SERVER_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "sandboxed_api/sandbox2/comms.h"
|
||||||
|
|
||||||
|
namespace sandbox2 {
|
||||||
|
|
||||||
|
// This is a proxy server that spawns connected sockets on requests.
|
||||||
|
// Then it sends the file descriptor to the requestor. It is used to get around
|
||||||
|
// limitations created by network namespaces.
|
||||||
|
class NetworkProxyServer {
|
||||||
|
public:
|
||||||
|
explicit NetworkProxyServer(int fd);
|
||||||
|
|
||||||
|
NetworkProxyServer(const NetworkProxyServer&) = delete;
|
||||||
|
NetworkProxyServer& operator=(const NetworkProxyServer&) = delete;
|
||||||
|
|
||||||
|
// Starts handling incoming connection requests.
|
||||||
|
void Run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Notifies the network proxy client about the error and sends its code.
|
||||||
|
void SendError(int saved_errno);
|
||||||
|
|
||||||
|
// Notifies the network proxy client that no error occurred.
|
||||||
|
void NotifySuccess();
|
||||||
|
|
||||||
|
// Serves connection requests from the network proxy client.
|
||||||
|
void ProcessConnectRequest();
|
||||||
|
|
||||||
|
std::unique_ptr<Comms> comms_;
|
||||||
|
bool fatal_error_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sandbox2
|
||||||
|
|
||||||
|
#endif // SANDBOXED_API_SANDBOX2_NETWORK_PROXY_SERVER_H_
|
|
@ -31,7 +31,6 @@
|
||||||
#include "absl/base/macros.h"
|
#include "absl/base/macros.h"
|
||||||
#include "absl/types/optional.h"
|
#include "absl/types/optional.h"
|
||||||
#include "sandboxed_api/sandbox2/namespace.h"
|
#include "sandboxed_api/sandbox2/namespace.h"
|
||||||
#include "sandboxed_api/sandbox2/network_proxy/filtering.h"
|
|
||||||
#include "sandboxed_api/sandbox2/syscall.h"
|
#include "sandboxed_api/sandbox2/syscall.h"
|
||||||
#include "sandboxed_api/sandbox2/violation.pb.h"
|
#include "sandboxed_api/sandbox2/violation.pb.h"
|
||||||
|
|
||||||
|
@ -105,9 +104,6 @@ class Policy final {
|
||||||
// Get a policy which would allow the Monitor module to track all syscalls.
|
// Get a policy which would allow the Monitor module to track all syscalls.
|
||||||
std::vector<sock_filter> GetTrackingPolicy() const;
|
std::vector<sock_filter> GetTrackingPolicy() const;
|
||||||
|
|
||||||
// Contains a list of hosts the sandboxee is allowed to connect to.
|
|
||||||
absl::optional<AllowedHosts> allowed_hosts_;
|
|
||||||
|
|
||||||
friend class Monitor;
|
friend class Monitor;
|
||||||
friend class PolicyBuilder;
|
friend class PolicyBuilder;
|
||||||
friend class PolicyBuilderPeer; // For testing
|
friend class PolicyBuilderPeer; // For testing
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
#include "sandboxed_api/sandbox2/namespace.h"
|
#include "sandboxed_api/sandbox2/namespace.h"
|
||||||
#include "sandboxed_api/sandbox2/util/bpf_helper.h"
|
#include "sandboxed_api/sandbox2/util/bpf_helper.h"
|
||||||
#include "sandboxed_api/sandbox2/util/path.h"
|
#include "sandboxed_api/sandbox2/util/path.h"
|
||||||
#include "sandboxed_api/sandbox2/util/strerror.h"
|
|
||||||
#include "sandboxed_api/util/canonical_errors.h"
|
#include "sandboxed_api/util/canonical_errors.h"
|
||||||
#include "sandboxed_api/util/status_macros.h"
|
#include "sandboxed_api/util/status_macros.h"
|
||||||
|
|
||||||
|
@ -48,7 +47,7 @@ namespace {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
PolicyBuilder& PolicyBuilder::AllowSyscall(uint32_t num) {
|
PolicyBuilder& PolicyBuilder::AllowSyscall(unsigned int num) {
|
||||||
if (handled_syscalls_.insert(num).second) {
|
if (handled_syscalls_.insert(num).second) {
|
||||||
user_policy_.insert(user_policy_.end(), {SYSCALL(num, ALLOW)});
|
user_policy_.insert(user_policy_.end(), {SYSCALL(num, ALLOW)});
|
||||||
}
|
}
|
||||||
|
@ -69,7 +68,8 @@ PolicyBuilder& PolicyBuilder::AllowSyscalls(SyscallInitializer nums) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
PolicyBuilder& PolicyBuilder::BlockSyscallWithErrno(uint32_t num, int error) {
|
PolicyBuilder& PolicyBuilder::BlockSyscallWithErrno(unsigned int num,
|
||||||
|
int error) {
|
||||||
if (handled_syscalls_.insert(num).second) {
|
if (handled_syscalls_.insert(num).second) {
|
||||||
user_policy_.insert(user_policy_.end(), {SYSCALL(num, ERRNO(error))});
|
user_policy_.insert(user_policy_.end(), {SYSCALL(num, ERRNO(error))});
|
||||||
}
|
}
|
||||||
|
@ -545,17 +545,17 @@ PolicyBuilder& PolicyBuilder::AllowDynamicStartup() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
PolicyBuilder& PolicyBuilder::AddPolicyOnSyscall(uint32_t num,
|
PolicyBuilder& PolicyBuilder::AddPolicyOnSyscall(unsigned int num,
|
||||||
BpfInitializer policy) {
|
BpfInitializer policy) {
|
||||||
return AddPolicyOnSyscalls({num}, policy);
|
return AddPolicyOnSyscalls({num}, policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
PolicyBuilder& PolicyBuilder::AddPolicyOnSyscall(
|
PolicyBuilder& PolicyBuilder::AddPolicyOnSyscall(
|
||||||
uint32_t num, const std::vector<sock_filter>& policy) {
|
unsigned int num, const std::vector<sock_filter>& policy) {
|
||||||
return AddPolicyOnSyscalls({num}, policy);
|
return AddPolicyOnSyscalls({num}, policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
PolicyBuilder& PolicyBuilder::AddPolicyOnSyscall(uint32_t num, BpfFunc f) {
|
PolicyBuilder& PolicyBuilder::AddPolicyOnSyscall(unsigned int num, BpfFunc f) {
|
||||||
return AddPolicyOnSyscalls({num}, f);
|
return AddPolicyOnSyscalls({num}, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -700,7 +700,6 @@ sapi::StatusOr<std::unique_ptr<Policy>> PolicyBuilder::TryBuild() {
|
||||||
|
|
||||||
StoreDescription(pb_description.get());
|
StoreDescription(pb_description.get());
|
||||||
output->policy_builder_description_ = std::move(pb_description);
|
output->policy_builder_description_ = std::move(pb_description);
|
||||||
output->allowed_hosts_ = std::move(allowed_hosts_);
|
|
||||||
already_built_ = true;
|
already_built_ = true;
|
||||||
return std::move(output);
|
return std::move(output);
|
||||||
}
|
}
|
||||||
|
@ -849,15 +848,6 @@ PolicyBuilder& PolicyBuilder::CollectStacktracesOnKill(bool enable) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PolicyBuilder& PolicyBuilder::AddNetworkProxyPolicy() {
|
PolicyBuilder& PolicyBuilder::AddNetworkProxyPolicy() {
|
||||||
if (allowed_hosts_) {
|
|
||||||
SetError(sapi::FailedPreconditionError(
|
|
||||||
"AddNetworkProxyPolicy or AddNetworkProxyHandlerPolicy can be called "
|
|
||||||
"at most once"));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
allowed_hosts_ = AllowedHosts();
|
|
||||||
|
|
||||||
AllowFutexOp(FUTEX_WAKE);
|
AllowFutexOp(FUTEX_WAKE);
|
||||||
AllowFutexOp(FUTEX_WAIT);
|
AllowFutexOp(FUTEX_WAIT);
|
||||||
AllowFutexOp(FUTEX_WAIT_BITSET);
|
AllowFutexOp(FUTEX_WAIT_BITSET);
|
||||||
|
@ -930,36 +920,4 @@ void PolicyBuilder::StoreDescription(PolicyBuilderDescription* pb_description) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PolicyBuilder& PolicyBuilder::AllowIPv4(const std::string& ip_and_mask,
|
|
||||||
uint32_t port) {
|
|
||||||
if (!allowed_hosts_) {
|
|
||||||
SetError(sapi::FailedPreconditionError(
|
|
||||||
"AddNetworkProxyPolicy or AddNetworkProxyHandlerPolicy must be called "
|
|
||||||
"before adding IP rules"));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
sapi::Status status = allowed_hosts_->AllowIPv4(ip_and_mask, port);
|
|
||||||
if (!status.ok()) {
|
|
||||||
SetError(status);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
PolicyBuilder& PolicyBuilder::AllowIPv6(const std::string& ip_and_mask,
|
|
||||||
uint32_t port) {
|
|
||||||
if (!allowed_hosts_) {
|
|
||||||
SetError(sapi::FailedPreconditionError(
|
|
||||||
"AddNetworkProxyPolicy or AddNetworkProxyHandlerPolicy must be called "
|
|
||||||
"before adding IP rules"));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
sapi::Status status = allowed_hosts_->AllowIPv6(ip_and_mask, port);
|
|
||||||
if (!status.ok()) {
|
|
||||||
SetError(status);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace sandbox2
|
} // namespace sandbox2
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#include "absl/memory/memory.h"
|
#include "absl/memory/memory.h"
|
||||||
#include "absl/strings/string_view.h"
|
#include "absl/strings/string_view.h"
|
||||||
#include "sandboxed_api/sandbox2/mounts.h"
|
#include "sandboxed_api/sandbox2/mounts.h"
|
||||||
#include "sandboxed_api/sandbox2/network_proxy/filtering.h"
|
|
||||||
#include "sandboxed_api/sandbox2/policy.h"
|
#include "sandboxed_api/sandbox2/policy.h"
|
||||||
#include "sandboxed_api/util/statusor.h"
|
#include "sandboxed_api/util/statusor.h"
|
||||||
|
|
||||||
|
@ -502,10 +501,6 @@ class PolicyBuilder final {
|
||||||
// Not recommended
|
// Not recommended
|
||||||
PolicyBuilder& SetRootWritable();
|
PolicyBuilder& SetRootWritable();
|
||||||
|
|
||||||
// Allows connections to this IP.
|
|
||||||
PolicyBuilder& AllowIPv4(const std::string& ip_and_mask, uint32_t port = 0);
|
|
||||||
PolicyBuilder& AllowIPv6(const std::string& ip_and_mask, uint32_t port = 0);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class PolicyBuilderPeer; // For testing
|
friend class PolicyBuilderPeer; // For testing
|
||||||
friend class StackTracePeer;
|
friend class StackTracePeer;
|
||||||
|
@ -547,9 +542,6 @@ class PolicyBuilder final {
|
||||||
// This function returns a PolicyBuilder so that we can use it in the status
|
// This function returns a PolicyBuilder so that we can use it in the status
|
||||||
// macros
|
// macros
|
||||||
PolicyBuilder& SetError(const sapi::Status& status);
|
PolicyBuilder& SetError(const sapi::Status& status);
|
||||||
|
|
||||||
// Contains list of allowed hosts.
|
|
||||||
absl::optional<AllowedHosts> allowed_hosts_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sandbox2
|
} // namespace sandbox2
|
||||||
|
|
|
@ -79,10 +79,6 @@ std::string Result::ToString() const {
|
||||||
Syscall(GetSyscallArch(), reason_code()).GetName(),
|
Syscall(GetSyscallArch(), reason_code()).GetName(),
|
||||||
"] Stack: ", GetStackTrace());
|
"] Stack: ", GetStackTrace());
|
||||||
break;
|
break;
|
||||||
case sandbox2::Result::NETWORK_VIOLATION:
|
|
||||||
result = absl::StrCat("NETWORK VIOLATION - Violating network policy: ",
|
|
||||||
network_violation_);
|
|
||||||
break;
|
|
||||||
case sandbox2::Result::SIGNALED:
|
case sandbox2::Result::SIGNALED:
|
||||||
result = absl::StrCat("Process terminated with a SIGNAL - Signal: ",
|
result = absl::StrCat("Process terminated with a SIGNAL - Signal: ",
|
||||||
util::GetSignalName(reason_code()),
|
util::GetSignalName(reason_code()),
|
||||||
|
@ -133,8 +129,6 @@ std::string Result::StatusEnumToString(StatusEnum value) {
|
||||||
return "SETUP_ERROR";
|
return "SETUP_ERROR";
|
||||||
case sandbox2::Result::VIOLATION:
|
case sandbox2::Result::VIOLATION:
|
||||||
return "VIOLATION";
|
return "VIOLATION";
|
||||||
case sandbox2::Result::NETWORK_VIOLATION:
|
|
||||||
return "NETWORK_VIOLATION";
|
|
||||||
case sandbox2::Result::SIGNALED:
|
case sandbox2::Result::SIGNALED:
|
||||||
return "SIGNALED";
|
return "SIGNALED";
|
||||||
case sandbox2::Result::TIMEOUT:
|
case sandbox2::Result::TIMEOUT:
|
||||||
|
|
|
@ -45,8 +45,6 @@ class Result {
|
||||||
SETUP_ERROR,
|
SETUP_ERROR,
|
||||||
// Syscall violation
|
// Syscall violation
|
||||||
VIOLATION,
|
VIOLATION,
|
||||||
// Network policy violation
|
|
||||||
NETWORK_VIOLATION,
|
|
||||||
// Process terminated with a signal
|
// Process terminated with a signal
|
||||||
SIGNALED,
|
SIGNALED,
|
||||||
// Process terminated with a timeout
|
// Process terminated with a timeout
|
||||||
|
@ -121,10 +119,6 @@ class Result {
|
||||||
syscall_ = std::move(syscall);
|
syscall_ = std::move(syscall);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetNetworkViolation(std::string network_violation) {
|
|
||||||
network_violation_ = std::move(network_violation);
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusEnum final_status() const { return final_status_; }
|
StatusEnum final_status() const { return final_status_; }
|
||||||
uintptr_t reason_code() const { return reason_code_; }
|
uintptr_t reason_code() const { return reason_code_; }
|
||||||
|
|
||||||
|
@ -143,8 +137,6 @@ class Result {
|
||||||
|
|
||||||
const std::string& GetProgName() const { return prog_name_; }
|
const std::string& GetProgName() const { return prog_name_; }
|
||||||
|
|
||||||
const std::string& GetNetworkViolation() const { return network_violation_; }
|
|
||||||
|
|
||||||
void SetProgName(const std::string& name) { prog_name_ = name; }
|
void SetProgName(const std::string& name) { prog_name_ = name; }
|
||||||
|
|
||||||
const std::string& GetProcMaps() const { return proc_maps_; }
|
const std::string& GetProcMaps() const { return proc_maps_; }
|
||||||
|
@ -187,8 +179,6 @@ class Result {
|
||||||
std::string prog_name_;
|
std::string prog_name_;
|
||||||
// /proc/pid/maps of the main process.
|
// /proc/pid/maps of the main process.
|
||||||
std::string proc_maps_;
|
std::string proc_maps_;
|
||||||
// IP and port if network violation occurred
|
|
||||||
std::string network_violation_;
|
|
||||||
// Final resource usage as defined in <sys/resource.h> (man getrusage), for
|
// Final resource usage as defined in <sys/resource.h> (man getrusage), for
|
||||||
// the Monitor thread.
|
// the Monitor thread.
|
||||||
rusage rusage_monitor_;
|
rusage rusage_monitor_;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user