mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
Replace sapi::Status with absl::Status
PiperOrigin-RevId: 297614681 Change-Id: I89fe1357a172ed4d28df6dd84b80fee364ce1c14
This commit is contained in:
parent
a5d931ec5f
commit
f6c3db4c6e
@ -18,7 +18,7 @@ project(absl-download NONE)
|
|||||||
include(ExternalProject)
|
include(ExternalProject)
|
||||||
ExternalProject_Add(absl
|
ExternalProject_Add(absl
|
||||||
GIT_REPOSITORY https://github.com/abseil/abseil-cpp
|
GIT_REPOSITORY https://github.com/abseil/abseil-cpp
|
||||||
GIT_TAG 8ba96a8244bbe334d09542e92d566673a65c1f78 # 2019-11-19
|
GIT_TAG 0033c9ea91a52ade7c6b725aa2ef3cbe15463421 # 2020-02-25
|
||||||
SOURCE_DIR "${CMAKE_BINARY_DIR}/absl-src"
|
SOURCE_DIR "${CMAKE_BINARY_DIR}/absl-src"
|
||||||
BINARY_DIR "${CMAKE_BINARY_DIR}/absl-build"
|
BINARY_DIR "${CMAKE_BINARY_DIR}/absl-build"
|
||||||
CONFIGURE_COMMAND ""
|
CONFIGURE_COMMAND ""
|
||||||
|
@ -35,6 +35,7 @@ endif()
|
|||||||
set(_sapi_saved_CMAKE_CXX_STANDARD ${CMAKE_CXX_STANDARD})
|
set(_sapi_saved_CMAKE_CXX_STANDARD ${CMAKE_CXX_STANDARD})
|
||||||
set(CMAKE_CXX_STANDARD ${SAPI_CXX_STANDARD})
|
set(CMAKE_CXX_STANDARD ${SAPI_CXX_STANDARD})
|
||||||
set(ABSL_USE_GOOGLETEST_HEAD OFF CACHE BOOL "" FORCE)
|
set(ABSL_USE_GOOGLETEST_HEAD OFF CACHE BOOL "" FORCE)
|
||||||
|
set(ABSL_CXX_STANDARD ${SAPI_CXX_STANDARD} CACHE STRING "" FORCE)
|
||||||
|
|
||||||
add_subdirectory("${CMAKE_BINARY_DIR}/absl-src"
|
add_subdirectory("${CMAKE_BINARY_DIR}/absl-src"
|
||||||
"${CMAKE_BINARY_DIR}/absl-build" EXCLUDE_FROM_ALL)
|
"${CMAKE_BINARY_DIR}/absl-build" EXCLUDE_FROM_ALL)
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
# Build in C++17 mode without a custom CROSSTOOL
|
# Build in C++17 mode without a custom CROSSTOOL
|
||||||
build --cxxopt='-std=c++17'
|
build --cxxopt=-std=c++17
|
||||||
|
@ -12,13 +12,13 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
load("//sandboxed_api/bazel:build_defs.bzl", "sapi_platform_copts")
|
||||||
|
load("//sandboxed_api/bazel:proto.bzl", "sapi_proto_library")
|
||||||
|
|
||||||
licenses(["notice"])
|
licenses(["notice"])
|
||||||
|
|
||||||
exports_files(["LICENSE"])
|
exports_files(["LICENSE"])
|
||||||
|
|
||||||
load("//sandboxed_api/bazel:build_defs.bzl", "sapi_platform_copts")
|
|
||||||
load("//sandboxed_api/bazel:proto.bzl", "sapi_proto_library")
|
|
||||||
|
|
||||||
sapi_proto_library(
|
sapi_proto_library(
|
||||||
name = "proto_arg",
|
name = "proto_arg",
|
||||||
srcs = ["proto_arg.proto"],
|
srcs = ["proto_arg.proto"],
|
||||||
@ -39,8 +39,8 @@ cc_library(
|
|||||||
"//sandboxed_api/sandbox2/util:fileops",
|
"//sandboxed_api/sandbox2/util:fileops",
|
||||||
"//sandboxed_api/sandbox2/util:strerror",
|
"//sandboxed_api/sandbox2/util:strerror",
|
||||||
"//sandboxed_api/util:raw_logging",
|
"//sandboxed_api/util:raw_logging",
|
||||||
"//sandboxed_api/util:status",
|
|
||||||
"@com_google_absl//absl/container:flat_hash_map",
|
"@com_google_absl//absl/container:flat_hash_map",
|
||||||
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
"@com_google_absl//absl/synchronization",
|
"@com_google_absl//absl/synchronization",
|
||||||
"@com_google_glog//:glog",
|
"@com_google_glog//:glog",
|
||||||
@ -80,6 +80,7 @@ cc_library(
|
|||||||
"@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/memory",
|
"@com_google_absl//absl/memory",
|
||||||
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
"@com_google_absl//absl/strings:str_format",
|
"@com_google_absl//absl/strings:str_format",
|
||||||
"@com_google_absl//absl/synchronization",
|
"@com_google_absl//absl/synchronization",
|
||||||
@ -149,6 +150,7 @@ cc_library(
|
|||||||
"//sandboxed_api/util:statusor",
|
"//sandboxed_api/util:statusor",
|
||||||
"@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/status",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
"@com_google_absl//absl/strings:str_format",
|
"@com_google_absl//absl/strings:str_format",
|
||||||
"@com_google_absl//absl/synchronization",
|
"@com_google_absl//absl/synchronization",
|
||||||
@ -189,9 +191,9 @@ cc_test(
|
|||||||
"//sandboxed_api/examples/stringop/lib:stringop_params_cc_proto",
|
"//sandboxed_api/examples/stringop/lib:stringop_params_cc_proto",
|
||||||
"//sandboxed_api/examples/sum/lib:sum-sapi",
|
"//sandboxed_api/examples/sum/lib:sum-sapi",
|
||||||
"//sandboxed_api/examples/sum/lib:sum-sapi_embed",
|
"//sandboxed_api/examples/sum/lib:sum-sapi_embed",
|
||||||
"//sandboxed_api/util:status",
|
|
||||||
"//sandboxed_api/util:status_matchers",
|
"//sandboxed_api/util:status_matchers",
|
||||||
"@com_google_absl//absl/memory",
|
"@com_google_absl//absl/memory",
|
||||||
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_benchmark//:benchmark",
|
"@com_google_benchmark//:benchmark",
|
||||||
"@com_google_googletest//:gtest_main",
|
"@com_google_googletest//:gtest_main",
|
||||||
],
|
],
|
||||||
|
@ -33,9 +33,9 @@ def sapi_deps():
|
|||||||
maybe(
|
maybe(
|
||||||
http_archive,
|
http_archive,
|
||||||
name = "com_google_absl",
|
name = "com_google_absl",
|
||||||
sha256 = "d8bc776c9702c7875c64410d1380cf3f3c0f75d5df9be08218589579604c539e", # 2019-11-19
|
sha256 = "a245e059514f2e3bd0bd6ca455b6a66e34656b1b447fec3dc98419153af23b14", # 2020-02-25
|
||||||
strip_prefix = "abseil-cpp-8ba96a8244bbe334d09542e92d566673a65c1f78",
|
strip_prefix = "abseil-cpp-0033c9ea91a52ade7c6b725aa2ef3cbe15463421",
|
||||||
urls = ["https://github.com/abseil/abseil-cpp/archive/8ba96a8244bbe334d09542e92d566673a65c1f78.zip"],
|
urls = ["https://github.com/abseil/abseil-cpp/archive/0033c9ea91a52ade7c6b725aa2ef3cbe15463421.zip"],
|
||||||
)
|
)
|
||||||
maybe(
|
maybe(
|
||||||
http_archive,
|
http_archive,
|
||||||
|
@ -21,13 +21,13 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "absl/strings/str_cat.h"
|
#include "absl/strings/str_cat.h"
|
||||||
#include "absl/strings/string_view.h"
|
#include "absl/strings/string_view.h"
|
||||||
#include "sandboxed_api/sandbox2/util.h"
|
#include "sandboxed_api/sandbox2/util.h"
|
||||||
#include "sandboxed_api/sandbox2/util/fileops.h"
|
#include "sandboxed_api/sandbox2/util/fileops.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"
|
||||||
#include "sandboxed_api/util/status.h"
|
|
||||||
|
|
||||||
namespace file_util = ::sandbox2::file_util;
|
namespace file_util = ::sandbox2::file_util;
|
||||||
|
|
||||||
|
@ -14,10 +14,10 @@
|
|||||||
|
|
||||||
# Description: Example using dynamic length structures for Sandboxed API
|
# Description: Example using dynamic length structures for Sandboxed API
|
||||||
|
|
||||||
licenses(["notice"])
|
|
||||||
|
|
||||||
load("//sandboxed_api/bazel:build_defs.bzl", "sapi_platform_copts")
|
load("//sandboxed_api/bazel:build_defs.bzl", "sapi_platform_copts")
|
||||||
|
|
||||||
|
licenses(["notice"])
|
||||||
|
|
||||||
cc_test(
|
cc_test(
|
||||||
name = "main_stringop",
|
name = "main_stringop",
|
||||||
srcs = ["main_stringop.cc"],
|
srcs = ["main_stringop.cc"],
|
||||||
@ -32,6 +32,7 @@ cc_test(
|
|||||||
"//sandboxed_api/util:status",
|
"//sandboxed_api/util:status",
|
||||||
"//sandboxed_api/util:status_matchers",
|
"//sandboxed_api/util:status_matchers",
|
||||||
"@com_google_absl//absl/memory",
|
"@com_google_absl//absl/memory",
|
||||||
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_absl//absl/time",
|
"@com_google_absl//absl/time",
|
||||||
"@com_google_googletest//:gtest_main",
|
"@com_google_googletest//:gtest_main",
|
||||||
],
|
],
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "sandboxed_api/util/flag.h"
|
#include "sandboxed_api/util/flag.h"
|
||||||
#include "absl/memory/memory.h"
|
#include "absl/memory/memory.h"
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "absl/time/time.h"
|
#include "absl/time/time.h"
|
||||||
#include "sandboxed_api/examples/stringop/lib/sandbox.h"
|
#include "sandboxed_api/examples/stringop/lib/sandbox.h"
|
||||||
#include "sandboxed_api/examples/stringop/lib/stringop-sapi.sapi.h"
|
#include "sandboxed_api/examples/stringop/lib/stringop-sapi.sapi.h"
|
||||||
@ -28,7 +29,6 @@
|
|||||||
#include "sandboxed_api/transaction.h"
|
#include "sandboxed_api/transaction.h"
|
||||||
#include "sandboxed_api/util/status_matchers.h"
|
#include "sandboxed_api/util/status_matchers.h"
|
||||||
#include "sandboxed_api/vars.h"
|
#include "sandboxed_api/vars.h"
|
||||||
#include "sandboxed_api/util/status.h"
|
|
||||||
#include "sandboxed_api/util/status_macros.h"
|
#include "sandboxed_api/util/status_macros.h"
|
||||||
|
|
||||||
using ::sapi::IsOk;
|
using ::sapi::IsOk;
|
||||||
@ -42,7 +42,7 @@ namespace {
|
|||||||
// Tests using a simple transaction (and function pointers):
|
// Tests using a simple transaction (and function pointers):
|
||||||
TEST(StringopTest, ProtobufStringDuplication) {
|
TEST(StringopTest, ProtobufStringDuplication) {
|
||||||
sapi::BasicTransaction st(absl::make_unique<StringopSapiSandbox>());
|
sapi::BasicTransaction st(absl::make_unique<StringopSapiSandbox>());
|
||||||
EXPECT_THAT(st.Run([](sapi::Sandbox* sandbox) -> sapi::Status {
|
EXPECT_THAT(st.Run([](sapi::Sandbox* sandbox) -> absl::Status {
|
||||||
StringopApi api(sandbox);
|
StringopApi api(sandbox);
|
||||||
stringop::StringDuplication proto;
|
stringop::StringDuplication proto;
|
||||||
proto.set_input("Hello");
|
proto.set_input("Hello");
|
||||||
@ -56,7 +56,7 @@ TEST(StringopTest, ProtobufStringDuplication) {
|
|||||||
LOG(INFO) << "Result PB: " << pb_result.DebugString();
|
LOG(INFO) << "Result PB: " << pb_result.DebugString();
|
||||||
TRANSACTION_FAIL_IF_NOT(pb_result.output() == "HelloHello",
|
TRANSACTION_FAIL_IF_NOT(pb_result.output() == "HelloHello",
|
||||||
"Incorrect output");
|
"Incorrect output");
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}),
|
}),
|
||||||
IsOk());
|
IsOk());
|
||||||
}
|
}
|
||||||
|
@ -12,10 +12,10 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
licenses(["notice"])
|
|
||||||
|
|
||||||
load("//sandboxed_api/bazel:build_defs.bzl", "sapi_platform_copts")
|
load("//sandboxed_api/bazel:build_defs.bzl", "sapi_platform_copts")
|
||||||
|
|
||||||
|
licenses(["notice"])
|
||||||
|
|
||||||
# A quick'n'dirty testing binary
|
# A quick'n'dirty testing binary
|
||||||
cc_binary(
|
cc_binary(
|
||||||
name = "main_sum",
|
name = "main_sum",
|
||||||
@ -27,8 +27,8 @@ cc_binary(
|
|||||||
"//sandboxed_api/examples/sum/lib:sum-sapi",
|
"//sandboxed_api/examples/sum/lib:sum-sapi",
|
||||||
"//sandboxed_api/examples/sum/lib:sum_params_cc_proto",
|
"//sandboxed_api/examples/sum/lib:sum_params_cc_proto",
|
||||||
"//sandboxed_api/util:flags",
|
"//sandboxed_api/util:flags",
|
||||||
"//sandboxed_api/util:status",
|
|
||||||
"@com_google_absl//absl/memory",
|
"@com_google_absl//absl/memory",
|
||||||
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -19,13 +19,13 @@
|
|||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include "sandboxed_api/util/flag.h"
|
#include "sandboxed_api/util/flag.h"
|
||||||
#include "absl/memory/memory.h"
|
#include "absl/memory/memory.h"
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "absl/strings/str_cat.h"
|
#include "absl/strings/str_cat.h"
|
||||||
#include "sandboxed_api/examples/sum/lib/sandbox.h"
|
#include "sandboxed_api/examples/sum/lib/sandbox.h"
|
||||||
#include "sandboxed_api/examples/sum/lib/sum-sapi.sapi.h"
|
#include "sandboxed_api/examples/sum/lib/sum-sapi.sapi.h"
|
||||||
#include "sandboxed_api/examples/sum/lib/sum_params.pb.h"
|
#include "sandboxed_api/examples/sum/lib/sum_params.pb.h"
|
||||||
#include "sandboxed_api/transaction.h"
|
#include "sandboxed_api/transaction.h"
|
||||||
#include "sandboxed_api/vars.h"
|
#include "sandboxed_api/vars.h"
|
||||||
#include "sandboxed_api/util/status.h"
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -53,10 +53,10 @@ class SumTransaction : public sapi::Transaction {
|
|||||||
bool time_out_;
|
bool time_out_;
|
||||||
|
|
||||||
// The main processing function.
|
// The main processing function.
|
||||||
sapi::Status Main() override;
|
absl::Status Main() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
sapi::Status SumTransaction::Main() {
|
absl::Status SumTransaction::Main() {
|
||||||
SumApi f(sandbox());
|
SumApi f(sandbox());
|
||||||
SAPI_ASSIGN_OR_RETURN(int v, f.sum(1000, 337));
|
SAPI_ASSIGN_OR_RETURN(int v, f.sum(1000, 337));
|
||||||
LOG(INFO) << "1000 + 337 = " << v;
|
LOG(INFO) << "1000 + 337 = " << v;
|
||||||
@ -187,15 +187,15 @@ sapi::Status SumTransaction::Main() {
|
|||||||
if (time_out_) {
|
if (time_out_) {
|
||||||
SAPI_RETURN_IF_ERROR(f.sleep_for_sec(kTimeOutVal * 2));
|
SAPI_RETURN_IF_ERROR(f.sleep_for_sec(kTimeOutVal * 2));
|
||||||
}
|
}
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status test_addition(sapi::Sandbox* sandbox, int a, int b, int c) {
|
absl::Status test_addition(sapi::Sandbox* sandbox, int a, int b, int c) {
|
||||||
SumApi f(sandbox);
|
SumApi f(sandbox);
|
||||||
|
|
||||||
SAPI_ASSIGN_OR_RETURN(int v, f.sum(a, b));
|
SAPI_ASSIGN_OR_RETURN(int v, f.sum(a, b));
|
||||||
TRANSACTION_FAIL_IF_NOT(v == c, absl::StrCat(a, " + ", b, " != ", c));
|
TRANSACTION_FAIL_IF_NOT(v == c, absl::StrCat(a, " + ", b, " != ", c));
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -204,16 +204,16 @@ int main(int argc, char** argv) {
|
|||||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||||
google::InitGoogleLogging(argv[0]);
|
google::InitGoogleLogging(argv[0]);
|
||||||
|
|
||||||
sapi::Status status;
|
absl::Status status;
|
||||||
|
|
||||||
sapi::BasicTransaction st{absl::make_unique<SumSapiSandbox>()};
|
sapi::BasicTransaction st{absl::make_unique<SumSapiSandbox>()};
|
||||||
// Using the simple transaction (and function pointers):
|
// Using the simple transaction (and function pointers):
|
||||||
CHECK(st.Run(test_addition, 1, 1, 2).ok());
|
CHECK(st.Run(test_addition, 1, 1, 2).ok());
|
||||||
CHECK(st.Run(test_addition, 1336, 1, 1337).ok());
|
CHECK(st.Run(test_addition, 1336, 1, 1337).ok());
|
||||||
CHECK(st.Run(test_addition, 1336, 1, 7).code() ==
|
CHECK(st.Run(test_addition, 1336, 1, 7).code() ==
|
||||||
sapi::StatusCode::kFailedPrecondition);
|
absl::StatusCode::kFailedPrecondition);
|
||||||
|
|
||||||
status = st.Run([](sapi::Sandbox* sandbox) -> sapi::Status {
|
status = st.Run([](sapi::Sandbox* sandbox) -> absl::Status {
|
||||||
SumApi f(sandbox);
|
SumApi f(sandbox);
|
||||||
|
|
||||||
// Sums two int's held in a structure.
|
// Sums two int's held in a structure.
|
||||||
@ -224,11 +224,11 @@ int main(int argc, char** argv) {
|
|||||||
SAPI_RETURN_IF_ERROR(f.sums(params.PtrBoth()));
|
SAPI_RETURN_IF_ERROR(f.sums(params.PtrBoth()));
|
||||||
LOG(INFO) << "1111 + 222 = " << params.data().ret;
|
LOG(INFO) << "1111 + 222 = " << params.data().ret;
|
||||||
TRANSACTION_FAIL_IF_NOT(params.data().ret == 1333, "1111 + 222 != 1333");
|
TRANSACTION_FAIL_IF_NOT(params.data().ret == 1333, "1111 + 222 != 1333");
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
});
|
});
|
||||||
CHECK(status.ok()) << status.message();
|
CHECK(status.ok()) << status.message();
|
||||||
|
|
||||||
status = st.Run([](sapi::Sandbox* sandbox) -> sapi::Status {
|
status = st.Run([](sapi::Sandbox* sandbox) -> absl::Status {
|
||||||
SumApi f(sandbox);
|
SumApi f(sandbox);
|
||||||
SumParams params;
|
SumParams params;
|
||||||
params.mutable_data()->a = 1111;
|
params.mutable_data()->a = 1111;
|
||||||
@ -246,7 +246,7 @@ int main(int argc, char** argv) {
|
|||||||
SAPI_RETURN_IF_ERROR(f.sums(p.PtrBoth()));
|
SAPI_RETURN_IF_ERROR(f.sums(p.PtrBoth()));
|
||||||
LOG(INFO) << "1234 + 5678 = " << p.data().ret;
|
LOG(INFO) << "1234 + 5678 = " << p.data().ret;
|
||||||
TRANSACTION_FAIL_IF_NOT(p.data().ret == 6912, "1234 + 5678 != 6912");
|
TRANSACTION_FAIL_IF_NOT(p.data().ret == 6912, "1234 + 5678 != 6912");
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
});
|
});
|
||||||
CHECK(status.ok()) << status.message();
|
CHECK(status.ok()) << status.message();
|
||||||
|
|
||||||
@ -256,7 +256,7 @@ int main(int argc, char** argv) {
|
|||||||
/*time_out=*/false};
|
/*time_out=*/false};
|
||||||
status = sapi_crash.Run();
|
status = sapi_crash.Run();
|
||||||
LOG(INFO) << "Final run result for crash: " << status;
|
LOG(INFO) << "Final run result for crash: " << status;
|
||||||
CHECK(status.code() == sapi::StatusCode::kUnavailable);
|
CHECK(status.code() == absl::StatusCode::kUnavailable);
|
||||||
|
|
||||||
SumTransaction sapi_violate{absl::make_unique<SumSapiSandbox>(),
|
SumTransaction sapi_violate{absl::make_unique<SumSapiSandbox>(),
|
||||||
/*crash=*/false,
|
/*crash=*/false,
|
||||||
@ -264,7 +264,7 @@ int main(int argc, char** argv) {
|
|||||||
/*time_out=*/false};
|
/*time_out=*/false};
|
||||||
status = sapi_violate.Run();
|
status = sapi_violate.Run();
|
||||||
LOG(INFO) << "Final run result for violate: " << status;
|
LOG(INFO) << "Final run result for violate: " << status;
|
||||||
CHECK(status.code() == sapi::StatusCode::kUnavailable);
|
CHECK(status.code() == absl::StatusCode::kUnavailable);
|
||||||
|
|
||||||
SumTransaction sapi_timeout{absl::make_unique<SumSapiSandbox>(),
|
SumTransaction sapi_timeout{absl::make_unique<SumSapiSandbox>(),
|
||||||
/*crash=*/false,
|
/*crash=*/false,
|
||||||
@ -272,7 +272,7 @@ int main(int argc, char** argv) {
|
|||||||
/*time_out=*/true};
|
/*time_out=*/true};
|
||||||
status = sapi_timeout.Run();
|
status = sapi_timeout.Run();
|
||||||
LOG(INFO) << "Final run result for timeout: " << status;
|
LOG(INFO) << "Final run result for timeout: " << status;
|
||||||
CHECK(status.code() == sapi::StatusCode::kUnavailable);
|
CHECK(status.code() == absl::StatusCode::kUnavailable);
|
||||||
|
|
||||||
SumTransaction sapi{absl::make_unique<SumSapiSandbox>(), /*crash=*/false,
|
SumTransaction sapi{absl::make_unique<SumSapiSandbox>(), /*crash=*/false,
|
||||||
/*violate=*/false, /*time_out=*/false};
|
/*violate=*/false, /*time_out=*/false};
|
||||||
|
@ -21,8 +21,8 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "sandboxed_api/proto_arg.pb.h"
|
#include "sandboxed_api/proto_arg.pb.h"
|
||||||
#include "sandboxed_api/util/status.h"
|
|
||||||
#include "sandboxed_api/util/statusor.h"
|
#include "sandboxed_api/util/statusor.h"
|
||||||
|
|
||||||
namespace sapi {
|
namespace sapi {
|
||||||
@ -40,7 +40,7 @@ sapi::StatusOr<std::vector<uint8_t>> SerializeProto(const T& proto) {
|
|||||||
std::vector<uint8_t> serialized_proto(proto_arg.ByteSizeLong());
|
std::vector<uint8_t> serialized_proto(proto_arg.ByteSizeLong());
|
||||||
if (!proto_arg.SerializeToArray(serialized_proto.data(),
|
if (!proto_arg.SerializeToArray(serialized_proto.data(),
|
||||||
serialized_proto.size())) {
|
serialized_proto.size())) {
|
||||||
return sapi::InternalError("Unable to serialize proto to array");
|
return absl::InternalError("Unable to serialize proto to array");
|
||||||
}
|
}
|
||||||
return serialized_proto;
|
return serialized_proto;
|
||||||
}
|
}
|
||||||
@ -51,13 +51,13 @@ sapi::StatusOr<T> DeserializeProto(const char* data, size_t len) {
|
|||||||
"Template argument must be a proto message");
|
"Template argument must be a proto message");
|
||||||
ProtoArg envelope;
|
ProtoArg envelope;
|
||||||
if (!envelope.ParseFromArray(data, len)) {
|
if (!envelope.ParseFromArray(data, len)) {
|
||||||
return sapi::InternalError("Unable to parse proto from array");
|
return absl::InternalError("Unable to parse proto from array");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pb_data = envelope.protobuf_data();
|
auto pb_data = envelope.protobuf_data();
|
||||||
T result;
|
T result;
|
||||||
if (!result.ParseFromArray(pb_data.data(), pb_data.size())) {
|
if (!result.ParseFromArray(pb_data.data(), pb_data.size())) {
|
||||||
return sapi::InternalError("Unable to parse proto from envelope data");
|
return absl::InternalError("Unable to parse proto from envelope data");
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -23,16 +23,16 @@
|
|||||||
|
|
||||||
namespace sapi {
|
namespace sapi {
|
||||||
|
|
||||||
sapi::Status RPCChannel::Call(const FuncCall& call, uint32_t tag, FuncRet* ret,
|
absl::Status RPCChannel::Call(const FuncCall& call, uint32_t tag, FuncRet* ret,
|
||||||
v::Type exp_type) {
|
v::Type exp_type) {
|
||||||
absl::MutexLock lock(&mutex_);
|
absl::MutexLock lock(&mutex_);
|
||||||
if (!comms_->SendTLV(tag, sizeof(call),
|
if (!comms_->SendTLV(tag, sizeof(call),
|
||||||
reinterpret_cast<const uint8_t*>(&call))) {
|
reinterpret_cast<const uint8_t*>(&call))) {
|
||||||
return sapi::UnavailableError("Sending TLV value failed");
|
return absl::UnavailableError("Sending TLV value failed");
|
||||||
}
|
}
|
||||||
SAPI_ASSIGN_OR_RETURN(auto fret, Return(exp_type));
|
SAPI_ASSIGN_OR_RETURN(auto fret, Return(exp_type));
|
||||||
*ret = fret;
|
*ret = fret;
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::StatusOr<FuncRet> RPCChannel::Return(v::Type exp_type) {
|
sapi::StatusOr<FuncRet> RPCChannel::Return(v::Type exp_type) {
|
||||||
@ -40,44 +40,44 @@ sapi::StatusOr<FuncRet> RPCChannel::Return(v::Type exp_type) {
|
|||||||
uint64_t len;
|
uint64_t len;
|
||||||
FuncRet ret;
|
FuncRet ret;
|
||||||
if (!comms_->RecvTLV(&tag, &len, &ret, sizeof(ret))) {
|
if (!comms_->RecvTLV(&tag, &len, &ret, sizeof(ret))) {
|
||||||
return sapi::UnavailableError("Receiving TLV value failed");
|
return absl::UnavailableError("Receiving TLV value failed");
|
||||||
}
|
}
|
||||||
if (tag != comms::kMsgReturn) {
|
if (tag != comms::kMsgReturn) {
|
||||||
LOG(ERROR) << "tag != comms::kMsgReturn (" << absl::StrCat(absl::Hex(tag))
|
LOG(ERROR) << "tag != comms::kMsgReturn (" << absl::StrCat(absl::Hex(tag))
|
||||||
<< " != " << absl::StrCat(absl::Hex(comms::kMsgReturn)) << ")";
|
<< " != " << absl::StrCat(absl::Hex(comms::kMsgReturn)) << ")";
|
||||||
return sapi::UnavailableError("Received TLV has incorrect tag");
|
return absl::UnavailableError("Received TLV has incorrect tag");
|
||||||
}
|
}
|
||||||
if (len != sizeof(FuncRet)) {
|
if (len != sizeof(FuncRet)) {
|
||||||
LOG(ERROR) << "len != sizeof(FuncReturn) (" << len
|
LOG(ERROR) << "len != sizeof(FuncReturn) (" << len
|
||||||
<< " != " << sizeof(FuncRet) << ")";
|
<< " != " << sizeof(FuncRet) << ")";
|
||||||
return sapi::UnavailableError("Received TLV has incorrect length");
|
return absl::UnavailableError("Received TLV has incorrect length");
|
||||||
}
|
}
|
||||||
if (ret.ret_type != exp_type) {
|
if (ret.ret_type != exp_type) {
|
||||||
LOG(ERROR) << "FuncRet->type != exp_type (" << ret.ret_type
|
LOG(ERROR) << "FuncRet->type != exp_type (" << ret.ret_type
|
||||||
<< " != " << exp_type << ")";
|
<< " != " << exp_type << ")";
|
||||||
return sapi::UnavailableError("Received TLV has incorrect return type");
|
return absl::UnavailableError("Received TLV has incorrect return type");
|
||||||
}
|
}
|
||||||
if (!ret.success) {
|
if (!ret.success) {
|
||||||
LOG(ERROR) << "FuncRet->success == false";
|
LOG(ERROR) << "FuncRet->success == false";
|
||||||
return sapi::UnavailableError("Function call failed");
|
return absl::UnavailableError("Function call failed");
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status RPCChannel::Allocate(size_t size, void** addr) {
|
absl::Status RPCChannel::Allocate(size_t size, void** addr) {
|
||||||
absl::MutexLock lock(&mutex_);
|
absl::MutexLock lock(&mutex_);
|
||||||
uint64_t sz = size;
|
uint64_t sz = size;
|
||||||
if (!comms_->SendTLV(comms::kMsgAllocate, sizeof(sz),
|
if (!comms_->SendTLV(comms::kMsgAllocate, sizeof(sz),
|
||||||
reinterpret_cast<uint8_t*>(&sz))) {
|
reinterpret_cast<uint8_t*>(&sz))) {
|
||||||
return sapi::UnavailableError("Sending TLV value failed");
|
return absl::UnavailableError("Sending TLV value failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kPointer));
|
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kPointer));
|
||||||
*addr = reinterpret_cast<void*>(fret.int_val);
|
*addr = reinterpret_cast<void*>(fret.int_val);
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status RPCChannel::Reallocate(void* old_addr, size_t size,
|
absl::Status RPCChannel::Reallocate(void* old_addr, size_t size,
|
||||||
void** new_addr) {
|
void** new_addr) {
|
||||||
absl::MutexLock lock(&mutex_);
|
absl::MutexLock lock(&mutex_);
|
||||||
comms::ReallocRequest req;
|
comms::ReallocRequest req;
|
||||||
@ -86,54 +86,54 @@ sapi::Status RPCChannel::Reallocate(void* old_addr, size_t size,
|
|||||||
|
|
||||||
if (!comms_->SendTLV(comms::kMsgReallocate, sizeof(comms::ReallocRequest),
|
if (!comms_->SendTLV(comms::kMsgReallocate, sizeof(comms::ReallocRequest),
|
||||||
reinterpret_cast<uint8_t*>(&req))) {
|
reinterpret_cast<uint8_t*>(&req))) {
|
||||||
return sapi::UnavailableError("Sending TLV value failed");
|
return absl::UnavailableError("Sending TLV value failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto fret_or = Return(v::Type::kPointer);
|
auto fret_or = Return(v::Type::kPointer);
|
||||||
if (!fret_or.ok()) {
|
if (!fret_or.ok()) {
|
||||||
*new_addr = nullptr;
|
*new_addr = nullptr;
|
||||||
return sapi::UnavailableError(
|
return absl::UnavailableError(
|
||||||
absl::StrCat("Reallocate() failed on the remote side: ",
|
absl::StrCat("Reallocate() failed on the remote side: ",
|
||||||
fret_or.status().message()));
|
fret_or.status().message()));
|
||||||
}
|
}
|
||||||
auto fret = std::move(fret_or).ValueOrDie();
|
auto fret = std::move(fret_or).ValueOrDie();
|
||||||
|
|
||||||
*new_addr = reinterpret_cast<void*>(fret.int_val);
|
*new_addr = reinterpret_cast<void*>(fret.int_val);
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status RPCChannel::Free(void* addr) {
|
absl::Status RPCChannel::Free(void* addr) {
|
||||||
absl::MutexLock lock(&mutex_);
|
absl::MutexLock lock(&mutex_);
|
||||||
uint64_t remote = reinterpret_cast<uint64_t>(addr);
|
uint64_t remote = reinterpret_cast<uint64_t>(addr);
|
||||||
if (!comms_->SendTLV(comms::kMsgFree, sizeof(remote),
|
if (!comms_->SendTLV(comms::kMsgFree, sizeof(remote),
|
||||||
reinterpret_cast<uint8_t*>(&remote))) {
|
reinterpret_cast<uint8_t*>(&remote))) {
|
||||||
return sapi::UnavailableError("Sending TLV value failed");
|
return absl::UnavailableError("Sending TLV value failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kVoid));
|
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kVoid));
|
||||||
if (!fret.success) {
|
if (!fret.success) {
|
||||||
return sapi::UnavailableError("Free() failed on the remote side");
|
return absl::UnavailableError("Free() failed on the remote side");
|
||||||
}
|
}
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status RPCChannel::Symbol(const char* symname, void** addr) {
|
absl::Status RPCChannel::Symbol(const char* symname, void** addr) {
|
||||||
absl::MutexLock lock(&mutex_);
|
absl::MutexLock lock(&mutex_);
|
||||||
if (!comms_->SendTLV(comms::kMsgSymbol, strlen(symname) + 1,
|
if (!comms_->SendTLV(comms::kMsgSymbol, strlen(symname) + 1,
|
||||||
reinterpret_cast<const uint8_t*>(symname))) {
|
reinterpret_cast<const uint8_t*>(symname))) {
|
||||||
return sapi::UnavailableError("Sending TLV value failed");
|
return absl::UnavailableError("Sending TLV value failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kPointer));
|
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kPointer));
|
||||||
*addr = reinterpret_cast<void*>(fret.int_val);
|
*addr = reinterpret_cast<void*>(fret.int_val);
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status RPCChannel::Exit() {
|
absl::Status RPCChannel::Exit() {
|
||||||
absl::MutexLock lock(&mutex_);
|
absl::MutexLock lock(&mutex_);
|
||||||
if (comms_->IsTerminated()) {
|
if (comms_->IsTerminated()) {
|
||||||
VLOG(2) << "Comms channel already terminated";
|
VLOG(2) << "Comms channel already terminated";
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try the RPC exit sequence. But, the only thing that matters as a success
|
// Try the RPC exit sequence. But, the only thing that matters as a success
|
||||||
@ -146,74 +146,74 @@ sapi::Status RPCChannel::Exit() {
|
|||||||
if (!comms_->IsTerminated()) {
|
if (!comms_->IsTerminated()) {
|
||||||
LOG(ERROR) << "Comms channel not terminated in Exit()";
|
LOG(ERROR) << "Comms channel not terminated in Exit()";
|
||||||
// TODO(hamacher): Better error code
|
// TODO(hamacher): Better error code
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
"Comms channel not terminated in Exit()");
|
"Comms channel not terminated in Exit()");
|
||||||
}
|
}
|
||||||
|
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status RPCChannel::SendFD(int local_fd, int* remote_fd) {
|
absl::Status RPCChannel::SendFD(int local_fd, int* remote_fd) {
|
||||||
absl::MutexLock lock(&mutex_);
|
absl::MutexLock lock(&mutex_);
|
||||||
bool unused = true;
|
bool unused = true;
|
||||||
if (!comms_->SendTLV(comms::kMsgSendFd, sizeof(unused),
|
if (!comms_->SendTLV(comms::kMsgSendFd, sizeof(unused),
|
||||||
reinterpret_cast<uint8_t*>(&unused))) {
|
reinterpret_cast<uint8_t*>(&unused))) {
|
||||||
return sapi::UnavailableError("Sending TLV value failed");
|
return absl::UnavailableError("Sending TLV value failed");
|
||||||
}
|
}
|
||||||
if (!comms_->SendFD(local_fd)) {
|
if (!comms_->SendFD(local_fd)) {
|
||||||
return sapi::UnavailableError("Sending FD failed");
|
return absl::UnavailableError("Sending FD failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kInt));
|
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kInt));
|
||||||
if (!fret.success) {
|
if (!fret.success) {
|
||||||
return sapi::UnavailableError("SendFD failed on the remote side");
|
return absl::UnavailableError("SendFD failed on the remote side");
|
||||||
}
|
}
|
||||||
*remote_fd = fret.int_val;
|
*remote_fd = fret.int_val;
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status RPCChannel::RecvFD(int remote_fd, int* local_fd) {
|
absl::Status RPCChannel::RecvFD(int remote_fd, int* local_fd) {
|
||||||
absl::MutexLock lock(&mutex_);
|
absl::MutexLock lock(&mutex_);
|
||||||
if (!comms_->SendTLV(comms::kMsgRecvFd, sizeof(remote_fd),
|
if (!comms_->SendTLV(comms::kMsgRecvFd, sizeof(remote_fd),
|
||||||
reinterpret_cast<uint8_t*>(&remote_fd))) {
|
reinterpret_cast<uint8_t*>(&remote_fd))) {
|
||||||
return sapi::UnavailableError("Sending TLV value failed");
|
return absl::UnavailableError("Sending TLV value failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!comms_->RecvFD(local_fd)) {
|
if (!comms_->RecvFD(local_fd)) {
|
||||||
return sapi::UnavailableError("Receving FD failed");
|
return absl::UnavailableError("Receving FD failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kVoid));
|
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kVoid));
|
||||||
if (!fret.success) {
|
if (!fret.success) {
|
||||||
return sapi::UnavailableError("RecvFD failed on the remote side");
|
return absl::UnavailableError("RecvFD failed on the remote side");
|
||||||
}
|
}
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status RPCChannel::Close(int remote_fd) {
|
absl::Status RPCChannel::Close(int remote_fd) {
|
||||||
absl::MutexLock lock(&mutex_);
|
absl::MutexLock lock(&mutex_);
|
||||||
if (!comms_->SendTLV(comms::kMsgClose, sizeof(remote_fd),
|
if (!comms_->SendTLV(comms::kMsgClose, sizeof(remote_fd),
|
||||||
reinterpret_cast<uint8_t*>(&remote_fd))) {
|
reinterpret_cast<uint8_t*>(&remote_fd))) {
|
||||||
return sapi::UnavailableError("Sending TLV value failed");
|
return absl::UnavailableError("Sending TLV value failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kVoid));
|
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kVoid));
|
||||||
if (!fret.success) {
|
if (!fret.success) {
|
||||||
return sapi::UnavailableError("Close() failed on the remote side");
|
return absl::UnavailableError("Close() failed on the remote side");
|
||||||
}
|
}
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::StatusOr<uint64_t> RPCChannel::Strlen(void* str) {
|
sapi::StatusOr<uint64_t> RPCChannel::Strlen(void* str) {
|
||||||
absl::MutexLock lock(&mutex_);
|
absl::MutexLock lock(&mutex_);
|
||||||
if (!comms_->SendTLV(comms::kMsgStrlen, sizeof(str),
|
if (!comms_->SendTLV(comms::kMsgStrlen, sizeof(str),
|
||||||
reinterpret_cast<uint8_t*>(&str))) {
|
reinterpret_cast<uint8_t*>(&str))) {
|
||||||
return sapi::UnavailableError("Sending TLV value failed");
|
return absl::UnavailableError("Sending TLV value failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kInt));
|
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kInt));
|
||||||
if (!fret.success) {
|
if (!fret.success) {
|
||||||
return sapi::UnavailableError("Close() failed on the remote side");
|
return absl::UnavailableError("Close() failed on the remote side");
|
||||||
}
|
}
|
||||||
return fret.int_val;
|
return fret.int_val;
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,11 @@
|
|||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "absl/synchronization/mutex.h"
|
#include "absl/synchronization/mutex.h"
|
||||||
#include "sandboxed_api/call.h"
|
#include "sandboxed_api/call.h"
|
||||||
#include "sandboxed_api/sandbox2/comms.h"
|
#include "sandboxed_api/sandbox2/comms.h"
|
||||||
#include "sandboxed_api/var_type.h"
|
#include "sandboxed_api/var_type.h"
|
||||||
#include "sandboxed_api/util/status.h"
|
|
||||||
#include "sandboxed_api/util/statusor.h"
|
#include "sandboxed_api/util/statusor.h"
|
||||||
|
|
||||||
namespace sapi {
|
namespace sapi {
|
||||||
@ -33,32 +33,32 @@ class RPCChannel {
|
|||||||
explicit RPCChannel(sandbox2::Comms* comms) : comms_(comms) {}
|
explicit RPCChannel(sandbox2::Comms* comms) : comms_(comms) {}
|
||||||
|
|
||||||
// Calls a function.
|
// Calls a function.
|
||||||
sapi::Status Call(const FuncCall& call, uint32_t tag, FuncRet* ret,
|
absl::Status Call(const FuncCall& call, uint32_t tag, FuncRet* ret,
|
||||||
v::Type exp_type);
|
v::Type exp_type);
|
||||||
|
|
||||||
// Allocates memory.
|
// Allocates memory.
|
||||||
sapi::Status Allocate(size_t size, void** addr);
|
absl::Status Allocate(size_t size, void** addr);
|
||||||
|
|
||||||
// Reallocates memory.
|
// Reallocates memory.
|
||||||
sapi::Status Reallocate(void* old_addr, size_t size, void** new_addr);
|
absl::Status Reallocate(void* old_addr, size_t size, void** new_addr);
|
||||||
|
|
||||||
// Frees memory.
|
// Frees memory.
|
||||||
sapi::Status Free(void* addr);
|
absl::Status Free(void* addr);
|
||||||
|
|
||||||
// Returns address of a symbol.
|
// Returns address of a symbol.
|
||||||
sapi::Status Symbol(const char* symname, void** addr);
|
absl::Status Symbol(const char* symname, void** addr);
|
||||||
|
|
||||||
// Makes the remote part exit.
|
// Makes the remote part exit.
|
||||||
sapi::Status Exit();
|
absl::Status Exit();
|
||||||
|
|
||||||
// Transfers fd to sandboxee.
|
// Transfers fd to sandboxee.
|
||||||
sapi::Status SendFD(int local_fd, int* remote_fd);
|
absl::Status SendFD(int local_fd, int* remote_fd);
|
||||||
|
|
||||||
// Retrieves fd from sandboxee.
|
// Retrieves fd from sandboxee.
|
||||||
sapi::Status RecvFD(int remote_fd, int* local_fd);
|
absl::Status RecvFD(int remote_fd, int* local_fd);
|
||||||
|
|
||||||
// Closes fd in sandboxee.
|
// Closes fd in sandboxee.
|
||||||
sapi::Status Close(int remote_fd);
|
absl::Status Close(int remote_fd);
|
||||||
|
|
||||||
// Returns length of a null-terminated c-style string (invokes strlen).
|
// Returns length of a null-terminated c-style string (invokes strlen).
|
||||||
sapi::StatusOr<uint64_t> Strlen(void* str);
|
sapi::StatusOr<uint64_t> Strlen(void* str);
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "absl/base/casts.h"
|
#include "absl/base/casts.h"
|
||||||
#include "absl/base/macros.h"
|
#include "absl/base/macros.h"
|
||||||
#include "absl/memory/memory.h"
|
#include "absl/memory/memory.h"
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "absl/strings/str_cat.h"
|
#include "absl/strings/str_cat.h"
|
||||||
#include "absl/strings/str_format.h"
|
#include "absl/strings/str_format.h"
|
||||||
#include "absl/time/time.h"
|
#include "absl/time/time.h"
|
||||||
@ -126,10 +127,10 @@ static std::string PathToSAPILib(const std::string& lib_path) {
|
|||||||
: sandbox2::GetDataDependencyFilePath(lib_path);
|
: sandbox2::GetDataDependencyFilePath(lib_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Sandbox::Init() {
|
absl::Status Sandbox::Init() {
|
||||||
// It's already initialized
|
// It's already initialized
|
||||||
if (IsActive()) {
|
if (IsActive()) {
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the forkserver if it is not already running.
|
// Initialize the forkserver if it is not already running.
|
||||||
@ -144,14 +145,14 @@ sapi::Status Sandbox::Init() {
|
|||||||
if (embed_lib_fd == -1) {
|
if (embed_lib_fd == -1) {
|
||||||
PLOG(ERROR) << "Cannot create executable FD for TOC:'"
|
PLOG(ERROR) << "Cannot create executable FD for TOC:'"
|
||||||
<< embed_lib_toc_->name << "'";
|
<< embed_lib_toc_->name << "'";
|
||||||
return sapi::UnavailableError("Could not create executable FD");
|
return absl::UnavailableError("Could not create executable FD");
|
||||||
}
|
}
|
||||||
lib_path = embed_lib_toc_->name;
|
lib_path = embed_lib_toc_->name;
|
||||||
} else {
|
} else {
|
||||||
lib_path = PathToSAPILib(GetLibPath());
|
lib_path = PathToSAPILib(GetLibPath());
|
||||||
if (lib_path.empty()) {
|
if (lib_path.empty()) {
|
||||||
LOG(ERROR) << "SAPI library path is empty";
|
LOG(ERROR) << "SAPI library path is empty";
|
||||||
return sapi::FailedPreconditionError("No SAPI library path given");
|
return absl::FailedPreconditionError("No SAPI library path given");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +172,7 @@ sapi::Status Sandbox::Init() {
|
|||||||
|
|
||||||
if (!fork_client_) {
|
if (!fork_client_) {
|
||||||
LOG(ERROR) << "Could not start forkserver";
|
LOG(ERROR) << "Could not start forkserver";
|
||||||
return sapi::UnavailableError("Could not start the forkserver");
|
return absl::UnavailableError("Could not start the forkserver");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,38 +209,38 @@ sapi::Status Sandbox::Init() {
|
|||||||
|
|
||||||
if (!res) {
|
if (!res) {
|
||||||
Terminate();
|
Terminate();
|
||||||
return sapi::UnavailableError("Could not start the sandbox");
|
return absl::UnavailableError("Could not start the sandbox");
|
||||||
}
|
}
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sandbox::IsActive() const { return s2_ && !s2_->IsTerminated(); }
|
bool Sandbox::IsActive() const { return s2_ && !s2_->IsTerminated(); }
|
||||||
|
|
||||||
sapi::Status Sandbox::Allocate(v::Var* var, bool automatic_free) {
|
absl::Status Sandbox::Allocate(v::Var* var, bool automatic_free) {
|
||||||
if (!IsActive()) {
|
if (!IsActive()) {
|
||||||
return sapi::UnavailableError("Sandbox not active");
|
return absl::UnavailableError("Sandbox not active");
|
||||||
}
|
}
|
||||||
return var->Allocate(GetRpcChannel(), automatic_free);
|
return var->Allocate(GetRpcChannel(), automatic_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Sandbox::Free(v::Var* var) {
|
absl::Status Sandbox::Free(v::Var* var) {
|
||||||
if (!IsActive()) {
|
if (!IsActive()) {
|
||||||
return sapi::UnavailableError("Sandbox not active");
|
return absl::UnavailableError("Sandbox not active");
|
||||||
}
|
}
|
||||||
return var->Free(GetRpcChannel());
|
return var->Free(GetRpcChannel());
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Sandbox::SynchronizePtrBefore(v::Callable* ptr) {
|
absl::Status Sandbox::SynchronizePtrBefore(v::Callable* ptr) {
|
||||||
if (!IsActive()) {
|
if (!IsActive()) {
|
||||||
return sapi::UnavailableError("Sandbox not active");
|
return absl::UnavailableError("Sandbox not active");
|
||||||
}
|
}
|
||||||
if (ptr->GetType() != v::Type::kPointer) {
|
if (ptr->GetType() != v::Type::kPointer) {
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
// Cast is safe, since type is v::Type::kPointer
|
// Cast is safe, since type is v::Type::kPointer
|
||||||
auto* p = static_cast<v::Ptr*>(ptr);
|
auto* p = static_cast<v::Ptr*>(ptr);
|
||||||
if (p->GetSyncType() == v::Pointable::SYNC_NONE) {
|
if (p->GetSyncType() == v::Pointable::SYNC_NONE) {
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->GetPointedVar()->GetRemote() == nullptr) {
|
if (p->GetPointedVar()->GetRemote() == nullptr) {
|
||||||
@ -252,7 +253,7 @@ sapi::Status Sandbox::SynchronizePtrBefore(v::Callable* ptr) {
|
|||||||
// memory is transferred to the sandboxee only if v::Pointable::SYNC_BEFORE
|
// memory is transferred to the sandboxee only if v::Pointable::SYNC_BEFORE
|
||||||
// was requested.
|
// was requested.
|
||||||
if ((p->GetSyncType() & v::Pointable::SYNC_BEFORE) == 0) {
|
if ((p->GetSyncType() & v::Pointable::SYNC_BEFORE) == 0) {
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
VLOG(3) << "Synchronization (TO), ptr " << p << ", Type: " << p->GetSyncType()
|
VLOG(3) << "Synchronization (TO), ptr " << p << ", Type: " << p->GetSyncType()
|
||||||
@ -261,16 +262,16 @@ sapi::Status Sandbox::SynchronizePtrBefore(v::Callable* ptr) {
|
|||||||
return p->GetPointedVar()->TransferToSandboxee(GetRpcChannel(), GetPid());
|
return p->GetPointedVar()->TransferToSandboxee(GetRpcChannel(), GetPid());
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Sandbox::SynchronizePtrAfter(v::Callable* ptr) const {
|
absl::Status Sandbox::SynchronizePtrAfter(v::Callable* ptr) const {
|
||||||
if (!IsActive()) {
|
if (!IsActive()) {
|
||||||
return sapi::UnavailableError("Sandbox not active");
|
return absl::UnavailableError("Sandbox not active");
|
||||||
}
|
}
|
||||||
if (ptr->GetType() != v::Type::kPointer) {
|
if (ptr->GetType() != v::Type::kPointer) {
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
v::Ptr* p = reinterpret_cast<v::Ptr*>(ptr);
|
v::Ptr* p = reinterpret_cast<v::Ptr*>(ptr);
|
||||||
if ((p->GetSyncType() & v::Pointable::SYNC_AFTER) == 0) {
|
if ((p->GetSyncType() & v::Pointable::SYNC_AFTER) == 0) {
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
VLOG(3) << "Synchronization (FROM), ptr " << p
|
VLOG(3) << "Synchronization (FROM), ptr " << p
|
||||||
@ -280,7 +281,7 @@ sapi::Status Sandbox::SynchronizePtrAfter(v::Callable* ptr) const {
|
|||||||
if (p->GetPointedVar()->GetRemote() == nullptr) {
|
if (p->GetPointedVar()->GetRemote() == nullptr) {
|
||||||
LOG(ERROR) << "Trying to synchronize a variable which is not allocated in "
|
LOG(ERROR) << "Trying to synchronize a variable which is not allocated in "
|
||||||
<< "the sandboxee p=" << p->ToString();
|
<< "the sandboxee p=" << p->ToString();
|
||||||
return sapi::FailedPreconditionError(absl::StrCat(
|
return absl::FailedPreconditionError(absl::StrCat(
|
||||||
"Trying to synchronize a variable which is not allocated in the "
|
"Trying to synchronize a variable which is not allocated in the "
|
||||||
"sandboxee p=",
|
"sandboxee p=",
|
||||||
p->ToString()));
|
p->ToString()));
|
||||||
@ -289,10 +290,10 @@ sapi::Status Sandbox::SynchronizePtrAfter(v::Callable* ptr) const {
|
|||||||
return p->GetPointedVar()->TransferFromSandboxee(GetRpcChannel(), GetPid());
|
return p->GetPointedVar()->TransferFromSandboxee(GetRpcChannel(), GetPid());
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Sandbox::Call(const std::string& func, v::Callable* ret,
|
absl::Status Sandbox::Call(const std::string& func, v::Callable* ret,
|
||||||
std::initializer_list<v::Callable*> args) {
|
std::initializer_list<v::Callable*> args) {
|
||||||
if (!IsActive()) {
|
if (!IsActive()) {
|
||||||
return sapi::UnavailableError("Sandbox not active");
|
return absl::UnavailableError("Sandbox not active");
|
||||||
}
|
}
|
||||||
// Send data.
|
// Send data.
|
||||||
FuncCall rfcall{};
|
FuncCall rfcall{};
|
||||||
@ -366,26 +367,26 @@ sapi::Status Sandbox::Call(const std::string& func, v::Callable* ret,
|
|||||||
VLOG(1) << "CALL EXIT: Type: " << ret->GetTypeString()
|
VLOG(1) << "CALL EXIT: Type: " << ret->GetTypeString()
|
||||||
<< ", Size: " << ret->GetSize() << ", Val: " << ret->ToString();
|
<< ", Size: " << ret->GetSize() << ", Val: " << ret->ToString();
|
||||||
|
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Sandbox::Symbol(const char* symname, void** addr) {
|
absl::Status Sandbox::Symbol(const char* symname, void** addr) {
|
||||||
if (!IsActive()) {
|
if (!IsActive()) {
|
||||||
return sapi::UnavailableError("Sandbox not active");
|
return absl::UnavailableError("Sandbox not active");
|
||||||
}
|
}
|
||||||
return rpc_channel_->Symbol(symname, addr);
|
return rpc_channel_->Symbol(symname, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Sandbox::TransferToSandboxee(v::Var* var) {
|
absl::Status Sandbox::TransferToSandboxee(v::Var* var) {
|
||||||
if (!IsActive()) {
|
if (!IsActive()) {
|
||||||
return sapi::UnavailableError("Sandbox not active");
|
return absl::UnavailableError("Sandbox not active");
|
||||||
}
|
}
|
||||||
return var->TransferToSandboxee(GetRpcChannel(), GetPid());
|
return var->TransferToSandboxee(GetRpcChannel(), GetPid());
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Sandbox::TransferFromSandboxee(v::Var* var) {
|
absl::Status Sandbox::TransferFromSandboxee(v::Var* var) {
|
||||||
if (!IsActive()) {
|
if (!IsActive()) {
|
||||||
return sapi::UnavailableError("Sandbox not active");
|
return absl::UnavailableError("Sandbox not active");
|
||||||
}
|
}
|
||||||
return var->TransferFromSandboxee(GetRpcChannel(), GetPid());
|
return var->TransferFromSandboxee(GetRpcChannel(), GetPid());
|
||||||
}
|
}
|
||||||
@ -393,12 +394,12 @@ sapi::Status Sandbox::TransferFromSandboxee(v::Var* var) {
|
|||||||
sapi::StatusOr<std::string> Sandbox::GetCString(const v::RemotePtr& str,
|
sapi::StatusOr<std::string> Sandbox::GetCString(const v::RemotePtr& str,
|
||||||
uint64_t max_length) {
|
uint64_t max_length) {
|
||||||
if (!IsActive()) {
|
if (!IsActive()) {
|
||||||
return sapi::UnavailableError("Sandbox not active");
|
return absl::UnavailableError("Sandbox not active");
|
||||||
}
|
}
|
||||||
|
|
||||||
SAPI_ASSIGN_OR_RETURN(auto len, GetRpcChannel()->Strlen(str.GetValue()));
|
SAPI_ASSIGN_OR_RETURN(auto len, GetRpcChannel()->Strlen(str.GetValue()));
|
||||||
if (len > max_length) {
|
if (len > max_length) {
|
||||||
return sapi::InvalidArgumentError(
|
return absl::InvalidArgumentError(
|
||||||
absl::StrCat("Target string too large: ", len, " > ", max_length));
|
absl::StrCat("Target string too large: ", len, " > ", max_length));
|
||||||
}
|
}
|
||||||
std::string buffer(len, '\0');
|
std::string buffer(len, '\0');
|
||||||
@ -415,13 +416,13 @@ sapi::StatusOr<std::string> Sandbox::GetCString(const v::RemotePtr& str,
|
|||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
PLOG(WARNING) << "reading c-string failed: process_vm_readv(pid: " << pid_
|
PLOG(WARNING) << "reading c-string failed: process_vm_readv(pid: " << pid_
|
||||||
<< " raddr: " << str.GetValue() << " size: " << len << ")";
|
<< " raddr: " << str.GetValue() << " size: " << len << ")";
|
||||||
return sapi::UnavailableError("process_vm_readv failed");
|
return absl::UnavailableError("process_vm_readv failed");
|
||||||
}
|
}
|
||||||
if (ret != len) {
|
if (ret != len) {
|
||||||
LOG(WARNING) << "partial read when reading c-string: process_vm_readv(pid: "
|
LOG(WARNING) << "partial read when reading c-string: process_vm_readv(pid: "
|
||||||
<< pid_ << " raddr: " << str.GetValue() << " size: " << len
|
<< pid_ << " raddr: " << str.GetValue() << " size: " << len
|
||||||
<< ") transferred " << ret << " bytes";
|
<< ") transferred " << ret << " bytes";
|
||||||
return sapi::UnavailableError("process_vm_readv succeeded partially");
|
return absl::UnavailableError("process_vm_readv succeeded partially");
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
@ -435,12 +436,12 @@ const sandbox2::Result& Sandbox::AwaitResult() {
|
|||||||
return result_;
|
return result_;
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Sandbox::SetWallTimeLimit(time_t limit) const {
|
absl::Status Sandbox::SetWallTimeLimit(time_t limit) const {
|
||||||
if (!IsActive()) {
|
if (!IsActive()) {
|
||||||
return sapi::UnavailableError("Sandbox not active");
|
return absl::UnavailableError("Sandbox not active");
|
||||||
}
|
}
|
||||||
s2_->SetWallTimeLimit(limit);
|
s2_->SetWallTimeLimit(limit);
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sandbox::Exit() const {
|
void Sandbox::Exit() const {
|
||||||
|
@ -43,7 +43,7 @@ class Sandbox {
|
|||||||
virtual ~Sandbox();
|
virtual ~Sandbox();
|
||||||
|
|
||||||
// Initializes a new sandboxing session.
|
// Initializes a new sandboxing session.
|
||||||
sapi::Status Init();
|
absl::Status Init();
|
||||||
|
|
||||||
// Is the current sandboxing session alive?
|
// Is the current sandboxing session alive?
|
||||||
bool IsActive() const;
|
bool IsActive() const;
|
||||||
@ -52,7 +52,7 @@ class Sandbox {
|
|||||||
void Terminate(bool attempt_graceful_exit = true);
|
void Terminate(bool attempt_graceful_exit = true);
|
||||||
|
|
||||||
// Restarts the sandbox.
|
// Restarts the sandbox.
|
||||||
sapi::Status Restart(bool attempt_graceful_exit) {
|
absl::Status Restart(bool attempt_graceful_exit) {
|
||||||
Terminate(attempt_graceful_exit);
|
Terminate(attempt_graceful_exit);
|
||||||
return Init();
|
return Init();
|
||||||
}
|
}
|
||||||
@ -65,35 +65,35 @@ class Sandbox {
|
|||||||
int GetPid() const { return pid_; }
|
int GetPid() const { return pid_; }
|
||||||
|
|
||||||
// Synchronizes the underlying memory for the pointer before the call.
|
// Synchronizes the underlying memory for the pointer before the call.
|
||||||
sapi::Status SynchronizePtrBefore(v::Callable* ptr);
|
absl::Status SynchronizePtrBefore(v::Callable* ptr);
|
||||||
|
|
||||||
// Synchronizes the underlying memory for pointer after the call.
|
// Synchronizes the underlying memory for pointer after the call.
|
||||||
sapi::Status SynchronizePtrAfter(v::Callable* ptr) const;
|
absl::Status SynchronizePtrAfter(v::Callable* ptr) const;
|
||||||
|
|
||||||
// Makes a call to the sandboxee.
|
// Makes a call to the sandboxee.
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
sapi::Status Call(const std::string& func, v::Callable* ret, Args&&... args) {
|
absl::Status Call(const std::string& func, v::Callable* ret, Args&&... args) {
|
||||||
static_assert(sizeof...(Args) <= FuncCall::kArgsMax,
|
static_assert(sizeof...(Args) <= FuncCall::kArgsMax,
|
||||||
"Too many arguments to sapi::Sandbox::Call()");
|
"Too many arguments to sapi::Sandbox::Call()");
|
||||||
return Call(func, ret, {std::forward<Args>(args)...});
|
return Call(func, ret, {std::forward<Args>(args)...});
|
||||||
}
|
}
|
||||||
sapi::Status Call(const std::string& func, v::Callable* ret,
|
absl::Status Call(const std::string& func, v::Callable* ret,
|
||||||
std::initializer_list<v::Callable*> args);
|
std::initializer_list<v::Callable*> args);
|
||||||
|
|
||||||
// Allocates memory in the sandboxee, automatic_free indicates whether the
|
// Allocates memory in the sandboxee, automatic_free indicates whether the
|
||||||
// memory should be freed on the remote side when the 'var' goes out of scope.
|
// memory should be freed on the remote side when the 'var' goes out of scope.
|
||||||
sapi::Status Allocate(v::Var* var, bool automatic_free = false);
|
absl::Status Allocate(v::Var* var, bool automatic_free = false);
|
||||||
|
|
||||||
// Frees memory in the sandboxee.
|
// Frees memory in the sandboxee.
|
||||||
sapi::Status Free(v::Var* var);
|
absl::Status Free(v::Var* var);
|
||||||
|
|
||||||
// Finds address of a symbol in the sandboxee.
|
// Finds address of a symbol in the sandboxee.
|
||||||
sapi::Status Symbol(const char* symname, void** addr);
|
absl::Status Symbol(const char* symname, void** addr);
|
||||||
|
|
||||||
// Transfers memory (both directions). Status is returned (memory transfer
|
// Transfers memory (both directions). Status is returned (memory transfer
|
||||||
// succeeded/failed).
|
// succeeded/failed).
|
||||||
sapi::Status TransferToSandboxee(v::Var* var);
|
absl::Status TransferToSandboxee(v::Var* var);
|
||||||
sapi::Status TransferFromSandboxee(v::Var* var);
|
absl::Status TransferFromSandboxee(v::Var* var);
|
||||||
|
|
||||||
sapi::StatusOr<std::string> GetCString(const v::RemotePtr& str,
|
sapi::StatusOr<std::string> GetCString(const v::RemotePtr& str,
|
||||||
uint64_t max_length = 10 * 1024 *
|
uint64_t max_length = 10 * 1024 *
|
||||||
@ -103,7 +103,7 @@ class Sandbox {
|
|||||||
const sandbox2::Result& AwaitResult();
|
const sandbox2::Result& AwaitResult();
|
||||||
const sandbox2::Result& result() const { return result_; }
|
const sandbox2::Result& result() const { return result_; }
|
||||||
|
|
||||||
sapi::Status SetWallTimeLimit(time_t limit) const;
|
absl::Status SetWallTimeLimit(time_t limit) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -43,8 +43,8 @@ cc_library(
|
|||||||
":syscall",
|
":syscall",
|
||||||
":violation_cc_proto",
|
":violation_cc_proto",
|
||||||
"//sandboxed_api/sandbox2/util:strerror",
|
"//sandboxed_api/sandbox2/util:strerror",
|
||||||
"//sandboxed_api/util:status",
|
|
||||||
"@com_google_absl//absl/base:core_headers",
|
"@com_google_absl//absl/base:core_headers",
|
||||||
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -88,9 +88,9 @@ cc_library(
|
|||||||
":regs",
|
":regs",
|
||||||
":syscall",
|
":syscall",
|
||||||
":util",
|
":util",
|
||||||
"//sandboxed_api/util:status",
|
|
||||||
"//sandboxed_api/util:statusor",
|
"//sandboxed_api/util:statusor",
|
||||||
"@com_google_absl//absl/memory",
|
"@com_google_absl//absl/memory",
|
||||||
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -295,6 +295,7 @@ cc_library(
|
|||||||
"@com_google_absl//absl/container:flat_hash_set",
|
"@com_google_absl//absl/container:flat_hash_set",
|
||||||
"//sandboxed_api/util:flags",
|
"//sandboxed_api/util:flags",
|
||||||
"@com_google_absl//absl/memory",
|
"@com_google_absl//absl/memory",
|
||||||
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
"@com_google_absl//absl/strings:str_format",
|
"@com_google_absl//absl/strings:str_format",
|
||||||
"@com_google_absl//absl/synchronization",
|
"@com_google_absl//absl/synchronization",
|
||||||
@ -369,9 +370,9 @@ cc_library(
|
|||||||
"//sandboxed_api/sandbox2/util:fileops",
|
"//sandboxed_api/sandbox2/util:fileops",
|
||||||
"//sandboxed_api/sandbox2/util:strerror",
|
"//sandboxed_api/sandbox2/util:strerror",
|
||||||
"//sandboxed_api/util:raw_logging",
|
"//sandboxed_api/util:raw_logging",
|
||||||
"//sandboxed_api/util:status",
|
|
||||||
"//sandboxed_api/util:statusor",
|
"//sandboxed_api/util:statusor",
|
||||||
"@com_google_absl//absl/memory",
|
"@com_google_absl//absl/memory",
|
||||||
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
"@com_google_absl//absl/strings:str_format",
|
"@com_google_absl//absl/strings:str_format",
|
||||||
"@com_google_absl//absl/synchronization",
|
"@com_google_absl//absl/synchronization",
|
||||||
@ -395,6 +396,7 @@ cc_library(
|
|||||||
"//sandboxed_api/util:statusor",
|
"//sandboxed_api/util:statusor",
|
||||||
"@com_google_absl//absl/base:core_headers",
|
"@com_google_absl//absl/base:core_headers",
|
||||||
"@com_google_absl//absl/container:flat_hash_set",
|
"@com_google_absl//absl/container:flat_hash_set",
|
||||||
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
"@com_google_protobuf//:protobuf",
|
"@com_google_protobuf//:protobuf",
|
||||||
],
|
],
|
||||||
@ -556,6 +558,7 @@ cc_library(
|
|||||||
"//sandboxed_api/util:statusor",
|
"//sandboxed_api/util:statusor",
|
||||||
"@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/status",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
"@com_google_absl//absl/strings:str_format",
|
"@com_google_absl//absl/strings:str_format",
|
||||||
"@com_google_absl//absl/synchronization",
|
"@com_google_absl//absl/synchronization",
|
||||||
@ -783,9 +786,9 @@ cc_test(
|
|||||||
":sandbox2",
|
":sandbox2",
|
||||||
":testing",
|
":testing",
|
||||||
"//sandboxed_api/sandbox2/util:bpf_helper",
|
"//sandboxed_api/sandbox2/util:bpf_helper",
|
||||||
"//sandboxed_api/util:status",
|
|
||||||
"//sandboxed_api/util:status_matchers",
|
"//sandboxed_api/util:status_matchers",
|
||||||
"@com_google_absl//absl/memory",
|
"@com_google_absl//absl/memory",
|
||||||
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
"@com_google_glog//:glog",
|
"@com_google_glog//:glog",
|
||||||
"@com_google_googletest//:gtest_main",
|
"@com_google_googletest//:gtest_main",
|
||||||
|
@ -250,6 +250,7 @@ target_link_libraries(sandbox2_executor PRIVATE
|
|||||||
sandbox2::namespace
|
sandbox2::namespace
|
||||||
sandbox2::util
|
sandbox2::util
|
||||||
sapi::base
|
sapi::base
|
||||||
|
sapi::status_proto
|
||||||
)
|
)
|
||||||
|
|
||||||
# sandboxed_api/sandbox2:sandbox2
|
# sandboxed_api/sandbox2:sandbox2
|
||||||
@ -356,6 +357,7 @@ target_link_libraries(sandbox2_forkserver PRIVATE
|
|||||||
sandbox2::util
|
sandbox2::util
|
||||||
sapi::base
|
sapi::base
|
||||||
sapi::raw_logging
|
sapi::raw_logging
|
||||||
|
sapi::statusor
|
||||||
)
|
)
|
||||||
|
|
||||||
# sandboxed_api/sandbox2:mounts
|
# sandboxed_api/sandbox2:mounts
|
||||||
@ -367,6 +369,7 @@ add_library(sandbox2::mounts ALIAS sandbox2_mounts)
|
|||||||
target_link_libraries(sandbox2_mounts PRIVATE
|
target_link_libraries(sandbox2_mounts PRIVATE
|
||||||
absl::core_headers
|
absl::core_headers
|
||||||
absl::flat_hash_set
|
absl::flat_hash_set
|
||||||
|
absl::status
|
||||||
absl::str_format
|
absl::str_format
|
||||||
absl::strings
|
absl::strings
|
||||||
protobuf::libprotobuf
|
protobuf::libprotobuf
|
||||||
@ -392,6 +395,7 @@ target_link_libraries(sandbox2_namespace PRIVATE
|
|||||||
absl::memory
|
absl::memory
|
||||||
absl::str_format
|
absl::str_format
|
||||||
absl::strings
|
absl::strings
|
||||||
|
protobuf::libprotobuf
|
||||||
sandbox2::file_base
|
sandbox2::file_base
|
||||||
sandbox2::fileops
|
sandbox2::fileops
|
||||||
sandbox2::mounts
|
sandbox2::mounts
|
||||||
@ -432,7 +436,7 @@ target_link_libraries(sandbox2_util
|
|||||||
sapi::base
|
sapi::base
|
||||||
sapi::raw_logging
|
sapi::raw_logging
|
||||||
sapi::statusor
|
sapi::statusor
|
||||||
PUBLIC sapi::status
|
PUBLIC absl::status
|
||||||
)
|
)
|
||||||
target_compile_options(sandbox2_util PRIVATE
|
target_compile_options(sandbox2_util PRIVATE
|
||||||
# The default is 16384, however we need to do a clone with a
|
# The default is 16384, however we need to do a clone with a
|
||||||
@ -497,7 +501,6 @@ target_link_libraries(sandbox2_comms
|
|||||||
PRIVATE absl::memory
|
PRIVATE absl::memory
|
||||||
absl::str_format
|
absl::str_format
|
||||||
absl::strings
|
absl::strings
|
||||||
protobuf::libprotobuf
|
|
||||||
sandbox2::strerror
|
sandbox2::strerror
|
||||||
sandbox2::util
|
sandbox2::util
|
||||||
sapi::base
|
sapi::base
|
||||||
@ -505,7 +508,9 @@ target_link_libraries(sandbox2_comms
|
|||||||
sapi::status_proto
|
sapi::status_proto
|
||||||
sapi::statusor
|
sapi::statusor
|
||||||
PUBLIC absl::core_headers
|
PUBLIC absl::core_headers
|
||||||
|
absl::status
|
||||||
absl::synchronization
|
absl::synchronization
|
||||||
|
protobuf::libprotobuf
|
||||||
sapi::status
|
sapi::status
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ sapi::StatusOr<std::unique_ptr<Buffer>> Buffer::CreateFromFd(int fd) {
|
|||||||
|
|
||||||
struct stat stat_buf;
|
struct stat stat_buf;
|
||||||
if (fstat(fd, &stat_buf) != 0) {
|
if (fstat(fd, &stat_buf) != 0) {
|
||||||
return sapi::InternalError(
|
return absl::InternalError(
|
||||||
absl::StrCat("Could not stat buffer fd: ", StrError(errno)));
|
absl::StrCat("Could not stat buffer fd: ", StrError(errno)));
|
||||||
}
|
}
|
||||||
size_t size = stat_buf.st_size;
|
size_t size = stat_buf.st_size;
|
||||||
@ -43,7 +43,7 @@ sapi::StatusOr<std::unique_ptr<Buffer>> Buffer::CreateFromFd(int fd) {
|
|||||||
buffer->buf_ =
|
buffer->buf_ =
|
||||||
reinterpret_cast<uint8_t*>(mmap(nullptr, size, prot, flags, fd, offset));
|
reinterpret_cast<uint8_t*>(mmap(nullptr, size, prot, flags, fd, offset));
|
||||||
if (buffer->buf_ == MAP_FAILED) {
|
if (buffer->buf_ == MAP_FAILED) {
|
||||||
return sapi::InternalError(
|
return absl::InternalError(
|
||||||
absl::StrCat("Could not map buffer fd: ", StrError(errno)));
|
absl::StrCat("Could not map buffer fd: ", StrError(errno)));
|
||||||
}
|
}
|
||||||
buffer->fd_ = fd;
|
buffer->fd_ = fd;
|
||||||
@ -56,10 +56,10 @@ sapi::StatusOr<std::unique_ptr<Buffer>> Buffer::CreateFromFd(int fd) {
|
|||||||
sapi::StatusOr<std::unique_ptr<Buffer>> Buffer::CreateWithSize(int64_t size) {
|
sapi::StatusOr<std::unique_ptr<Buffer>> Buffer::CreateWithSize(int64_t size) {
|
||||||
int fd;
|
int fd;
|
||||||
if (!util::CreateMemFd(&fd)) {
|
if (!util::CreateMemFd(&fd)) {
|
||||||
return sapi::InternalError("Could not create buffer temp file");
|
return absl::InternalError("Could not create buffer temp file");
|
||||||
}
|
}
|
||||||
if (ftruncate(fd, size) != 0) {
|
if (ftruncate(fd, size) != 0) {
|
||||||
return sapi::InternalError(
|
return absl::InternalError(
|
||||||
absl::StrCat("Could not extend buffer fd: ", StrError(errno)));
|
absl::StrCat("Could not extend buffer fd: ", StrError(errno)));
|
||||||
}
|
}
|
||||||
return CreateFromFd(fd);
|
return CreateFromFd(fd);
|
||||||
|
@ -256,9 +256,9 @@ NetworkProxyClient* Client::GetNetworkProxyClient() {
|
|||||||
return proxy_client_.get();
|
return proxy_client_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Client::InstallNetworkProxyHandler() {
|
absl::Status Client::InstallNetworkProxyHandler() {
|
||||||
if (fd_map_.find(NetworkProxyClient::kFDName) == fd_map_.end()) {
|
if (fd_map_.find(NetworkProxyClient::kFDName) == fd_map_.end()) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
"InstallNetworkProxyHandler() must be called at most once after the "
|
"InstallNetworkProxyHandler() must be called at most once after the "
|
||||||
"sandbox is installed. Also, the NetworkProxyServer needs to be "
|
"sandbox is installed. Also, the NetworkProxyServer needs to be "
|
||||||
"enabled.");
|
"enabled.");
|
||||||
|
@ -60,7 +60,7 @@ class Client {
|
|||||||
|
|
||||||
// Redirects the connect() syscall to the ConnectHandler() method in
|
// Redirects the connect() syscall to the ConnectHandler() method in
|
||||||
// the NetworkProxyClient class.
|
// the NetworkProxyClient class.
|
||||||
sapi::Status InstallNetworkProxyHandler();
|
absl::Status InstallNetworkProxyHandler();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Comms used for synchronization with the monitor, not owned by the object.
|
// Comms used for synchronization with the monitor, not owned by the object.
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
#include "google/protobuf/message.h"
|
#include "google/protobuf/message.h"
|
||||||
#include "absl/memory/memory.h"
|
#include "absl/memory/memory.h"
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "absl/strings/str_cat.h"
|
#include "absl/strings/str_cat.h"
|
||||||
#include "absl/strings/str_format.h"
|
#include "absl/strings/str_format.h"
|
||||||
#include "absl/synchronization/mutex.h"
|
#include "absl/synchronization/mutex.h"
|
||||||
@ -657,4 +658,19 @@ bool Comms::RecvInt(void* buffer, uint64_t len, uint32_t tag) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Comms::RecvStatus(absl::Status* status) {
|
||||||
|
sapi::StatusProto proto;
|
||||||
|
if (!RecvProtoBuf(&proto)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*status = sapi::MakeStatusFromProto(proto);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Comms::SendStatus(const absl::Status& status) {
|
||||||
|
sapi::StatusProto proto;
|
||||||
|
sapi::SaveStatusToProto(status, &proto);
|
||||||
|
return SendProtoBuf(proto);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sandbox2
|
} // namespace sandbox2
|
||||||
|
@ -32,8 +32,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "absl/base/attributes.h"
|
#include "absl/base/attributes.h"
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "absl/synchronization/mutex.h"
|
#include "absl/synchronization/mutex.h"
|
||||||
#include "sandboxed_api/util/status.h"
|
|
||||||
#include "sandboxed_api/util/status.pb.h"
|
#include "sandboxed_api/util/status.pb.h"
|
||||||
|
|
||||||
namespace proto2 {
|
namespace proto2 {
|
||||||
@ -150,10 +150,8 @@ class Comms {
|
|||||||
bool SendProtoBuf(const google::protobuf::Message& message);
|
bool SendProtoBuf(const google::protobuf::Message& message);
|
||||||
|
|
||||||
// Receives/sends Status objects.
|
// Receives/sends Status objects.
|
||||||
template <typename StatusT>
|
bool RecvStatus(absl::Status* status);
|
||||||
bool RecvStatus(StatusT* status);
|
bool SendStatus(const absl::Status& status);
|
||||||
template <typename StatusT>
|
|
||||||
bool SendStatus(const StatusT& status);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// State of the channel
|
// State of the channel
|
||||||
@ -220,23 +218,6 @@ class Comms {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename StatusT>
|
|
||||||
bool Comms::RecvStatus(StatusT* status) {
|
|
||||||
sapi::StatusProto proto;
|
|
||||||
if (!RecvProtoBuf(&proto)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*status = sapi::MakeStatusFromProto(proto);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename StatusT>
|
|
||||||
bool Comms::SendStatus(const StatusT& status) {
|
|
||||||
sapi::StatusProto proto;
|
|
||||||
sapi::SaveStatusToProto(status, &proto);
|
|
||||||
return SendProtoBuf(proto);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace sandbox2
|
} // namespace sandbox2
|
||||||
|
|
||||||
#endif // SANDBOXED_API_SANDBOX2_COMMS_H_
|
#endif // SANDBOXED_API_SANDBOX2_COMMS_H_
|
||||||
|
@ -302,13 +302,13 @@ TEST_F(CommsTest, TestSendRecvProto) {
|
|||||||
TEST_F(CommsTest, TestSendRecvStatusOK) {
|
TEST_F(CommsTest, TestSendRecvStatusOK) {
|
||||||
auto a = [](Comms* comms) {
|
auto a = [](Comms* comms) {
|
||||||
// Receive a good status.
|
// Receive a good status.
|
||||||
sapi::Status status;
|
absl::Status status;
|
||||||
ASSERT_THAT(comms->RecvStatus(&status), IsTrue());
|
ASSERT_THAT(comms->RecvStatus(&status), IsTrue());
|
||||||
EXPECT_THAT(status, IsOk());
|
EXPECT_THAT(status, IsOk());
|
||||||
};
|
};
|
||||||
auto b = [](Comms* comms) {
|
auto b = [](Comms* comms) {
|
||||||
// Send a good status.
|
// Send a good status.
|
||||||
ASSERT_THAT(comms->SendStatus(sapi::OkStatus()), IsTrue());
|
ASSERT_THAT(comms->SendStatus(absl::OkStatus()), IsTrue());
|
||||||
};
|
};
|
||||||
HandleCommunication(sockname_, a, b);
|
HandleCommunication(sockname_, a, b);
|
||||||
}
|
}
|
||||||
@ -316,15 +316,15 @@ TEST_F(CommsTest, TestSendRecvStatusOK) {
|
|||||||
TEST_F(CommsTest, TestSendRecvStatusFailing) {
|
TEST_F(CommsTest, TestSendRecvStatusFailing) {
|
||||||
auto a = [](Comms* comms) {
|
auto a = [](Comms* comms) {
|
||||||
// Receive a failing status.
|
// Receive a failing status.
|
||||||
sapi::Status status;
|
absl::Status status;
|
||||||
ASSERT_THAT(comms->RecvStatus(&status), IsTrue());
|
ASSERT_THAT(comms->RecvStatus(&status), IsTrue());
|
||||||
EXPECT_THAT(status, Not(IsOk()));
|
EXPECT_THAT(status, Not(IsOk()));
|
||||||
EXPECT_THAT(status, StatusIs(sapi::StatusCode::kInternal, "something odd"));
|
EXPECT_THAT(status, StatusIs(absl::StatusCode::kInternal, "something odd"));
|
||||||
};
|
};
|
||||||
auto b = [](Comms* comms) {
|
auto b = [](Comms* comms) {
|
||||||
// Send a failing status.
|
// Send a failing status.
|
||||||
ASSERT_THAT(comms->SendStatus(
|
ASSERT_THAT(comms->SendStatus(
|
||||||
sapi::Status{sapi::StatusCode::kInternal, "something odd"}),
|
absl::Status{absl::StatusCode::kInternal, "something odd"}),
|
||||||
IsTrue());
|
IsTrue());
|
||||||
};
|
};
|
||||||
HandleCommunication(sockname_, a, b);
|
HandleCommunication(sockname_, a, b);
|
||||||
|
@ -92,7 +92,7 @@ int main(int argc, char** argv) {
|
|||||||
// Enable sandboxing from here.
|
// Enable sandboxing from here.
|
||||||
sandbox2_client.SandboxMeHere();
|
sandbox2_client.SandboxMeHere();
|
||||||
|
|
||||||
sapi::Status status = sandbox2_client.InstallNetworkProxyHandler();
|
absl::Status status = sandbox2_client.InstallNetworkProxyHandler();
|
||||||
if (!status.ok()) {
|
if (!status.ok()) {
|
||||||
LOG(ERROR) << "InstallNetworkProxyHandler() failed: " << status.message();
|
LOG(ERROR) << "InstallNetworkProxyHandler() failed: " << status.message();
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include "absl/memory/memory.h"
|
#include "absl/memory/memory.h"
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "absl/strings/match.h"
|
#include "absl/strings/match.h"
|
||||||
#include "absl/strings/str_cat.h"
|
#include "absl/strings/str_cat.h"
|
||||||
#include "absl/strings/str_format.h"
|
#include "absl/strings/str_format.h"
|
||||||
@ -57,7 +58,6 @@
|
|||||||
#include "sandboxed_api/sandbox2/util/fileops.h"
|
#include "sandboxed_api/sandbox2/util/fileops.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"
|
||||||
#include "sandboxed_api/util/status.h"
|
|
||||||
#include "sandboxed_api/util/statusor.h"
|
#include "sandboxed_api/util/statusor.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -133,16 +133,16 @@ void RunInitProcess(std::set<int> open_fds) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status SendPid(int signaling_fd) {
|
absl::Status SendPid(int signaling_fd) {
|
||||||
// Send our PID (the actual sandboxee process) via SCM_CREDENTIALS.
|
// Send our PID (the actual sandboxee process) via SCM_CREDENTIALS.
|
||||||
// The ancillary message will be attached to the message as SO_PASSCRED is set
|
// The ancillary message will be attached to the message as SO_PASSCRED is set
|
||||||
// on the socket.
|
// on the socket.
|
||||||
char dummy = ' ';
|
char dummy = ' ';
|
||||||
if (TEMP_FAILURE_RETRY(send(signaling_fd, &dummy, 1, 0)) != 1) {
|
if (TEMP_FAILURE_RETRY(send(signaling_fd, &dummy, 1, 0)) != 1) {
|
||||||
return sapi::InternalError(
|
return absl::InternalError(
|
||||||
absl::StrCat("Sending PID: send: ", sandbox2::StrError(errno)));
|
absl::StrCat("Sending PID: send: ", sandbox2::StrError(errno)));
|
||||||
}
|
}
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::StatusOr<pid_t> ReceivePid(int signaling_fd) {
|
sapi::StatusOr<pid_t> ReceivePid(int signaling_fd) {
|
||||||
@ -164,13 +164,13 @@ sapi::StatusOr<pid_t> ReceivePid(int signaling_fd) {
|
|||||||
iov.iov_len = sizeof(char);
|
iov.iov_len = sizeof(char);
|
||||||
|
|
||||||
if (TEMP_FAILURE_RETRY(recvmsg(signaling_fd, &msgh, MSG_WAITALL)) != 1) {
|
if (TEMP_FAILURE_RETRY(recvmsg(signaling_fd, &msgh, MSG_WAITALL)) != 1) {
|
||||||
return sapi::InternalError(absl::StrCat("Receiving pid failed: recvmsg: ",
|
return absl::InternalError(absl::StrCat("Receiving pid failed: recvmsg: ",
|
||||||
sandbox2::StrError(errno)));
|
sandbox2::StrError(errno)));
|
||||||
}
|
}
|
||||||
struct cmsghdr* cmsgp = CMSG_FIRSTHDR(&msgh);
|
struct cmsghdr* cmsgp = CMSG_FIRSTHDR(&msgh);
|
||||||
if (cmsgp->cmsg_len != CMSG_LEN(sizeof(struct ucred)) ||
|
if (cmsgp->cmsg_len != CMSG_LEN(sizeof(struct ucred)) ||
|
||||||
cmsgp->cmsg_level != SOL_SOCKET || cmsgp->cmsg_type != SCM_CREDENTIALS) {
|
cmsgp->cmsg_level != SOL_SOCKET || cmsgp->cmsg_type != SCM_CREDENTIALS) {
|
||||||
return sapi::InternalError("Receiving pid failed");
|
return absl::InternalError("Receiving pid failed");
|
||||||
}
|
}
|
||||||
struct ucred* ucredp = reinterpret_cast<struct ucred*>(CMSG_DATA(cmsgp));
|
struct ucred* ucredp = reinterpret_cast<struct ucred*>(CMSG_DATA(cmsgp));
|
||||||
return ucredp->pid;
|
return ucredp->pid;
|
||||||
@ -456,7 +456,7 @@ pid_t ForkServer::ServeRequest() {
|
|||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
// Send sandboxee pid
|
// Send sandboxee pid
|
||||||
sapi::Status status = SendPid(fd_closer1.get());
|
absl::Status status = SendPid(fd_closer1.get());
|
||||||
SAPI_RAW_CHECK(status.ok(), "sending pid: %s", status.message());
|
SAPI_RAW_CHECK(status.ok(), "sending pid: %s", status.message());
|
||||||
} else {
|
} else {
|
||||||
auto pid_or = ReceivePid(fd_closer0.get());
|
auto pid_or = ReceivePid(fd_closer0.get());
|
||||||
|
@ -101,24 +101,24 @@ sapi::StatusOr<std::string> ExistingPathInsideDir(
|
|||||||
absl::string_view dir_path, absl::string_view relative_path) {
|
absl::string_view dir_path, absl::string_view relative_path) {
|
||||||
auto path = file::CleanPath(file::JoinPath(dir_path, relative_path));
|
auto path = file::CleanPath(file::JoinPath(dir_path, relative_path));
|
||||||
if (file_util::fileops::StripBasename(path) != dir_path) {
|
if (file_util::fileops::StripBasename(path) != dir_path) {
|
||||||
return sapi::InvalidArgumentError("Relative path goes above the base dir");
|
return absl::InvalidArgumentError("Relative path goes above the base dir");
|
||||||
}
|
}
|
||||||
if (!file_util::fileops::Exists(path, false)) {
|
if (!file_util::fileops::Exists(path, false)) {
|
||||||
return sapi::NotFoundError(absl::StrCat("Does not exist: ", path));
|
return absl::NotFoundError(absl::StrCat("Does not exist: ", path));
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status ValidateInterpreter(absl::string_view interpreter) {
|
absl::Status ValidateInterpreter(absl::string_view interpreter) {
|
||||||
const absl::flat_hash_set<std::string> allowed_interpreters = {
|
const absl::flat_hash_set<std::string> allowed_interpreters = {
|
||||||
"/lib64/ld-linux-x86-64.so.2",
|
"/lib64/ld-linux-x86-64.so.2",
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!allowed_interpreters.contains(interpreter)) {
|
if (!allowed_interpreters.contains(interpreter)) {
|
||||||
return sapi::InvalidArgumentError(
|
return absl::InvalidArgumentError(
|
||||||
absl::StrCat("Interpreter not on the whitelist: ", interpreter));
|
absl::StrCat("Interpreter not on the whitelist: ", interpreter));
|
||||||
}
|
}
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ResolveLibraryPath(absl::string_view lib_name,
|
std::string ResolveLibraryPath(absl::string_view lib_name,
|
||||||
@ -145,7 +145,7 @@ std::string GetPlatform(absl::string_view interpreter) {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
sapi::Status Mounts::Insert(absl::string_view path,
|
absl::Status Mounts::Insert(absl::string_view path,
|
||||||
const MountTree::Node& new_node) {
|
const MountTree::Node& new_node) {
|
||||||
// Some sandboxes allow the inside/outside paths to be partially
|
// Some sandboxes allow the inside/outside paths to be partially
|
||||||
// user-controlled with some sanitization.
|
// user-controlled with some sanitization.
|
||||||
@ -154,7 +154,7 @@ sapi::Status Mounts::Insert(absl::string_view path,
|
|||||||
// and mount something not expected by the caller. Check for null bytes in the
|
// and mount something not expected by the caller. Check for null bytes in the
|
||||||
// strings to protect against this.
|
// strings to protect against this.
|
||||||
if (PathContainsNullByte(path)) {
|
if (PathContainsNullByte(path)) {
|
||||||
return sapi::InvalidArgumentError(
|
return absl::InvalidArgumentError(
|
||||||
absl::StrCat("Inside path contains a null byte: ", path));
|
absl::StrCat("Inside path contains a null byte: ", path));
|
||||||
}
|
}
|
||||||
switch (new_node.node_case()) {
|
switch (new_node.node_case()) {
|
||||||
@ -162,16 +162,16 @@ sapi::Status Mounts::Insert(absl::string_view path,
|
|||||||
case MountTree::Node::kDirNode: {
|
case MountTree::Node::kDirNode: {
|
||||||
auto outside_path = GetOutsidePath(new_node);
|
auto outside_path = GetOutsidePath(new_node);
|
||||||
if (outside_path.empty()) {
|
if (outside_path.empty()) {
|
||||||
return sapi::InvalidArgumentError("Outside path cannot be empty");
|
return absl::InvalidArgumentError("Outside path cannot be empty");
|
||||||
}
|
}
|
||||||
if (PathContainsNullByte(outside_path)) {
|
if (PathContainsNullByte(outside_path)) {
|
||||||
return sapi::InvalidArgumentError(
|
return absl::InvalidArgumentError(
|
||||||
absl::StrCat("Outside path contains a null byte: ", outside_path));
|
absl::StrCat("Outside path contains a null byte: ", outside_path));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MountTree::Node::kRootNode:
|
case MountTree::Node::kRootNode:
|
||||||
return sapi::InvalidArgumentError("Cannot insert a RootNode");
|
return absl::InvalidArgumentError("Cannot insert a RootNode");
|
||||||
case MountTree::Node::kTmpfsNode:
|
case MountTree::Node::kTmpfsNode:
|
||||||
case MountTree::Node::NODE_NOT_SET:
|
case MountTree::Node::NODE_NOT_SET:
|
||||||
break;
|
break;
|
||||||
@ -180,11 +180,11 @@ sapi::Status Mounts::Insert(absl::string_view path,
|
|||||||
std::string fixed_path = file::CleanPath(path);
|
std::string fixed_path = file::CleanPath(path);
|
||||||
|
|
||||||
if (!absl::StartsWith(fixed_path, "/")) {
|
if (!absl::StartsWith(fixed_path, "/")) {
|
||||||
return sapi::InvalidArgumentError("Only absolute paths are supported");
|
return absl::InvalidArgumentError("Only absolute paths are supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fixed_path == "/") {
|
if (fixed_path == "/") {
|
||||||
return sapi::InvalidArgumentError("The root already exists");
|
return absl::InvalidArgumentError("The root already exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<absl::string_view> parts;
|
std::vector<absl::string_view> parts;
|
||||||
@ -205,7 +205,7 @@ sapi::Status Mounts::Insert(absl::string_view path,
|
|||||||
->insert({std::string(*part), MountTree()})
|
->insert({std::string(*part), MountTree()})
|
||||||
.first->second);
|
.first->second);
|
||||||
if (curtree->has_node() && curtree->node().has_file_node()) {
|
if (curtree->has_node() && curtree->node().has_file_node()) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("Cannot insert ", path,
|
absl::StrCat("Cannot insert ", path,
|
||||||
" since a file is mounted as a parent directory"));
|
" since a file is mounted as a parent directory"));
|
||||||
}
|
}
|
||||||
@ -218,27 +218,27 @@ sapi::Status Mounts::Insert(absl::string_view path,
|
|||||||
if (curtree->has_node()) {
|
if (curtree->has_node()) {
|
||||||
if (IsEquivalentNode(curtree->node(), new_node)) {
|
if (IsEquivalentNode(curtree->node(), new_node)) {
|
||||||
SAPI_RAW_LOG(INFO, "Inserting %s with the same value twice", path);
|
SAPI_RAW_LOG(INFO, "Inserting %s with the same value twice", path);
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
return sapi::FailedPreconditionError(absl::StrCat(
|
return absl::FailedPreconditionError(absl::StrCat(
|
||||||
"Inserting ", path, " twice with conflicting values ",
|
"Inserting ", path, " twice with conflicting values ",
|
||||||
curtree->node().DebugString(), " vs. ", new_node.DebugString()));
|
curtree->node().DebugString(), " vs. ", new_node.DebugString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_node.has_file_node() && !curtree->entries().empty()) {
|
if (new_node.has_file_node() && !curtree->entries().empty()) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("Trying to mount file over existing directory at ", path));
|
absl::StrCat("Trying to mount file over existing directory at ", path));
|
||||||
}
|
}
|
||||||
|
|
||||||
*curtree->mutable_node() = new_node;
|
*curtree->mutable_node() = new_node;
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Mounts::AddFile(absl::string_view path, bool is_ro) {
|
absl::Status Mounts::AddFile(absl::string_view path, bool is_ro) {
|
||||||
return AddFileAt(path, path, is_ro);
|
return AddFileAt(path, path, is_ro);
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Mounts::AddFileAt(absl::string_view outside,
|
absl::Status Mounts::AddFileAt(absl::string_view outside,
|
||||||
absl::string_view inside, bool is_ro) {
|
absl::string_view inside, bool is_ro) {
|
||||||
MountTree::Node node;
|
MountTree::Node node;
|
||||||
auto* file_node = node.mutable_file_node();
|
auto* file_node = node.mutable_file_node();
|
||||||
@ -247,7 +247,7 @@ sapi::Status Mounts::AddFileAt(absl::string_view outside,
|
|||||||
return Insert(inside, node);
|
return Insert(inside, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Mounts::AddDirectoryAt(absl::string_view outside,
|
absl::Status Mounts::AddDirectoryAt(absl::string_view outside,
|
||||||
absl::string_view inside, bool is_ro) {
|
absl::string_view inside, bool is_ro) {
|
||||||
MountTree::Node node;
|
MountTree::Node node;
|
||||||
auto dir_node = node.mutable_dir_node();
|
auto dir_node = node.mutable_dir_node();
|
||||||
@ -288,12 +288,12 @@ void LogContainer(const std::vector<std::string>& container) {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
sapi::Status Mounts::AddMappingsForBinary(const std::string& path,
|
absl::Status Mounts::AddMappingsForBinary(const std::string& path,
|
||||||
absl::string_view ld_library_path) {
|
absl::string_view ld_library_path) {
|
||||||
auto elf_or = ElfFile::ParseFromFile(
|
auto elf_or = ElfFile::ParseFromFile(
|
||||||
path, ElfFile::kGetInterpreter | ElfFile::kLoadImportedLibraries);
|
path, ElfFile::kGetInterpreter | ElfFile::kLoadImportedLibraries);
|
||||||
if (!elf_or.ok()) {
|
if (!elf_or.ok()) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("Could not parse ELF file: ", elf_or.status().message()));
|
absl::StrCat("Could not parse ELF file: ", elf_or.status().message()));
|
||||||
}
|
}
|
||||||
auto elf = elf_or.ValueOrDie();
|
auto elf = elf_or.ValueOrDie();
|
||||||
@ -301,7 +301,7 @@ sapi::Status Mounts::AddMappingsForBinary(const std::string& path,
|
|||||||
|
|
||||||
if (interpreter.empty()) {
|
if (interpreter.empty()) {
|
||||||
SAPI_RAW_VLOG(1, "The file %s is not a dynamic executable", path);
|
SAPI_RAW_VLOG(1, "The file %s is not a dynamic executable", path);
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
SAPI_RAW_VLOG(1, "The file %s is using interpreter %s", path, interpreter);
|
SAPI_RAW_VLOG(1, "The file %s is using interpreter %s", path, interpreter);
|
||||||
@ -354,7 +354,7 @@ sapi::Status Mounts::AddMappingsForBinary(const std::string& path,
|
|||||||
{
|
{
|
||||||
auto imported_libs = elf.imported_libraries();
|
auto imported_libs = elf.imported_libraries();
|
||||||
if (imported_libs.size() > kMaxWorkQueueSize) {
|
if (imported_libs.size() > kMaxWorkQueueSize) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
"Exceeded max entries pending resolving limit");
|
"Exceeded max entries pending resolving limit");
|
||||||
}
|
}
|
||||||
for (const auto& imported_lib : imported_libs) {
|
for (const auto& imported_lib : imported_libs) {
|
||||||
@ -383,11 +383,11 @@ sapi::Status Mounts::AddMappingsForBinary(const std::string& path,
|
|||||||
to_resolve.pop_back();
|
to_resolve.pop_back();
|
||||||
++resolved;
|
++resolved;
|
||||||
if (resolved > kMaxResolvedEntries) {
|
if (resolved > kMaxResolvedEntries) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
"Exceeded max resolved entries limit");
|
"Exceeded max resolved entries limit");
|
||||||
}
|
}
|
||||||
if (depth > kMaxResolvingDepth) {
|
if (depth > kMaxResolvingDepth) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
"Exceeded max resolving depth limit");
|
"Exceeded max resolving depth limit");
|
||||||
}
|
}
|
||||||
std::string resolved_lib = ResolveLibraryPath(lib, full_search_paths);
|
std::string resolved_lib = ResolveLibraryPath(lib, full_search_paths);
|
||||||
@ -403,19 +403,19 @@ sapi::Status Mounts::AddMappingsForBinary(const std::string& path,
|
|||||||
|
|
||||||
imported_libraries.insert(resolved_lib);
|
imported_libraries.insert(resolved_lib);
|
||||||
if (imported_libraries.size() > kMaxImportedLibraries) {
|
if (imported_libraries.size() > kMaxImportedLibraries) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
"Exceeded max imported libraries limit");
|
"Exceeded max imported libraries limit");
|
||||||
}
|
}
|
||||||
++loaded;
|
++loaded;
|
||||||
if (loaded > kMaxLoadedEntries) {
|
if (loaded > kMaxLoadedEntries) {
|
||||||
return sapi::FailedPreconditionError("Exceeded max loaded entries limit");
|
return absl::FailedPreconditionError("Exceeded max loaded entries limit");
|
||||||
}
|
}
|
||||||
SAPI_ASSIGN_OR_RETURN(
|
SAPI_ASSIGN_OR_RETURN(
|
||||||
auto lib_elf,
|
auto lib_elf,
|
||||||
ElfFile::ParseFromFile(resolved_lib, ElfFile::kLoadImportedLibraries));
|
ElfFile::ParseFromFile(resolved_lib, ElfFile::kLoadImportedLibraries));
|
||||||
auto imported_libs = lib_elf.imported_libraries();
|
auto imported_libs = lib_elf.imported_libraries();
|
||||||
if (imported_libs.size() > kMaxWorkQueueSize - to_resolve.size()) {
|
if (imported_libs.size() > kMaxWorkQueueSize - to_resolve.size()) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
"Exceeded max entries pending resolving limit");
|
"Exceeded max entries pending resolving limit");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,10 +436,10 @@ sapi::Status Mounts::AddMappingsForBinary(const std::string& path,
|
|||||||
SAPI_RETURN_IF_ERROR(AddFile(lib));
|
SAPI_RETURN_IF_ERROR(AddFile(lib));
|
||||||
}
|
}
|
||||||
|
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Mounts::AddTmpfs(absl::string_view inside, size_t sz) {
|
absl::Status Mounts::AddTmpfs(absl::string_view inside, size_t sz) {
|
||||||
MountTree::Node node;
|
MountTree::Node node;
|
||||||
auto tmpfs_node = node.mutable_tmpfs_node();
|
auto tmpfs_node = node.mutable_tmpfs_node();
|
||||||
tmpfs_node->set_tmpfs_options(absl::StrCat("size=", sz));
|
tmpfs_node->set_tmpfs_options(absl::StrCat("size=", sz));
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "absl/base/attributes.h"
|
#include "absl/base/attributes.h"
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "absl/strings/string_view.h"
|
#include "absl/strings/string_view.h"
|
||||||
#include "sandboxed_api/sandbox2/mounttree.pb.h"
|
#include "sandboxed_api/sandbox2/mounttree.pb.h"
|
||||||
#include "sandboxed_api/util/status.h"
|
|
||||||
|
|
||||||
namespace sandbox2 {
|
namespace sandbox2 {
|
||||||
|
|
||||||
@ -40,18 +40,18 @@ class Mounts {
|
|||||||
Mounts& operator=(const Mounts&) = default;
|
Mounts& operator=(const Mounts&) = default;
|
||||||
Mounts& operator=(Mounts&&) = default;
|
Mounts& operator=(Mounts&&) = default;
|
||||||
|
|
||||||
sapi::Status AddFile(absl::string_view path, bool is_ro = true);
|
absl::Status AddFile(absl::string_view path, bool is_ro = true);
|
||||||
|
|
||||||
sapi::Status AddFileAt(absl::string_view outside, absl::string_view inside,
|
absl::Status AddFileAt(absl::string_view outside, absl::string_view inside,
|
||||||
bool is_ro = true);
|
bool is_ro = true);
|
||||||
|
|
||||||
sapi::Status AddDirectoryAt(absl::string_view outside,
|
absl::Status AddDirectoryAt(absl::string_view outside,
|
||||||
absl::string_view inside, bool is_ro = true);
|
absl::string_view inside, bool is_ro = true);
|
||||||
|
|
||||||
sapi::Status AddMappingsForBinary(const std::string& path,
|
absl::Status AddMappingsForBinary(const std::string& path,
|
||||||
absl::string_view ld_library_path = {});
|
absl::string_view ld_library_path = {});
|
||||||
|
|
||||||
sapi::Status AddTmpfs(absl::string_view inside, size_t sz);
|
absl::Status AddTmpfs(absl::string_view inside, size_t sz);
|
||||||
|
|
||||||
void CreateMounts(const std::string& root_path) const;
|
void CreateMounts(const std::string& root_path) const;
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ class Mounts {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
friend class MountTreeTest;
|
friend class MountTreeTest;
|
||||||
sapi::Status Insert(absl::string_view path, const MountTree::Node& node);
|
absl::Status Insert(absl::string_view path, const MountTree::Node& node);
|
||||||
MountTree mount_tree_;
|
MountTree mount_tree_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,19 +41,19 @@ constexpr size_t kTmpfsSize = 1024;
|
|||||||
TEST(MountTreeTest, TestInvalidFilenames) {
|
TEST(MountTreeTest, TestInvalidFilenames) {
|
||||||
Mounts mounts;
|
Mounts mounts;
|
||||||
|
|
||||||
EXPECT_THAT(mounts.AddFile(""), StatusIs(sapi::StatusCode::kInvalidArgument));
|
EXPECT_THAT(mounts.AddFile(""), StatusIs(absl::StatusCode::kInvalidArgument));
|
||||||
EXPECT_THAT(mounts.AddFile("a"),
|
EXPECT_THAT(mounts.AddFile("a"),
|
||||||
StatusIs(sapi::StatusCode::kInvalidArgument));
|
StatusIs(absl::StatusCode::kInvalidArgument));
|
||||||
EXPECT_THAT(mounts.AddFileAt("/a", ""),
|
EXPECT_THAT(mounts.AddFileAt("/a", ""),
|
||||||
StatusIs(sapi::StatusCode::kInvalidArgument));
|
StatusIs(absl::StatusCode::kInvalidArgument));
|
||||||
EXPECT_THAT(mounts.AddFileAt("", "/a"),
|
EXPECT_THAT(mounts.AddFileAt("", "/a"),
|
||||||
StatusIs(sapi::StatusCode::kInvalidArgument));
|
StatusIs(absl::StatusCode::kInvalidArgument));
|
||||||
EXPECT_THAT(mounts.AddFileAt("/a", "a"),
|
EXPECT_THAT(mounts.AddFileAt("/a", "a"),
|
||||||
StatusIs(sapi::StatusCode::kInvalidArgument));
|
StatusIs(absl::StatusCode::kInvalidArgument));
|
||||||
EXPECT_THAT(mounts.AddFile("/"),
|
EXPECT_THAT(mounts.AddFile("/"),
|
||||||
StatusIs(sapi::StatusCode::kInvalidArgument));
|
StatusIs(absl::StatusCode::kInvalidArgument));
|
||||||
EXPECT_THAT(mounts.AddFileAt("/a", "/"),
|
EXPECT_THAT(mounts.AddFileAt("/a", "/"),
|
||||||
StatusIs(sapi::StatusCode::kInvalidArgument));
|
StatusIs(absl::StatusCode::kInvalidArgument));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(MountTreeTest, TestAddFile) {
|
TEST(MountTreeTest, TestAddFile) {
|
||||||
@ -127,17 +127,17 @@ TEST(MountTreeTest, TestMultipleInsertion) {
|
|||||||
EXPECT_THAT(mounts.AddFile("/c/d"), IsOk());
|
EXPECT_THAT(mounts.AddFile("/c/d"), IsOk());
|
||||||
|
|
||||||
EXPECT_THAT(mounts.AddFile("/c"),
|
EXPECT_THAT(mounts.AddFile("/c"),
|
||||||
StatusIs(sapi::StatusCode::kFailedPrecondition));
|
StatusIs(absl::StatusCode::kFailedPrecondition));
|
||||||
EXPECT_THAT(mounts.AddFileAt("/f", "/c"),
|
EXPECT_THAT(mounts.AddFileAt("/f", "/c"),
|
||||||
StatusIs(sapi::StatusCode::kFailedPrecondition));
|
StatusIs(absl::StatusCode::kFailedPrecondition));
|
||||||
EXPECT_THAT(mounts.AddDirectoryAt("/f", "/c"), IsOk());
|
EXPECT_THAT(mounts.AddDirectoryAt("/f", "/c"), IsOk());
|
||||||
|
|
||||||
EXPECT_THAT(mounts.AddFile("/c/d/e"),
|
EXPECT_THAT(mounts.AddFile("/c/d/e"),
|
||||||
StatusIs(sapi::StatusCode::kFailedPrecondition));
|
StatusIs(absl::StatusCode::kFailedPrecondition));
|
||||||
EXPECT_THAT(mounts.AddFileAt("/f", "/c/d/e"),
|
EXPECT_THAT(mounts.AddFileAt("/f", "/c/d/e"),
|
||||||
StatusIs(sapi::StatusCode::kFailedPrecondition));
|
StatusIs(absl::StatusCode::kFailedPrecondition));
|
||||||
EXPECT_THAT(mounts.AddDirectoryAt("/f", "/c/d/e"),
|
EXPECT_THAT(mounts.AddDirectoryAt("/f", "/c/d/e"),
|
||||||
StatusIs(sapi::StatusCode::kFailedPrecondition));
|
StatusIs(absl::StatusCode::kFailedPrecondition));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(MountTreeTest, TestEvilNullByte) {
|
TEST(MountTreeTest, TestEvilNullByte) {
|
||||||
@ -148,17 +148,17 @@ TEST(MountTreeTest, TestEvilNullByte) {
|
|||||||
filename[2] = '\0';
|
filename[2] = '\0';
|
||||||
|
|
||||||
EXPECT_THAT(mounts.AddFile(filename),
|
EXPECT_THAT(mounts.AddFile(filename),
|
||||||
StatusIs(sapi::StatusCode::kInvalidArgument));
|
StatusIs(absl::StatusCode::kInvalidArgument));
|
||||||
EXPECT_THAT(mounts.AddFileAt(filename, "/a"),
|
EXPECT_THAT(mounts.AddFileAt(filename, "/a"),
|
||||||
StatusIs(sapi::StatusCode::kInvalidArgument));
|
StatusIs(absl::StatusCode::kInvalidArgument));
|
||||||
EXPECT_THAT(mounts.AddFileAt("/a", filename),
|
EXPECT_THAT(mounts.AddFileAt("/a", filename),
|
||||||
StatusIs(sapi::StatusCode::kInvalidArgument));
|
StatusIs(absl::StatusCode::kInvalidArgument));
|
||||||
EXPECT_THAT(mounts.AddDirectoryAt(filename, "/a"),
|
EXPECT_THAT(mounts.AddDirectoryAt(filename, "/a"),
|
||||||
StatusIs(sapi::StatusCode::kInvalidArgument));
|
StatusIs(absl::StatusCode::kInvalidArgument));
|
||||||
EXPECT_THAT(mounts.AddDirectoryAt("/a", filename),
|
EXPECT_THAT(mounts.AddDirectoryAt("/a", filename),
|
||||||
StatusIs(sapi::StatusCode::kInvalidArgument));
|
StatusIs(absl::StatusCode::kInvalidArgument));
|
||||||
EXPECT_THAT(mounts.AddTmpfs(filename, kTmpfsSize),
|
EXPECT_THAT(mounts.AddTmpfs(filename, kTmpfsSize),
|
||||||
StatusIs(sapi::StatusCode::kInvalidArgument));
|
StatusIs(absl::StatusCode::kInvalidArgument));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(MountTreeTest, TestMinimalDynamicBinary) {
|
TEST(MountTreeTest, TestMinimalDynamicBinary) {
|
||||||
|
@ -55,7 +55,7 @@ constexpr char NetworkProxyClient::kFDName[];
|
|||||||
|
|
||||||
int NetworkProxyClient::ConnectHandler(int sockfd, const struct sockaddr* addr,
|
int NetworkProxyClient::ConnectHandler(int sockfd, const struct sockaddr* addr,
|
||||||
socklen_t addrlen) {
|
socklen_t addrlen) {
|
||||||
sapi::Status status = Connect(sockfd, addr, addrlen);
|
absl::Status status = Connect(sockfd, addr, addrlen);
|
||||||
if (status.ok()) {
|
if (status.ok()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ int NetworkProxyClient::ConnectHandler(int sockfd, const struct sockaddr* addr,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status NetworkProxyClient::Connect(int sockfd,
|
absl::Status NetworkProxyClient::Connect(int sockfd,
|
||||||
const struct sockaddr* addr,
|
const struct sockaddr* addr,
|
||||||
socklen_t addrlen) {
|
socklen_t addrlen) {
|
||||||
absl::MutexLock lock(&mutex_);
|
absl::MutexLock lock(&mutex_);
|
||||||
@ -73,18 +73,18 @@ sapi::Status NetworkProxyClient::Connect(int sockfd,
|
|||||||
socklen_t type_size = sizeof(int);
|
socklen_t type_size = sizeof(int);
|
||||||
int result = getsockopt(sockfd, SOL_SOCKET, SO_TYPE, &type, &type_size);
|
int result = getsockopt(sockfd, SOL_SOCKET, SO_TYPE, &type, &type_size);
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
return sapi::FailedPreconditionError("Invalid socket FD");
|
return absl::FailedPreconditionError("Invalid socket FD");
|
||||||
}
|
}
|
||||||
if (type_size != sizeof(int) || type != SOCK_STREAM) {
|
if (type_size != sizeof(int) || type != SOCK_STREAM) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return sapi::InvalidArgumentError(
|
return absl::InvalidArgumentError(
|
||||||
"Invalid socket, only SOCK_STREAM is allowed");
|
"Invalid socket, only SOCK_STREAM is allowed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send sockaddr struct
|
// Send sockaddr struct
|
||||||
if (!comms_.SendBytes(reinterpret_cast<const uint8_t*>(addr), addrlen)) {
|
if (!comms_.SendBytes(reinterpret_cast<const uint8_t*>(addr), addrlen)) {
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
return sapi::InternalError("Sending data to network proxy failed");
|
return absl::InternalError("Sending data to network proxy failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
SAPI_RETURN_IF_ERROR(ReceiveRemoteResult());
|
SAPI_RETURN_IF_ERROR(ReceiveRemoteResult());
|
||||||
@ -93,27 +93,27 @@ sapi::Status NetworkProxyClient::Connect(int sockfd,
|
|||||||
int s;
|
int s;
|
||||||
if (!comms_.RecvFD(&s)) {
|
if (!comms_.RecvFD(&s)) {
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
return sapi::InternalError("Receiving data from network proxy failed");
|
return absl::InternalError("Receiving data from network proxy failed");
|
||||||
}
|
}
|
||||||
if (dup2(s, sockfd) == -1) {
|
if (dup2(s, sockfd) == -1) {
|
||||||
close(s);
|
close(s);
|
||||||
return sapi::InternalError("Processing data from network proxy failed");
|
return absl::InternalError("Processing data from network proxy failed");
|
||||||
}
|
}
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status NetworkProxyClient::ReceiveRemoteResult() {
|
absl::Status NetworkProxyClient::ReceiveRemoteResult() {
|
||||||
int result;
|
int result;
|
||||||
if (!comms_.RecvInt32(&result)) {
|
if (!comms_.RecvInt32(&result)) {
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
return sapi::InternalError("Receiving data from the network proxy failed");
|
return absl::InternalError("Receiving data from the network proxy failed");
|
||||||
}
|
}
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
errno = result;
|
errno = result;
|
||||||
return sapi::InternalError(
|
return absl::InternalError(
|
||||||
absl::StrCat("Error in network proxy server: ", StrError(errno)));
|
absl::StrCat("Error in network proxy server: ", StrError(errno)));
|
||||||
}
|
}
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -126,14 +126,14 @@ void SignalHandler(int nr, siginfo_t* info, void* void_context) {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
sapi::Status NetworkProxyHandler::InstallNetworkProxyHandler(
|
absl::Status NetworkProxyHandler::InstallNetworkProxyHandler(
|
||||||
NetworkProxyClient* npc) {
|
NetworkProxyClient* npc) {
|
||||||
if (g_network_proxy_handler) {
|
if (g_network_proxy_handler) {
|
||||||
return sapi::AlreadyExistsError(
|
return absl::AlreadyExistsError(
|
||||||
"Network proxy handler is already installed");
|
"Network proxy handler is already installed");
|
||||||
}
|
}
|
||||||
g_network_proxy_handler = new NetworkProxyHandler(npc);
|
g_network_proxy_handler = new NetworkProxyHandler(npc);
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkProxyHandler::InvokeOldAct(int nr, siginfo_t* info,
|
void NetworkProxyHandler::InvokeOldAct(int nr, siginfo_t* info,
|
||||||
@ -192,7 +192,7 @@ void NetworkProxyHandler::ProcessSeccompTrap(int nr, siginfo_t* info,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status result = network_proxy_client_->Connect(sockfd, addr, addrlen);
|
absl::Status result = network_proxy_client_->Connect(sockfd, addr, addrlen);
|
||||||
if (result.ok()) {
|
if (result.ok()) {
|
||||||
registers[kRegResult] = 0;
|
registers[kRegResult] = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -36,7 +36,7 @@ class NetworkProxyClient {
|
|||||||
// Semantic is similar to a regular connect() call.
|
// Semantic is similar to a regular connect() call.
|
||||||
// Arguments are sent to network proxy server, which sends back a connected
|
// Arguments are sent to network proxy server, which sends back a connected
|
||||||
// socket.
|
// socket.
|
||||||
sapi::Status Connect(int sockfd, const struct sockaddr* addr,
|
absl::Status Connect(int sockfd, const struct sockaddr* addr,
|
||||||
socklen_t addrlen);
|
socklen_t addrlen);
|
||||||
// Same as Connect, but with same API as regular connect() call.
|
// Same as Connect, but with same API as regular connect() call.
|
||||||
int ConnectHandler(int sockfd, const struct sockaddr* addr,
|
int ConnectHandler(int sockfd, const struct sockaddr* addr,
|
||||||
@ -44,7 +44,7 @@ class NetworkProxyClient {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Comms comms_;
|
Comms comms_;
|
||||||
sapi::Status ReceiveRemoteResult();
|
absl::Status ReceiveRemoteResult();
|
||||||
|
|
||||||
// Needed to make the Proxy thread safe.
|
// Needed to make the Proxy thread safe.
|
||||||
absl::Mutex mutex_;
|
absl::Mutex mutex_;
|
||||||
@ -56,7 +56,7 @@ class NetworkProxyHandler {
|
|||||||
// function. This function exchange data with NetworkProxyServer that checks
|
// function. This function exchange data with NetworkProxyServer that checks
|
||||||
// if this connection is allowed and sends the connected socket to us.
|
// if this connection is allowed and sends the connected socket to us.
|
||||||
// In other words, this function just use NetworkProxyClient class.
|
// In other words, this function just use NetworkProxyClient class.
|
||||||
static sapi::Status InstallNetworkProxyHandler(NetworkProxyClient* npc);
|
static absl::Status InstallNetworkProxyHandler(NetworkProxyClient* npc);
|
||||||
void ProcessSeccompTrap(int nr, siginfo_t* info, void* void_context);
|
void ProcessSeccompTrap(int nr, siginfo_t* info, void* void_context);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -31,7 +31,7 @@ static sapi::StatusOr<std::string> Addr6ToString(
|
|||||||
char addr[INET6_ADDRSTRLEN];
|
char addr[INET6_ADDRSTRLEN];
|
||||||
int port = htons(saddr->sin6_port);
|
int port = htons(saddr->sin6_port);
|
||||||
if (!inet_ntop(AF_INET6, &saddr->sin6_addr, addr, sizeof addr)) {
|
if (!inet_ntop(AF_INET6, &saddr->sin6_addr, addr, sizeof addr)) {
|
||||||
return sapi::InternalError(
|
return absl::InternalError(
|
||||||
"Error in converting sockaddr_in6 addres to string");
|
"Error in converting sockaddr_in6 addres to string");
|
||||||
}
|
}
|
||||||
return absl::StrCat("IP: ", addr, ", port: ", port);
|
return absl::StrCat("IP: ", addr, ", port: ", port);
|
||||||
@ -43,7 +43,7 @@ static sapi::StatusOr<std::string> Addr4ToString(
|
|||||||
char addr[INET_ADDRSTRLEN];
|
char addr[INET_ADDRSTRLEN];
|
||||||
int port = htons(saddr->sin_port);
|
int port = htons(saddr->sin_port);
|
||||||
if (!inet_ntop(AF_INET, &saddr->sin_addr, addr, sizeof addr)) {
|
if (!inet_ntop(AF_INET, &saddr->sin_addr, addr, sizeof addr)) {
|
||||||
return sapi::InternalError(
|
return absl::InternalError(
|
||||||
"Error in converting sockaddr_in addres to string");
|
"Error in converting sockaddr_in addres to string");
|
||||||
}
|
}
|
||||||
return absl::StrCat("IP: ", addr, ", port: ", port);
|
return absl::StrCat("IP: ", addr, ", port: ", port);
|
||||||
@ -57,33 +57,33 @@ sapi::StatusOr<std::string> AddrToString(const struct sockaddr* saddr) {
|
|||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
return Addr6ToString(reinterpret_cast<const struct sockaddr_in6*>(saddr));
|
return Addr6ToString(reinterpret_cast<const struct sockaddr_in6*>(saddr));
|
||||||
default:
|
default:
|
||||||
return sapi::InternalError(
|
return absl::InternalError(
|
||||||
absl::StrCat("Unexpected sa_family value: ", saddr->sa_family));
|
absl::StrCat("Unexpected sa_family value: ", saddr->sa_family));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static sapi::Status IPStringToAddr(const std::string& ip, int address_family,
|
static absl::Status IPStringToAddr(const std::string& ip, int address_family,
|
||||||
void* addr) {
|
void* addr) {
|
||||||
int err = inet_pton(address_family, ip.c_str(), addr);
|
int err = inet_pton(address_family, ip.c_str(), addr);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
return sapi::InvalidArgumentError(absl::StrCat("Invalid address: ", ip));
|
return absl::InvalidArgumentError(absl::StrCat("Invalid address: ", ip));
|
||||||
}
|
}
|
||||||
if (err == -1) {
|
if (err == -1) {
|
||||||
return sapi::InternalError(
|
return absl::InternalError(
|
||||||
absl::StrCat("inet_pton() failed for ", ip, ": ", StrError(errno)));
|
absl::StrCat("inet_pton() failed for ", ip, ": ", StrError(errno)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parses a string of type IP or IP/mask or IP/cidr and saves appropriate
|
// Parses a string of type IP or IP/mask or IP/cidr and saves appropriate
|
||||||
// values in output arguments.
|
// values in output arguments.
|
||||||
static sapi::Status ParseIpAndMask(const std::string& ip_and_mask,
|
static absl::Status ParseIpAndMask(const std::string& ip_and_mask,
|
||||||
std::string* ip, std::string* mask,
|
std::string* ip, std::string* mask,
|
||||||
uint32_t* cidr) {
|
uint32_t* cidr) {
|
||||||
// mask is checked later because only IPv4 format supports mask
|
// mask is checked later because only IPv4 format supports mask
|
||||||
if (ip == nullptr || cidr == nullptr) {
|
if (ip == nullptr || cidr == nullptr) {
|
||||||
return sapi::InvalidArgumentError(
|
return absl::InvalidArgumentError(
|
||||||
"ip and cidr arguments of ParseIpAndMask cannot be nullptr");
|
"ip and cidr arguments of ParseIpAndMask cannot be nullptr");
|
||||||
}
|
}
|
||||||
*cidr = 0;
|
*cidr = 0;
|
||||||
@ -93,7 +93,7 @@ static sapi::Status ParseIpAndMask(const std::string& ip_and_mask,
|
|||||||
|
|
||||||
*ip = ip_and_mask_split[0];
|
*ip = ip_and_mask_split[0];
|
||||||
if (ip_and_mask_split.size() == 1) {
|
if (ip_and_mask_split.size() == 1) {
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
std::string mask_or_cidr = ip_and_mask_split[1];
|
std::string mask_or_cidr = ip_and_mask_split[1];
|
||||||
|
|
||||||
@ -101,22 +101,22 @@ static sapi::Status ParseIpAndMask(const std::string& ip_and_mask,
|
|||||||
if (has_dot) { // mask_or_cidr is cidr
|
if (has_dot) { // mask_or_cidr is cidr
|
||||||
bool res = absl::SimpleAtoi<uint32_t>(mask_or_cidr, cidr);
|
bool res = absl::SimpleAtoi<uint32_t>(mask_or_cidr, cidr);
|
||||||
if (!res || !*cidr) {
|
if (!res || !*cidr) {
|
||||||
return sapi::InvalidArgumentError(
|
return absl::InvalidArgumentError(
|
||||||
absl::StrCat(mask_or_cidr, " is not a correct cidr"));
|
absl::StrCat(mask_or_cidr, " is not a correct cidr"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (mask == nullptr) {
|
if (mask == nullptr) {
|
||||||
return sapi::InvalidArgumentError(
|
return absl::InvalidArgumentError(
|
||||||
"mask argument of ParseIpAndMask cannot be NULL in this case");
|
"mask argument of ParseIpAndMask cannot be NULL in this case");
|
||||||
}
|
}
|
||||||
*mask = std::string(mask_or_cidr);
|
*mask = std::string(mask_or_cidr);
|
||||||
}
|
}
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
static sapi::Status CidrToIn6Addr(uint32_t cidr, in6_addr* addr) {
|
static absl::Status CidrToIn6Addr(uint32_t cidr, in6_addr* addr) {
|
||||||
if (cidr > 128) {
|
if (cidr > 128) {
|
||||||
return sapi::InvalidArgumentError(
|
return absl::InvalidArgumentError(
|
||||||
absl::StrCat(cidr, " is not a correct cidr"));
|
absl::StrCat(cidr, " is not a correct cidr"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,12 +135,12 @@ static sapi::Status CidrToIn6Addr(uint32_t cidr, in6_addr* addr) {
|
|||||||
}
|
}
|
||||||
addr->s6_addr[i] = tmp;
|
addr->s6_addr[i] = tmp;
|
||||||
}
|
}
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
static sapi::Status CidrToInAddr(uint32_t cidr, in_addr* addr) {
|
static absl::Status CidrToInAddr(uint32_t cidr, in_addr* addr) {
|
||||||
if (cidr > 32) {
|
if (cidr > 32) {
|
||||||
return sapi::InvalidArgumentError(
|
return absl::InvalidArgumentError(
|
||||||
absl::StrCat(cidr, " is not a correct cidr"));
|
absl::StrCat(cidr, " is not a correct cidr"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +152,7 @@ static sapi::Status CidrToInAddr(uint32_t cidr, in_addr* addr) {
|
|||||||
tmp |= 0x80000000;
|
tmp |= 0x80000000;
|
||||||
}
|
}
|
||||||
addr->s_addr = htonl(tmp);
|
addr->s_addr = htonl(tmp);
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsIPv4MaskCorrect(in_addr_t m) {
|
static bool IsIPv4MaskCorrect(in_addr_t m) {
|
||||||
@ -164,26 +164,26 @@ static bool IsIPv4MaskCorrect(in_addr_t m) {
|
|||||||
return !(m & (m - 1));
|
return !(m & (m - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status AllowedHosts::AllowIPv4(const std::string& ip_and_mask,
|
absl::Status AllowedHosts::AllowIPv4(const std::string& ip_and_mask,
|
||||||
uint32_t port) {
|
uint32_t port) {
|
||||||
std::string ip, mask;
|
std::string ip, mask;
|
||||||
uint32_t cidr;
|
uint32_t cidr;
|
||||||
SAPI_RETURN_IF_ERROR(ParseIpAndMask(ip_and_mask, &ip, &mask, &cidr));
|
SAPI_RETURN_IF_ERROR(ParseIpAndMask(ip_and_mask, &ip, &mask, &cidr));
|
||||||
SAPI_RETURN_IF_ERROR(AllowIPv4(ip, mask, cidr, port));
|
SAPI_RETURN_IF_ERROR(AllowIPv4(ip, mask, cidr, port));
|
||||||
|
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status AllowedHosts::AllowIPv6(const std::string& ip_and_mask,
|
absl::Status AllowedHosts::AllowIPv6(const std::string& ip_and_mask,
|
||||||
uint32_t port) {
|
uint32_t port) {
|
||||||
std::string ip;
|
std::string ip;
|
||||||
uint32_t cidr;
|
uint32_t cidr;
|
||||||
SAPI_RETURN_IF_ERROR(ParseIpAndMask(ip_and_mask, &ip, NULL, &cidr));
|
SAPI_RETURN_IF_ERROR(ParseIpAndMask(ip_and_mask, &ip, NULL, &cidr));
|
||||||
SAPI_RETURN_IF_ERROR(AllowIPv6(ip, cidr, port));
|
SAPI_RETURN_IF_ERROR(AllowIPv6(ip, cidr, port));
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status AllowedHosts::AllowIPv4(const std::string& ip,
|
absl::Status AllowedHosts::AllowIPv4(const std::string& ip,
|
||||||
const std::string& mask, uint32_t cidr,
|
const std::string& mask, uint32_t cidr,
|
||||||
uint32_t port) {
|
uint32_t port) {
|
||||||
in_addr addr{};
|
in_addr addr{};
|
||||||
@ -193,13 +193,13 @@ sapi::Status AllowedHosts::AllowIPv4(const std::string& ip,
|
|||||||
SAPI_RETURN_IF_ERROR(IPStringToAddr(mask, AF_INET, &m));
|
SAPI_RETURN_IF_ERROR(IPStringToAddr(mask, AF_INET, &m));
|
||||||
|
|
||||||
if (!IsIPv4MaskCorrect(m.s_addr)) {
|
if (!IsIPv4MaskCorrect(m.s_addr)) {
|
||||||
return sapi::InvalidArgumentError(
|
return absl::InvalidArgumentError(
|
||||||
absl::StrCat(mask, " is not a correct mask"));
|
absl::StrCat(mask, " is not a correct mask"));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (cidr > 32) {
|
if (cidr > 32) {
|
||||||
return sapi::InvalidArgumentError(
|
return absl::InvalidArgumentError(
|
||||||
absl::StrCat(cidr, " is not a correct cidr"));
|
absl::StrCat(cidr, " is not a correct cidr"));
|
||||||
}
|
}
|
||||||
if (!cidr) {
|
if (!cidr) {
|
||||||
@ -212,10 +212,10 @@ sapi::Status AllowedHosts::AllowIPv4(const std::string& ip,
|
|||||||
SAPI_RETURN_IF_ERROR(IPStringToAddr(ip, AF_INET, &addr));
|
SAPI_RETURN_IF_ERROR(IPStringToAddr(ip, AF_INET, &addr));
|
||||||
allowed_IPv4_.emplace_back(addr.s_addr, m.s_addr, htons(port));
|
allowed_IPv4_.emplace_back(addr.s_addr, m.s_addr, htons(port));
|
||||||
|
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status AllowedHosts::AllowIPv6(const std::string& ip, uint32_t cidr,
|
absl::Status AllowedHosts::AllowIPv6(const std::string& ip, uint32_t cidr,
|
||||||
uint32_t port) {
|
uint32_t port) {
|
||||||
if (cidr == 0) {
|
if (cidr == 0) {
|
||||||
cidr = 128;
|
cidr = 128;
|
||||||
@ -228,7 +228,7 @@ sapi::Status AllowedHosts::AllowIPv6(const std::string& ip, uint32_t cidr,
|
|||||||
SAPI_RETURN_IF_ERROR(CidrToIn6Addr(cidr, &m));
|
SAPI_RETURN_IF_ERROR(CidrToIn6Addr(cidr, &m));
|
||||||
|
|
||||||
allowed_IPv6_.emplace_back(addr, m, htons(port));
|
allowed_IPv6_.emplace_back(addr, m, htons(port));
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AllowedHosts::IsHostAllowed(const struct sockaddr* saddr) const {
|
bool AllowedHosts::IsHostAllowed(const struct sockaddr* saddr) const {
|
||||||
|
@ -49,16 +49,16 @@ struct IPv6 {
|
|||||||
class AllowedHosts {
|
class AllowedHosts {
|
||||||
public:
|
public:
|
||||||
// ip_and_mask should have one of following formats: IP, IP/mask, IP/cidr.
|
// ip_and_mask should have one of following formats: IP, IP/mask, IP/cidr.
|
||||||
sapi::Status AllowIPv4(const std::string& ip_and_mask, uint32_t port = 0);
|
absl::Status AllowIPv4(const std::string& ip_and_mask, uint32_t port = 0);
|
||||||
// ip_and_mask should have following format: IP or IP/cidr.
|
// ip_and_mask should have following format: IP or IP/cidr.
|
||||||
sapi::Status AllowIPv6(const std::string& ip_and_mask, uint32_t port = 0);
|
absl::Status AllowIPv6(const std::string& ip_and_mask, uint32_t port = 0);
|
||||||
// Checks if this host is allowed.
|
// Checks if this host is allowed.
|
||||||
bool IsHostAllowed(const struct sockaddr* saddr) const;
|
bool IsHostAllowed(const struct sockaddr* saddr) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sapi::Status AllowIPv4(const std::string& ip, const std::string& mask,
|
absl::Status AllowIPv4(const std::string& ip, const std::string& mask,
|
||||||
uint32_t cidr, uint32_t port);
|
uint32_t cidr, uint32_t port);
|
||||||
sapi::Status AllowIPv6(const std::string& ip, uint32_t cidr, uint32_t port);
|
absl::Status AllowIPv6(const std::string& ip, uint32_t cidr, uint32_t port);
|
||||||
bool IsIPv4Allowed(const struct sockaddr_in* saddr) const;
|
bool IsIPv4Allowed(const struct sockaddr_in* saddr) const;
|
||||||
bool IsIPv6Allowed(const struct sockaddr_in6* saddr) const;
|
bool IsIPv6Allowed(const struct sockaddr_in6* saddr) const;
|
||||||
|
|
||||||
|
@ -637,7 +637,7 @@ PolicyBuilder& PolicyBuilder::DangerDefaultAllowAll() {
|
|||||||
sapi::StatusOr<std::string> PolicyBuilder::ValidateAbsolutePath(
|
sapi::StatusOr<std::string> PolicyBuilder::ValidateAbsolutePath(
|
||||||
absl::string_view path) {
|
absl::string_view path) {
|
||||||
if (!file::IsAbsolutePath(path)) {
|
if (!file::IsAbsolutePath(path)) {
|
||||||
return sapi::InvalidArgumentError(
|
return absl::InvalidArgumentError(
|
||||||
absl::StrCat("Path is not absolute: '", path, "'"));
|
absl::StrCat("Path is not absolute: '", path, "'"));
|
||||||
}
|
}
|
||||||
return ValidatePath(path);
|
return ValidatePath(path);
|
||||||
@ -647,7 +647,7 @@ sapi::StatusOr<std::string> PolicyBuilder::ValidatePath(
|
|||||||
absl::string_view path) {
|
absl::string_view path) {
|
||||||
std::string fixed_path = file::CleanPath(path);
|
std::string fixed_path = file::CleanPath(path);
|
||||||
if (fixed_path != path) {
|
if (fixed_path != path) {
|
||||||
return sapi::InvalidArgumentError(absl::StrCat(
|
return absl::InvalidArgumentError(absl::StrCat(
|
||||||
"Path was not normalized. '", path, "' != '", fixed_path, "'"));
|
"Path was not normalized. '", path, "' != '", fixed_path, "'"));
|
||||||
}
|
}
|
||||||
return fixed_path;
|
return fixed_path;
|
||||||
@ -658,7 +658,7 @@ std::vector<sock_filter> PolicyBuilder::ResolveBpfFunc(BpfFunc f) {
|
|||||||
|
|
||||||
std::vector<sock_filter> policy = f(l);
|
std::vector<sock_filter> policy = f(l);
|
||||||
if (bpf_resolve_jumps(&l, policy.data(), policy.size()) != 0) {
|
if (bpf_resolve_jumps(&l, policy.data(), policy.size()) != 0) {
|
||||||
SetError(sapi::InternalError("Cannot resolve bpf jumps"));
|
SetError(absl::InternalError("Cannot resolve bpf jumps"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return policy;
|
return policy;
|
||||||
@ -672,12 +672,12 @@ sapi::StatusOr<std::unique_ptr<Policy>> PolicyBuilder::TryBuild() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (already_built_) {
|
if (already_built_) {
|
||||||
return sapi::FailedPreconditionError("Can only build policy once.");
|
return absl::FailedPreconditionError("Can only build policy once.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_namespaces_) {
|
if (use_namespaces_) {
|
||||||
if (allow_unrestricted_networking_ && hostname_ != kDefaultHostname) {
|
if (allow_unrestricted_networking_ && hostname_ != kDefaultHostname) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
"Cannot set hostname without network namespaces.");
|
"Cannot set hostname without network namespaces.");
|
||||||
}
|
}
|
||||||
output->SetNamespace(absl::make_unique<Namespace>(
|
output->SetNamespace(absl::make_unique<Namespace>(
|
||||||
@ -708,7 +708,7 @@ PolicyBuilder& PolicyBuilder::AddFile(absl::string_view path, bool is_ro) {
|
|||||||
return AddFileAt(path, path, is_ro);
|
return AddFileAt(path, path, is_ro);
|
||||||
}
|
}
|
||||||
|
|
||||||
PolicyBuilder& PolicyBuilder::SetError(const sapi::Status& status) {
|
PolicyBuilder& PolicyBuilder::SetError(const absl::Status& status) {
|
||||||
LOG(ERROR) << status;
|
LOG(ERROR) << status;
|
||||||
last_status_ = status;
|
last_status_ = status;
|
||||||
return *this;
|
return *this;
|
||||||
@ -726,7 +726,7 @@ PolicyBuilder& PolicyBuilder::AddFileAt(absl::string_view outside,
|
|||||||
auto fixed_outside = std::move(fixed_outside_or.ValueOrDie());
|
auto fixed_outside = std::move(fixed_outside_or.ValueOrDie());
|
||||||
|
|
||||||
if (absl::StartsWith(fixed_outside, "/proc/self")) {
|
if (absl::StartsWith(fixed_outside, "/proc/self")) {
|
||||||
SetError(sapi::InvalidArgumentError(
|
SetError(absl::InvalidArgumentError(
|
||||||
absl::StrCat("Cannot add /proc/self mounts, you need to mount the "
|
absl::StrCat("Cannot add /proc/self mounts, you need to mount the "
|
||||||
"whole /proc instead. You tried to mount ",
|
"whole /proc instead. You tried to mount ",
|
||||||
outside)));
|
outside)));
|
||||||
@ -736,7 +736,7 @@ PolicyBuilder& PolicyBuilder::AddFileAt(absl::string_view outside,
|
|||||||
auto status = mounts_.AddFileAt(fixed_outside, inside, is_ro);
|
auto status = mounts_.AddFileAt(fixed_outside, inside, is_ro);
|
||||||
if (!status.ok()) {
|
if (!status.ok()) {
|
||||||
SetError(
|
SetError(
|
||||||
sapi::InternalError(absl::StrCat("Could not add file ", outside, " => ",
|
absl::InternalError(absl::StrCat("Could not add file ", outside, " => ",
|
||||||
inside, ": ", status.message())));
|
inside, ": ", status.message())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -756,7 +756,7 @@ PolicyBuilder& PolicyBuilder::AddLibrariesForBinary(
|
|||||||
|
|
||||||
auto status = mounts_.AddMappingsForBinary(fixed_path, ld_library_path);
|
auto status = mounts_.AddMappingsForBinary(fixed_path, ld_library_path);
|
||||||
if (!status.ok()) {
|
if (!status.ok()) {
|
||||||
SetError(sapi::InternalError(absl::StrCat(
|
SetError(absl::InternalError(absl::StrCat(
|
||||||
"Could not add libraries for ", fixed_path, ": ", status.message())));
|
"Could not add libraries for ", fixed_path, ": ", status.message())));
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
@ -784,7 +784,7 @@ PolicyBuilder& PolicyBuilder::AddDirectoryAt(absl::string_view outside,
|
|||||||
}
|
}
|
||||||
auto fixed_outside = std::move(fixed_outside_or.ValueOrDie());
|
auto fixed_outside = std::move(fixed_outside_or.ValueOrDie());
|
||||||
if (absl::StartsWith(fixed_outside, "/proc/self")) {
|
if (absl::StartsWith(fixed_outside, "/proc/self")) {
|
||||||
SetError(sapi::InvalidArgumentError(
|
SetError(absl::InvalidArgumentError(
|
||||||
absl::StrCat("Cannot add /proc/self mounts, you need to mount the "
|
absl::StrCat("Cannot add /proc/self mounts, you need to mount the "
|
||||||
"whole /proc instead. You tried to mount ",
|
"whole /proc instead. You tried to mount ",
|
||||||
outside)));
|
outside)));
|
||||||
@ -793,7 +793,7 @@ PolicyBuilder& PolicyBuilder::AddDirectoryAt(absl::string_view outside,
|
|||||||
|
|
||||||
auto status = mounts_.AddDirectoryAt(fixed_outside, inside, is_ro);
|
auto status = mounts_.AddDirectoryAt(fixed_outside, inside, is_ro);
|
||||||
if (!status.ok()) {
|
if (!status.ok()) {
|
||||||
SetError(sapi::InternalError(absl::StrCat("Could not add directory ",
|
SetError(absl::InternalError(absl::StrCat("Could not add directory ",
|
||||||
outside, " => ", inside, ": ",
|
outside, " => ", inside, ": ",
|
||||||
status.message())));
|
status.message())));
|
||||||
}
|
}
|
||||||
@ -806,7 +806,7 @@ PolicyBuilder& PolicyBuilder::AddTmpfs(absl::string_view inside, size_t sz) {
|
|||||||
|
|
||||||
auto status = mounts_.AddTmpfs(inside, sz);
|
auto status = mounts_.AddTmpfs(inside, sz);
|
||||||
if (!status.ok()) {
|
if (!status.ok()) {
|
||||||
SetError(sapi::InternalError(absl::StrCat("Could not mount tmpfs ", inside,
|
SetError(absl::InternalError(absl::StrCat("Could not mount tmpfs ", inside,
|
||||||
": ", status.message())));
|
": ", status.message())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -849,7 +849,7 @@ PolicyBuilder& PolicyBuilder::CollectStacktracesOnKill(bool enable) {
|
|||||||
|
|
||||||
PolicyBuilder& PolicyBuilder::AddNetworkProxyPolicy() {
|
PolicyBuilder& PolicyBuilder::AddNetworkProxyPolicy() {
|
||||||
if (allowed_hosts_) {
|
if (allowed_hosts_) {
|
||||||
SetError(sapi::FailedPreconditionError(
|
SetError(absl::FailedPreconditionError(
|
||||||
"AddNetworkProxyPolicy or AddNetworkProxyHandlerPolicy can be called "
|
"AddNetworkProxyPolicy or AddNetworkProxyHandlerPolicy can be called "
|
||||||
"at most once"));
|
"at most once"));
|
||||||
return *this;
|
return *this;
|
||||||
@ -932,13 +932,13 @@ void PolicyBuilder::StoreDescription(PolicyBuilderDescription* pb_description) {
|
|||||||
PolicyBuilder& PolicyBuilder::AllowIPv4(const std::string& ip_and_mask,
|
PolicyBuilder& PolicyBuilder::AllowIPv4(const std::string& ip_and_mask,
|
||||||
uint32_t port) {
|
uint32_t port) {
|
||||||
if (!allowed_hosts_) {
|
if (!allowed_hosts_) {
|
||||||
SetError(sapi::FailedPreconditionError(
|
SetError(absl::FailedPreconditionError(
|
||||||
"AddNetworkProxyPolicy or AddNetworkProxyHandlerPolicy must be called "
|
"AddNetworkProxyPolicy or AddNetworkProxyHandlerPolicy must be called "
|
||||||
"before adding IP rules"));
|
"before adding IP rules"));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status status = allowed_hosts_->AllowIPv4(ip_and_mask, port);
|
absl::Status status = allowed_hosts_->AllowIPv4(ip_and_mask, port);
|
||||||
if (!status.ok()) {
|
if (!status.ok()) {
|
||||||
SetError(status);
|
SetError(status);
|
||||||
}
|
}
|
||||||
@ -948,13 +948,13 @@ PolicyBuilder& PolicyBuilder::AllowIPv4(const std::string& ip_and_mask,
|
|||||||
PolicyBuilder& PolicyBuilder::AllowIPv6(const std::string& ip_and_mask,
|
PolicyBuilder& PolicyBuilder::AllowIPv6(const std::string& ip_and_mask,
|
||||||
uint32_t port) {
|
uint32_t port) {
|
||||||
if (!allowed_hosts_) {
|
if (!allowed_hosts_) {
|
||||||
SetError(sapi::FailedPreconditionError(
|
SetError(absl::FailedPreconditionError(
|
||||||
"AddNetworkProxyPolicy or AddNetworkProxyHandlerPolicy must be called "
|
"AddNetworkProxyPolicy or AddNetworkProxyHandlerPolicy must be called "
|
||||||
"before adding IP rules"));
|
"before adding IP rules"));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status status = allowed_hosts_->AllowIPv6(ip_and_mask, port);
|
absl::Status status = allowed_hosts_->AllowIPv6(ip_and_mask, port);
|
||||||
if (!status.ok()) {
|
if (!status.ok()) {
|
||||||
SetError(status);
|
SetError(status);
|
||||||
}
|
}
|
||||||
|
@ -542,11 +542,11 @@ class PolicyBuilder final {
|
|||||||
std::set<unsigned int> handled_syscalls_;
|
std::set<unsigned int> handled_syscalls_;
|
||||||
|
|
||||||
// Error handling
|
// Error handling
|
||||||
sapi::Status last_status_;
|
absl::Status last_status_;
|
||||||
bool already_built_ = false;
|
bool already_built_ = false;
|
||||||
// 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 absl::Status& status);
|
||||||
|
|
||||||
// Contains list of allowed hosts.
|
// Contains list of allowed hosts.
|
||||||
absl::optional<AllowedHosts> allowed_hosts_;
|
absl::optional<AllowedHosts> allowed_hosts_;
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
#include "sandboxed_api/sandbox2/testing.h"
|
#include "sandboxed_api/sandbox2/testing.h"
|
||||||
#include "sandboxed_api/sandbox2/util/bpf_helper.h"
|
#include "sandboxed_api/sandbox2/util/bpf_helper.h"
|
||||||
#include "sandboxed_api/util/status_matchers.h"
|
#include "sandboxed_api/util/status_matchers.h"
|
||||||
#include "sandboxed_api/util/status.h"
|
#include "absl/status/status.h"
|
||||||
|
|
||||||
using ::testing::AllOf;
|
using ::testing::AllOf;
|
||||||
using ::testing::AnyOf;
|
using ::testing::AnyOf;
|
||||||
@ -143,7 +143,7 @@ TEST_F(PolicyBuilderTest, TestValidateAbsolutePath) {
|
|||||||
"/a/bAAAAAAAAAAAAAAAAAAAAAA/c/d/",
|
"/a/bAAAAAAAAAAAAAAAAAAAAAA/c/d/",
|
||||||
}) {
|
}) {
|
||||||
auto path_or = PolicyBuilderPeer::ValidateAbsolutePath(bad_path);
|
auto path_or = PolicyBuilderPeer::ValidateAbsolutePath(bad_path);
|
||||||
EXPECT_THAT(path_or.status(), StatusIs(sapi::StatusCode::kInvalidArgument));
|
EXPECT_THAT(path_or.status(), StatusIs(absl::StatusCode::kInvalidArgument));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto const& good_path :
|
for (auto const& good_path :
|
||||||
|
@ -28,47 +28,47 @@
|
|||||||
|
|
||||||
namespace sandbox2 {
|
namespace sandbox2 {
|
||||||
|
|
||||||
sapi::Status Regs::Fetch() {
|
absl::Status Regs::Fetch() {
|
||||||
#if defined(__powerpc64__)
|
#if defined(__powerpc64__)
|
||||||
iovec pt_iov = {&user_regs_, sizeof(user_regs_)};
|
iovec pt_iov = {&user_regs_, sizeof(user_regs_)};
|
||||||
|
|
||||||
if (ptrace(PTRACE_GETREGSET, pid_, NT_PRSTATUS, &pt_iov) == -1L) {
|
if (ptrace(PTRACE_GETREGSET, pid_, NT_PRSTATUS, &pt_iov) == -1L) {
|
||||||
return sapi::InternalError(absl::StrCat(
|
return absl::InternalError(absl::StrCat(
|
||||||
"ptrace(PTRACE_GETREGSET, pid=", pid_, ") failed: ", StrError(errno)));
|
"ptrace(PTRACE_GETREGSET, pid=", pid_, ") failed: ", StrError(errno)));
|
||||||
}
|
}
|
||||||
if (pt_iov.iov_len != sizeof(user_regs_)) {
|
if (pt_iov.iov_len != sizeof(user_regs_)) {
|
||||||
return sapi::InternalError(absl::StrCat(
|
return absl::InternalError(absl::StrCat(
|
||||||
"ptrace(PTRACE_GETREGSET, pid=", pid_,
|
"ptrace(PTRACE_GETREGSET, pid=", pid_,
|
||||||
") size returned: ", pt_iov.iov_len,
|
") size returned: ", pt_iov.iov_len,
|
||||||
" different than sizeof(user_regs_): ", sizeof(user_regs_)));
|
" different than sizeof(user_regs_): ", sizeof(user_regs_)));
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (ptrace(PTRACE_GETREGS, pid_, 0, &user_regs_) == -1L) {
|
if (ptrace(PTRACE_GETREGS, pid_, 0, &user_regs_) == -1L) {
|
||||||
return sapi::InternalError(absl::StrCat("ptrace(PTRACE_GETREGS, pid=", pid_,
|
return absl::InternalError(absl::StrCat("ptrace(PTRACE_GETREGS, pid=", pid_,
|
||||||
") failed: ", StrError(errno)));
|
") failed: ", StrError(errno)));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Regs::Store() {
|
absl::Status Regs::Store() {
|
||||||
#if defined(__powerpc64__)
|
#if defined(__powerpc64__)
|
||||||
iovec pt_iov = {&user_regs_, sizeof(user_regs_)};
|
iovec pt_iov = {&user_regs_, sizeof(user_regs_)};
|
||||||
|
|
||||||
if (ptrace(PTRACE_SETREGSET, pid_, NT_PRSTATUS, &pt_iov) == -1L) {
|
if (ptrace(PTRACE_SETREGSET, pid_, NT_PRSTATUS, &pt_iov) == -1L) {
|
||||||
return sapi::InternalError(absl::StrCat(
|
return absl::InternalError(absl::StrCat(
|
||||||
"ptrace(PTRACE_SETREGSET, pid=", pid_, ") failed: ", StrError(errno)));
|
"ptrace(PTRACE_SETREGSET, pid=", pid_, ") failed: ", StrError(errno)));
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (ptrace(PTRACE_SETREGS, pid_, 0, &user_regs_) == -1) {
|
if (ptrace(PTRACE_SETREGS, pid_, 0, &user_regs_) == -1) {
|
||||||
return sapi::InternalError(absl::StrCat("ptrace(PTRACE_SETREGS, pid=", pid_,
|
return absl::InternalError(absl::StrCat("ptrace(PTRACE_SETREGS, pid=", pid_,
|
||||||
") failed: ", StrError(errno)));
|
") failed: ", StrError(errno)));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Regs::SkipSyscallReturnValue(uint64_t value) {
|
absl::Status Regs::SkipSyscallReturnValue(uint64_t value) {
|
||||||
#if defined(__x86_64__)
|
#if defined(__x86_64__)
|
||||||
user_regs_.orig_rax = -1;
|
user_regs_.orig_rax = -1;
|
||||||
user_regs_.rax = value;
|
user_regs_.rax = value;
|
||||||
|
@ -23,9 +23,9 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "absl/status/status.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"
|
||||||
#include "sandboxed_api/util/status.h"
|
|
||||||
|
|
||||||
namespace sandbox2 {
|
namespace sandbox2 {
|
||||||
|
|
||||||
@ -40,13 +40,13 @@ class Regs {
|
|||||||
explicit Regs(pid_t pid) : pid_(pid) {}
|
explicit Regs(pid_t pid) : pid_(pid) {}
|
||||||
|
|
||||||
// Copies register values from the process
|
// Copies register values from the process
|
||||||
sapi::Status Fetch();
|
absl::Status Fetch();
|
||||||
|
|
||||||
// Copies register values to the process
|
// Copies register values to the process
|
||||||
sapi::Status Store();
|
absl::Status Store();
|
||||||
|
|
||||||
// Causes the process to skip current syscall and return given value instead
|
// Causes the process to skip current syscall and return given value instead
|
||||||
sapi::Status SkipSyscallReturnValue(uint64_t value);
|
absl::Status SkipSyscallReturnValue(uint64_t value);
|
||||||
|
|
||||||
// Converts raw register values obtained on syscall entry to syscall info
|
// Converts raw register values obtained on syscall entry to syscall info
|
||||||
Syscall ToSyscall(Syscall::CpuArch syscall_arch) const;
|
Syscall ToSyscall(Syscall::CpuArch syscall_arch) const;
|
||||||
|
@ -42,19 +42,19 @@ Result& Result::operator=(const Result& other) {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Result::ToStatus() const {
|
absl::Status Result::ToStatus() const {
|
||||||
switch (final_status()) {
|
switch (final_status()) {
|
||||||
case OK:
|
case OK:
|
||||||
if (reason_code() == 0) {
|
if (reason_code() == 0) {
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TIMEOUT:
|
case TIMEOUT:
|
||||||
return sapi::DeadlineExceededError(ToString());
|
return absl::DeadlineExceededError(ToString());
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return sapi::InternalError(ToString());
|
return absl::InternalError(ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Result::ToString() const {
|
std::string Result::ToString() const {
|
||||||
|
@ -27,9 +27,9 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "absl/memory/memory.h"
|
#include "absl/memory/memory.h"
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "sandboxed_api/sandbox2/regs.h"
|
#include "sandboxed_api/sandbox2/regs.h"
|
||||||
#include "sandboxed_api/sandbox2/syscall.h"
|
#include "sandboxed_api/sandbox2/syscall.h"
|
||||||
#include "sandboxed_api/util/status.h"
|
|
||||||
|
|
||||||
namespace sandbox2 {
|
namespace sandbox2 {
|
||||||
|
|
||||||
@ -151,9 +151,9 @@ class Result {
|
|||||||
|
|
||||||
void SetProcMaps(const std::string& proc_maps) { proc_maps_ = proc_maps; }
|
void SetProcMaps(const std::string& proc_maps) { proc_maps_ = proc_maps; }
|
||||||
|
|
||||||
// Converts this result to a sapi::Status object. The status will only be
|
// Converts this result to a absl::Status object. The status will only be
|
||||||
// OK if the sandbox process exited normally with an exit code of 0.
|
// OK if the sandbox process exited normally with an exit code of 0.
|
||||||
sapi::Status ToStatus() const;
|
absl::Status ToStatus() const;
|
||||||
|
|
||||||
// Returns a descriptive string for final result.
|
// Returns a descriptive string for final result.
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
|
@ -41,7 +41,7 @@ sapi::StatusOr<Result> Sandbox2::AwaitResultWithTimeout(
|
|||||||
auto done =
|
auto done =
|
||||||
monitor_->done_notification_.WaitForNotificationWithTimeout(timeout);
|
monitor_->done_notification_.WaitForNotificationWithTimeout(timeout);
|
||||||
if (!done) {
|
if (!done) {
|
||||||
return sapi::DeadlineExceededError("Sandbox did not finish within timeout");
|
return absl::DeadlineExceededError("Sandbox did not finish within timeout");
|
||||||
}
|
}
|
||||||
monitor_thread_->join();
|
monitor_thread_->join();
|
||||||
|
|
||||||
|
@ -186,7 +186,7 @@ sapi::StatusOr<int> Communicate(const std::vector<std::string>& argv,
|
|||||||
posix_spawn_file_actions_t action;
|
posix_spawn_file_actions_t action;
|
||||||
|
|
||||||
if (pipe(cout_pipe) == -1) {
|
if (pipe(cout_pipe) == -1) {
|
||||||
return sapi::UnknownError(absl::StrCat("creating pipe: ", StrError(errno)));
|
return absl::UnknownError(absl::StrCat("creating pipe: ", StrError(errno)));
|
||||||
}
|
}
|
||||||
file_util::fileops::FDCloser cout_closer{cout_pipe[1]};
|
file_util::fileops::FDCloser cout_closer{cout_pipe[1]};
|
||||||
|
|
||||||
@ -215,7 +215,7 @@ sapi::StatusOr<int> Communicate(const std::vector<std::string>& argv,
|
|||||||
|
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
if (posix_spawnp(&pid, args[0], &action, nullptr, args, envp) != 0) {
|
if (posix_spawnp(&pid, args[0], &action, nullptr, args, envp) != 0) {
|
||||||
return sapi::UnknownError(
|
return absl::UnknownError(
|
||||||
absl::StrCat("posix_spawnp() failed: ", StrError(errno)));
|
absl::StrCat("posix_spawnp() failed: ", StrError(errno)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,7 +227,7 @@ sapi::StatusOr<int> Communicate(const std::vector<std::string>& argv,
|
|||||||
int bytes_read =
|
int bytes_read =
|
||||||
TEMP_FAILURE_RETRY(read(cout_pipe[0], &buffer[0], buffer.length()));
|
TEMP_FAILURE_RETRY(read(cout_pipe[0], &buffer[0], buffer.length()));
|
||||||
if (bytes_read < 0) {
|
if (bytes_read < 0) {
|
||||||
return sapi::InternalError(
|
return absl::InternalError(
|
||||||
absl::StrCat("reading from cout pipe failed: ", StrError(errno)));
|
absl::StrCat("reading from cout pipe failed: ", StrError(errno)));
|
||||||
}
|
}
|
||||||
if (bytes_read == 0) {
|
if (bytes_read == 0) {
|
||||||
@ -302,7 +302,7 @@ sapi::StatusOr<std::string> ReadCPathFromPid(pid_t pid, uintptr_t ptr) {
|
|||||||
ssize_t sz = process_vm_readv(pid, local_iov, ABSL_ARRAYSIZE(local_iov),
|
ssize_t sz = process_vm_readv(pid, local_iov, ABSL_ARRAYSIZE(local_iov),
|
||||||
remote_iov, ABSL_ARRAYSIZE(remote_iov), 0);
|
remote_iov, ABSL_ARRAYSIZE(remote_iov), 0);
|
||||||
if (sz < 0) {
|
if (sz < 0) {
|
||||||
return sapi::InternalError(absl::StrFormat(
|
return absl::InternalError(absl::StrFormat(
|
||||||
"process_vm_readv() failed for PID: %d at address: %#x: %s", pid,
|
"process_vm_readv() failed for PID: %d at address: %#x: %s", pid,
|
||||||
reinterpret_cast<uintptr_t>(ptr), StrError(errno)));
|
reinterpret_cast<uintptr_t>(ptr), StrError(errno)));
|
||||||
}
|
}
|
||||||
@ -311,7 +311,7 @@ sapi::StatusOr<std::string> ReadCPathFromPid(pid_t pid, uintptr_t ptr) {
|
|||||||
// incorrect path (or >PATH_MAX).
|
// incorrect path (or >PATH_MAX).
|
||||||
auto pos = path.find('\0');
|
auto pos = path.find('\0');
|
||||||
if (pos == std::string::npos) {
|
if (pos == std::string::npos) {
|
||||||
return sapi::FailedPreconditionError(absl::StrCat(
|
return absl::FailedPreconditionError(absl::StrCat(
|
||||||
"No NUL-byte inside the C string '", absl::CHexEscape(path), "'"));
|
"No NUL-byte inside the C string '", absl::CHexEscape(path), "'"));
|
||||||
}
|
}
|
||||||
path.resize(pos);
|
path.resize(pos);
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
load("//sandboxed_api/bazel:build_defs.bzl", "sapi_platform_copts")
|
||||||
|
|
||||||
package(default_visibility = [
|
package(default_visibility = [
|
||||||
"//sandboxed_api:__subpackages__",
|
"//sandboxed_api:__subpackages__",
|
||||||
"//security/gfence:__subpackages__",
|
"//security/gfence:__subpackages__",
|
||||||
@ -19,8 +21,6 @@ package(default_visibility = [
|
|||||||
|
|
||||||
licenses(["notice"]) # Apache 2.0
|
licenses(["notice"]) # Apache 2.0
|
||||||
|
|
||||||
load("//sandboxed_api/bazel:build_defs.bzl", "sapi_platform_copts")
|
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "bpf_helper",
|
name = "bpf_helper",
|
||||||
srcs = ["bpf_helper.c"],
|
srcs = ["bpf_helper.c"],
|
||||||
@ -37,7 +37,7 @@ cc_library(
|
|||||||
hdrs = ["file_helpers.h"],
|
hdrs = ["file_helpers.h"],
|
||||||
copts = sapi_platform_copts(),
|
copts = sapi_platform_copts(),
|
||||||
deps = [
|
deps = [
|
||||||
"//sandboxed_api/util:status",
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -141,6 +141,7 @@ cc_library(
|
|||||||
"//sandboxed_api/util:status",
|
"//sandboxed_api/util:status",
|
||||||
"//sandboxed_api/util:statusor",
|
"//sandboxed_api/util:statusor",
|
||||||
"@com_google_absl//absl/base:endian",
|
"@com_google_absl//absl/base:endian",
|
||||||
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -172,8 +173,8 @@ cc_library(
|
|||||||
deps = [
|
deps = [
|
||||||
":fileops",
|
":fileops",
|
||||||
":strerror",
|
":strerror",
|
||||||
"//sandboxed_api/util:status",
|
|
||||||
"//sandboxed_api/util:statusor",
|
"//sandboxed_api/util:statusor",
|
||||||
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -198,8 +199,8 @@ cc_library(
|
|||||||
hdrs = ["maps_parser.h"],
|
hdrs = ["maps_parser.h"],
|
||||||
copts = sapi_platform_copts(),
|
copts = sapi_platform_copts(),
|
||||||
deps = [
|
deps = [
|
||||||
"//sandboxed_api/util:status",
|
|
||||||
"//sandboxed_api/util:statusor",
|
"//sandboxed_api/util:statusor",
|
||||||
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -29,9 +29,9 @@ add_library(sandbox2_util_file_helpers STATIC
|
|||||||
)
|
)
|
||||||
add_library(sandbox2::file_helpers ALIAS sandbox2_util_file_helpers)
|
add_library(sandbox2::file_helpers ALIAS sandbox2_util_file_helpers)
|
||||||
target_link_libraries(sandbox2_util_file_helpers PRIVATE
|
target_link_libraries(sandbox2_util_file_helpers PRIVATE
|
||||||
|
absl::status
|
||||||
absl::strings
|
absl::strings
|
||||||
sapi::base
|
sapi::base
|
||||||
sapi::status
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# sandboxed_api/sandbox2/util:fileops
|
# sandboxed_api/sandbox2/util:fileops
|
||||||
@ -75,11 +75,11 @@ add_library(sandbox2_util_minielf STATIC
|
|||||||
)
|
)
|
||||||
add_library(sandbox2::minielf ALIAS sandbox2_util_minielf)
|
add_library(sandbox2::minielf ALIAS sandbox2_util_minielf)
|
||||||
target_link_libraries(sandbox2_util_minielf PRIVATE
|
target_link_libraries(sandbox2_util_minielf PRIVATE
|
||||||
|
absl::status
|
||||||
absl::strings
|
absl::strings
|
||||||
sandbox2::util
|
sandbox2::util
|
||||||
sapi::base
|
sapi::base
|
||||||
sapi::raw_logging
|
sapi::raw_logging
|
||||||
sapi::status
|
|
||||||
sapi::statusor
|
sapi::statusor
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ target_link_libraries(sandbox2_util_temp_file
|
|||||||
sandbox2::fileops
|
sandbox2::fileops
|
||||||
sandbox2::strerror
|
sandbox2::strerror
|
||||||
sapi::base
|
sapi::base
|
||||||
PUBLIC sapi::status
|
PUBLIC absl::status
|
||||||
sapi::statusor
|
sapi::statusor
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -105,9 +105,9 @@ add_library(sandbox2_util_maps_parser STATIC
|
|||||||
)
|
)
|
||||||
add_library(sandbox2::maps_parser ALIAS sandbox2_util_maps_parser)
|
add_library(sandbox2::maps_parser ALIAS sandbox2_util_maps_parser)
|
||||||
target_link_libraries(sandbox2_util_maps_parser PRIVATE
|
target_link_libraries(sandbox2_util_maps_parser PRIVATE
|
||||||
|
absl::status
|
||||||
absl::strings
|
absl::strings
|
||||||
sapi::base
|
sapi::base
|
||||||
sapi::status
|
|
||||||
sapi::statusor
|
sapi::statusor
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "absl/strings/str_cat.h"
|
#include "absl/strings/str_cat.h"
|
||||||
|
|
||||||
namespace sandbox2 {
|
namespace sandbox2 {
|
||||||
@ -27,33 +28,30 @@ const Options& Defaults() {
|
|||||||
return *instance;
|
return *instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status GetContents(absl::string_view path, std::string* output,
|
absl::Status GetContents(absl::string_view path, std::string* output,
|
||||||
const file::Options& options) {
|
const file::Options& options) {
|
||||||
std::ifstream in_stream{std::string(path), std::ios_base::binary};
|
std::ifstream in_stream{std::string(path), std::ios_base::binary};
|
||||||
std::ostringstream out_stream;
|
std::ostringstream out_stream;
|
||||||
out_stream << in_stream.rdbuf();
|
out_stream << in_stream.rdbuf();
|
||||||
if (!in_stream || !out_stream) {
|
if (!in_stream || !out_stream) {
|
||||||
return sapi::Status{sapi::StatusCode::kUnknown,
|
return absl::UnknownError(absl::StrCat("Error during read: ", path));
|
||||||
absl::StrCat("Error during read: ", path)};
|
|
||||||
}
|
}
|
||||||
*output = out_stream.str();
|
*output = out_stream.str();
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status SetContents(absl::string_view path, absl::string_view content,
|
absl::Status SetContents(absl::string_view path, absl::string_view content,
|
||||||
const file::Options& options) {
|
const file::Options& options) {
|
||||||
std::ofstream out_stream{std::string(path),
|
std::ofstream out_stream(std::string(path),
|
||||||
std::ios_base::trunc | std::ios_base::binary};
|
std::ios_base::trunc | std::ios_base::binary);
|
||||||
if (!out_stream) {
|
if (!out_stream) {
|
||||||
return sapi::Status{sapi::StatusCode::kUnknown,
|
return absl::UnknownError(absl::StrCat("Failed to open file: ", path));
|
||||||
absl::StrCat("Failed to open file: ", path)};
|
|
||||||
}
|
}
|
||||||
out_stream.write(content.data(), content.size());
|
out_stream.write(content.data(), content.size());
|
||||||
if (!out_stream) {
|
if (!out_stream) {
|
||||||
return sapi::Status{sapi::StatusCode::kUnknown,
|
return absl::UnknownError(absl::StrCat("Error during write: ", path));
|
||||||
absl::StrCat("Error during write: ", path)};
|
|
||||||
}
|
}
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace file
|
} // namespace file
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "absl/strings/string_view.h"
|
#include "absl/strings/string_view.h"
|
||||||
#include "sandboxed_api/util/status.h"
|
|
||||||
|
|
||||||
namespace sandbox2 {
|
namespace sandbox2 {
|
||||||
namespace file {
|
namespace file {
|
||||||
@ -29,10 +29,10 @@ struct Options {};
|
|||||||
// Default constructed Options struct for compatiblity with Google File.
|
// Default constructed Options struct for compatiblity with Google File.
|
||||||
const Options& Defaults();
|
const Options& Defaults();
|
||||||
|
|
||||||
sapi::Status GetContents(absl::string_view path, std::string* output,
|
absl::Status GetContents(absl::string_view path, std::string* output,
|
||||||
const file::Options& options);
|
const file::Options& options);
|
||||||
|
|
||||||
sapi::Status SetContents(absl::string_view path, absl::string_view content,
|
absl::Status SetContents(absl::string_view path, absl::string_view content,
|
||||||
const file::Options& options);
|
const file::Options& options);
|
||||||
|
|
||||||
} // namespace file
|
} // namespace file
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "sandboxed_api/sandbox2/util/maps_parser.h"
|
#include "sandboxed_api/sandbox2/util/maps_parser.h"
|
||||||
|
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "absl/strings/str_split.h"
|
#include "absl/strings/str_split.h"
|
||||||
|
|
||||||
namespace sandbox2 {
|
namespace sandbox2 {
|
||||||
@ -44,7 +46,7 @@ sapi::StatusOr<std::vector<MapsEntry>> ParseProcMaps(
|
|||||||
} else if (n_matches == 11) {
|
} else if (n_matches == 11) {
|
||||||
entry.path.resize(strlen(entry.path.c_str()));
|
entry.path.resize(strlen(entry.path.c_str()));
|
||||||
} else {
|
} else {
|
||||||
return sapi::FailedPreconditionError("Invalid format");
|
return absl::FailedPreconditionError("Invalid format");
|
||||||
}
|
}
|
||||||
entry.is_readable = r == 'r';
|
entry.is_readable = r == 'r';
|
||||||
entry.is_writable = w == 'w';
|
entry.is_writable = w == 'w';
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "sandboxed_api/util/status.h"
|
|
||||||
#include "sandboxed_api/util/statusor.h"
|
#include "sandboxed_api/util/statusor.h"
|
||||||
|
|
||||||
namespace sandbox2 {
|
namespace sandbox2 {
|
||||||
|
@ -20,12 +20,12 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "absl/base/internal/endian.h"
|
#include "absl/base/internal/endian.h"
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "absl/strings/match.h"
|
#include "absl/strings/match.h"
|
||||||
#include "absl/strings/str_cat.h"
|
#include "absl/strings/str_cat.h"
|
||||||
#include "sandboxed_api/sandbox2/util.h"
|
#include "sandboxed_api/sandbox2/util.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"
|
||||||
#include "sandboxed_api/util/status.h"
|
|
||||||
#include "sandboxed_api/util/status_macros.h"
|
#include "sandboxed_api/util/status_macros.h"
|
||||||
|
|
||||||
namespace sandbox2 {
|
namespace sandbox2 {
|
||||||
@ -50,23 +50,23 @@ constexpr int kEvCurrent = 1; // ELF version
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// NOLINTNEXTLINE
|
// NOLINTNEXTLINE
|
||||||
sapi::Status CheckedFSeek(FILE* f, long offset, int whence) {
|
absl::Status CheckedFSeek(FILE* f, long offset, int whence) {
|
||||||
if (fseek(f, offset, whence)) {
|
if (fseek(f, offset, whence)) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("Fseek on ELF failed: ", StrError(errno)));
|
absl::StrCat("Fseek on ELF failed: ", StrError(errno)));
|
||||||
}
|
}
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status CheckedFRead(void* dst, size_t size, size_t nmemb, FILE* f) {
|
absl::Status CheckedFRead(void* dst, size_t size, size_t nmemb, FILE* f) {
|
||||||
if (fread(dst, size, nmemb, f) == nmemb) {
|
if (fread(dst, size, nmemb, f) == nmemb) {
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("Reading ELF data failed: ", StrError(errno)));
|
absl::StrCat("Reading ELF data failed: ", StrError(errno)));
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status CheckedRead(std::string* s, FILE* f) {
|
absl::Status CheckedRead(std::string* s, FILE* f) {
|
||||||
return CheckedFRead(&(*s)[0], 1, s->size(), f);
|
return CheckedFRead(&(*s)[0], 1, s->size(), f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,25 +129,25 @@ class ElfParser {
|
|||||||
void Load(int64_t* dst, const void* src) { *dst = Load64(src); }
|
void Load(int64_t* dst, const void* src) { *dst = Load64(src); }
|
||||||
|
|
||||||
// Reads elf file size.
|
// Reads elf file size.
|
||||||
sapi::Status ReadFileSize();
|
absl::Status ReadFileSize();
|
||||||
// Reads elf header.
|
// Reads elf header.
|
||||||
sapi::Status ReadFileHeader();
|
absl::Status ReadFileHeader();
|
||||||
// Reads a single elf program header.
|
// Reads a single elf program header.
|
||||||
sapi::StatusOr<Elf64_Phdr> ReadProgramHeader(absl::string_view src);
|
sapi::StatusOr<Elf64_Phdr> ReadProgramHeader(absl::string_view src);
|
||||||
// Reads all elf program headers.
|
// Reads all elf program headers.
|
||||||
sapi::Status ReadProgramHeaders();
|
absl::Status ReadProgramHeaders();
|
||||||
// Reads a single elf section header.
|
// Reads a single elf section header.
|
||||||
sapi::StatusOr<Elf64_Shdr> ReadSectionHeader(absl::string_view src);
|
sapi::StatusOr<Elf64_Shdr> ReadSectionHeader(absl::string_view src);
|
||||||
// Reads all elf section headers.
|
// Reads all elf section headers.
|
||||||
sapi::Status ReadSectionHeaders();
|
absl::Status ReadSectionHeaders();
|
||||||
// Reads contents of an elf section.
|
// Reads contents of an elf section.
|
||||||
sapi::StatusOr<std::string> ReadSectionContents(int idx);
|
sapi::StatusOr<std::string> ReadSectionContents(int idx);
|
||||||
sapi::StatusOr<std::string> ReadSectionContents(
|
sapi::StatusOr<std::string> ReadSectionContents(
|
||||||
const Elf64_Shdr& section_header);
|
const Elf64_Shdr& section_header);
|
||||||
// Reads all symbols from symtab section.
|
// Reads all symbols from symtab section.
|
||||||
sapi::Status ReadSymbolsFromSymtab(const Elf64_Shdr& symtab);
|
absl::Status ReadSymbolsFromSymtab(const Elf64_Shdr& symtab);
|
||||||
// Reads all imported libraries from dynamic section.
|
// Reads all imported libraries from dynamic section.
|
||||||
sapi::Status ReadImportedLibrariesFromDynamic(const Elf64_Shdr& dynamic);
|
absl::Status ReadImportedLibrariesFromDynamic(const Elf64_Shdr& dynamic);
|
||||||
|
|
||||||
ElfFile result_;
|
ElfFile result_;
|
||||||
FILE* elf_ = nullptr;
|
FILE* elf_ = nullptr;
|
||||||
@ -170,37 +170,37 @@ constexpr int ElfParser::kMaxSymbolEntries;
|
|||||||
constexpr int ElfParser::kMaxDynamicEntries;
|
constexpr int ElfParser::kMaxDynamicEntries;
|
||||||
constexpr size_t ElfParser::kMaxInterpreterSize;
|
constexpr size_t ElfParser::kMaxInterpreterSize;
|
||||||
|
|
||||||
sapi::Status ElfParser::ReadFileSize() {
|
absl::Status ElfParser::ReadFileSize() {
|
||||||
fseek(elf_, 0, SEEK_END);
|
fseek(elf_, 0, SEEK_END);
|
||||||
file_size_ = ftell(elf_);
|
file_size_ = ftell(elf_);
|
||||||
if (file_size_ < kElfHeaderSize) {
|
if (file_size_ < kElfHeaderSize) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("file too small: ", file_size_, " bytes, at least ",
|
absl::StrCat("file too small: ", file_size_, " bytes, at least ",
|
||||||
kElfHeaderSize, " bytes expected"));
|
kElfHeaderSize, " bytes expected"));
|
||||||
}
|
}
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status ElfParser::ReadFileHeader() {
|
absl::Status ElfParser::ReadFileHeader() {
|
||||||
std::string header(kElfHeaderSize, '\0');
|
std::string header(kElfHeaderSize, '\0');
|
||||||
SAPI_RETURN_IF_ERROR(CheckedFSeek(elf_, 0, SEEK_SET));
|
SAPI_RETURN_IF_ERROR(CheckedFSeek(elf_, 0, SEEK_SET));
|
||||||
SAPI_RETURN_IF_ERROR(CheckedRead(&header, elf_));
|
SAPI_RETURN_IF_ERROR(CheckedRead(&header, elf_));
|
||||||
|
|
||||||
if (!absl::StartsWith(header, kElfMagic)) {
|
if (!absl::StartsWith(header, kElfMagic)) {
|
||||||
return sapi::FailedPreconditionError("magic not found, not an ELF");
|
return absl::FailedPreconditionError("magic not found, not an ELF");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header[kEiClassOffset] != kEiClass64) {
|
if (header[kEiClassOffset] != kEiClass64) {
|
||||||
return sapi::FailedPreconditionError("invalid ELF class");
|
return absl::FailedPreconditionError("invalid ELF class");
|
||||||
}
|
}
|
||||||
const auto elf_data = header[kEiDataOffset];
|
const auto elf_data = header[kEiDataOffset];
|
||||||
elf_little_ = elf_data == kEiDataLittle;
|
elf_little_ = elf_data == kEiDataLittle;
|
||||||
if (!elf_little_ && elf_data != kEiDataBig) {
|
if (!elf_little_ && elf_data != kEiDataBig) {
|
||||||
return sapi::FailedPreconditionError("invalid endianness");
|
return absl::FailedPreconditionError("invalid endianness");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header[kEiVersionOffset] != kEvCurrent) {
|
if (header[kEiVersionOffset] != kEvCurrent) {
|
||||||
return sapi::FailedPreconditionError("invalid ELF version");
|
return absl::FailedPreconditionError("invalid ELF version");
|
||||||
}
|
}
|
||||||
LOAD_MEMBER(file_header_, e_ident, header.data());
|
LOAD_MEMBER(file_header_, e_ident, header.data());
|
||||||
LOAD_MEMBER(file_header_, e_type, header.data());
|
LOAD_MEMBER(file_header_, e_type, header.data());
|
||||||
@ -216,13 +216,13 @@ sapi::Status ElfParser::ReadFileHeader() {
|
|||||||
LOAD_MEMBER(file_header_, e_shentsize, header.data());
|
LOAD_MEMBER(file_header_, e_shentsize, header.data());
|
||||||
LOAD_MEMBER(file_header_, e_shnum, header.data());
|
LOAD_MEMBER(file_header_, e_shnum, header.data());
|
||||||
LOAD_MEMBER(file_header_, e_shstrndx, header.data());
|
LOAD_MEMBER(file_header_, e_shstrndx, header.data());
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::StatusOr<Elf64_Shdr> ElfParser::ReadSectionHeader(
|
sapi::StatusOr<Elf64_Shdr> ElfParser::ReadSectionHeader(
|
||||||
absl::string_view src) {
|
absl::string_view src) {
|
||||||
if (src.size() < sizeof(Elf64_Shdr)) {
|
if (src.size() < sizeof(Elf64_Shdr)) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("invalid section header data: got ", src.size(),
|
absl::StrCat("invalid section header data: got ", src.size(),
|
||||||
" bytes, ", sizeof(Elf64_Shdr), " bytes expected."));
|
" bytes, ", sizeof(Elf64_Shdr), " bytes expected."));
|
||||||
}
|
}
|
||||||
@ -240,18 +240,18 @@ sapi::StatusOr<Elf64_Shdr> ElfParser::ReadSectionHeader(
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status ElfParser::ReadSectionHeaders() {
|
absl::Status ElfParser::ReadSectionHeaders() {
|
||||||
if (file_header_.e_shoff > file_size_) {
|
if (file_header_.e_shoff > file_size_) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("invalid section header offset: ", file_header_.e_shoff));
|
absl::StrCat("invalid section header offset: ", file_header_.e_shoff));
|
||||||
}
|
}
|
||||||
if (file_header_.e_shentsize != sizeof(Elf64_Shdr)) {
|
if (file_header_.e_shentsize != sizeof(Elf64_Shdr)) {
|
||||||
return sapi::FailedPreconditionError(absl::StrCat(
|
return absl::FailedPreconditionError(absl::StrCat(
|
||||||
"section header entry size incorrect: ", file_header_.e_shentsize,
|
"section header entry size incorrect: ", file_header_.e_shentsize,
|
||||||
" bytes, ", sizeof(Elf64_Shdr), " expected."));
|
" bytes, ", sizeof(Elf64_Shdr), " expected."));
|
||||||
}
|
}
|
||||||
if (file_header_.e_shnum > kMaxSectionHeaderEntries) {
|
if (file_header_.e_shnum > kMaxSectionHeaderEntries) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("too many section header entries: ", file_header_.e_shnum,
|
absl::StrCat("too many section header entries: ", file_header_.e_shnum,
|
||||||
" limit: ", kMaxSectionHeaderEntries));
|
" limit: ", kMaxSectionHeaderEntries));
|
||||||
}
|
}
|
||||||
@ -264,12 +264,12 @@ sapi::Status ElfParser::ReadSectionHeaders() {
|
|||||||
SAPI_ASSIGN_OR_RETURN(section_headers_[i], ReadSectionHeader(src));
|
SAPI_ASSIGN_OR_RETURN(section_headers_[i], ReadSectionHeader(src));
|
||||||
src = src.substr(file_header_.e_shentsize);
|
src = src.substr(file_header_.e_shentsize);
|
||||||
}
|
}
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::StatusOr<std::string> ElfParser::ReadSectionContents(int idx) {
|
sapi::StatusOr<std::string> ElfParser::ReadSectionContents(int idx) {
|
||||||
if (idx < 0 || idx >= section_headers_.size()) {
|
if (idx < 0 || idx >= section_headers_.size()) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("invalid section header index: ", idx));
|
absl::StrCat("invalid section header index: ", idx));
|
||||||
}
|
}
|
||||||
return ReadSectionContents(section_headers_.at(idx));
|
return ReadSectionContents(section_headers_.at(idx));
|
||||||
@ -279,12 +279,12 @@ sapi::StatusOr<std::string> ElfParser::ReadSectionContents(
|
|||||||
const Elf64_Shdr& section_header) {
|
const Elf64_Shdr& section_header) {
|
||||||
auto offset = section_header.sh_offset;
|
auto offset = section_header.sh_offset;
|
||||||
if (offset > file_size_) {
|
if (offset > file_size_) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("invalid section offset: ", offset));
|
absl::StrCat("invalid section offset: ", offset));
|
||||||
}
|
}
|
||||||
auto size = section_header.sh_size;
|
auto size = section_header.sh_size;
|
||||||
if (size > kMaxSectionSize) {
|
if (size > kMaxSectionSize) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("section too big: ", size, " limit: ", kMaxSectionSize));
|
absl::StrCat("section too big: ", size, " limit: ", kMaxSectionSize));
|
||||||
}
|
}
|
||||||
std::string rv(size, '\0');
|
std::string rv(size, '\0');
|
||||||
@ -296,7 +296,7 @@ sapi::StatusOr<std::string> ElfParser::ReadSectionContents(
|
|||||||
sapi::StatusOr<Elf64_Phdr> ElfParser::ReadProgramHeader(
|
sapi::StatusOr<Elf64_Phdr> ElfParser::ReadProgramHeader(
|
||||||
absl::string_view src) {
|
absl::string_view src) {
|
||||||
if (src.size() < sizeof(Elf64_Phdr)) {
|
if (src.size() < sizeof(Elf64_Phdr)) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("invalid program header data: got ", src.size(),
|
absl::StrCat("invalid program header data: got ", src.size(),
|
||||||
" bytes, ", sizeof(Elf64_Phdr), " bytes expected."));
|
" bytes, ", sizeof(Elf64_Phdr), " bytes expected."));
|
||||||
}
|
}
|
||||||
@ -312,18 +312,18 @@ sapi::StatusOr<Elf64_Phdr> ElfParser::ReadProgramHeader(
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status ElfParser::ReadProgramHeaders() {
|
absl::Status ElfParser::ReadProgramHeaders() {
|
||||||
if (file_header_.e_phoff > file_size_) {
|
if (file_header_.e_phoff > file_size_) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("invalid program header offset: ", file_header_.e_phoff));
|
absl::StrCat("invalid program header offset: ", file_header_.e_phoff));
|
||||||
}
|
}
|
||||||
if (file_header_.e_phentsize != sizeof(Elf64_Phdr)) {
|
if (file_header_.e_phentsize != sizeof(Elf64_Phdr)) {
|
||||||
return sapi::FailedPreconditionError(absl::StrCat(
|
return absl::FailedPreconditionError(absl::StrCat(
|
||||||
"section header entry size incorrect: ", file_header_.e_phentsize,
|
"section header entry size incorrect: ", file_header_.e_phentsize,
|
||||||
" bytes, ", sizeof(Elf64_Phdr), " expected."));
|
" bytes, ", sizeof(Elf64_Phdr), " expected."));
|
||||||
}
|
}
|
||||||
if (file_header_.e_phnum > kMaxProgramHeaderEntries) {
|
if (file_header_.e_phnum > kMaxProgramHeaderEntries) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("too many program header entries: ", file_header_.e_phnum,
|
absl::StrCat("too many program header entries: ", file_header_.e_phnum,
|
||||||
" limit: ", kMaxProgramHeaderEntries));
|
" limit: ", kMaxProgramHeaderEntries));
|
||||||
}
|
}
|
||||||
@ -336,29 +336,29 @@ sapi::Status ElfParser::ReadProgramHeaders() {
|
|||||||
SAPI_ASSIGN_OR_RETURN(program_headers_[i], ReadProgramHeader(src));
|
SAPI_ASSIGN_OR_RETURN(program_headers_[i], ReadProgramHeader(src));
|
||||||
src = src.substr(file_header_.e_phentsize);
|
src = src.substr(file_header_.e_phentsize);
|
||||||
}
|
}
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status ElfParser::ReadSymbolsFromSymtab(const Elf64_Shdr& symtab) {
|
absl::Status ElfParser::ReadSymbolsFromSymtab(const Elf64_Shdr& symtab) {
|
||||||
if (symtab.sh_type != SHT_SYMTAB) {
|
if (symtab.sh_type != SHT_SYMTAB) {
|
||||||
return sapi::FailedPreconditionError("invalid symtab type");
|
return absl::FailedPreconditionError("invalid symtab type");
|
||||||
}
|
}
|
||||||
if (symtab.sh_entsize != sizeof(Elf64_Sym)) {
|
if (symtab.sh_entsize != sizeof(Elf64_Sym)) {
|
||||||
return sapi::InternalError(
|
return absl::InternalError(
|
||||||
absl::StrCat("invalid symbol entry size: ", symtab.sh_entsize));
|
absl::StrCat("invalid symbol entry size: ", symtab.sh_entsize));
|
||||||
}
|
}
|
||||||
if ((symtab.sh_size % symtab.sh_entsize) != 0) {
|
if ((symtab.sh_size % symtab.sh_entsize) != 0) {
|
||||||
return sapi::InternalError(
|
return absl::InternalError(
|
||||||
absl::StrCat("invalid symbol table size: ", symtab.sh_size));
|
absl::StrCat("invalid symbol table size: ", symtab.sh_size));
|
||||||
}
|
}
|
||||||
size_t symbol_entries = symtab.sh_size / symtab.sh_entsize;
|
size_t symbol_entries = symtab.sh_size / symtab.sh_entsize;
|
||||||
if (symbol_entries > kMaxSymbolEntries - symbol_entries_read) {
|
if (symbol_entries > kMaxSymbolEntries - symbol_entries_read) {
|
||||||
return sapi::InternalError(
|
return absl::InternalError(
|
||||||
absl::StrCat("too many symbols: ", symbol_entries));
|
absl::StrCat("too many symbols: ", symbol_entries));
|
||||||
}
|
}
|
||||||
symbol_entries_read += symbol_entries;
|
symbol_entries_read += symbol_entries;
|
||||||
if (symtab.sh_link >= section_headers_.size()) {
|
if (symtab.sh_link >= section_headers_.size()) {
|
||||||
return sapi::InternalError(
|
return absl::InternalError(
|
||||||
absl::StrCat("invalid symtab's strtab reference: ", symtab.sh_link));
|
absl::StrCat("invalid symtab's strtab reference: ", symtab.sh_link));
|
||||||
}
|
}
|
||||||
SAPI_RAW_VLOG(1, "Symbol table with %d entries found", symbol_entries);
|
SAPI_RAW_VLOG(1, "Symbol table with %d entries found", symbol_entries);
|
||||||
@ -383,53 +383,53 @@ sapi::Status ElfParser::ReadSymbolsFromSymtab(const Elf64_Shdr& symtab) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (symbol.st_shndx >= section_headers_.size()) {
|
if (symbol.st_shndx >= section_headers_.size()) {
|
||||||
return sapi::FailedPreconditionError(absl::StrCat(
|
return absl::FailedPreconditionError(absl::StrCat(
|
||||||
"invalid symbol data: section index: ", symbol.st_shndx));
|
"invalid symbol data: section index: ", symbol.st_shndx));
|
||||||
}
|
}
|
||||||
if (symbol.st_name >= strtab.size()) {
|
if (symbol.st_name >= strtab.size()) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("invalid name reference: REL", symbol.st_value));
|
absl::StrCat("invalid name reference: REL", symbol.st_value));
|
||||||
}
|
}
|
||||||
result_.symbols_.push_back(
|
result_.symbols_.push_back(
|
||||||
{symbol.st_value, std::string(ReadName(symbol.st_name, strtab))});
|
{symbol.st_value, std::string(ReadName(symbol.st_name, strtab))});
|
||||||
}
|
}
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status ElfParser::ReadImportedLibrariesFromDynamic(
|
absl::Status ElfParser::ReadImportedLibrariesFromDynamic(
|
||||||
const Elf64_Shdr& dynamic) {
|
const Elf64_Shdr& dynamic) {
|
||||||
if (dynamic.sh_type != SHT_DYNAMIC) {
|
if (dynamic.sh_type != SHT_DYNAMIC) {
|
||||||
return sapi::FailedPreconditionError("invalid dynamic type");
|
return absl::FailedPreconditionError("invalid dynamic type");
|
||||||
}
|
}
|
||||||
if (dynamic.sh_entsize != sizeof(Elf64_Dyn)) {
|
if (dynamic.sh_entsize != sizeof(Elf64_Dyn)) {
|
||||||
return sapi::InternalError(
|
return absl::InternalError(
|
||||||
absl::StrCat("invalid dynamic entry size: ", dynamic.sh_entsize));
|
absl::StrCat("invalid dynamic entry size: ", dynamic.sh_entsize));
|
||||||
}
|
}
|
||||||
if ((dynamic.sh_size % dynamic.sh_entsize) != 0) {
|
if ((dynamic.sh_size % dynamic.sh_entsize) != 0) {
|
||||||
return sapi::InternalError(
|
return absl::InternalError(
|
||||||
absl::StrCat("invalid dynamic table size: ", dynamic.sh_size));
|
absl::StrCat("invalid dynamic table size: ", dynamic.sh_size));
|
||||||
}
|
}
|
||||||
size_t entries = dynamic.sh_size / dynamic.sh_entsize;
|
size_t entries = dynamic.sh_size / dynamic.sh_entsize;
|
||||||
if (entries > kMaxDynamicEntries - dynamic_entries_read) {
|
if (entries > kMaxDynamicEntries - dynamic_entries_read) {
|
||||||
return sapi::InternalError(
|
return absl::InternalError(
|
||||||
absl::StrCat("too many dynamic entries: ", entries));
|
absl::StrCat("too many dynamic entries: ", entries));
|
||||||
}
|
}
|
||||||
dynamic_entries_read += entries;
|
dynamic_entries_read += entries;
|
||||||
if (dynamic.sh_link >= section_headers_.size()) {
|
if (dynamic.sh_link >= section_headers_.size()) {
|
||||||
return sapi::InternalError(
|
return absl::InternalError(
|
||||||
absl::StrCat("invalid dynamic's strtab reference: ", dynamic.sh_link));
|
absl::StrCat("invalid dynamic's strtab reference: ", dynamic.sh_link));
|
||||||
}
|
}
|
||||||
SAPI_RAW_VLOG(1, "Dynamic section with %d entries found", entries);
|
SAPI_RAW_VLOG(1, "Dynamic section with %d entries found", entries);
|
||||||
// strtab may be shared with symbols and therefore huge
|
// strtab may be shared with symbols and therefore huge
|
||||||
const auto& strtab_section = section_headers_.at(dynamic.sh_link);
|
const auto& strtab_section = section_headers_.at(dynamic.sh_link);
|
||||||
if (strtab_section.sh_offset > file_size_) {
|
if (strtab_section.sh_offset > file_size_) {
|
||||||
return sapi::FailedPreconditionError(absl::StrCat(
|
return absl::FailedPreconditionError(absl::StrCat(
|
||||||
"invalid symtab's strtab section offset: ", strtab_section.sh_offset));
|
"invalid symtab's strtab section offset: ", strtab_section.sh_offset));
|
||||||
}
|
}
|
||||||
if (strtab_section.sh_size >= kMaxStrtabSize ||
|
if (strtab_section.sh_size >= kMaxStrtabSize ||
|
||||||
strtab_section.sh_size >= file_size_ ||
|
strtab_section.sh_size >= file_size_ ||
|
||||||
strtab_section.sh_offset >= file_size_ - strtab_section.sh_size) {
|
strtab_section.sh_offset >= file_size_ - strtab_section.sh_size) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("symtab's strtab too big: ", strtab_section.sh_size));
|
absl::StrCat("symtab's strtab too big: ", strtab_section.sh_size));
|
||||||
}
|
}
|
||||||
auto strtab_end = strtab_section.sh_offset + strtab_section.sh_size;
|
auto strtab_end = strtab_section.sh_offset + strtab_section.sh_size;
|
||||||
@ -443,7 +443,7 @@ sapi::Status ElfParser::ReadImportedLibrariesFromDynamic(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (dyn.d_un.d_val >= strtab_section.sh_size) {
|
if (dyn.d_un.d_val >= strtab_section.sh_size) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("invalid name reference"));
|
absl::StrCat("invalid name reference"));
|
||||||
}
|
}
|
||||||
auto offset = strtab_section.sh_offset + dyn.d_un.d_val;
|
auto offset = strtab_section.sh_offset + dyn.d_un.d_val;
|
||||||
@ -453,14 +453,14 @@ sapi::Status ElfParser::ReadImportedLibrariesFromDynamic(
|
|||||||
path.resize(size);
|
path.resize(size);
|
||||||
result_.imported_libraries_.push_back(path.substr(0, path.find('\0')));
|
result_.imported_libraries_.push_back(path.substr(0, path.find('\0')));
|
||||||
}
|
}
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::StatusOr<ElfFile> ElfParser::Parse(FILE* elf, uint32_t features) {
|
sapi::StatusOr<ElfFile> ElfParser::Parse(FILE* elf, uint32_t features) {
|
||||||
elf_ = elf;
|
elf_ = elf;
|
||||||
// Basic sanity check.
|
// Basic sanity check.
|
||||||
if (features & ~(ElfFile::kAll)) {
|
if (features & ~(ElfFile::kAll)) {
|
||||||
return sapi::InvalidArgumentError("Unknown feature flags specified");
|
return absl::InvalidArgumentError("Unknown feature flags specified");
|
||||||
}
|
}
|
||||||
SAPI_RETURN_IF_ERROR(ReadFileSize());
|
SAPI_RETURN_IF_ERROR(ReadFileSize());
|
||||||
SAPI_RETURN_IF_ERROR(ReadFileHeader());
|
SAPI_RETURN_IF_ERROR(ReadFileHeader());
|
||||||
@ -472,7 +472,7 @@ sapi::StatusOr<ElfFile> ElfParser::Parse(FILE* elf, uint32_t features) {
|
|||||||
result_.position_independent_ = true;
|
result_.position_independent_ = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return sapi::FailedPreconditionError("not an executable: ");
|
return absl::FailedPreconditionError("not an executable: ");
|
||||||
}
|
}
|
||||||
if (features & ElfFile::kGetInterpreter) {
|
if (features & ElfFile::kGetInterpreter) {
|
||||||
SAPI_RETURN_IF_ERROR(ReadProgramHeaders());
|
SAPI_RETURN_IF_ERROR(ReadProgramHeaders());
|
||||||
@ -483,7 +483,7 @@ sapi::StatusOr<ElfFile> ElfParser::Parse(FILE* elf, uint32_t features) {
|
|||||||
// No interpreter usually means that the executable was statically linked.
|
// No interpreter usually means that the executable was statically linked.
|
||||||
if (it != program_headers_.end()) {
|
if (it != program_headers_.end()) {
|
||||||
if (it->p_filesz > kMaxInterpreterSize) {
|
if (it->p_filesz > kMaxInterpreterSize) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("program interpeter path too long: ", it->p_filesz));
|
absl::StrCat("program interpeter path too long: ", it->p_filesz));
|
||||||
}
|
}
|
||||||
SAPI_RETURN_IF_ERROR(CheckedFSeek(elf, it->p_offset, SEEK_SET));
|
SAPI_RETURN_IF_ERROR(CheckedFSeek(elf, it->p_offset, SEEK_SET));
|
||||||
@ -518,7 +518,7 @@ sapi::StatusOr<ElfFile> ElfFile::ParseFromFile(const std::string& filename,
|
|||||||
std::unique_ptr<FILE, void (*)(FILE*)> elf{fopen(filename.c_str(), "r"),
|
std::unique_ptr<FILE, void (*)(FILE*)> elf{fopen(filename.c_str(), "r"),
|
||||||
[](FILE* f) { fclose(f); }};
|
[](FILE* f) { fclose(f); }};
|
||||||
if (!elf) {
|
if (!elf) {
|
||||||
return sapi::UnknownError(
|
return absl::UnknownError(
|
||||||
absl::StrCat("cannot open file: ", filename, ": ", StrError(errno)));
|
absl::StrCat("cannot open file: ", filename, ": ", StrError(errno)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ sapi::StatusOr<std::pair<std::string, int>> CreateNamedTempFile(
|
|||||||
std::string name_template = absl::StrCat(prefix, kMktempSuffix);
|
std::string name_template = absl::StrCat(prefix, kMktempSuffix);
|
||||||
int fd = mkstemp(&name_template[0]);
|
int fd = mkstemp(&name_template[0]);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
return sapi::UnknownError(absl::StrCat("mkstemp():", StrError(errno)));
|
return absl::UnknownError(absl::StrCat("mkstemp():", StrError(errno)));
|
||||||
}
|
}
|
||||||
return std::pair<std::string, int>{std::move(name_template), fd};
|
return std::pair<std::string, int>{std::move(name_template), fd};
|
||||||
}
|
}
|
||||||
@ -58,7 +58,7 @@ sapi::StatusOr<std::string> CreateNamedTempFileAndClose(
|
|||||||
sapi::StatusOr<std::string> CreateTempDir(absl::string_view prefix) {
|
sapi::StatusOr<std::string> CreateTempDir(absl::string_view prefix) {
|
||||||
std::string name_template = absl::StrCat(prefix, kMktempSuffix);
|
std::string name_template = absl::StrCat(prefix, kMktempSuffix);
|
||||||
if (mkdtemp(&name_template[0]) == nullptr) {
|
if (mkdtemp(&name_template[0]) == nullptr) {
|
||||||
return sapi::UnknownError(absl::StrCat("mkdtemp():", StrError(errno)));
|
return absl::UnknownError(absl::StrCat("mkdtemp():", StrError(errno)));
|
||||||
}
|
}
|
||||||
return name_template;
|
return name_template;
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ TEST(TempFileTest, CreateTempDirTest) {
|
|||||||
EXPECT_THAT(path, StartsWith(prefix));
|
EXPECT_THAT(path, StartsWith(prefix));
|
||||||
EXPECT_THAT(file_util::fileops::Exists(path, false), IsTrue());
|
EXPECT_THAT(file_util::fileops::Exists(path, false), IsTrue());
|
||||||
result_or = CreateTempDir("non_existing_dir/prefix");
|
result_or = CreateTempDir("non_existing_dir/prefix");
|
||||||
EXPECT_THAT(result_or, StatusIs(sapi::StatusCode::kUnknown));
|
EXPECT_THAT(result_or, StatusIs(absl::StatusCode::kUnknown));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(TempFileTest, MakeTempFileTest) {
|
TEST(TempFileTest, MakeTempFileTest) {
|
||||||
@ -57,7 +57,7 @@ TEST(TempFileTest, MakeTempFileTest) {
|
|||||||
EXPECT_THAT(fcntl(fd, F_GETFD), Ne(-1));
|
EXPECT_THAT(fcntl(fd, F_GETFD), Ne(-1));
|
||||||
EXPECT_THAT(close(fd), Eq(0));
|
EXPECT_THAT(close(fd), Eq(0));
|
||||||
result_or = CreateNamedTempFile("non_existing_dir/prefix");
|
result_or = CreateNamedTempFile("non_existing_dir/prefix");
|
||||||
EXPECT_THAT(result_or, StatusIs(sapi::StatusCode::kUnknown));
|
EXPECT_THAT(result_or, StatusIs(absl::StatusCode::kUnknown));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "absl/memory/memory.h"
|
#include "absl/memory/memory.h"
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "sandboxed_api/examples/stringop/lib/sandbox.h"
|
#include "sandboxed_api/examples/stringop/lib/sandbox.h"
|
||||||
#include "sandboxed_api/examples/stringop/lib/stringop-sapi.sapi.h"
|
#include "sandboxed_api/examples/stringop/lib/stringop-sapi.sapi.h"
|
||||||
#include "sandboxed_api/examples/stringop/lib/stringop_params.pb.h"
|
#include "sandboxed_api/examples/stringop/lib/stringop_params.pb.h"
|
||||||
@ -26,7 +27,6 @@
|
|||||||
#include "sandboxed_api/examples/sum/lib/sum-sapi_embed.h"
|
#include "sandboxed_api/examples/sum/lib/sum-sapi_embed.h"
|
||||||
#include "sandboxed_api/transaction.h"
|
#include "sandboxed_api/transaction.h"
|
||||||
#include "sandboxed_api/util/status_matchers.h"
|
#include "sandboxed_api/util/status_matchers.h"
|
||||||
#include "sandboxed_api/util/status.h"
|
|
||||||
|
|
||||||
using ::sapi::IsOk;
|
using ::sapi::IsOk;
|
||||||
using ::sapi::StatusIs;
|
using ::sapi::StatusIs;
|
||||||
@ -39,14 +39,14 @@ namespace {
|
|||||||
// Functions that will be used during the benchmarks:
|
// Functions that will be used during the benchmarks:
|
||||||
|
|
||||||
// Function causing no load in the sandboxee.
|
// Function causing no load in the sandboxee.
|
||||||
sapi::Status InvokeNop(Sandbox* sandbox) {
|
absl::Status InvokeNop(Sandbox* sandbox) {
|
||||||
StringopApi api(sandbox);
|
StringopApi api(sandbox);
|
||||||
return api.nop();
|
return api.nop();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function that makes use of our special protobuf (de)-serialization code
|
// Function that makes use of our special protobuf (de)-serialization code
|
||||||
// inside SAPI (including the back-synchronization of the structure).
|
// inside SAPI (including the back-synchronization of the structure).
|
||||||
sapi::Status InvokeStringReversal(Sandbox* sandbox) {
|
absl::Status InvokeStringReversal(Sandbox* sandbox) {
|
||||||
StringopApi api(sandbox);
|
StringopApi api(sandbox);
|
||||||
stringop::StringReverse proto;
|
stringop::StringReverse proto;
|
||||||
proto.set_input("Hello");
|
proto.set_input("Hello");
|
||||||
@ -55,7 +55,7 @@ sapi::Status InvokeStringReversal(Sandbox* sandbox) {
|
|||||||
TRANSACTION_FAIL_IF_NOT(return_code != 0, "pb_reverse_string failed");
|
TRANSACTION_FAIL_IF_NOT(return_code != 0, "pb_reverse_string failed");
|
||||||
SAPI_ASSIGN_OR_RETURN(auto pb_result, pp.GetMessage());
|
SAPI_ASSIGN_OR_RETURN(auto pb_result, pp.GetMessage());
|
||||||
TRANSACTION_FAIL_IF_NOT(pb_result.output() == "olleH", "Incorrect output");
|
TRANSACTION_FAIL_IF_NOT(pb_result.output() == "olleH", "Incorrect output");
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Benchmark functions:
|
// Benchmark functions:
|
||||||
@ -138,7 +138,7 @@ TEST(SAPITest, HasStackTraces) {
|
|||||||
auto sandbox = absl::make_unique<StringopSandbox>();
|
auto sandbox = absl::make_unique<StringopSandbox>();
|
||||||
ASSERT_THAT(sandbox->Init(), IsOk());
|
ASSERT_THAT(sandbox->Init(), IsOk());
|
||||||
StringopApi api(sandbox.get());
|
StringopApi api(sandbox.get());
|
||||||
EXPECT_THAT(api.violate(), StatusIs(sapi::StatusCode::kUnavailable));
|
EXPECT_THAT(api.violate(), StatusIs(absl::StatusCode::kUnavailable));
|
||||||
const auto& result = sandbox->AwaitResult();
|
const auto& result = sandbox->AwaitResult();
|
||||||
EXPECT_THAT(result.GetStackTrace(), HasSubstr("violate"));
|
EXPECT_THAT(result.GetStackTrace(), HasSubstr("violate"));
|
||||||
EXPECT_THAT(result.final_status(), Eq(sandbox2::Result::VIOLATION));
|
EXPECT_THAT(result.final_status(), Eq(sandbox2::Result::VIOLATION));
|
||||||
@ -160,7 +160,7 @@ int leak_file_descriptor(sapi::Sandbox* sandbox, const char* path) {
|
|||||||
TEST(SandboxTest, RestartSandboxFD) {
|
TEST(SandboxTest, RestartSandboxFD) {
|
||||||
sapi::BasicTransaction st{absl::make_unique<SumSandbox>()};
|
sapi::BasicTransaction st{absl::make_unique<SumSandbox>()};
|
||||||
|
|
||||||
auto test_body = [](sapi::Sandbox* sandbox) -> sapi::Status {
|
auto test_body = [](sapi::Sandbox* sandbox) -> absl::Status {
|
||||||
// Open some FDs and check their value.
|
// Open some FDs and check their value.
|
||||||
EXPECT_THAT(leak_file_descriptor(sandbox, "/proc/self/exe"), Eq(3));
|
EXPECT_THAT(leak_file_descriptor(sandbox, "/proc/self/exe"), Eq(3));
|
||||||
EXPECT_THAT(leak_file_descriptor(sandbox, "/proc/self/exe"), Eq(4));
|
EXPECT_THAT(leak_file_descriptor(sandbox, "/proc/self/exe"), Eq(4));
|
||||||
@ -168,7 +168,7 @@ TEST(SandboxTest, RestartSandboxFD) {
|
|||||||
// We should have a fresh sandbox now = FDs open previously should be
|
// We should have a fresh sandbox now = FDs open previously should be
|
||||||
// closed now.
|
// closed now.
|
||||||
EXPECT_THAT(leak_file_descriptor(sandbox, "/proc/self/exe"), Eq(3));
|
EXPECT_THAT(leak_file_descriptor(sandbox, "/proc/self/exe"), Eq(3));
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
};
|
};
|
||||||
|
|
||||||
EXPECT_THAT(st.Run(test_body), IsOk());
|
EXPECT_THAT(st.Run(test_body), IsOk());
|
||||||
@ -177,23 +177,23 @@ TEST(SandboxTest, RestartSandboxFD) {
|
|||||||
TEST(SandboxTest, RestartTransactionSandboxFD) {
|
TEST(SandboxTest, RestartTransactionSandboxFD) {
|
||||||
sapi::BasicTransaction st{absl::make_unique<SumSandbox>()};
|
sapi::BasicTransaction st{absl::make_unique<SumSandbox>()};
|
||||||
|
|
||||||
EXPECT_THAT(st.Run([](sapi::Sandbox* sandbox) -> sapi::Status {
|
EXPECT_THAT(st.Run([](sapi::Sandbox* sandbox) -> absl::Status {
|
||||||
EXPECT_THAT(leak_file_descriptor(sandbox, "/proc/self/exe"), Eq(3));
|
EXPECT_THAT(leak_file_descriptor(sandbox, "/proc/self/exe"), Eq(3));
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}),
|
}),
|
||||||
IsOk());
|
IsOk());
|
||||||
|
|
||||||
EXPECT_THAT(st.Run([](sapi::Sandbox* sandbox) -> sapi::Status {
|
EXPECT_THAT(st.Run([](sapi::Sandbox* sandbox) -> absl::Status {
|
||||||
EXPECT_THAT(leak_file_descriptor(sandbox, "/proc/self/exe"), Eq(4));
|
EXPECT_THAT(leak_file_descriptor(sandbox, "/proc/self/exe"), Eq(4));
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}),
|
}),
|
||||||
IsOk());
|
IsOk());
|
||||||
|
|
||||||
EXPECT_THAT(st.Restart(), IsOk());
|
EXPECT_THAT(st.Restart(), IsOk());
|
||||||
|
|
||||||
EXPECT_THAT(st.Run([](sapi::Sandbox* sandbox) -> sapi::Status {
|
EXPECT_THAT(st.Run([](sapi::Sandbox* sandbox) -> absl::Status {
|
||||||
EXPECT_THAT(leak_file_descriptor(sandbox, "/proc/self/exe"), Eq(3));
|
EXPECT_THAT(leak_file_descriptor(sandbox, "/proc/self/exe"), Eq(3));
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}),
|
}),
|
||||||
IsOk());
|
IsOk());
|
||||||
}
|
}
|
||||||
@ -202,12 +202,12 @@ TEST(SandboxTest, RestartTransactionSandboxFD) {
|
|||||||
TEST(SandboxTest, RestartSandboxAfterCrash) {
|
TEST(SandboxTest, RestartSandboxAfterCrash) {
|
||||||
sapi::BasicTransaction st{absl::make_unique<SumSandbox>()};
|
sapi::BasicTransaction st{absl::make_unique<SumSandbox>()};
|
||||||
|
|
||||||
auto test_body = [](sapi::Sandbox* sandbox) -> sapi::Status {
|
auto test_body = [](sapi::Sandbox* sandbox) -> absl::Status {
|
||||||
SumApi sumapi(sandbox);
|
SumApi sumapi(sandbox);
|
||||||
// Crash the sandbox.
|
// Crash the sandbox.
|
||||||
EXPECT_THAT(sumapi.crash(), StatusIs(sapi::StatusCode::kUnavailable));
|
EXPECT_THAT(sumapi.crash(), StatusIs(absl::StatusCode::kUnavailable));
|
||||||
EXPECT_THAT(sumapi.sum(1, 2).status(),
|
EXPECT_THAT(sumapi.sum(1, 2).status(),
|
||||||
StatusIs(sapi::StatusCode::kUnavailable));
|
StatusIs(absl::StatusCode::kUnavailable));
|
||||||
EXPECT_THAT(sandbox->AwaitResult().final_status(),
|
EXPECT_THAT(sandbox->AwaitResult().final_status(),
|
||||||
Eq(sandbox2::Result::SIGNALED));
|
Eq(sandbox2::Result::SIGNALED));
|
||||||
|
|
||||||
@ -216,7 +216,7 @@ TEST(SandboxTest, RestartSandboxAfterCrash) {
|
|||||||
// The sandbox should now be responsive again.
|
// The sandbox should now be responsive again.
|
||||||
auto result_or = sumapi.sum(1, 2);
|
auto result_or = sumapi.sum(1, 2);
|
||||||
EXPECT_THAT(result_or.ValueOrDie(), Eq(3));
|
EXPECT_THAT(result_or.ValueOrDie(), Eq(3));
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
};
|
};
|
||||||
|
|
||||||
EXPECT_THAT(st.Run(test_body), IsOk());
|
EXPECT_THAT(st.Run(test_body), IsOk());
|
||||||
@ -225,12 +225,12 @@ TEST(SandboxTest, RestartSandboxAfterCrash) {
|
|||||||
TEST(SandboxTest, RestartSandboxAfterViolation) {
|
TEST(SandboxTest, RestartSandboxAfterViolation) {
|
||||||
sapi::BasicTransaction st{absl::make_unique<SumSandbox>()};
|
sapi::BasicTransaction st{absl::make_unique<SumSandbox>()};
|
||||||
|
|
||||||
auto test_body = [](sapi::Sandbox* sandbox) -> sapi::Status {
|
auto test_body = [](sapi::Sandbox* sandbox) -> absl::Status {
|
||||||
SumApi sumapi(sandbox);
|
SumApi sumapi(sandbox);
|
||||||
// Violate the sandbox policy.
|
// Violate the sandbox policy.
|
||||||
EXPECT_THAT(sumapi.violate(), StatusIs(sapi::StatusCode::kUnavailable));
|
EXPECT_THAT(sumapi.violate(), StatusIs(absl::StatusCode::kUnavailable));
|
||||||
EXPECT_THAT(sumapi.sum(1, 2).status(),
|
EXPECT_THAT(sumapi.sum(1, 2).status(),
|
||||||
StatusIs(sapi::StatusCode::kUnavailable));
|
StatusIs(absl::StatusCode::kUnavailable));
|
||||||
EXPECT_THAT(sandbox->AwaitResult().final_status(),
|
EXPECT_THAT(sandbox->AwaitResult().final_status(),
|
||||||
Eq(sandbox2::Result::VIOLATION));
|
Eq(sandbox2::Result::VIOLATION));
|
||||||
|
|
||||||
@ -240,7 +240,7 @@ TEST(SandboxTest, RestartSandboxAfterViolation) {
|
|||||||
auto result_or = sumapi.sum(1, 2);
|
auto result_or = sumapi.sum(1, 2);
|
||||||
EXPECT_THAT(result_or, IsOk());
|
EXPECT_THAT(result_or, IsOk());
|
||||||
EXPECT_THAT(result_or.ValueOrDie(), Eq(3));
|
EXPECT_THAT(result_or.ValueOrDie(), Eq(3));
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
};
|
};
|
||||||
|
|
||||||
EXPECT_THAT(st.Run(test_body), IsOk());
|
EXPECT_THAT(st.Run(test_body), IsOk());
|
||||||
@ -250,7 +250,7 @@ TEST(SandboxTest, NoRaceInAwaitResult) {
|
|||||||
auto sandbox = absl::make_unique<StringopSandbox>();
|
auto sandbox = absl::make_unique<StringopSandbox>();
|
||||||
ASSERT_THAT(sandbox->Init(), IsOk());
|
ASSERT_THAT(sandbox->Init(), IsOk());
|
||||||
StringopApi api(sandbox.get());
|
StringopApi api(sandbox.get());
|
||||||
EXPECT_THAT(api.violate(), StatusIs(sapi::StatusCode::kUnavailable));
|
EXPECT_THAT(api.violate(), StatusIs(absl::StatusCode::kUnavailable));
|
||||||
absl::SleepFor(absl::Milliseconds(200)); // make sure we lose the race
|
absl::SleepFor(absl::Milliseconds(200)); // make sure we lose the race
|
||||||
const auto& result = sandbox->AwaitResult();
|
const auto& result = sandbox->AwaitResult();
|
||||||
EXPECT_THAT(result.final_status(), Eq(sandbox2::Result::VIOLATION));
|
EXPECT_THAT(result.final_status(), Eq(sandbox2::Result::VIOLATION));
|
||||||
|
@ -462,7 +462,7 @@ class ReturnType(ArgumentType):
|
|||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
return_type: sapi::StatusOr<T> where T is original return type, or
|
return_type: sapi::StatusOr<T> where T is original return type, or
|
||||||
sapi::Status for functions returning void
|
absl::Status for functions returning void
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, function, arg_type):
|
def __init__(self, function, arg_type):
|
||||||
@ -475,7 +475,7 @@ class ReturnType(ArgumentType):
|
|||||||
# TODO(szwl): const ptrs do not play well with SAPI C++ API...
|
# TODO(szwl): const ptrs do not play well with SAPI C++ API...
|
||||||
spelling = self._clang_type.spelling.replace('const', '')
|
spelling = self._clang_type.spelling.replace('const', '')
|
||||||
return_type = 'sapi::StatusOr<{}>'.format(spelling)
|
return_type = 'sapi::StatusOr<{}>'.format(spelling)
|
||||||
return_type = 'sapi::Status' if self.is_void() else return_type
|
return_type = 'absl::Status' if self.is_void() else return_type
|
||||||
return return_type
|
return return_type
|
||||||
|
|
||||||
|
|
||||||
@ -862,7 +862,7 @@ class Generator(object):
|
|||||||
result.append(' SAPI_RETURN_IF_ERROR(sandbox_->Call("{}", &ret{}));'
|
result.append(' SAPI_RETURN_IF_ERROR(sandbox_->Call("{}", &ret{}));'
|
||||||
''.format(f.name, ', '.join(call_arguments)))
|
''.format(f.name, ', '.join(call_arguments)))
|
||||||
|
|
||||||
return_status = 'return sapi::OkStatus();'
|
return_status = 'return absl::OkStatus();'
|
||||||
if f.result and not f.result.is_void():
|
if f.result and not f.result.is_void():
|
||||||
if f.result and f.result.is_enum():
|
if f.result and f.result.is_enum():
|
||||||
return_status = ('return static_cast<{}>'
|
return_status = ('return static_cast<{}>'
|
||||||
|
@ -101,11 +101,11 @@ class TestApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// void types_6(char *)
|
// void types_6(char *)
|
||||||
sapi::Status types_6(::sapi::v::Ptr* a0) {
|
absl::Status types_6(::sapi::v::Ptr* a0) {
|
||||||
::sapi::v::Void ret;
|
::sapi::v::Void ret;
|
||||||
|
|
||||||
SAPI_RETURN_IF_ERROR(sandbox_->Call("types_6", &ret, a0));
|
SAPI_RETURN_IF_ERROR(sandbox_->Call("types_6", &ret, a0));
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -19,8 +19,8 @@ namespace sapi {
|
|||||||
|
|
||||||
constexpr absl::Duration TransactionBase::kDefaultTimeLimit;
|
constexpr absl::Duration TransactionBase::kDefaultTimeLimit;
|
||||||
|
|
||||||
sapi::Status TransactionBase::RunTransactionFunctionInSandbox(
|
absl::Status TransactionBase::RunTransactionFunctionInSandbox(
|
||||||
const std::function<sapi::Status()>& f) {
|
const std::function<absl::Status()>& f) {
|
||||||
// Run Main(), invoking Init() if this hasn't been yet done.
|
// Run Main(), invoking Init() if this hasn't been yet done.
|
||||||
SAPI_RETURN_IF_ERROR(sandbox_->Init());
|
SAPI_RETURN_IF_ERROR(sandbox_->Init());
|
||||||
|
|
||||||
@ -44,11 +44,11 @@ sapi::Status TransactionBase::RunTransactionFunctionInSandbox(
|
|||||||
return f();
|
return f();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status TransactionBase::RunTransactionLoop(
|
absl::Status TransactionBase::RunTransactionLoop(
|
||||||
const std::function<sapi::Status()>& f) {
|
const std::function<absl::Status()>& f) {
|
||||||
// Try to run Main() for a few times, return error if none of the tries
|
// Try to run Main() for a few times, return error if none of the tries
|
||||||
// succeeded.
|
// succeeded.
|
||||||
sapi::Status status;
|
absl::Status status;
|
||||||
for (int i = 0; i <= retry_count_; ++i) {
|
for (int i = 0; i <= retry_count_; ++i) {
|
||||||
status = RunTransactionFunctionInSandbox(f);
|
status = RunTransactionFunctionInSandbox(f);
|
||||||
if (status.ok()) {
|
if (status.ok()) {
|
||||||
|
@ -18,15 +18,15 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "absl/strings/str_cat.h"
|
#include "absl/strings/str_cat.h"
|
||||||
#include "absl/time/time.h"
|
#include "absl/time/time.h"
|
||||||
#include "sandboxed_api/sandbox.h"
|
#include "sandboxed_api/sandbox.h"
|
||||||
#include "sandboxed_api/util/status.h"
|
|
||||||
#include "sandboxed_api/util/status_macros.h"
|
#include "sandboxed_api/util/status_macros.h"
|
||||||
|
|
||||||
#define TRANSACTION_FAIL_IF_NOT(x, y) \
|
#define TRANSACTION_FAIL_IF_NOT(x, y) \
|
||||||
if (!(x)) { \
|
if (!(x)) { \
|
||||||
return sapi::FailedPreconditionError(y); \
|
return absl::FailedPreconditionError(y); \
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace sapi {
|
namespace sapi {
|
||||||
@ -76,7 +76,7 @@ class TransactionBase {
|
|||||||
// WARNING: This will invalidate any references to the remote process, make
|
// WARNING: This will invalidate any references to the remote process, make
|
||||||
// sure you don't keep any vars or FDs to the remote process when
|
// sure you don't keep any vars or FDs to the remote process when
|
||||||
// calling this.
|
// calling this.
|
||||||
sapi::Status Restart() {
|
absl::Status Restart() {
|
||||||
if (initialized_) {
|
if (initialized_) {
|
||||||
Finish().IgnoreError();
|
Finish().IgnoreError();
|
||||||
initialized_ = false;
|
initialized_ = false;
|
||||||
@ -92,7 +92,7 @@ class TransactionBase {
|
|||||||
sandbox_(std::move(sandbox)) {}
|
sandbox_(std::move(sandbox)) {}
|
||||||
|
|
||||||
// Runs the main (retrying) transaction loop.
|
// Runs the main (retrying) transaction loop.
|
||||||
sapi::Status RunTransactionLoop(const std::function<sapi::Status()>& f);
|
absl::Status RunTransactionLoop(const std::function<absl::Status()>& f);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Number of default transaction execution re-tries, in case of failures.
|
// Number of default transaction execution re-tries, in case of failures.
|
||||||
@ -103,16 +103,16 @@ class TransactionBase {
|
|||||||
|
|
||||||
// Executes a single function in the sandbox, used in the main transaction
|
// Executes a single function in the sandbox, used in the main transaction
|
||||||
// loop. Asserts that the sandbox has been set up and Init() was called.
|
// loop. Asserts that the sandbox has been set up and Init() was called.
|
||||||
sapi::Status RunTransactionFunctionInSandbox(
|
absl::Status RunTransactionFunctionInSandbox(
|
||||||
const std::function<sapi::Status()>& f);
|
const std::function<absl::Status()>& f);
|
||||||
|
|
||||||
// Initialization routine of the sandboxed process that will be called only
|
// Initialization routine of the sandboxed process that will be called only
|
||||||
// once upon sandboxee startup.
|
// once upon sandboxee startup.
|
||||||
virtual sapi::Status Init() { return sapi::OkStatus(); }
|
virtual absl::Status Init() { return absl::OkStatus(); }
|
||||||
|
|
||||||
// End routine for the sandboxee that gets calls when the transaction is
|
// End routine for the sandboxee that gets calls when the transaction is
|
||||||
// destroyed/restarted to clean up resources.
|
// destroyed/restarted to clean up resources.
|
||||||
virtual sapi::Status Finish() { return sapi::OkStatus(); }
|
virtual absl::Status Finish() { return absl::OkStatus(); }
|
||||||
|
|
||||||
// Number of tries this transaction will be re-executed until it succeeds.
|
// Number of tries this transaction will be re-executed until it succeeds.
|
||||||
int retry_count_;
|
int retry_count_;
|
||||||
@ -136,20 +136,20 @@ class Transaction : public TransactionBase {
|
|||||||
using TransactionBase::TransactionBase;
|
using TransactionBase::TransactionBase;
|
||||||
|
|
||||||
// Run the transaction.
|
// Run the transaction.
|
||||||
sapi::Status Run() {
|
absl::Status Run() {
|
||||||
return RunTransactionLoop([this] { return Main(); });
|
return RunTransactionLoop([this] { return Main(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// The main sandboxee routine: Can be called multiple times.
|
// The main sandboxee routine: Can be called multiple times.
|
||||||
virtual sapi::Status Main() { return sapi::OkStatus(); }
|
virtual absl::Status Main() { return absl::OkStatus(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Callback style transactions:
|
// Callback style transactions:
|
||||||
class BasicTransaction final : public TransactionBase {
|
class BasicTransaction final : public TransactionBase {
|
||||||
private:
|
private:
|
||||||
using InitFunction = std::function<sapi::Status(Sandbox*)>;
|
using InitFunction = std::function<absl::Status(Sandbox*)>;
|
||||||
using FinishFunction = std::function<sapi::Status(Sandbox*)>;
|
using FinishFunction = std::function<absl::Status(Sandbox*)>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit BasicTransaction(std::unique_ptr<Sandbox> sandbox)
|
explicit BasicTransaction(std::unique_ptr<Sandbox> sandbox)
|
||||||
@ -174,7 +174,7 @@ class BasicTransaction final : public TransactionBase {
|
|||||||
// (that is: Returning a Status and accepting a Sandbox object as first
|
// (that is: Returning a Status and accepting a Sandbox object as first
|
||||||
// parameter).
|
// parameter).
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
sapi::Status Run(T func, Args&&... args) {
|
absl::Status Run(T func, Args&&... args) {
|
||||||
return RunTransactionLoop(
|
return RunTransactionLoop(
|
||||||
[&] { return func(sandbox(), std::forward<Args>(args)...); });
|
[&] { return func(sandbox(), std::forward<Args>(args)...); });
|
||||||
}
|
}
|
||||||
@ -183,12 +183,12 @@ class BasicTransaction final : public TransactionBase {
|
|||||||
InitFunction init_function_;
|
InitFunction init_function_;
|
||||||
FinishFunction finish_function_;
|
FinishFunction finish_function_;
|
||||||
|
|
||||||
sapi::Status Init() final {
|
absl::Status Init() final {
|
||||||
return init_function_ ? init_function_(sandbox()) : sapi::OkStatus();
|
return init_function_ ? init_function_(sandbox()) : absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Finish() final {
|
absl::Status Finish() final {
|
||||||
return finish_function_ ? finish_function_(sandbox()) : sapi::OkStatus();
|
return finish_function_ ? finish_function_(sandbox()) : absl::OkStatus();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,26 +12,24 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
load("//sandboxed_api/bazel:build_defs.bzl", "sapi_platform_copts")
|
||||||
|
load("//sandboxed_api/bazel:proto.bzl", "sapi_proto_library")
|
||||||
|
|
||||||
package(default_visibility = ["//sandboxed_api:__subpackages__"])
|
package(default_visibility = ["//sandboxed_api:__subpackages__"])
|
||||||
|
|
||||||
licenses(["notice"])
|
licenses(["notice"])
|
||||||
|
|
||||||
load("//sandboxed_api/bazel:proto.bzl", "sapi_proto_library")
|
|
||||||
load("//sandboxed_api/bazel:build_defs.bzl", "sapi_platform_copts")
|
|
||||||
|
|
||||||
sapi_proto_library(
|
sapi_proto_library(
|
||||||
name = "status_proto",
|
name = "status_proto",
|
||||||
srcs = ["status.proto"],
|
srcs = ["status.proto"],
|
||||||
)
|
)
|
||||||
|
|
||||||
# A custom fork of util/task/status.h. This will become obsolete and will be
|
# Reimplementations of utility functions not released with absl::Status.
|
||||||
# replaced once Abseil releases absl::Status.
|
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "status",
|
name = "status",
|
||||||
srcs = ["status.cc"],
|
srcs = ["status.cc"],
|
||||||
hdrs = [
|
hdrs = [
|
||||||
"status.h",
|
"status.h",
|
||||||
"status_internal.h",
|
|
||||||
"status_macros.h",
|
"status_macros.h",
|
||||||
],
|
],
|
||||||
copts = sapi_platform_copts(),
|
copts = sapi_platform_copts(),
|
||||||
@ -39,7 +37,7 @@ cc_library(
|
|||||||
deps = [
|
deps = [
|
||||||
":status_cc_proto",
|
":status_cc_proto",
|
||||||
"@com_google_absl//absl/base:core_headers",
|
"@com_google_absl//absl/base:core_headers",
|
||||||
"@com_google_absl//absl/meta:type_traits",
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -58,11 +56,12 @@ cc_library(
|
|||||||
"@com_google_absl//absl/base",
|
"@com_google_absl//absl/base",
|
||||||
"@com_google_absl//absl/base:core_headers",
|
"@com_google_absl//absl/base:core_headers",
|
||||||
"@com_google_absl//absl/base:log_severity",
|
"@com_google_absl//absl/base:log_severity",
|
||||||
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_absl//absl/types:variant",
|
"@com_google_absl//absl/types:variant",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
# gMock matchers for sapi::Status and sapi::StatusOr<T> and a gUnit printer
|
# gMock matchers for absl::Status and sapi::StatusOr<T> and a gUnit printer
|
||||||
# extension for sapi::StatusOr<T>.
|
# extension for sapi::StatusOr<T>.
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "status_matchers",
|
name = "status_matchers",
|
||||||
@ -73,6 +72,7 @@ cc_library(
|
|||||||
deps = [
|
deps = [
|
||||||
":status",
|
":status",
|
||||||
":statusor",
|
":statusor",
|
||||||
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_absl//absl/types:optional",
|
"@com_google_absl//absl/types:optional",
|
||||||
"@com_google_googletest//:gtest",
|
"@com_google_googletest//:gtest",
|
||||||
],
|
],
|
||||||
@ -86,6 +86,7 @@ cc_test(
|
|||||||
deps = [
|
deps = [
|
||||||
":status",
|
":status",
|
||||||
":status_matchers",
|
":status_matchers",
|
||||||
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_googletest//:gtest_main",
|
"@com_google_googletest//:gtest_main",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -113,6 +114,7 @@ cc_test(
|
|||||||
":status_matchers",
|
":status_matchers",
|
||||||
":statusor",
|
":statusor",
|
||||||
"@com_google_absl//absl/memory",
|
"@com_google_absl//absl/memory",
|
||||||
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
"@com_google_googletest//:gtest_main",
|
"@com_google_googletest//:gtest_main",
|
||||||
],
|
],
|
||||||
|
@ -30,15 +30,15 @@ target_link_libraries(sapi_util_status_proto
|
|||||||
add_library(sapi_util_status STATIC
|
add_library(sapi_util_status STATIC
|
||||||
status.cc
|
status.cc
|
||||||
status.h
|
status.h
|
||||||
status_internal.h
|
|
||||||
status_macros.h
|
status_macros.h
|
||||||
)
|
)
|
||||||
add_library(sapi::status ALIAS sapi_util_status)
|
add_library(sapi::status ALIAS sapi_util_status)
|
||||||
target_link_libraries(sapi_util_status
|
target_link_libraries(sapi_util_status
|
||||||
PRIVATE absl::core_headers
|
PRIVATE absl::core_headers
|
||||||
|
absl::status
|
||||||
absl::strings
|
absl::strings
|
||||||
absl::type_traits
|
|
||||||
sapi::base
|
sapi::base
|
||||||
|
protobuf::libprotobuf
|
||||||
PUBLIC sapi::status_proto
|
PUBLIC sapi::status_proto
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -88,7 +88,8 @@ if(SAPI_ENABLE_TESTS)
|
|||||||
gmock
|
gmock
|
||||||
gtest
|
gtest
|
||||||
sapi::base
|
sapi::base
|
||||||
PUBLIC sapi::status
|
PUBLIC absl::status
|
||||||
|
sapi::status
|
||||||
sapi::statusor
|
sapi::statusor
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -102,4 +103,15 @@ if(SAPI_ENABLE_TESTS)
|
|||||||
absl::type_traits
|
absl::type_traits
|
||||||
)
|
)
|
||||||
gtest_discover_tests(status_test)
|
gtest_discover_tests(status_test)
|
||||||
|
|
||||||
|
# sandboxed_api/util:statusor_test
|
||||||
|
add_executable(statusor_test
|
||||||
|
statusor_test.cc
|
||||||
|
)
|
||||||
|
target_link_libraries(statusor_test PRIVATE
|
||||||
|
sapi::status_matchers
|
||||||
|
sapi::test_main
|
||||||
|
absl::type_traits
|
||||||
|
)
|
||||||
|
gtest_discover_tests(statusor_test)
|
||||||
endif()
|
endif()
|
||||||
|
@ -14,177 +14,27 @@
|
|||||||
|
|
||||||
#include "sandboxed_api/util/status.h"
|
#include "sandboxed_api/util/status.h"
|
||||||
|
|
||||||
#include "absl/strings/str_cat.h"
|
#include "absl/status/status.h"
|
||||||
|
|
||||||
namespace sapi {
|
namespace sapi {
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
std::string CodeEnumToString(StatusCode code) {
|
void SaveStatusToProto(const absl::Status& status, StatusProto* out) {
|
||||||
switch (code) {
|
out->set_code(status.raw_code());
|
||||||
case StatusCode::kOk:
|
out->set_message(std::string(status.message()));
|
||||||
return "OK";
|
auto* payloads = out->mutable_payloads();
|
||||||
case StatusCode::kCancelled:
|
status.ForEachPayload(
|
||||||
return "CANCELLED";
|
[payloads](absl::string_view type_key, const absl::Cord& payload) {
|
||||||
case StatusCode::kUnknown:
|
(*payloads)[std::string(type_key)] = static_cast<std::string>(payload);
|
||||||
return "UNKNOWN";
|
});
|
||||||
case StatusCode::kInvalidArgument:
|
}
|
||||||
return "INVALID_ARGUMENT";
|
|
||||||
case StatusCode::kDeadlineExceeded:
|
absl::Status MakeStatusFromProto(const StatusProto& proto) {
|
||||||
return "DEADLINE_EXCEEDED";
|
absl::Status status(static_cast<absl::StatusCode>(proto.code()),
|
||||||
case StatusCode::kNotFound:
|
proto.message());
|
||||||
return "NOT_FOUND";
|
for (const auto& [type_key, payload] : proto.payloads()) {
|
||||||
case StatusCode::kAlreadyExists:
|
status.SetPayload(type_key, absl::Cord(payload));
|
||||||
return "ALREADY_EXISTS";
|
|
||||||
case StatusCode::kPermissionDenied:
|
|
||||||
return "PERMISSION_DENIED";
|
|
||||||
case StatusCode::kUnauthenticated:
|
|
||||||
return "UNAUTHENTICATED";
|
|
||||||
case StatusCode::kResourceExhausted:
|
|
||||||
return "RESOURCE_EXHAUSTED";
|
|
||||||
case StatusCode::kFailedPrecondition:
|
|
||||||
return "FAILED_PRECONDITION";
|
|
||||||
case StatusCode::kAborted:
|
|
||||||
return "ABORTED";
|
|
||||||
case StatusCode::kOutOfRange:
|
|
||||||
return "OUT_OF_RANGE";
|
|
||||||
case StatusCode::kUnimplemented:
|
|
||||||
return "UNIMPLEMENTED";
|
|
||||||
case StatusCode::kInternal:
|
|
||||||
return "INTERNAL";
|
|
||||||
case StatusCode::kUnavailable:
|
|
||||||
return "UNAVAILABLE";
|
|
||||||
case StatusCode::kDataLoss:
|
|
||||||
return "DATA_LOSS";
|
|
||||||
}
|
}
|
||||||
return "UNKNOWN";
|
return status;
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
|
|
||||||
Status::Status() : error_code_{static_cast<int>(StatusCode::kOk)} {}
|
|
||||||
|
|
||||||
Status::Status(Status&& other)
|
|
||||||
: error_code_(other.error_code_), message_(std::move(other.message_)) {
|
|
||||||
other.Set(StatusCode::kUnknown, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
Status& Status::operator=(Status&& other) {
|
|
||||||
error_code_ = other.error_code_;
|
|
||||||
message_ = std::move(other.message_);
|
|
||||||
other.Set(StatusCode::kUnknown, "");
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Status::ToString() const {
|
|
||||||
return ok() ? "OK"
|
|
||||||
: absl::StrCat("generic::",
|
|
||||||
internal::CodeEnumToString(
|
|
||||||
static_cast<StatusCode>(error_code_)),
|
|
||||||
": ", message_);
|
|
||||||
}
|
|
||||||
|
|
||||||
Status OkStatus() { return Status{}; }
|
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, const Status& status) {
|
|
||||||
return os << status.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
Status AbortedError(absl::string_view message) {
|
|
||||||
return Status{StatusCode::kAborted, message};
|
|
||||||
}
|
|
||||||
Status AlreadyExistsError(absl::string_view message) {
|
|
||||||
return Status{StatusCode::kAlreadyExists, message};
|
|
||||||
}
|
|
||||||
Status CancelledError(absl::string_view message) {
|
|
||||||
return Status{StatusCode::kCancelled, message};
|
|
||||||
}
|
|
||||||
Status DataLossError(absl::string_view message) {
|
|
||||||
return Status{StatusCode::kDataLoss, message};
|
|
||||||
}
|
|
||||||
Status DeadlineExceededError(absl::string_view message) {
|
|
||||||
return Status{StatusCode::kDeadlineExceeded, message};
|
|
||||||
}
|
|
||||||
Status FailedPreconditionError(absl::string_view message) {
|
|
||||||
return Status{StatusCode::kFailedPrecondition, message};
|
|
||||||
}
|
|
||||||
Status InternalError(absl::string_view message) {
|
|
||||||
return Status{StatusCode::kInternal, message};
|
|
||||||
}
|
|
||||||
Status InvalidArgumentError(absl::string_view message) {
|
|
||||||
return Status{StatusCode::kInvalidArgument, message};
|
|
||||||
}
|
|
||||||
Status NotFoundError(absl::string_view message) {
|
|
||||||
return Status{StatusCode::kNotFound, message};
|
|
||||||
}
|
|
||||||
Status OutOfRangeError(absl::string_view message) {
|
|
||||||
return Status{StatusCode::kOutOfRange, message};
|
|
||||||
}
|
|
||||||
Status PermissionDeniedError(absl::string_view message) {
|
|
||||||
return Status{StatusCode::kPermissionDenied, message};
|
|
||||||
}
|
|
||||||
Status ResourceExhaustedError(absl::string_view message) {
|
|
||||||
return Status{StatusCode::kResourceExhausted, message};
|
|
||||||
}
|
|
||||||
Status UnauthenticatedError(absl::string_view message) {
|
|
||||||
return Status{StatusCode::kUnauthenticated, message};
|
|
||||||
}
|
|
||||||
Status UnavailableError(absl::string_view message) {
|
|
||||||
return Status{StatusCode::kUnavailable, message};
|
|
||||||
}
|
|
||||||
Status UnimplementedError(absl::string_view message) {
|
|
||||||
return Status{StatusCode::kUnimplemented, message};
|
|
||||||
}
|
|
||||||
Status UnknownError(absl::string_view message) {
|
|
||||||
return Status{StatusCode::kUnknown, message};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsAborted(const Status& status) {
|
|
||||||
return status.code() == StatusCode::kAborted;
|
|
||||||
}
|
|
||||||
bool IsAlreadyExists(const Status& status) {
|
|
||||||
return status.code() == StatusCode::kAlreadyExists;
|
|
||||||
}
|
|
||||||
bool IsCancelled(const Status& status) {
|
|
||||||
return status.code() == StatusCode::kCancelled;
|
|
||||||
}
|
|
||||||
bool IsDataLoss(const Status& status) {
|
|
||||||
return status.code() == StatusCode::kDataLoss;
|
|
||||||
}
|
|
||||||
bool IsDeadlineExceeded(const Status& status) {
|
|
||||||
return status.code() == StatusCode::kDeadlineExceeded;
|
|
||||||
}
|
|
||||||
bool IsFailedPrecondition(const Status& status) {
|
|
||||||
return status.code() == StatusCode::kFailedPrecondition;
|
|
||||||
}
|
|
||||||
bool IsInternal(const Status& status) {
|
|
||||||
return status.code() == StatusCode::kInternal;
|
|
||||||
}
|
|
||||||
bool IsInvalidArgument(const Status& status) {
|
|
||||||
return status.code() == StatusCode::kInvalidArgument;
|
|
||||||
}
|
|
||||||
bool IsNotFound(const Status& status) {
|
|
||||||
return status.code() == StatusCode::kNotFound;
|
|
||||||
}
|
|
||||||
bool IsOutOfRange(const Status& status) {
|
|
||||||
return status.code() == StatusCode::kOutOfRange;
|
|
||||||
}
|
|
||||||
bool IsPermissionDenied(const Status& status) {
|
|
||||||
return status.code() == StatusCode::kPermissionDenied;
|
|
||||||
}
|
|
||||||
bool IsResourceExhausted(const Status& status) {
|
|
||||||
return status.code() == StatusCode::kResourceExhausted;
|
|
||||||
}
|
|
||||||
bool IsUnauthenticated(const Status& status) {
|
|
||||||
return status.code() == StatusCode::kUnauthenticated;
|
|
||||||
}
|
|
||||||
bool IsUnavailable(const Status& status) {
|
|
||||||
return status.code() == StatusCode::kUnavailable;
|
|
||||||
}
|
|
||||||
bool IsUnimplemented(const Status& status) {
|
|
||||||
return status.code() == StatusCode::kUnimplemented;
|
|
||||||
}
|
|
||||||
bool IsUnknown(const Status& status) {
|
|
||||||
return status.code() == StatusCode::kUnknown;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sapi
|
} // namespace sapi
|
||||||
|
@ -19,161 +19,13 @@
|
|||||||
#ifndef THIRD_PARTY_SAPI_UTIL_STATUS_H_
|
#ifndef THIRD_PARTY_SAPI_UTIL_STATUS_H_
|
||||||
#define THIRD_PARTY_SAPI_UTIL_STATUS_H_
|
#define THIRD_PARTY_SAPI_UTIL_STATUS_H_
|
||||||
|
|
||||||
#include <ostream>
|
#include "absl/status/status.h"
|
||||||
#include <string>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
#include "absl/base/attributes.h"
|
|
||||||
#include "absl/meta/type_traits.h"
|
|
||||||
#include "absl/strings/string_view.h"
|
|
||||||
#include "sandboxed_api/util/status.pb.h"
|
#include "sandboxed_api/util/status.pb.h"
|
||||||
#include "sandboxed_api/util/status_internal.h"
|
|
||||||
|
|
||||||
namespace sapi {
|
namespace sapi {
|
||||||
|
|
||||||
enum class StatusCode {
|
void SaveStatusToProto(const absl::Status& status, StatusProto* out);
|
||||||
kOk = 0,
|
absl::Status MakeStatusFromProto(const StatusProto& proto);
|
||||||
kCancelled = 1,
|
|
||||||
kUnknown = 2,
|
|
||||||
kInvalidArgument = 3,
|
|
||||||
kDeadlineExceeded = 4,
|
|
||||||
kNotFound = 5,
|
|
||||||
kAlreadyExists = 6,
|
|
||||||
kPermissionDenied = 7,
|
|
||||||
kResourceExhausted = 8,
|
|
||||||
kFailedPrecondition = 9,
|
|
||||||
kAborted = 10,
|
|
||||||
kOutOfRange = 11,
|
|
||||||
kUnimplemented = 12,
|
|
||||||
kInternal = 13,
|
|
||||||
kUnavailable = 14,
|
|
||||||
kDataLoss = 15,
|
|
||||||
kUnauthenticated = 16,
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
std::string CodeEnumToString(StatusCode code);
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
|
|
||||||
class Status {
|
|
||||||
public:
|
|
||||||
Status();
|
|
||||||
|
|
||||||
template <typename Enum>
|
|
||||||
Status(Enum code, absl::string_view message) {
|
|
||||||
Set(code, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
Status(const Status&) = default;
|
|
||||||
Status(Status&& other);
|
|
||||||
|
|
||||||
template <typename StatusT,
|
|
||||||
typename E = typename absl::enable_if_t<
|
|
||||||
status_internal::status_type_traits<StatusT>::is_status>>
|
|
||||||
explicit Status(const StatusT& other) {
|
|
||||||
Set(status_internal::status_type_traits<StatusT>::CanonicalCode(other),
|
|
||||||
other.message());
|
|
||||||
}
|
|
||||||
|
|
||||||
Status& operator=(const Status&) = default;
|
|
||||||
Status& operator=(Status&& other);
|
|
||||||
|
|
||||||
template <typename StatusT,
|
|
||||||
typename E = typename absl::enable_if_t<
|
|
||||||
status_internal::status_type_traits<StatusT>::is_status>>
|
|
||||||
StatusT ToOtherStatus() {
|
|
||||||
return StatusT(status_internal::ErrorCodeHolder(error_code_), message_);
|
|
||||||
}
|
|
||||||
|
|
||||||
int error_code() const { return error_code_; }
|
|
||||||
absl::string_view error_message() const { return message_; }
|
|
||||||
absl::string_view message() const { return message_; }
|
|
||||||
ABSL_MUST_USE_RESULT bool ok() const { return error_code_ == 0; }
|
|
||||||
StatusCode code() const { return static_cast<StatusCode>(error_code_); }
|
|
||||||
|
|
||||||
std::string ToString() const;
|
|
||||||
|
|
||||||
void IgnoreError() const {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
template <typename Enum, typename StringViewT>
|
|
||||||
void Set(Enum code, StringViewT message) {
|
|
||||||
error_code_ = static_cast<int>(code);
|
|
||||||
if (error_code_ != 0) {
|
|
||||||
message_ = std::string(message);
|
|
||||||
} else {
|
|
||||||
message_.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int error_code_;
|
|
||||||
std::string message_;
|
|
||||||
};
|
|
||||||
|
|
||||||
Status OkStatus();
|
|
||||||
|
|
||||||
inline bool operator==(const Status& lhs, const Status& rhs) {
|
|
||||||
return (lhs.error_code() == rhs.error_code()) &&
|
|
||||||
(lhs.error_message() == rhs.error_message());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator!=(const Status& lhs, const Status& rhs) {
|
|
||||||
return !(lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Each of the functions below creates a canonical error with the given
|
|
||||||
// message. The error code of the returned status object matches the name of
|
|
||||||
// the function.
|
|
||||||
Status AbortedError(absl::string_view message);
|
|
||||||
Status AlreadyExistsError(absl::string_view message);
|
|
||||||
Status CancelledError(absl::string_view message);
|
|
||||||
Status DataLossError(absl::string_view message);
|
|
||||||
Status DeadlineExceededError(absl::string_view message);
|
|
||||||
Status FailedPreconditionError(absl::string_view message);
|
|
||||||
Status InternalError(absl::string_view message);
|
|
||||||
Status InvalidArgumentError(absl::string_view message);
|
|
||||||
Status NotFoundError(absl::string_view message);
|
|
||||||
Status OutOfRangeError(absl::string_view message);
|
|
||||||
Status PermissionDeniedError(absl::string_view message);
|
|
||||||
Status ResourceExhaustedError(absl::string_view message);
|
|
||||||
Status UnauthenticatedError(absl::string_view message);
|
|
||||||
Status UnavailableError(absl::string_view message);
|
|
||||||
Status UnimplementedError(absl::string_view message);
|
|
||||||
Status UnknownError(absl::string_view message);
|
|
||||||
|
|
||||||
// Each of the functions below returns true if the given status matches the
|
|
||||||
// canonical error code implied by the function's name. If necessary, the
|
|
||||||
// status will be converted to the canonical error space to perform the
|
|
||||||
// comparison.
|
|
||||||
ABSL_MUST_USE_RESULT bool IsAborted(const Status& status);
|
|
||||||
ABSL_MUST_USE_RESULT bool IsAlreadyExists(const Status& status);
|
|
||||||
ABSL_MUST_USE_RESULT bool IsCancelled(const Status& status);
|
|
||||||
ABSL_MUST_USE_RESULT bool IsDataLoss(const Status& status);
|
|
||||||
ABSL_MUST_USE_RESULT bool IsDeadlineExceeded(const Status& status);
|
|
||||||
ABSL_MUST_USE_RESULT bool IsFailedPrecondition(const Status& status);
|
|
||||||
ABSL_MUST_USE_RESULT bool IsInternal(const Status& status);
|
|
||||||
ABSL_MUST_USE_RESULT bool IsInvalidArgument(const Status& status);
|
|
||||||
ABSL_MUST_USE_RESULT bool IsNotFound(const Status& status);
|
|
||||||
ABSL_MUST_USE_RESULT bool IsOutOfRange(const Status& status);
|
|
||||||
ABSL_MUST_USE_RESULT bool IsPermissionDenied(const Status& status);
|
|
||||||
ABSL_MUST_USE_RESULT bool IsResourceExhausted(const Status& status);
|
|
||||||
ABSL_MUST_USE_RESULT bool IsUnauthenticated(const Status& status);
|
|
||||||
ABSL_MUST_USE_RESULT bool IsUnavailable(const Status& status);
|
|
||||||
ABSL_MUST_USE_RESULT bool IsUnimplemented(const Status& status);
|
|
||||||
ABSL_MUST_USE_RESULT bool IsUnknown(const Status& status);
|
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, const Status& status);
|
|
||||||
|
|
||||||
inline void SaveStatusToProto(const Status& status, StatusProto* out) {
|
|
||||||
out->set_code(status.error_code());
|
|
||||||
out->set_error_message(std::string(status.error_message()));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Status MakeStatusFromProto(const StatusProto& proto) {
|
|
||||||
return Status(proto.code(), proto.error_message());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace sapi
|
} // namespace sapi
|
||||||
|
|
||||||
|
@ -17,7 +17,8 @@ syntax = "proto3";
|
|||||||
package sapi;
|
package sapi;
|
||||||
|
|
||||||
message StatusProto {
|
message StatusProto {
|
||||||
reserved 2; // For wire compatibility with the original StatusProto
|
reserved 2, 4, 5; // For compatibility with the original StatusProto
|
||||||
int32 code = 1;
|
int32 code = 1;
|
||||||
string error_message = 3;
|
string message = 3;
|
||||||
};
|
map<string, bytes> payloads = 297070138;
|
||||||
|
}
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
// 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 THIRD_PARTY_SAPI_UTIL_STATUS_INTERNAL_H_
|
|
||||||
#define THIRD_PARTY_SAPI_UTIL_STATUS_INTERNAL_H_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
#include "absl/meta/type_traits.h"
|
|
||||||
|
|
||||||
namespace sapi {
|
|
||||||
namespace status_internal {
|
|
||||||
|
|
||||||
struct ErrorCodeHolder {
|
|
||||||
explicit ErrorCodeHolder(int code) : error_code(code) {}
|
|
||||||
|
|
||||||
template <typename EnumT,
|
|
||||||
typename E = typename absl::enable_if_t<std::is_enum<EnumT>::value>>
|
|
||||||
operator EnumT() { // NOLINT(runtime/explicit)
|
|
||||||
return static_cast<EnumT>(error_code);
|
|
||||||
}
|
|
||||||
int error_code;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename StatusT>
|
|
||||||
struct status_type_traits {
|
|
||||||
private:
|
|
||||||
template <typename StatusU>
|
|
||||||
static auto CheckMinimalApi(StatusU* s, int* i, std::string* str, bool* b)
|
|
||||||
-> decltype(StatusU(ErrorCodeHolder(0), ""), *i = s->error_code(),
|
|
||||||
*str = s->error_message(), *b = s->ok(), std::true_type());
|
|
||||||
|
|
||||||
template <typename StatusU>
|
|
||||||
static auto CheckMinimalApi(...) -> decltype(std::false_type());
|
|
||||||
using minimal_api_type = decltype(CheckMinimalApi<StatusT>(
|
|
||||||
static_cast<StatusT*>(0), static_cast<int*>(0),
|
|
||||||
static_cast<std::string*>(0), static_cast<bool*>(0)));
|
|
||||||
|
|
||||||
public:
|
|
||||||
static constexpr bool is_status = minimal_api_type::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace status_internal
|
|
||||||
} // namespace sapi
|
|
||||||
|
|
||||||
#endif // THIRD_PARTY_SAPI_UTIL_STATUS_INTERNAL_H_
|
|
@ -19,7 +19,7 @@
|
|||||||
#define THIRD_PARTY_SAPI_UTIL_STATUS_MACROS_H_
|
#define THIRD_PARTY_SAPI_UTIL_STATUS_MACROS_H_
|
||||||
|
|
||||||
#include "absl/base/optimization.h"
|
#include "absl/base/optimization.h"
|
||||||
#include "sandboxed_api/util/status.h"
|
#include "absl/status/status.h"
|
||||||
|
|
||||||
// Internal helper for concatenating macro values.
|
// Internal helper for concatenating macro values.
|
||||||
#define SAPI_MACROS_IMPL_CONCAT_INNER_(x, y) x##y
|
#define SAPI_MACROS_IMPL_CONCAT_INNER_(x, y) x##y
|
||||||
|
@ -28,29 +28,29 @@ namespace sapi {
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
TEST(ReturnIfError, ReturnsOnErrorStatus) {
|
TEST(ReturnIfError, ReturnsOnErrorStatus) {
|
||||||
auto func = []() -> Status {
|
auto func = []() -> absl::Status {
|
||||||
SAPI_RETURN_IF_ERROR(OkStatus());
|
SAPI_RETURN_IF_ERROR(absl::OkStatus());
|
||||||
SAPI_RETURN_IF_ERROR(OkStatus());
|
SAPI_RETURN_IF_ERROR(absl::OkStatus());
|
||||||
SAPI_RETURN_IF_ERROR(Status(sapi::StatusCode::kUnknown, "EXPECTED"));
|
SAPI_RETURN_IF_ERROR(absl::Status(absl::StatusCode::kUnknown, "EXPECTED"));
|
||||||
return Status(sapi::StatusCode::kUnknown, "ERROR");
|
return absl::Status(absl::StatusCode::kUnknown, "ERROR");
|
||||||
};
|
};
|
||||||
|
|
||||||
EXPECT_THAT(func(), StatusIs(sapi::StatusCode::kUnknown, "EXPECTED"));
|
EXPECT_THAT(func(), StatusIs(absl::StatusCode::kUnknown, "EXPECTED"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ReturnIfError, ReturnsOnErrorFromLambda) {
|
TEST(ReturnIfError, ReturnsOnErrorFromLambda) {
|
||||||
auto func = []() -> Status {
|
auto func = []() -> absl::Status {
|
||||||
SAPI_RETURN_IF_ERROR([] { return sapi::OkStatus(); }());
|
SAPI_RETURN_IF_ERROR([] { return absl::OkStatus(); }());
|
||||||
SAPI_RETURN_IF_ERROR(
|
SAPI_RETURN_IF_ERROR(
|
||||||
[] { return Status(sapi::StatusCode::kUnknown, "EXPECTED"); }());
|
[] { return absl::Status(absl::StatusCode::kUnknown, "EXPECTED"); }());
|
||||||
return Status(sapi::StatusCode::kUnknown, "ERROR");
|
return absl::Status(absl::StatusCode::kUnknown, "ERROR");
|
||||||
};
|
};
|
||||||
|
|
||||||
EXPECT_THAT(func(), StatusIs(sapi::StatusCode::kUnknown, "EXPECTED"));
|
EXPECT_THAT(func(), StatusIs(absl::StatusCode::kUnknown, "EXPECTED"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AssignOrReturn, AssignsMultipleVariablesInSequence) {
|
TEST(AssignOrReturn, AssignsMultipleVariablesInSequence) {
|
||||||
auto func = []() -> Status {
|
auto func = []() -> absl::Status {
|
||||||
int value1;
|
int value1;
|
||||||
SAPI_ASSIGN_OR_RETURN(value1, StatusOr<int>(1));
|
SAPI_ASSIGN_OR_RETURN(value1, StatusOr<int>(1));
|
||||||
EXPECT_EQ(1, value1);
|
EXPECT_EQ(1, value1);
|
||||||
@ -61,56 +61,56 @@ TEST(AssignOrReturn, AssignsMultipleVariablesInSequence) {
|
|||||||
SAPI_ASSIGN_OR_RETURN(value3, StatusOr<int>(3));
|
SAPI_ASSIGN_OR_RETURN(value3, StatusOr<int>(3));
|
||||||
EXPECT_EQ(3, value3);
|
EXPECT_EQ(3, value3);
|
||||||
int value4;
|
int value4;
|
||||||
SAPI_ASSIGN_OR_RETURN(
|
SAPI_ASSIGN_OR_RETURN(value4, StatusOr<int>(absl::Status(
|
||||||
value4, StatusOr<int>(Status(sapi::StatusCode::kUnknown, "EXPECTED")));
|
absl::StatusCode::kUnknown, "EXPECTED")));
|
||||||
return Status(sapi::StatusCode::kUnknown,
|
return absl::Status(absl::StatusCode::kUnknown,
|
||||||
absl::StrCat("ERROR: assigned value ", value4));
|
absl::StrCat("ERROR: assigned value ", value4));
|
||||||
};
|
};
|
||||||
|
|
||||||
EXPECT_THAT(func(), StatusIs(sapi::StatusCode::kUnknown, "EXPECTED"));
|
EXPECT_THAT(func(), StatusIs(absl::StatusCode::kUnknown, "EXPECTED"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AssignOrReturn, AssignsRepeatedlyToSingleVariable) {
|
TEST(AssignOrReturn, AssignsRepeatedlyToSingleVariable) {
|
||||||
auto func = []() -> Status {
|
auto func = []() -> absl::Status {
|
||||||
int value = 1;
|
int value = 1;
|
||||||
SAPI_ASSIGN_OR_RETURN(value, StatusOr<int>(2));
|
SAPI_ASSIGN_OR_RETURN(value, StatusOr<int>(2));
|
||||||
EXPECT_EQ(2, value);
|
EXPECT_EQ(2, value);
|
||||||
SAPI_ASSIGN_OR_RETURN(value, StatusOr<int>(3));
|
SAPI_ASSIGN_OR_RETURN(value, StatusOr<int>(3));
|
||||||
EXPECT_EQ(3, value);
|
EXPECT_EQ(3, value);
|
||||||
SAPI_ASSIGN_OR_RETURN(
|
SAPI_ASSIGN_OR_RETURN(value, StatusOr<int>(absl::Status(
|
||||||
value, StatusOr<int>(Status(sapi::StatusCode::kUnknown, "EXPECTED")));
|
absl::StatusCode::kUnknown, "EXPECTED")));
|
||||||
return Status(sapi::StatusCode::kUnknown, "ERROR");
|
return absl::Status(absl::StatusCode::kUnknown, "ERROR");
|
||||||
};
|
};
|
||||||
|
|
||||||
EXPECT_THAT(func(), StatusIs(sapi::StatusCode::kUnknown, "EXPECTED"));
|
EXPECT_THAT(func(), StatusIs(absl::StatusCode::kUnknown, "EXPECTED"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AssignOrReturn, MovesUniquePtr) {
|
TEST(AssignOrReturn, MovesUniquePtr) {
|
||||||
auto func = []() -> Status {
|
auto func = []() -> absl::Status {
|
||||||
std::unique_ptr<int> ptr;
|
std::unique_ptr<int> ptr;
|
||||||
SAPI_ASSIGN_OR_RETURN(
|
SAPI_ASSIGN_OR_RETURN(
|
||||||
ptr, StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(1)));
|
ptr, StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(1)));
|
||||||
EXPECT_EQ(*ptr, 1);
|
EXPECT_EQ(*ptr, 1);
|
||||||
return Status(sapi::StatusCode::kUnknown, "EXPECTED");
|
return absl::Status(absl::StatusCode::kUnknown, "EXPECTED");
|
||||||
};
|
};
|
||||||
|
|
||||||
EXPECT_THAT(func(), StatusIs(sapi::StatusCode::kUnknown, "EXPECTED"));
|
EXPECT_THAT(func(), StatusIs(absl::StatusCode::kUnknown, "EXPECTED"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AssignOrReturn, DoesNotAssignUniquePtrOnErrorStatus) {
|
TEST(AssignOrReturn, DoesNotAssignUniquePtrOnErrorStatus) {
|
||||||
auto func = []() -> Status {
|
auto func = []() -> absl::Status {
|
||||||
std::unique_ptr<int> ptr;
|
std::unique_ptr<int> ptr;
|
||||||
SAPI_ASSIGN_OR_RETURN(ptr, StatusOr<std::unique_ptr<int>>(Status(
|
SAPI_ASSIGN_OR_RETURN(ptr, StatusOr<std::unique_ptr<int>>(absl::Status(
|
||||||
sapi::StatusCode::kUnknown, "EXPECTED")));
|
absl::StatusCode::kUnknown, "EXPECTED")));
|
||||||
EXPECT_EQ(ptr, nullptr);
|
EXPECT_EQ(ptr, nullptr);
|
||||||
return OkStatus();
|
return absl::OkStatus();
|
||||||
};
|
};
|
||||||
|
|
||||||
EXPECT_THAT(func(), StatusIs(sapi::StatusCode::kUnknown, "EXPECTED"));
|
EXPECT_THAT(func(), StatusIs(absl::StatusCode::kUnknown, "EXPECTED"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AssignOrReturn, MovesUniquePtrRepeatedlyToSingleVariable) {
|
TEST(AssignOrReturn, MovesUniquePtrRepeatedlyToSingleVariable) {
|
||||||
auto func = []() -> Status {
|
auto func = []() -> absl::Status {
|
||||||
std::unique_ptr<int> ptr;
|
std::unique_ptr<int> ptr;
|
||||||
SAPI_ASSIGN_OR_RETURN(
|
SAPI_ASSIGN_OR_RETURN(
|
||||||
ptr, StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(1)));
|
ptr, StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(1)));
|
||||||
@ -118,10 +118,10 @@ TEST(AssignOrReturn, MovesUniquePtrRepeatedlyToSingleVariable) {
|
|||||||
SAPI_ASSIGN_OR_RETURN(
|
SAPI_ASSIGN_OR_RETURN(
|
||||||
ptr, StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(2)));
|
ptr, StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(2)));
|
||||||
EXPECT_EQ(*ptr, 2);
|
EXPECT_EQ(*ptr, 2);
|
||||||
return Status(sapi::StatusCode::kUnknown, "EXPECTED");
|
return absl::Status(absl::StatusCode::kUnknown, "EXPECTED");
|
||||||
};
|
};
|
||||||
|
|
||||||
EXPECT_THAT(func(), StatusIs(sapi::StatusCode::kUnknown, "EXPECTED"));
|
EXPECT_THAT(func(), StatusIs(absl::StatusCode::kUnknown, "EXPECTED"));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "absl/types/optional.h"
|
#include "absl/types/optional.h"
|
||||||
#include "sandboxed_api/util/status.h"
|
|
||||||
#include "sandboxed_api/util/status_macros.h"
|
#include "sandboxed_api/util/status_macros.h"
|
||||||
#include "sandboxed_api/util/statusor.h"
|
#include "sandboxed_api/util/statusor.h"
|
||||||
|
|
||||||
@ -52,25 +52,25 @@ class IsOkMatcher {
|
|||||||
void DescribeNegationTo(std::ostream* os) const { *os << "is not OK"; }
|
void DescribeNegationTo(std::ostream* os) const { *os << "is not OK"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Enum>
|
|
||||||
class StatusIsMatcher {
|
class StatusIsMatcher {
|
||||||
public:
|
public:
|
||||||
StatusIsMatcher(const StatusIsMatcher&) = default;
|
StatusIsMatcher(const StatusIsMatcher&) = default;
|
||||||
StatusIsMatcher& operator=(const StatusIsMatcher&) = default;
|
StatusIsMatcher& operator=(const StatusIsMatcher&) = default;
|
||||||
|
|
||||||
StatusIsMatcher(Enum code, absl::optional<absl::string_view> message)
|
StatusIsMatcher(absl::StatusCode code,
|
||||||
: code_{code}, message_{message} {}
|
absl::optional<absl::string_view> message)
|
||||||
|
: code_(code), message_(message) {}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool MatchAndExplain(const T& value,
|
bool MatchAndExplain(const T& value,
|
||||||
::testing::MatchResultListener* listener) const {
|
::testing::MatchResultListener* listener) const {
|
||||||
auto status = GetStatus(value);
|
auto status = GetStatus(value);
|
||||||
if (code_ != status.code()) {
|
if (code_ != status.code()) {
|
||||||
*listener << "whose error code is generic::"
|
*listener << "whose error code is "
|
||||||
<< internal::CodeEnumToString(status.code());
|
<< absl::StatusCodeToString(status.code());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (message_.has_value() && status.error_message() != message_.value()) {
|
if (message_.has_value() && status.message() != message_.value()) {
|
||||||
*listener << "whose error message is '" << message_.value() << "'";
|
*listener << "whose error message is '" << message_.value() << "'";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -78,16 +78,14 @@ class StatusIsMatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DescribeTo(std::ostream* os) const {
|
void DescribeTo(std::ostream* os) const {
|
||||||
*os << "has a status code that is generic::"
|
*os << "has a status code that is " << absl::StatusCodeToString(code_);
|
||||||
<< internal::CodeEnumToString(code_);
|
|
||||||
if (message_.has_value()) {
|
if (message_.has_value()) {
|
||||||
*os << ", and has an error message that is '" << message_.value() << "'";
|
*os << ", and has an error message that is '" << message_.value() << "'";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescribeNegationTo(std::ostream* os) const {
|
void DescribeNegationTo(std::ostream* os) const {
|
||||||
*os << "has a status code that is not generic::"
|
*os << "has a status code that is not " << absl::StatusCodeToString(code_);
|
||||||
<< internal::CodeEnumToString(code_);
|
|
||||||
if (message_.has_value()) {
|
if (message_.has_value()) {
|
||||||
*os << ", and has an error message that is not '" << message_.value()
|
*os << ", and has an error message that is not '" << message_.value()
|
||||||
<< "'";
|
<< "'";
|
||||||
@ -109,7 +107,7 @@ class StatusIsMatcher {
|
|||||||
return status_or.status();
|
return status_or.status();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Enum code_;
|
const absl::StatusCode code_;
|
||||||
const absl::optional<std::string> message_;
|
const absl::optional<std::string> message_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -119,11 +117,11 @@ inline ::testing::PolymorphicMatcher<internal::IsOkMatcher> IsOk() {
|
|||||||
return ::testing::MakePolymorphicMatcher(internal::IsOkMatcher{});
|
return ::testing::MakePolymorphicMatcher(internal::IsOkMatcher{});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Enum>
|
inline ::testing::PolymorphicMatcher<internal::StatusIsMatcher> StatusIs(
|
||||||
::testing::PolymorphicMatcher<internal::StatusIsMatcher<Enum>> StatusIs(
|
absl::StatusCode code,
|
||||||
Enum code, absl::optional<absl::string_view> message = absl::nullopt) {
|
absl::optional<absl::string_view> message = absl::nullopt) {
|
||||||
return ::testing::MakePolymorphicMatcher(
|
return ::testing::MakePolymorphicMatcher(
|
||||||
internal::StatusIsMatcher<Enum>{code, message});
|
internal::StatusIsMatcher(code, message));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sapi
|
} // namespace sapi
|
||||||
|
@ -12,209 +12,49 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "sandboxed_api/util/status.h"
|
#include "absl/status/status.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "sandboxed_api/util/status_matchers.h"
|
#include "sandboxed_api/util/status.h"
|
||||||
|
|
||||||
using ::testing::Eq;
|
using ::testing::Eq;
|
||||||
using ::testing::IsEmpty;
|
|
||||||
using ::testing::IsFalse;
|
|
||||||
using ::testing::IsTrue;
|
|
||||||
using ::testing::Ne;
|
|
||||||
using ::testing::Not;
|
|
||||||
using ::testing::StrEq;
|
using ::testing::StrEq;
|
||||||
|
|
||||||
namespace sapi {
|
namespace sapi {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr char kErrorMessage1[] = "Bad foo argument";
|
|
||||||
constexpr char kErrorMessage2[] = "Internal foobar error";
|
|
||||||
|
|
||||||
TEST(StatusTest, OkSuccess) { EXPECT_THAT(OkStatus(), IsOk()); }
|
|
||||||
|
|
||||||
TEST(StatusTest, OkFailure) {
|
|
||||||
Status status{StatusCode::kInvalidArgument, kErrorMessage1};
|
|
||||||
EXPECT_THAT(status, Not(IsOk()));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StatusTest, GetErrorCodeOkStatus) {
|
|
||||||
EXPECT_THAT(OkStatus().code(), Eq(StatusCode::kOk));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StatusTest, GetErrorCodeNonOkStatus) {
|
|
||||||
Status status{StatusCode::kInvalidArgument, kErrorMessage1};
|
|
||||||
EXPECT_THAT(status.code(), Eq(StatusCode::kInvalidArgument));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StatusTest, GetErrorMessageOkStatus) {
|
|
||||||
EXPECT_THAT(OkStatus().error_message(), IsEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StatusTest, GetErrorMessageNonOkStatus) {
|
|
||||||
Status status{StatusCode::kInvalidArgument, kErrorMessage1};
|
|
||||||
EXPECT_THAT(status.error_message(), Eq(kErrorMessage1));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StatusTest, ToStringOkStatus) {
|
|
||||||
Status status = OkStatus();
|
|
||||||
std::string error_code_name = internal::CodeEnumToString(status.code());
|
|
||||||
|
|
||||||
// The ToString() representation for an ok Status should contain the error
|
|
||||||
// code name.
|
|
||||||
std::string status_rep = status.ToString();
|
|
||||||
EXPECT_THAT(status_rep.find(error_code_name), Ne(std::string::npos));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StatusTest, ToStringNonOkStatus) {
|
|
||||||
Status status{StatusCode::kInvalidArgument, kErrorMessage1};
|
|
||||||
std::string error_code_name = internal::CodeEnumToString(status.code());
|
|
||||||
constexpr char kErrorSpaceName[] = "generic";
|
|
||||||
// The format of ToString() is subject to change for a non-ok Status, but it
|
|
||||||
// should contain the error space name, the error code name, and the error
|
|
||||||
// message.
|
|
||||||
std::string status_rep = status.ToString();
|
|
||||||
EXPECT_THAT(status_rep.find(kErrorSpaceName), Ne(std::string::npos));
|
|
||||||
EXPECT_THAT(status_rep.find(error_code_name), Ne(std::string::npos));
|
|
||||||
EXPECT_THAT(status_rep.find(std::string(status.error_message())),
|
|
||||||
Ne(std::string::npos));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StatusTest, Equality) {
|
|
||||||
Status ok_status = OkStatus();
|
|
||||||
Status error_status(StatusCode::kInvalidArgument, kErrorMessage1);
|
|
||||||
|
|
||||||
EXPECT_THAT(ok_status == ok_status, IsTrue());
|
|
||||||
EXPECT_THAT(error_status == error_status, IsTrue());
|
|
||||||
EXPECT_THAT(ok_status == error_status, IsFalse());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StatusTest, Inequality) {
|
|
||||||
Status ok_status = OkStatus();
|
|
||||||
Status invalid_arg_status(StatusCode::kInvalidArgument, kErrorMessage1);
|
|
||||||
Status internal_status(StatusCode::kInternal, kErrorMessage2);
|
|
||||||
|
|
||||||
EXPECT_THAT(ok_status != ok_status, IsFalse());
|
|
||||||
EXPECT_THAT(invalid_arg_status != invalid_arg_status, IsFalse());
|
|
||||||
|
|
||||||
EXPECT_THAT(ok_status != invalid_arg_status, IsTrue());
|
|
||||||
EXPECT_THAT(invalid_arg_status != ok_status, IsTrue());
|
|
||||||
|
|
||||||
EXPECT_THAT(invalid_arg_status != internal_status, IsTrue());
|
|
||||||
EXPECT_THAT(internal_status != invalid_arg_status, IsTrue());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StatusTest, IsPositiveTest) {
|
|
||||||
EXPECT_THAT(OkStatus().code(), Eq(StatusCode::kOk));
|
|
||||||
|
|
||||||
Status invalid_arg_status(StatusCode::kInvalidArgument, kErrorMessage1);
|
|
||||||
EXPECT_THAT(invalid_arg_status.code(), Eq(StatusCode::kInvalidArgument));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StatusTest, IsNegativeTest) {
|
|
||||||
// Verify correctness of Is() within an error space.
|
|
||||||
Status invalid_arg_status(StatusCode::kInvalidArgument, kErrorMessage1);
|
|
||||||
EXPECT_THAT(invalid_arg_status.code(), Ne(StatusCode::kOk));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StatusTest, StatusIsMatcher) {
|
|
||||||
EXPECT_THAT(OkStatus(), StatusIs(StatusCode::kOk));
|
|
||||||
|
|
||||||
Status invalid_arg_status(StatusCode::kInvalidArgument, kErrorMessage1);
|
|
||||||
EXPECT_THAT(invalid_arg_status, StatusIs(StatusCode::kInvalidArgument));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StatusTest, IsOkMatcher) {
|
|
||||||
EXPECT_THAT(OkStatus(), IsOk());
|
|
||||||
|
|
||||||
// Negation of IsOk() matcher.
|
|
||||||
Status einval_status(StatusCode::kInvalidArgument, kErrorMessage1);
|
|
||||||
EXPECT_THAT(einval_status, Not(IsOk()));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StatusTest, MoveConstructorTest) {
|
|
||||||
Status invalid_arg_status(StatusCode::kInvalidArgument, kErrorMessage1);
|
|
||||||
EXPECT_THAT(invalid_arg_status, StatusIs(StatusCode::kInvalidArgument));
|
|
||||||
|
|
||||||
Status that(std::move(invalid_arg_status));
|
|
||||||
|
|
||||||
EXPECT_THAT(that, StatusIs(StatusCode::kInvalidArgument));
|
|
||||||
// NOLINTNEXTLINE
|
|
||||||
EXPECT_THAT(invalid_arg_status, StatusIs(StatusCode::kUnknown));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StatusTest, MoveAssignmentTestNonOk) {
|
|
||||||
Status invalid_arg_status(StatusCode::kInvalidArgument, kErrorMessage1);
|
|
||||||
EXPECT_THAT(invalid_arg_status, StatusIs(StatusCode::kInvalidArgument));
|
|
||||||
|
|
||||||
Status that(StatusCode::kCancelled, kErrorMessage2);
|
|
||||||
that = std::move(invalid_arg_status);
|
|
||||||
|
|
||||||
EXPECT_THAT(that, StatusIs(StatusCode::kInvalidArgument));
|
|
||||||
// NOLINTNEXTLINE
|
|
||||||
EXPECT_THAT(invalid_arg_status, StatusIs(StatusCode::kUnknown));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StatusTest, MoveAssignmentTestOk) {
|
|
||||||
Status invalid_arg_status(StatusCode::kInvalidArgument, kErrorMessage1);
|
|
||||||
EXPECT_THAT(invalid_arg_status, StatusIs(StatusCode::kInvalidArgument));
|
|
||||||
|
|
||||||
Status ok = OkStatus();
|
|
||||||
invalid_arg_status = std::move(ok);
|
|
||||||
|
|
||||||
EXPECT_THAT(invalid_arg_status, StatusIs(StatusCode::kOk, ""));
|
|
||||||
// NOLINTNEXTLINE
|
|
||||||
EXPECT_THAT(ok, StatusIs(StatusCode::kUnknown));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StatusTest, CopyConstructorTestOk) {
|
|
||||||
Status that(OkStatus());
|
|
||||||
|
|
||||||
EXPECT_THAT(that, IsOk());
|
|
||||||
EXPECT_TRUE(that.error_message().empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(StatusTest, CopyConstructorTestNonOk) {
|
|
||||||
Status invalid_arg_status(StatusCode::kInvalidArgument, kErrorMessage1);
|
|
||||||
EXPECT_THAT(invalid_arg_status, StatusIs(StatusCode::kInvalidArgument));
|
|
||||||
|
|
||||||
Status that(invalid_arg_status);
|
|
||||||
|
|
||||||
EXPECT_THAT(that, StatusIs(StatusCode::kInvalidArgument));
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusProto OkStatusProto() {
|
StatusProto OkStatusProto() {
|
||||||
StatusProto proto;
|
StatusProto proto;
|
||||||
proto.set_code(static_cast<int>(StatusCode::kOk));
|
proto.set_code(static_cast<int>(absl::StatusCode::kOk));
|
||||||
return proto;
|
return proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusProto InvalidArgumentStatusProto(absl::string_view msg) {
|
StatusProto InvalidArgumentStatusProto(absl::string_view msg) {
|
||||||
StatusProto proto;
|
StatusProto proto;
|
||||||
proto.set_code(static_cast<int>(StatusCode::kInvalidArgument));
|
proto.set_code(static_cast<int>(absl::StatusCode::kInvalidArgument));
|
||||||
proto.set_error_message(std::string(msg));
|
proto.set_message(std::string(msg));
|
||||||
return proto;
|
return proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(StatusTest, SaveStatusToProto) {
|
TEST(StatusTest, SaveOkStatusProto) {
|
||||||
{
|
|
||||||
StatusProto proto;
|
StatusProto proto;
|
||||||
SaveStatusToProto(OkStatus(), &proto);
|
SaveStatusToProto(absl::OkStatus(), &proto);
|
||||||
const auto ok_proto = OkStatusProto();
|
const auto ok_proto = OkStatusProto();
|
||||||
EXPECT_THAT(proto.code(), Eq(ok_proto.code()));
|
EXPECT_THAT(proto.code(), Eq(ok_proto.code()));
|
||||||
EXPECT_THAT(proto.error_message(), StrEq(ok_proto.error_message()));
|
EXPECT_THAT(proto.message(), StrEq(ok_proto.message()));
|
||||||
}
|
}
|
||||||
{
|
|
||||||
Status status(StatusCode::kInvalidArgument, kErrorMessage1);
|
TEST(StatusTest, SaveStatusWithMessage) {
|
||||||
|
constexpr char kErrorMessage[] = "Bad foo argument";
|
||||||
|
absl::Status status(absl::StatusCode::kInvalidArgument, kErrorMessage);
|
||||||
StatusProto proto;
|
StatusProto proto;
|
||||||
SaveStatusToProto(status, &proto);
|
SaveStatusToProto(status, &proto);
|
||||||
const auto invalid_proto = InvalidArgumentStatusProto(kErrorMessage1);
|
const auto invalid_proto = InvalidArgumentStatusProto(kErrorMessage);
|
||||||
EXPECT_THAT(proto.code(), Eq(invalid_proto.code()));
|
EXPECT_THAT(proto.code(), Eq(invalid_proto.code()));
|
||||||
EXPECT_THAT(proto.error_message(), StrEq(invalid_proto.error_message()));
|
EXPECT_THAT(proto.message(), StrEq(invalid_proto.message()));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -22,20 +22,20 @@
|
|||||||
#include "absl/base/internal/raw_logging.h"
|
#include "absl/base/internal/raw_logging.h"
|
||||||
#include "absl/base/attributes.h"
|
#include "absl/base/attributes.h"
|
||||||
#include "absl/base/log_severity.h"
|
#include "absl/base/log_severity.h"
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "absl/types/variant.h"
|
#include "absl/types/variant.h"
|
||||||
#include "sandboxed_api/util/raw_logging.h"
|
#include "sandboxed_api/util/raw_logging.h"
|
||||||
#include "sandboxed_api/util/status.h"
|
|
||||||
|
|
||||||
namespace sapi {
|
namespace sapi {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class StatusOr {
|
class StatusOr {
|
||||||
public:
|
public:
|
||||||
explicit StatusOr() : variant_{Status{StatusCode::kUnknown, ""}} {}
|
explicit StatusOr() : variant_(absl::UnknownError("")) {}
|
||||||
|
|
||||||
StatusOr(const Status& status) : variant_{status} { EnsureNotOk(); }
|
StatusOr(const absl::Status& status) : variant_(status) { EnsureNotOk(); }
|
||||||
|
|
||||||
StatusOr& operator=(const Status& status) {
|
StatusOr& operator=(const absl::Status& status) {
|
||||||
variant_ = status;
|
variant_ = status;
|
||||||
EnsureNotOk();
|
EnsureNotOk();
|
||||||
}
|
}
|
||||||
@ -69,8 +69,8 @@ class StatusOr {
|
|||||||
return absl::holds_alternative<T>(variant_);
|
return absl::holds_alternative<T>(variant_);
|
||||||
}
|
}
|
||||||
|
|
||||||
Status status() const {
|
absl::Status status() const {
|
||||||
return ok() ? OkStatus() : absl::get<Status>(variant_);
|
return ok() ? absl::OkStatus() : absl::get<absl::Status>(variant_);
|
||||||
}
|
}
|
||||||
|
|
||||||
const T& ValueOrDie() const& {
|
const T& ValueOrDie() const& {
|
||||||
@ -83,10 +83,9 @@ class StatusOr {
|
|||||||
return absl::get<T>(variant_);
|
return absl::get<T>(variant_);
|
||||||
}
|
}
|
||||||
|
|
||||||
T ValueOrDie() && {
|
T&& ValueOrDie() && {
|
||||||
EnsureOk();
|
EnsureOk();
|
||||||
T tmp(std::move(absl::get<T>(variant_)));
|
return std::move(absl::get<T>(variant_));
|
||||||
return std::move(tmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -107,7 +106,7 @@ class StatusOr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::variant<Status, T> variant_;
|
absl::variant<absl::Status, T> variant_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sapi
|
} // namespace sapi
|
||||||
|
@ -32,7 +32,7 @@ using ::testing::Not;
|
|||||||
namespace sapi {
|
namespace sapi {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr auto kErrorCode = StatusCode::kInvalidArgument;
|
constexpr auto kErrorCode = absl::StatusCode::kInvalidArgument;
|
||||||
constexpr char kErrorMessage[] = "Invalid argument";
|
constexpr char kErrorMessage[] = "Invalid argument";
|
||||||
|
|
||||||
const int kIntElement = 47;
|
const int kIntElement = 47;
|
||||||
@ -140,17 +140,17 @@ TYPED_TEST_SUITE(StatusOrTest, TestTypes);
|
|||||||
TYPED_TEST(StatusOrTest, ConstructorDefault) {
|
TYPED_TEST(StatusOrTest, ConstructorDefault) {
|
||||||
StatusOr<typename TypeParam::value_type> statusor;
|
StatusOr<typename TypeParam::value_type> statusor;
|
||||||
EXPECT_THAT(statusor.ok(), IsFalse());
|
EXPECT_THAT(statusor.ok(), IsFalse());
|
||||||
EXPECT_THAT(statusor.status().code(), Eq(StatusCode::kUnknown));
|
EXPECT_THAT(statusor.status().code(), Eq(absl::StatusCode::kUnknown));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that StatusOr can be constructed from a Status object.
|
// Verify that StatusOr can be constructed from a Status object.
|
||||||
TYPED_TEST(StatusOrTest, ConstructorStatus) {
|
TYPED_TEST(StatusOrTest, ConstructorStatus) {
|
||||||
StatusOr<typename TypeParam::value_type> statusor{
|
StatusOr<typename TypeParam::value_type> statusor(
|
||||||
Status{kErrorCode, kErrorMessage}};
|
absl::Status(kErrorCode, kErrorMessage));
|
||||||
|
|
||||||
EXPECT_THAT(statusor.ok(), IsFalse());
|
EXPECT_THAT(statusor.ok(), IsFalse());
|
||||||
EXPECT_THAT(statusor.status().ok(), IsFalse());
|
EXPECT_THAT(statusor.status().ok(), IsFalse());
|
||||||
EXPECT_THAT(statusor.status(), Eq(Status(kErrorCode, kErrorMessage)));
|
EXPECT_THAT(statusor.status(), Eq(absl::Status(kErrorCode, kErrorMessage)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that StatusOr can be constructed from an object of its element type.
|
// Verify that StatusOr can be constructed from an object of its element type.
|
||||||
@ -181,8 +181,8 @@ TYPED_TEST(StatusOrTest, ConstructorElementRValue) {
|
|||||||
// status.
|
// status.
|
||||||
TYPED_TEST(StatusOrTest, CopyConstructorNonOkStatus) {
|
TYPED_TEST(StatusOrTest, CopyConstructorNonOkStatus) {
|
||||||
StatusOr<typename TypeParam::value_type> statusor1 =
|
StatusOr<typename TypeParam::value_type> statusor1 =
|
||||||
Status{kErrorCode, kErrorMessage};
|
absl::Status(kErrorCode, kErrorMessage);
|
||||||
StatusOr<typename TypeParam::value_type> statusor2{statusor1};
|
StatusOr<typename TypeParam::value_type> statusor2(statusor1);
|
||||||
|
|
||||||
EXPECT_THAT(statusor1.ok(), Eq(statusor2.ok()));
|
EXPECT_THAT(statusor1.ok(), Eq(statusor2.ok()));
|
||||||
EXPECT_THAT(statusor1.status(), Eq(statusor2.status()));
|
EXPECT_THAT(statusor1.status(), Eq(statusor2.status()));
|
||||||
@ -203,7 +203,7 @@ TYPED_TEST(StatusOrTest, CopyConstructorOkStatus) {
|
|||||||
// expected.
|
// expected.
|
||||||
TYPED_TEST(StatusOrTest, CopyAssignmentNonOkStatus) {
|
TYPED_TEST(StatusOrTest, CopyAssignmentNonOkStatus) {
|
||||||
StatusOr<typename TypeParam::value_type> statusor1{
|
StatusOr<typename TypeParam::value_type> statusor1{
|
||||||
Status(kErrorCode, kErrorMessage)};
|
absl::Status(kErrorCode, kErrorMessage)};
|
||||||
StatusOr<typename TypeParam::value_type> statusor2{TypeParam()()};
|
StatusOr<typename TypeParam::value_type> statusor2{TypeParam()()};
|
||||||
|
|
||||||
// Invoke the copy-assignment operator.
|
// Invoke the copy-assignment operator.
|
||||||
@ -217,7 +217,7 @@ TYPED_TEST(StatusOrTest, CopyAssignmentNonOkStatus) {
|
|||||||
TYPED_TEST(StatusOrTest, CopyAssignmentOkStatus) {
|
TYPED_TEST(StatusOrTest, CopyAssignmentOkStatus) {
|
||||||
StatusOr<typename TypeParam::value_type> statusor1{TypeParam()()};
|
StatusOr<typename TypeParam::value_type> statusor1{TypeParam()()};
|
||||||
StatusOr<typename TypeParam::value_type> statusor2{
|
StatusOr<typename TypeParam::value_type> statusor2{
|
||||||
Status(kErrorCode, kErrorMessage)};
|
absl::Status(kErrorCode, kErrorMessage)};
|
||||||
|
|
||||||
// Invoke the copy-assignment operator.
|
// Invoke the copy-assignment operator.
|
||||||
statusor2 = statusor1;
|
statusor2 = statusor1;
|
||||||
@ -229,14 +229,13 @@ TYPED_TEST(StatusOrTest, CopyAssignmentOkStatus) {
|
|||||||
// Verify that StatusOr can be move-constructed from a StatusOr with a non-ok
|
// Verify that StatusOr can be move-constructed from a StatusOr with a non-ok
|
||||||
// status.
|
// status.
|
||||||
TYPED_TEST(StatusOrTest, MoveConstructorNonOkStatus) {
|
TYPED_TEST(StatusOrTest, MoveConstructorNonOkStatus) {
|
||||||
Status status{kErrorCode, kErrorMessage};
|
absl::Status status(kErrorCode, kErrorMessage);
|
||||||
StatusOr<typename TypeParam::value_type> statusor1{status};
|
StatusOr<typename TypeParam::value_type> statusor1(status);
|
||||||
StatusOr<typename TypeParam::value_type> statusor2{std::move(statusor1)};
|
StatusOr<typename TypeParam::value_type> statusor2(std::move(statusor1));
|
||||||
|
|
||||||
// Verify that the status of the donor object was updated.
|
// Verify that the status of the donor object was updated.
|
||||||
EXPECT_THAT(statusor1.ok(), IsFalse()); // NOLINT
|
EXPECT_THAT(statusor1.ok(), IsFalse()); // NOLINT
|
||||||
// NOLINTNEXTLINE
|
EXPECT_THAT(statusor1.status(), StatusIs(absl::StatusCode::kInternal));
|
||||||
EXPECT_THAT(statusor1.status(), StatusIs(StatusCode::kUnknown, ""));
|
|
||||||
|
|
||||||
// Verify that the destination object contains the status previously held by
|
// Verify that the destination object contains the status previously held by
|
||||||
// the donor.
|
// the donor.
|
||||||
@ -260,7 +259,7 @@ TYPED_TEST(StatusOrTest, MoveConstructorOkStatus) {
|
|||||||
// Verify that move-assignment from a StatusOr with a non-ok status is working
|
// Verify that move-assignment from a StatusOr with a non-ok status is working
|
||||||
// as expected.
|
// as expected.
|
||||||
TYPED_TEST(StatusOrTest, MoveAssignmentOperatorNonOkStatus) {
|
TYPED_TEST(StatusOrTest, MoveAssignmentOperatorNonOkStatus) {
|
||||||
Status status(kErrorCode, kErrorMessage);
|
absl::Status status(kErrorCode, kErrorMessage);
|
||||||
StatusOr<typename TypeParam::value_type> statusor1{status};
|
StatusOr<typename TypeParam::value_type> statusor1{status};
|
||||||
StatusOr<typename TypeParam::value_type> statusor2{TypeParam()()};
|
StatusOr<typename TypeParam::value_type> statusor2{TypeParam()()};
|
||||||
|
|
||||||
@ -269,8 +268,7 @@ TYPED_TEST(StatusOrTest, MoveAssignmentOperatorNonOkStatus) {
|
|||||||
|
|
||||||
// Verify that the status of the donor object was updated.
|
// Verify that the status of the donor object was updated.
|
||||||
EXPECT_THAT(statusor1.ok(), IsFalse()); // NOLINT
|
EXPECT_THAT(statusor1.ok(), IsFalse()); // NOLINT
|
||||||
// NOLINTNEXTLINE
|
EXPECT_THAT(statusor1.status(), StatusIs(absl::StatusCode::kInternal));
|
||||||
EXPECT_THAT(statusor1.status(), StatusIs(StatusCode::kUnknown, ""));
|
|
||||||
|
|
||||||
// Verify that the destination object contains the status previously held by
|
// Verify that the destination object contains the status previously held by
|
||||||
// the donor.
|
// the donor.
|
||||||
@ -282,9 +280,9 @@ TYPED_TEST(StatusOrTest, MoveAssignmentOperatorNonOkStatus) {
|
|||||||
// expected.
|
// expected.
|
||||||
TYPED_TEST(StatusOrTest, MoveAssignmentOperatorOkStatus) {
|
TYPED_TEST(StatusOrTest, MoveAssignmentOperatorOkStatus) {
|
||||||
auto value = TypeParam()();
|
auto value = TypeParam()();
|
||||||
StatusOr<typename TypeParam::value_type> statusor1{value};
|
StatusOr<typename TypeParam::value_type> statusor1(value);
|
||||||
StatusOr<typename TypeParam::value_type> statusor2{
|
StatusOr<typename TypeParam::value_type> statusor2(
|
||||||
Status{kErrorCode, kErrorMessage}};
|
absl::Status(kErrorCode, kErrorMessage));
|
||||||
|
|
||||||
// Invoke the move-assignment operator.
|
// Invoke the move-assignment operator.
|
||||||
statusor2 = std::move(statusor1);
|
statusor2 = std::move(statusor1);
|
||||||
@ -302,8 +300,8 @@ TYPED_TEST(StatusOrTest, IsOkMatcher) {
|
|||||||
|
|
||||||
EXPECT_THAT(statusor, IsOk());
|
EXPECT_THAT(statusor, IsOk());
|
||||||
|
|
||||||
statusor = StatusOr<typename TypeParam::value_type>{
|
statusor = StatusOr<typename TypeParam::value_type>(
|
||||||
Status{kErrorCode, kErrorMessage}};
|
absl::Status(kErrorCode, kErrorMessage));
|
||||||
EXPECT_THAT(statusor, Not(IsOk()));
|
EXPECT_THAT(statusor, Not(IsOk()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,7 +316,7 @@ TYPED_TEST(StatusOrTest, IsOkMatcher) {
|
|||||||
|
|
||||||
// Verify that a StatusOr object can be constructed from a move-only type.
|
// Verify that a StatusOr object can be constructed from a move-only type.
|
||||||
TEST(StatusOrTest, InitializationMoveOnlyType) {
|
TEST(StatusOrTest, InitializationMoveOnlyType) {
|
||||||
std::string* str = new std::string{kStringElement};
|
auto* str = new std::string(kStringElement);
|
||||||
std::unique_ptr<std::string> value(str);
|
std::unique_ptr<std::string> value(str);
|
||||||
StatusOr<std::unique_ptr<std::string>> statusor(std::move(value));
|
StatusOr<std::unique_ptr<std::string>> statusor(std::move(value));
|
||||||
|
|
||||||
@ -328,10 +326,10 @@ TEST(StatusOrTest, InitializationMoveOnlyType) {
|
|||||||
|
|
||||||
// Verify that a StatusOr object can be move-constructed from a move-only type.
|
// Verify that a StatusOr object can be move-constructed from a move-only type.
|
||||||
TEST(StatusOrTest, MoveConstructorMoveOnlyType) {
|
TEST(StatusOrTest, MoveConstructorMoveOnlyType) {
|
||||||
std::string* str = new std::string{kStringElement};
|
auto* str = new std::string(kStringElement);
|
||||||
std::unique_ptr<std::string> value{str};
|
std::unique_ptr<std::string> value{str};
|
||||||
StatusOr<std::unique_ptr<std::string>> statusor1{std::move(value)};
|
StatusOr<std::unique_ptr<std::string>> statusor1(std::move(value));
|
||||||
StatusOr<std::unique_ptr<std::string>> statusor2{std::move(statusor1)};
|
StatusOr<std::unique_ptr<std::string>> statusor2(std::move(statusor1));
|
||||||
|
|
||||||
// The destination object should possess the value previously held by the
|
// The destination object should possess the value previously held by the
|
||||||
// donor.
|
// donor.
|
||||||
@ -342,11 +340,11 @@ TEST(StatusOrTest, MoveConstructorMoveOnlyType) {
|
|||||||
// Verify that a StatusOr object can be move-assigned to from a StatusOr object
|
// Verify that a StatusOr object can be move-assigned to from a StatusOr object
|
||||||
// containing a move-only type.
|
// containing a move-only type.
|
||||||
TEST(StatusOrTest, MoveAssignmentMoveOnlyType) {
|
TEST(StatusOrTest, MoveAssignmentMoveOnlyType) {
|
||||||
std::string* str = new std::string{kStringElement};
|
auto* str = new std::string(kStringElement);
|
||||||
std::unique_ptr<std::string> value{str};
|
std::unique_ptr<std::string> value(str);
|
||||||
StatusOr<std::unique_ptr<std::string>> statusor1(std::move(value));
|
StatusOr<std::unique_ptr<std::string>> statusor1(std::move(value));
|
||||||
StatusOr<std::unique_ptr<std::string>> statusor2(
|
StatusOr<std::unique_ptr<std::string>> statusor2(
|
||||||
Status(kErrorCode, kErrorMessage));
|
absl::Status(kErrorCode, kErrorMessage));
|
||||||
|
|
||||||
// Invoke the move-assignment operator.
|
// Invoke the move-assignment operator.
|
||||||
statusor2 = std::move(statusor1);
|
statusor2 = std::move(statusor1);
|
||||||
@ -359,9 +357,9 @@ TEST(StatusOrTest, MoveAssignmentMoveOnlyType) {
|
|||||||
|
|
||||||
// Verify that a value can be moved out of a StatusOr object via ValueOrDie().
|
// Verify that a value can be moved out of a StatusOr object via ValueOrDie().
|
||||||
TEST(StatusOrTest, ValueOrDieMovedValue) {
|
TEST(StatusOrTest, ValueOrDieMovedValue) {
|
||||||
std::string* str = new std::string{kStringElement};
|
auto* str = new std::string(kStringElement);
|
||||||
std::unique_ptr<std::string> value{str};
|
std::unique_ptr<std::string> value(str);
|
||||||
StatusOr<std::unique_ptr<std::string>> statusor{std::move(value)};
|
StatusOr<std::unique_ptr<std::string>> statusor(std::move(value));
|
||||||
|
|
||||||
std::unique_ptr<std::string> moved_value = std::move(statusor).ValueOrDie();
|
std::unique_ptr<std::string> moved_value = std::move(statusor).ValueOrDie();
|
||||||
EXPECT_THAT(moved_value.get(), Eq(str));
|
EXPECT_THAT(moved_value.get(), Eq(str));
|
||||||
|
@ -32,13 +32,13 @@ Var::~Var() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Var::Allocate(RPCChannel* rpc_channel, bool automatic_free) {
|
absl::Status Var::Allocate(RPCChannel* rpc_channel, bool automatic_free) {
|
||||||
void* addr;
|
void* addr;
|
||||||
SAPI_RETURN_IF_ERROR(rpc_channel->Allocate(GetSize(), &addr));
|
SAPI_RETURN_IF_ERROR(rpc_channel->Allocate(GetSize(), &addr));
|
||||||
|
|
||||||
if (!addr) {
|
if (!addr) {
|
||||||
LOG(ERROR) << "Allocate: returned nullptr";
|
LOG(ERROR) << "Allocate: returned nullptr";
|
||||||
return sapi::UnavailableError("Allocating memory failed");
|
return absl::UnavailableError("Allocating memory failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
SetRemote(addr);
|
SetRemote(addr);
|
||||||
@ -46,24 +46,24 @@ sapi::Status Var::Allocate(RPCChannel* rpc_channel, bool automatic_free) {
|
|||||||
SetFreeRPCChannel(rpc_channel);
|
SetFreeRPCChannel(rpc_channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Var::Free(RPCChannel* rpc_channel) {
|
absl::Status Var::Free(RPCChannel* rpc_channel) {
|
||||||
SAPI_RETURN_IF_ERROR(rpc_channel->Free(GetRemote()));
|
SAPI_RETURN_IF_ERROR(rpc_channel->Free(GetRemote()));
|
||||||
|
|
||||||
SetRemote(nullptr);
|
SetRemote(nullptr);
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Var::TransferToSandboxee(RPCChannel* rpc_channel, pid_t pid) {
|
absl::Status Var::TransferToSandboxee(RPCChannel* rpc_channel, pid_t pid) {
|
||||||
VLOG(3) << "TransferToSandboxee for: " << ToString()
|
VLOG(3) << "TransferToSandboxee for: " << ToString()
|
||||||
<< ", local: " << GetLocal() << ", remote: " << GetRemote()
|
<< ", local: " << GetLocal() << ", remote: " << GetRemote()
|
||||||
<< ", size: " << GetSize();
|
<< ", size: " << GetSize();
|
||||||
|
|
||||||
if (remote_ == nullptr) {
|
if (remote_ == nullptr) {
|
||||||
LOG(WARNING) << "Object: " << GetType() << " has no remote object set";
|
LOG(WARNING) << "Object: " << GetType() << " has no remote object set";
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("Object: ", GetType(), " has no remote object set"));
|
absl::StrCat("Object: ", GetType(), " has no remote object set"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,25 +81,25 @@ sapi::Status Var::TransferToSandboxee(RPCChannel* rpc_channel, pid_t pid) {
|
|||||||
PLOG(WARNING) << "process_vm_writev(pid: " << pid
|
PLOG(WARNING) << "process_vm_writev(pid: " << pid
|
||||||
<< " laddr: " << GetLocal() << " raddr: " << GetRemote()
|
<< " laddr: " << GetLocal() << " raddr: " << GetRemote()
|
||||||
<< " size: " << GetSize() << ")";
|
<< " size: " << GetSize() << ")";
|
||||||
return sapi::UnavailableError("process_vm_writev failed");
|
return absl::UnavailableError("process_vm_writev failed");
|
||||||
}
|
}
|
||||||
if (ret != GetSize()) {
|
if (ret != GetSize()) {
|
||||||
LOG(WARNING) << "process_vm_writev(pid: " << pid << " laddr: " << GetLocal()
|
LOG(WARNING) << "process_vm_writev(pid: " << pid << " laddr: " << GetLocal()
|
||||||
<< " raddr: " << GetRemote() << " size: " << GetSize() << ")"
|
<< " raddr: " << GetRemote() << " size: " << GetSize() << ")"
|
||||||
<< " transferred " << ret << " bytes";
|
<< " transferred " << ret << " bytes";
|
||||||
return sapi::UnavailableError("process_vm_writev: partial success");
|
return absl::UnavailableError("process_vm_writev: partial success");
|
||||||
}
|
}
|
||||||
|
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Var::TransferFromSandboxee(RPCChannel* rpc_channel, pid_t pid) {
|
absl::Status Var::TransferFromSandboxee(RPCChannel* rpc_channel, pid_t pid) {
|
||||||
VLOG(3) << "TransferFromSandboxee for: " << ToString()
|
VLOG(3) << "TransferFromSandboxee for: " << ToString()
|
||||||
<< ", local: " << GetLocal() << ", remote: " << GetRemote()
|
<< ", local: " << GetLocal() << ", remote: " << GetRemote()
|
||||||
<< ", size: " << GetSize();
|
<< ", size: " << GetSize();
|
||||||
|
|
||||||
if (local_ == nullptr) {
|
if (local_ == nullptr) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
absl::StrCat("Object: ", GetType(), " has no local storage set"));
|
absl::StrCat("Object: ", GetType(), " has no local storage set"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,16 +116,16 @@ sapi::Status Var::TransferFromSandboxee(RPCChannel* rpc_channel, pid_t pid) {
|
|||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
PLOG(WARNING) << "process_vm_readv(pid: " << pid << " laddr: " << GetLocal()
|
PLOG(WARNING) << "process_vm_readv(pid: " << pid << " laddr: " << GetLocal()
|
||||||
<< " raddr: " << GetRemote() << " size: " << GetSize() << ")";
|
<< " raddr: " << GetRemote() << " size: " << GetSize() << ")";
|
||||||
return sapi::UnavailableError("process_vm_readv failed");
|
return absl::UnavailableError("process_vm_readv failed");
|
||||||
}
|
}
|
||||||
if (ret != GetSize()) {
|
if (ret != GetSize()) {
|
||||||
LOG(WARNING) << "process_vm_readv(pid: " << pid << " laddr: " << GetLocal()
|
LOG(WARNING) << "process_vm_readv(pid: " << pid << " laddr: " << GetLocal()
|
||||||
<< " raddr: " << GetRemote() << " size: " << GetSize() << ")"
|
<< " raddr: " << GetRemote() << " size: " << GetSize() << ")"
|
||||||
<< " transferred " << ret << " bytes";
|
<< " transferred " << ret << " bytes";
|
||||||
return sapi::UnavailableError("process_vm_readv succeeded partially");
|
return absl::UnavailableError("process_vm_readv succeeded partially");
|
||||||
}
|
}
|
||||||
|
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sapi::v
|
} // namespace sapi::v
|
||||||
|
@ -20,8 +20,8 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
#include "absl/base/macros.h"
|
#include "absl/base/macros.h"
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "sandboxed_api/var_type.h"
|
#include "sandboxed_api/var_type.h"
|
||||||
#include "sandboxed_api/util/status.h"
|
|
||||||
|
|
||||||
namespace sandbox2 {
|
namespace sandbox2 {
|
||||||
class Comms;
|
class Comms;
|
||||||
@ -82,17 +82,17 @@ class Var {
|
|||||||
// Allocates the local variable on the remote side. The 'automatic_free'
|
// Allocates the local variable on the remote side. The 'automatic_free'
|
||||||
// argument dictates whether the remote memory should be freed upon end of
|
// argument dictates whether the remote memory should be freed upon end of
|
||||||
// this object's lifetime.
|
// this object's lifetime.
|
||||||
virtual sapi::Status Allocate(RPCChannel* rpc_channel, bool automatic_free);
|
virtual absl::Status Allocate(RPCChannel* rpc_channel, bool automatic_free);
|
||||||
|
|
||||||
// Frees the local variable on the remote side.
|
// Frees the local variable on the remote side.
|
||||||
virtual sapi::Status Free(RPCChannel* rpc_channel);
|
virtual absl::Status Free(RPCChannel* rpc_channel);
|
||||||
|
|
||||||
// Transfers the variable to the sandboxee's address space, has to be
|
// Transfers the variable to the sandboxee's address space, has to be
|
||||||
// allocated there first.
|
// allocated there first.
|
||||||
virtual sapi::Status TransferToSandboxee(RPCChannel* rpc_channel, pid_t pid);
|
virtual absl::Status TransferToSandboxee(RPCChannel* rpc_channel, pid_t pid);
|
||||||
|
|
||||||
// Transfers the variable from the sandboxee's address space.
|
// Transfers the variable from the sandboxee's address space.
|
||||||
virtual sapi::Status TransferFromSandboxee(RPCChannel* rpc_channel,
|
virtual absl::Status TransferFromSandboxee(RPCChannel* rpc_channel,
|
||||||
pid_t pid);
|
pid_t pid);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "absl/base/macros.h"
|
#include "absl/base/macros.h"
|
||||||
|
#include "absl/status/status.h"
|
||||||
#include "absl/strings/str_cat.h"
|
#include "absl/strings/str_cat.h"
|
||||||
#include "sandboxed_api/rpcchannel.h"
|
#include "sandboxed_api/rpcchannel.h"
|
||||||
#include "sandboxed_api/var_abstract.h"
|
#include "sandboxed_api/var_abstract.h"
|
||||||
@ -74,7 +75,7 @@ class Array : public Var, public Pointable {
|
|||||||
// Resizes the local and remote buffer using realloc(). Note that this will
|
// Resizes the local and remote buffer using realloc(). Note that this will
|
||||||
// make all pointers to the current data (inside and outside of the sandbox)
|
// make all pointers to the current data (inside and outside of the sandbox)
|
||||||
// invalid.
|
// invalid.
|
||||||
sapi::Status Resize(RPCChannel* rpc_channel, size_t nelems) {
|
absl::Status Resize(RPCChannel* rpc_channel, size_t nelems) {
|
||||||
size_t absolute_size = sizeof(T) * nelems;
|
size_t absolute_size = sizeof(T) * nelems;
|
||||||
// Resize local buffer.
|
// Resize local buffer.
|
||||||
SAPI_RETURN_IF_ERROR(EnsureOwnedLocalBuffer(absolute_size));
|
SAPI_RETURN_IF_ERROR(EnsureOwnedLocalBuffer(absolute_size));
|
||||||
@ -85,23 +86,23 @@ class Array : public Var, public Pointable {
|
|||||||
SAPI_RETURN_IF_ERROR(
|
SAPI_RETURN_IF_ERROR(
|
||||||
rpc_channel->Reallocate(GetRemote(), absolute_size, &new_addr));
|
rpc_channel->Reallocate(GetRemote(), absolute_size, &new_addr));
|
||||||
if (!new_addr) {
|
if (!new_addr) {
|
||||||
return sapi::UnavailableError("Reallocate() returned nullptr");
|
return absl::UnavailableError("Reallocate() returned nullptr");
|
||||||
}
|
}
|
||||||
SetRemote(new_addr);
|
SetRemote(new_addr);
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Resizes the internal storage.
|
// Resizes the internal storage.
|
||||||
sapi::Status EnsureOwnedLocalBuffer(size_t size) {
|
absl::Status EnsureOwnedLocalBuffer(size_t size) {
|
||||||
if (size % sizeof(T)) {
|
if (size % sizeof(T)) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
"Array size not a multiple of the item size");
|
"Array size not a multiple of the item size");
|
||||||
}
|
}
|
||||||
// Do not (re-)allocate memory if the new size matches our size - except
|
// Do not (re-)allocate memory if the new size matches our size - except
|
||||||
// when we don't own that buffer.
|
// when we don't own that buffer.
|
||||||
if (size == total_size_ && buffer_owned_) {
|
if (size == total_size_ && buffer_owned_) {
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
void* new_addr = nullptr;
|
void* new_addr = nullptr;
|
||||||
if (buffer_owned_) {
|
if (buffer_owned_) {
|
||||||
@ -114,14 +115,14 @@ class Array : public Var, public Pointable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!new_addr) {
|
if (!new_addr) {
|
||||||
return sapi::UnavailableError("(Re-)malloc failed");
|
return absl::UnavailableError("(Re-)malloc failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
arr_ = static_cast<T*>(new_addr);
|
arr_ = static_cast<T*>(new_addr);
|
||||||
total_size_ = size;
|
total_size_ = size;
|
||||||
nelem_ = size / sizeof(T);
|
nelem_ = size / sizeof(T);
|
||||||
SetLocal(arr_);
|
SetLocal(arr_);
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pointer to the data, owned by the object if buffer_owned_ is 'true'.
|
// Pointer to the data, owned by the object if buffer_owned_ is 'true'.
|
||||||
|
@ -27,11 +27,11 @@ Fd::~Fd() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Fd::CloseRemoteFd(RPCChannel* rpc_channel) {
|
absl::Status Fd::CloseRemoteFd(RPCChannel* rpc_channel) {
|
||||||
SAPI_RETURN_IF_ERROR(rpc_channel->Close(GetRemoteFd()));
|
SAPI_RETURN_IF_ERROR(rpc_channel->Close(GetRemoteFd()));
|
||||||
|
|
||||||
SetRemoteFd(-1);
|
SetRemoteFd(-1);
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fd::CloseLocalFd() {
|
void Fd::CloseLocalFd() {
|
||||||
@ -45,29 +45,29 @@ void Fd::CloseLocalFd() {
|
|||||||
SetValue(-1);
|
SetValue(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Fd::TransferToSandboxee(RPCChannel* rpc_channel, pid_t /* pid */) {
|
absl::Status Fd::TransferToSandboxee(RPCChannel* rpc_channel, pid_t /* pid */) {
|
||||||
int remote_fd;
|
int remote_fd;
|
||||||
|
|
||||||
SetFreeRPCChannel(rpc_channel);
|
SetFreeRPCChannel(rpc_channel);
|
||||||
OwnRemoteFd(true);
|
OwnRemoteFd(true);
|
||||||
|
|
||||||
if (GetValue() < 0) {
|
if (GetValue() < 0) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
"Cannot transfer FD: Local FD not valid");
|
"Cannot transfer FD: Local FD not valid");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetRemoteFd() >= 0) {
|
if (GetRemoteFd() >= 0) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
"Cannot transfer FD: Sandboxee already has a valid FD");
|
"Cannot transfer FD: Sandboxee already has a valid FD");
|
||||||
}
|
}
|
||||||
|
|
||||||
SAPI_RETURN_IF_ERROR(rpc_channel->SendFD(GetValue(), &remote_fd));
|
SAPI_RETURN_IF_ERROR(rpc_channel->SendFD(GetValue(), &remote_fd));
|
||||||
SetRemoteFd(remote_fd);
|
SetRemoteFd(remote_fd);
|
||||||
|
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Fd::TransferFromSandboxee(RPCChannel* rpc_channel,
|
absl::Status Fd::TransferFromSandboxee(RPCChannel* rpc_channel,
|
||||||
pid_t /* pid */) {
|
pid_t /* pid */) {
|
||||||
int local_fd;
|
int local_fd;
|
||||||
|
|
||||||
@ -75,19 +75,19 @@ sapi::Status Fd::TransferFromSandboxee(RPCChannel* rpc_channel,
|
|||||||
OwnRemoteFd(false);
|
OwnRemoteFd(false);
|
||||||
|
|
||||||
if (GetValue()) {
|
if (GetValue()) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
"Cannot transfer FD back: Our FD is already valid");
|
"Cannot transfer FD back: Our FD is already valid");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetRemoteFd() < 0) {
|
if (GetRemoteFd() < 0) {
|
||||||
return sapi::FailedPreconditionError(
|
return absl::FailedPreconditionError(
|
||||||
"Cannot transfer FD back: Sandboxee has no valid FD");
|
"Cannot transfer FD back: Sandboxee has no valid FD");
|
||||||
}
|
}
|
||||||
|
|
||||||
SAPI_RETURN_IF_ERROR(rpc_channel->RecvFD(GetRemoteFd(), &local_fd));
|
SAPI_RETURN_IF_ERROR(rpc_channel->RecvFD(GetRemoteFd(), &local_fd));
|
||||||
SetValue(local_fd);
|
SetValue(local_fd);
|
||||||
|
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sapi::v
|
} // namespace sapi::v
|
||||||
|
@ -82,17 +82,17 @@ class Fd : public Int {
|
|||||||
void OwnLocalFd(bool owned) { own_local_ = owned; }
|
void OwnLocalFd(bool owned) { own_local_ = owned; }
|
||||||
|
|
||||||
// Close remote fd in the sadboxee.
|
// Close remote fd in the sadboxee.
|
||||||
sapi::Status CloseRemoteFd(RPCChannel* rpc_channel);
|
absl::Status CloseRemoteFd(RPCChannel* rpc_channel);
|
||||||
// Close local fd.
|
// Close local fd.
|
||||||
void CloseLocalFd();
|
void CloseLocalFd();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Sends local fd to sandboxee, takes ownership of the fd.
|
// Sends local fd to sandboxee, takes ownership of the fd.
|
||||||
sapi::Status TransferFromSandboxee(RPCChannel* rpc_channel,
|
absl::Status TransferFromSandboxee(RPCChannel* rpc_channel,
|
||||||
pid_t pid) override;
|
pid_t pid) override;
|
||||||
|
|
||||||
// Retrieves remote file descriptor, does not own fd.
|
// Retrieves remote file descriptor, does not own fd.
|
||||||
sapi::Status TransferToSandboxee(RPCChannel* rpc_channel, pid_t pid) override;
|
absl::Status TransferToSandboxee(RPCChannel* rpc_channel, pid_t pid) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int remote_fd_;
|
int remote_fd_;
|
||||||
|
@ -24,29 +24,29 @@
|
|||||||
|
|
||||||
namespace sapi::v {
|
namespace sapi::v {
|
||||||
|
|
||||||
sapi::Status LenVal::Allocate(RPCChannel* rpc_channel, bool automatic_free) {
|
absl::Status LenVal::Allocate(RPCChannel* rpc_channel, bool automatic_free) {
|
||||||
SAPI_RETURN_IF_ERROR(struct_.Allocate(rpc_channel, automatic_free));
|
SAPI_RETURN_IF_ERROR(struct_.Allocate(rpc_channel, automatic_free));
|
||||||
SAPI_RETURN_IF_ERROR(array_.Allocate(rpc_channel, true));
|
SAPI_RETURN_IF_ERROR(array_.Allocate(rpc_channel, true));
|
||||||
|
|
||||||
// Set data pointer.
|
// Set data pointer.
|
||||||
struct_.mutable_data()->data = array_.GetRemote();
|
struct_.mutable_data()->data = array_.GetRemote();
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status LenVal::Free(RPCChannel* rpc_channel) {
|
absl::Status LenVal::Free(RPCChannel* rpc_channel) {
|
||||||
SAPI_RETURN_IF_ERROR(array_.Free(rpc_channel));
|
SAPI_RETURN_IF_ERROR(array_.Free(rpc_channel));
|
||||||
SAPI_RETURN_IF_ERROR(struct_.Free(rpc_channel));
|
SAPI_RETURN_IF_ERROR(struct_.Free(rpc_channel));
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status LenVal::TransferToSandboxee(RPCChannel* rpc_channel, pid_t pid) {
|
absl::Status LenVal::TransferToSandboxee(RPCChannel* rpc_channel, pid_t pid) {
|
||||||
// Sync the structure and the underlying array.
|
// Sync the structure and the underlying array.
|
||||||
SAPI_RETURN_IF_ERROR(struct_.TransferToSandboxee(rpc_channel, pid));
|
SAPI_RETURN_IF_ERROR(struct_.TransferToSandboxee(rpc_channel, pid));
|
||||||
SAPI_RETURN_IF_ERROR(array_.TransferToSandboxee(rpc_channel, pid));
|
SAPI_RETURN_IF_ERROR(array_.TransferToSandboxee(rpc_channel, pid));
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status LenVal::TransferFromSandboxee(RPCChannel* rpc_channel, pid_t pid) {
|
absl::Status LenVal::TransferFromSandboxee(RPCChannel* rpc_channel, pid_t pid) {
|
||||||
// Sync the structure back.
|
// Sync the structure back.
|
||||||
SAPI_RETURN_IF_ERROR(struct_.TransferFromSandboxee(rpc_channel, pid));
|
SAPI_RETURN_IF_ERROR(struct_.TransferFromSandboxee(rpc_channel, pid));
|
||||||
|
|
||||||
@ -60,12 +60,12 @@ sapi::Status LenVal::TransferFromSandboxee(RPCChannel* rpc_channel, pid_t pid) {
|
|||||||
return array_.TransferFromSandboxee(rpc_channel, pid);
|
return array_.TransferFromSandboxee(rpc_channel, pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status LenVal::ResizeData(RPCChannel* rpc_channel, size_t size) {
|
absl::Status LenVal::ResizeData(RPCChannel* rpc_channel, size_t size) {
|
||||||
SAPI_RETURN_IF_ERROR(array_.Resize(rpc_channel, size));
|
SAPI_RETURN_IF_ERROR(array_.Resize(rpc_channel, size));
|
||||||
auto* struct_data = struct_.mutable_data();
|
auto* struct_data = struct_.mutable_data();
|
||||||
struct_data->data = array_.GetRemote();
|
struct_data->data = array_.GetRemote();
|
||||||
struct_data->size = size;
|
struct_data->size = size;
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sapi::v
|
} // namespace sapi::v
|
||||||
|
@ -58,17 +58,17 @@ class LenVal : public Var, public Pointable {
|
|||||||
return new Ptr(this, type);
|
return new Ptr(this, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status ResizeData(RPCChannel* rpc_channel, size_t size);
|
absl::Status ResizeData(RPCChannel* rpc_channel, size_t size);
|
||||||
size_t GetDataSize() const { return struct_.data().size; }
|
size_t GetDataSize() const { return struct_.data().size; }
|
||||||
uint8_t* GetData() const { return array_.GetData(); }
|
uint8_t* GetData() const { return array_.GetData(); }
|
||||||
void* GetRemote() const final { return struct_.GetRemote(); }
|
void* GetRemote() const final { return struct_.GetRemote(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t GetSize() const final { return 0; }
|
size_t GetSize() const final { return 0; }
|
||||||
sapi::Status Allocate(RPCChannel* rpc_channel, bool automatic_free) override;
|
absl::Status Allocate(RPCChannel* rpc_channel, bool automatic_free) override;
|
||||||
sapi::Status Free(RPCChannel* rpc_channel) override;
|
absl::Status Free(RPCChannel* rpc_channel) override;
|
||||||
sapi::Status TransferToSandboxee(RPCChannel* rpc_channel, pid_t pid) override;
|
absl::Status TransferToSandboxee(RPCChannel* rpc_channel, pid_t pid) override;
|
||||||
sapi::Status TransferFromSandboxee(RPCChannel* rpc_channel,
|
absl::Status TransferFromSandboxee(RPCChannel* rpc_channel,
|
||||||
pid_t pid) override;
|
pid_t pid) override;
|
||||||
|
|
||||||
Array<uint8_t> array_;
|
Array<uint8_t> array_;
|
||||||
|
@ -83,20 +83,20 @@ class Proto : public Pointable, public Var {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Forward a couple of function calls to the actual var.
|
// Forward a couple of function calls to the actual var.
|
||||||
sapi::Status Allocate(RPCChannel* rpc_channel, bool automatic_free) override {
|
absl::Status Allocate(RPCChannel* rpc_channel, bool automatic_free) override {
|
||||||
return wrapped_var_.Allocate(rpc_channel, automatic_free);
|
return wrapped_var_.Allocate(rpc_channel, automatic_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status Free(RPCChannel* rpc_channel) override {
|
absl::Status Free(RPCChannel* rpc_channel) override {
|
||||||
return sapi::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status TransferToSandboxee(RPCChannel* rpc_channel,
|
absl::Status TransferToSandboxee(RPCChannel* rpc_channel,
|
||||||
pid_t pid) override {
|
pid_t pid) override {
|
||||||
return wrapped_var_.TransferToSandboxee(rpc_channel, pid);
|
return wrapped_var_.TransferToSandboxee(rpc_channel, pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
sapi::Status TransferFromSandboxee(RPCChannel* rpc_channel,
|
absl::Status TransferFromSandboxee(RPCChannel* rpc_channel,
|
||||||
pid_t pid) override {
|
pid_t pid) override {
|
||||||
return wrapped_var_.TransferFromSandboxee(rpc_channel, pid);
|
return wrapped_var_.TransferFromSandboxee(rpc_channel, pid);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user