Merge branch 'master' into master

pull/50/head
Katarzyna Miernikiewicz 2020-09-15 18:26:58 +02:00 committed by GitHub
commit 5eed4ec606
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
91 changed files with 1384 additions and 1035 deletions

3
.gitmodules vendored
View File

@ -1,3 +1,6 @@
[submodule "oss-internship-2020/openjpeg/openjpeg"]
path = oss-internship-2020/openjpeg/openjpeg
url = https://github.com/uclouvain/openjpeg.git
[submodule "oss-internship-2020/pffft/master"]
path = oss-internship-2020/pffft/master
url = https://bitbucket.org/jpommier/pffft/src/master/

View File

@ -18,7 +18,7 @@ project(absl-download NONE)
include(ExternalProject)
ExternalProject_Add(absl
GIT_REPOSITORY https://github.com/abseil/abseil-cpp
GIT_TAG 6e18c7115df9b7ca0987cc346b1b1d4b3cc829b3 # 2020-04-28
GIT_TAG 0e9921b75a0fdd639a504ec8443fc1fe801becd7 # 2020-09-02
SOURCE_DIR "${CMAKE_BINARY_DIR}/absl-src"
BINARY_DIR "${CMAKE_BINARY_DIR}/absl-build"
CONFIGURE_COMMAND ""

3
oss-internship-2020/pffft/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.o
*.a
pffft_main

View File

@ -0,0 +1,104 @@
# Copyright 2020 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.
cmake_minimum_required(VERSION 3.10)
project(pffft CXX C)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
add_library(pffft STATIC
master/pffft.c
master/pffft.h
master/fftpack.c
master/fftpack.h
)
add_executable(pffft_main
master/test_pffft.c
)
target_link_libraries(pffft_main PRIVATE
pffft
)
set(MATH_LIBS "")
include(CheckLibraryExists)
check_library_exists(m sin "" LIBM)
if(LIBM)
list(APPEND MATH_LIBS "m")
endif()
target_link_libraries(pffft PUBLIC ${MATH_LIBS})
# Adding dependencies
set(SAPI_ROOT "../.." CACHE PATH "Path to the Sandboxed API source tree")
# Then configure:
# mkdir -p build && cd build
# cmake .. -G Ninja -DSAPI_ROOT=$HOME/sapi_root
set(SAPI_ENABLE_EXAMPLES OFF CACHE BOOL "")
set(SAPI_ENABLE_TESTS OFF CACHE BOOL "")
add_subdirectory("${SAPI_ROOT}"
"${CMAKE_BINARY_DIR}/sandboxed-api-build"
# Omit this to have the full Sandboxed API in IDE
EXCLUDE_FROM_ALL)
add_sapi_library(pffft_sapi
FUNCTIONS pffft_new_setup
pffft_destroy_setup
pffft_transform
pffft_transform_ordered
pffft_zreorder
pffft_zconvolve_accumulate
pffft_aligned_malloc
pffft_aligned_free
pffft_simd_size
cffti
cfftf
cfftb
rffti
rfftf
rfftb
cosqi
cosqf
cosqb
costi
cost
sinqi
sinqb
sinqf
sinti
sint
INPUTS master/pffft.h master/fftpack.h
LIBRARY pffft
LIBRARY_NAME Pffft
NAMESPACE ""
)
target_include_directories(pffft_sapi INTERFACE
"${PROJECT_BINARY_DIR}"
)
add_executable(pffft_sandboxed
main_pffft_sandboxed.cc
)
target_link_libraries(pffft_sandboxed PRIVATE
pffft_sapi
sapi::sapi
)

View File

@ -0,0 +1,87 @@
# Sandboxing PFFFT library
Build System: CMake
OS: Linux
### Check out the PFFFT library & CMake set up
```
git submodule update --init --recursive
mkdir -p build && cd build
cmake .. -G Ninja -DPFFFT_ROOT_DIR=$PWD
ninjas
```
### For testing:
`cd build`, then `./pffft_sandboxed`
### For debug:
display custom info with
`./pffft_sandboxed --logtostderr`
## ***About the project***
*PFFFT library is concerned with 1D Fast-Fourier Transformations finding a
compromise between accuracy and speed. It deals with real and complex
vectors, both cases being illustrated in the testing part (`test_pffft.c`
for initially and original version, `main_pffft_sandboxed.cc` for our
currently implemented sandboxed version).
The original files can be found at: https://bitbucket.org/jpommier/pffft/src.*
*The purpose of sandboxing is to limit the permissions and capabilities of
librarys methods, in order to secure the usage of them.
After obtaining the sandbox, the functions will be called through an
Sandbox API (being called `api` in the current test) and so, the
operations, system calls or namspaces access may be controlled.
From both `pffft.h` and `fftpack.h` headers, useful methods are added to
sapi library builded with CMake. There is also a need to link math library
as the transformations made require mathematical operators.
Regarding the testing of the methods, one main is doing this job by
iterating through a set of values, that represents the accuracy of
transformations and print the speed for each value and type of
transformation. More specifically, the input length is the target for
accuracy (named as `n`) and it stands for the number of data points from
the series that calculate the result of transformation. It is also
important to mention that the `complex` variable stands for a boolean value
that tells the type of transformation (0 for REAL and 1 for COMPLEX) and
it is taken into account while testing.
In the end, the performance of PFFFT library it is outlined by the output.
There are two output formats available, from which you can choose through
`--output_format=` command-line flag.
Without using this type of argument when running, the output format is set
by default.*
#### CMake observations resume:
* linking pffft and fftpack (which contains necessary functions for pffft)
* set math library
#### Sandboxed main observations resume:
* containing two testing parts (fft / pffft benchmarks)
* showing the performance of the transformations implies
testing them through various FFT dimenstions.
Variable n, the input length, will take specific values
meaning the number of points to which it is set the calculus
(more details of mathematical purpose of n - https://en.wikipedia.org/wiki/Cooley%E2%80%93Tukey_FFT_algorithm).
* output shows speed depending on the input length
* use `--output_format=0` or `--output_format=1` arguments to choose between output formats.
`0` is for a detailed output, while `1` is only displaying each transformation process speed.
### Bugs history
1. [Solved] pffft benchmark bug: "Sandbox not active"
n = 64, status OK, `pffft_transform` generates error
n > 64, status not OK
Problem on initialising `sapi::StatusOr<PFFFT_Setup *> s;` the memory that stays
for s is not the same with the address passed in `pffft_transform` function.
(`sapi::v::GenericPtr` - to be changed)
Temporary solution: change the generated files to accept
`uintptr_t` instead of `PFFFT_Setup`
Solution: using `sapi::v::RemotePtr` instead of `sapi::v::GenericPtr`
to access the memory of object `s`
2. [Unresolved] compiling bug: "No space left on device"
The building process creates some `embed` files that use lots of
memory, trying to write them on `/tmp`.
Temporary solution: clean /tmp directory by `sudo rm -rf /tmp/*`

View File

@ -0,0 +1,207 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <gflags/gflags.h>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <glog/logging.h>
#include "pffft_sapi.sapi.h" // NOLINT(build/include)
#include "sandboxed_api/util/flag.h"
#include "sandboxed_api/vars.h"
ABSL_DECLARE_FLAG(string, sandbox2_danger_danger_permit_all);
ABSL_DECLARE_FLAG(string, sandbox2_danger_danger_permit_all_and_log);
class PffftSapiSandbox : public PffftSandbox {
public:
std::unique_ptr<sandbox2::Policy> ModifyPolicy(sandbox2::PolicyBuilder*) {
return sandbox2::PolicyBuilder()
.AllowStaticStartup()
.AllowOpen()
.AllowRead()
.AllowWrite()
.AllowSystemMalloc()
.AllowExit()
.AllowSyscalls({
__NR_futex,
__NR_close,
__NR_getrusage,
})
.BuildOrDie();
}
};
// output_format flag determines whether the output shows information in detail
// or not. By default, the flag is set as 0, meaning an elaborate display
// (see ShowOutput method).
static bool ValidateFlag(const char* flagname, int32_t value) {
if (value >= 0 && value < 32768) {
return true;
}
LOG(ERROR) << "Invalid value for --" << flagname << ".";
return false;
}
DEFINE_int32(output_format, 0, "Value to specific the output format.");
DEFINE_validator(output_format, &ValidateFlag);
double UclockSec() { return static_cast<double>(clock()) / CLOCKS_PER_SEC; }
void ShowOutput(const char* name, int n, int complex, float flops, float t0,
float t1, int max_iter) {
float mflops = flops / 1e6 / (t1 - t0 + 1e-16);
if (FLAGS_output_format) {
if (flops != -1) {
printf("|%9.0f ", mflops);
} else {
printf("| n/a ");
}
} else if (flops != -1) {
printf("n=%5d, %s %16s : %6.0f MFlops [t=%6.0f ns, %d runs]\n", n,
(complex ? "CPLX" : "REAL"), name, mflops,
(t1 - t0) / 2 / max_iter * 1e9, max_iter);
}
fflush(stdout);
}
absl::Status PffftMain() {
LOG(INFO) << "Initializing sandbox...\n";
PffftSapiSandbox sandbox;
SAPI_RETURN_IF_ERROR(sandbox.Init());
PffftApi api(&sandbox);
// kTransformSizes is a vector keeping the values by which iterates n, its
// value representing the input length. More concrete, n is the number of data
// points the caclulus is up to (determinating its accuracy). To show the
// performance of Fast-Fourier Transformations the program is testing for
// various values of n.
constexpr int kTransformSizes[] = {
64, 96, 128, 160, 192, 256, 384, 5 * 96, 512, 5 * 128,
3 * 256, 800, 1024, 2048, 2400, 4096, 8192, 9 * 1024, 16384, 32768};
for (int complex : {0, 1}) {
for (int n : kTransformSizes) {
const int n_float = n * (complex ? 2 : 1);
int n_bytes = n_float * sizeof(float);
std::vector<float> work(2 * n_float + 15, 0.0);
sapi::v::Array<float> work_array(&work[0], work.size());
std::vector<float> x(n_bytes, 0.0);
sapi::v::Array<float> x_array(&x[0], x.size());
std::vector<float> y(n_bytes, 0.0);
sapi::v::Array<float> y_array(&y[0], y.size());
std::vector<float> z(n_bytes, 0.0);
sapi::v::Array<float> z_array(&z[0], z.size());
double t0;
double t1;
double flops;
int max_iter = 5120000 / n * 4;
for (int k = 0; k < n_float; ++k) {
x[k] = 0;
}
// FFTPack benchmark
{
// SIMD_SZ == 4 (returning value of pffft_simd_size())
int simd_size_iter = max_iter / 4;
if (simd_size_iter == 0) simd_size_iter = 1;
if (complex) {
SAPI_RETURN_IF_ERROR(api.cffti(n, work_array.PtrBoth()))
} else {
SAPI_RETURN_IF_ERROR(api.rffti(n, work_array.PtrBoth()));
}
t0 = UclockSec();
for (int iter = 0; iter < simd_size_iter; ++iter) {
if (complex) {
SAPI_RETURN_IF_ERROR(
api.cfftf(n, x_array.PtrBoth(), work_array.PtrBoth()));
SAPI_RETURN_IF_ERROR(
api.cfftb(n, x_array.PtrBoth(), work_array.PtrBoth()));
} else {
SAPI_RETURN_IF_ERROR(
api.rfftf(n, x_array.PtrBoth(), work_array.PtrBoth()));
SAPI_RETURN_IF_ERROR(
api.rfftb(n, x_array.PtrBoth(), work_array.PtrBoth()));
}
}
t1 = UclockSec();
flops = (simd_size_iter * 2) *
((complex ? 5 : 2.5) * static_cast<double>(n) *
log(static_cast<double>(n)) / M_LN2);
ShowOutput("FFTPack", n, complex, flops, t0, t1, simd_size_iter);
}
// PFFFT benchmark
{
SAPI_ASSIGN_OR_RETURN(
PFFFT_Setup * s,
api.pffft_new_setup(n, complex ? PFFFT_COMPLEX : PFFFT_REAL));
sapi::v::RemotePtr s_reg(s);
t0 = UclockSec();
for (int iter = 0; iter < max_iter; ++iter) {
SAPI_RETURN_IF_ERROR(
api.pffft_transform(&s_reg, x_array.PtrBoth(), z_array.PtrBoth(),
y_array.PtrBoth(), PFFFT_FORWARD));
SAPI_RETURN_IF_ERROR(
api.pffft_transform(&s_reg, x_array.PtrBoth(), z_array.PtrBoth(),
y_array.PtrBoth(), PFFFT_FORWARD));
}
t1 = UclockSec();
SAPI_RETURN_IF_ERROR(api.pffft_destroy_setup(&s_reg));
flops = (max_iter * 2) * ((complex ? 5 : 2.5) * static_cast<double>(n) *
log(static_cast<double>(n)) / M_LN2);
ShowOutput("PFFFT", n, complex, flops, t0, t1, max_iter);
LOG(INFO) << "n = " << n << " SUCCESSFULLY";
}
}
}
return absl::OkStatus();
}
int main(int argc, char* argv[]) {
// Initialize Google's logging library.
google::InitGoogleLogging(argv[0]);
gflags::ParseCommandLineFlags(&argc, &argv, true);
if (absl::Status status = PffftMain(); !status.ok()) {
LOG(ERROR) << "Initialization failed: " << status.ToString();
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

View File

@ -147,10 +147,10 @@ cc_library(
":var_type",
"//sandboxed_api/sandbox2:comms",
"//sandboxed_api/util:status",
"//sandboxed_api/util:statusor",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
"@com_google_absl//absl/synchronization",

View File

@ -43,6 +43,8 @@ add_library(sapi_embed_file STATIC
add_library(sapi::embed_file ALIAS sapi_embed_file)
target_link_libraries(sapi_embed_file PRIVATE
absl::flat_hash_map
absl::status
absl::statusor
absl::strings
absl::synchronization
glog::glog
@ -65,6 +67,8 @@ add_library(sapi::sapi ALIAS sapi_sapi)
target_link_libraries(sapi_sapi
PRIVATE absl::flat_hash_map
absl::memory
absl::status
absl::statusor
absl::str_format
absl::strings
absl::synchronization
@ -76,7 +80,6 @@ target_link_libraries(sapi_sapi
sandbox2::strerror
sandbox2::util
sapi::embed_file
sapi::status
sapi::vars
PUBLIC absl::core_headers
sandbox2::client
@ -137,6 +140,8 @@ add_library(sapi_vars STATIC
add_library(sapi::vars ALIAS sapi_vars)
target_link_libraries(sapi_vars PRIVATE
absl::core_headers
absl::status
absl::statusor
absl::str_format
absl::strings
absl::synchronization
@ -147,7 +152,6 @@ target_link_libraries(sapi_vars PRIVATE
sapi::lenval_core
sapi::proto_arg_proto
sapi::status
sapi::statusor
sapi::var_type
)
@ -178,6 +182,7 @@ if(SAPI_ENABLE_TESTS)
)
target_link_libraries(sapi_test PRIVATE
absl::memory
absl::status
benchmark
sapi::sapi
sapi::status

View File

@ -34,9 +34,9 @@ def sapi_deps():
maybe(
http_archive,
name = "com_google_absl",
sha256 = "6668ada01192e2b95b42bb3668cfa5282c047de5176f5e567028e12f8bfb8aef", # 2020-04-28
strip_prefix = "abseil-cpp-6e18c7115df9b7ca0987cc346b1b1d4b3cc829b3",
urls = ["https://github.com/abseil/abseil-cpp/archive/6e18c7115df9b7ca0987cc346b1b1d4b3cc829b3.zip"],
sha256 = "8061df0ebbd3f599bcd3f5e57fb8003564d50a9b6a81a7f968fb0196b952365d", # 2020-09-02
strip_prefix = "abseil-cpp-0e9921b75a0fdd639a504ec8443fc1fe801becd7",
urls = ["https://github.com/abseil/abseil-cpp/archive/0e9921b75a0fdd639a504ec8443fc1fe801becd7.zip"],
)
maybe(
http_archive,

View File

@ -14,11 +14,11 @@
# Description: Sandboxed API reimplementation of zlib's zpipe.c example.
licenses(["notice"])
load("//sandboxed_api/bazel:build_defs.bzl", "sapi_platform_copts")
load("//sandboxed_api/bazel:sapi.bzl", "sapi_library")
licenses(["notice"])
sapi_library(
name = "zlib-sapi",
srcs = [],
@ -43,5 +43,6 @@ cc_binary(
"//sandboxed_api:vars",
"//sandboxed_api/util:flags",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/status:statusor",
],
)

View File

@ -32,11 +32,11 @@ add_executable(main_zlib
main_zlib.cc
)
target_link_libraries(main_zlib PRIVATE
absl::status
sapi::base
glog::glog
sapi::flags
sapi::sapi
sapi::status
sapi::statusor
sapi::zlib_sapi
)

View File

@ -20,6 +20,7 @@
#include <glog/logging.h>
#include "absl/base/macros.h"
#include "sandboxed_api/util/flag.h"
#include "absl/status/statusor.h"
#include "sandboxed_api/examples/zlib/zlib-sapi.sapi.h"
#include "sandboxed_api/examples/zlib/zlib-sapi_embed.h"
#include "sandboxed_api/vars.h"
@ -47,7 +48,7 @@ int main(int argc, char** argv) {
<< status.message();
}
sapi::StatusOr<int> ret;
absl::StatusOr<int> ret;
int flush;
unsigned have;
sapi::v::Struct<sapi::zlib::z_stream> strm;

View File

@ -22,13 +22,13 @@
#include <vector>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "sandboxed_api/proto_arg.pb.h"
#include "sandboxed_api/util/statusor.h"
namespace sapi {
template <typename T>
sapi::StatusOr<std::vector<uint8_t>> SerializeProto(const T& proto) {
absl::StatusOr<std::vector<uint8_t>> SerializeProto(const T& proto) {
static_assert(std::is_base_of<google::protobuf::Message, T>::value,
"Template argument must be a proto message");
// Wrap protobuf in a envelope so that we know the name of the protobuf
@ -46,7 +46,7 @@ sapi::StatusOr<std::vector<uint8_t>> SerializeProto(const T& proto) {
}
template <typename T>
sapi::StatusOr<T> DeserializeProto(const char* data, size_t len) {
absl::StatusOr<T> DeserializeProto(const char* data, size_t len) {
static_assert(std::is_base_of<google::protobuf::Message, T>::value,
"Template argument must be a proto message");
ProtoArg envelope;

View File

@ -15,6 +15,7 @@
#include "sandboxed_api/rpcchannel.h"
#include <glog/logging.h>
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/synchronization/mutex.h"
#include "sandboxed_api/call.h"
@ -35,7 +36,7 @@ absl::Status RPCChannel::Call(const FuncCall& call, uint32_t tag, FuncRet* ret,
return absl::OkStatus();
}
sapi::StatusOr<FuncRet> RPCChannel::Return(v::Type exp_type) {
absl::StatusOr<FuncRet> RPCChannel::Return(v::Type exp_type) {
uint32_t tag;
uint64_t len;
FuncRet ret;
@ -202,7 +203,7 @@ absl::Status RPCChannel::Close(int remote_fd) {
return absl::OkStatus();
}
sapi::StatusOr<uint64_t> RPCChannel::Strlen(void* str) {
absl::StatusOr<uint64_t> RPCChannel::Strlen(void* str) {
absl::MutexLock lock(&mutex_);
if (!comms_->SendTLV(comms::kMsgStrlen, sizeof(str),
reinterpret_cast<uint8_t*>(&str))) {

View File

@ -18,11 +18,11 @@
#include <cstddef>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/synchronization/mutex.h"
#include "sandboxed_api/call.h"
#include "sandboxed_api/sandbox2/comms.h"
#include "sandboxed_api/var_type.h"
#include "sandboxed_api/util/statusor.h"
namespace sapi {
@ -61,13 +61,13 @@ class RPCChannel {
absl::Status Close(int remote_fd);
// Returns length of a null-terminated c-style string (invokes strlen).
sapi::StatusOr<uint64_t> Strlen(void* str);
absl::StatusOr<uint64_t> Strlen(void* str);
sandbox2::Comms* comms() const { return comms_; }
private:
// Receives the result after a call.
sapi::StatusOr<FuncRet> Return(v::Type exp_type);
absl::StatusOr<FuncRet> Return(v::Type exp_type);
sandbox2::Comms* comms_; // Owned by sandbox2;
absl::Mutex mutex_;

View File

@ -84,7 +84,9 @@ void InitDefaultPolicyBuilder(sandbox2::PolicyBuilder* builder) {
__NR_kill,
__NR_tgkill,
__NR_tkill,
#ifdef __NR_readlink
__NR_readlink,
#endif
#ifdef __NR_arch_prctl // x86-64 only
__NR_arch_prctl,
#endif
@ -391,8 +393,8 @@ absl::Status Sandbox::TransferFromSandboxee(v::Var* var) {
return var->TransferFromSandboxee(GetRpcChannel(), pid());
}
sapi::StatusOr<std::string> Sandbox::GetCString(const v::RemotePtr& str,
uint64_t max_length) {
absl::StatusOr<std::string> Sandbox::GetCString(const v::RemotePtr& str,
uint64_t max_length) {
if (!is_active()) {
return absl::UnavailableError("Sandbox not active");
}

View File

@ -102,8 +102,9 @@ class Sandbox {
absl::Status TransferToSandboxee(v::Var* var);
absl::Status TransferFromSandboxee(v::Var* var);
sapi::StatusOr<std::string> GetCString(
const v::RemotePtr& str, uint64_t max_length = 10ULL << 20 /* 10 MiB*/
absl::StatusOr<std::string> GetCString(const v::RemotePtr& str,
uint64_t max_length = 10ULL
<< 20 /* 10 MiB*/
);
// Waits until the sandbox terminated and returns the result.

View File

@ -26,6 +26,13 @@ licenses(["notice"]) # Apache 2.0
exports_files(["testdata/hostname"])
cc_library(
name = "config",
hdrs = ["config.h"],
copts = sapi_platform_copts(),
deps = ["@com_google_absl//absl/base:config"],
)
cc_library(
name = "bpfdisassembler",
srcs = ["bpfdisassembler.cc"],
@ -40,6 +47,7 @@ cc_library(
hdrs = ["regs.h"],
copts = sapi_platform_copts(),
deps = [
":config",
":syscall",
":violation_cc_proto",
"//sandboxed_api/sandbox2/util:strerror",
@ -60,6 +68,7 @@ cc_library(
copts = sapi_platform_copts(),
visibility = ["//visibility:public"],
deps = [
":config",
":util",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
@ -73,6 +82,7 @@ cc_test(
srcs = ["syscall_test.cc"],
copts = sapi_platform_copts(),
deps = [
":config",
":syscall",
"@com_google_absl//absl/strings",
"@com_google_googletest//:gtest_main",
@ -85,12 +95,13 @@ cc_library(
hdrs = ["result.h"],
copts = sapi_platform_copts(),
deps = [
":config",
":regs",
":syscall",
":util",
"//sandboxed_api/util:statusor",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
],
)
@ -272,6 +283,7 @@ cc_library(
deps = [
":client",
":comms",
":config",
":executor",
":fork_client",
":forkserver_cc_proto",
@ -300,12 +312,12 @@ cc_library(
"//sandboxed_api/util:flags",
"//sandboxed_api/util:raw_logging",
"//sandboxed_api/util:status",
"//sandboxed_api/util:statusor",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
"@com_google_absl//absl/synchronization",
@ -374,9 +386,9 @@ cc_library(
"//sandboxed_api/sandbox2/util:fileops",
"//sandboxed_api/sandbox2/util:strerror",
"//sandboxed_api/util:raw_logging",
"//sandboxed_api/util:statusor",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
"@org_kernel_libcap//:libcap",
@ -404,6 +416,7 @@ cc_library(
hdrs = ["mounts.h"],
copts = sapi_platform_copts(),
deps = [
":config",
":mounttree_cc_proto",
"//sandboxed_api/sandbox2/util:file_base",
"//sandboxed_api/sandbox2/util:fileops",
@ -411,10 +424,10 @@ cc_library(
"//sandboxed_api/sandbox2/util:strerror",
"//sandboxed_api/util:raw_logging",
"//sandboxed_api/util:status",
"//sandboxed_api/util:statusor",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_protobuf//:protobuf",
],
@ -468,6 +481,7 @@ cc_test(
],
deps = [
":comms",
":config",
":namespace",
":sandbox2",
":testing",
@ -505,12 +519,13 @@ cc_library(
copts = sapi_platform_copts(),
visibility = ["//visibility:public"],
deps = [
":config",
"//sandboxed_api/sandbox2/util:file_base",
"//sandboxed_api/sandbox2/util:fileops",
"//sandboxed_api/sandbox2/util:strerror",
"//sandboxed_api/util:raw_logging",
"//sandboxed_api/util:statusor",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
],
@ -526,9 +541,9 @@ cc_library(
":util",
"//sandboxed_api/sandbox2/util:strerror",
"//sandboxed_api/util:status",
"//sandboxed_api/util:statusor",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
],
)
@ -541,6 +556,7 @@ cc_test(
deps = [
":buffer",
":comms",
":config",
":sandbox2",
":testing",
"//sandboxed_api/util:status_matchers",
@ -573,10 +589,10 @@ cc_library(
"//sandboxed_api/util:raw_logging",
"//sandboxed_api/util:status",
"//sandboxed_api/util:status_proto",
"//sandboxed_api/util:statusor",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
"@com_google_absl//absl/synchronization",
@ -629,6 +645,7 @@ cc_test(
copts = sapi_platform_copts(),
data = ["//sandboxed_api/sandbox2/testcases:limits"],
deps = [
":config",
":limits",
":sandbox2",
":testing",
@ -671,6 +688,7 @@ cc_test(
"//sandboxed_api/sandbox2/testcases:policy",
],
deps = [
":config",
":limits",
":regs",
":sandbox2",
@ -695,6 +713,7 @@ cc_test(
],
tags = ["local"],
deps = [
":config",
":sandbox2",
":testing",
"//sandboxed_api/sandbox2/util:bpf_helper",
@ -805,6 +824,7 @@ cc_test(
"//sandboxed_api/util:status_matchers",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_glog//:glog",
"@com_google_googletest//:gtest_main",

View File

@ -17,6 +17,16 @@ add_subdirectory(unwind)
add_subdirectory(util)
add_subdirectory(network_proxy)
# sandboxed_api/sandbox2:config
add_library(sandbox2_config STATIC
config.h
)
add_library(sandbox2::config ALIAS sandbox2_config)
target_link_libraries(sandbox2_config PRIVATE
absl::config
sapi::base
)
# sandboxed_api/sandbox2:bpfdisassembler
add_library(sandbox2_bpfdisassembler STATIC
bpfdisassembler.cc
@ -37,6 +47,7 @@ add_library(sandbox2::regs ALIAS sandbox2_regs)
target_link_libraries(sandbox2_regs PRIVATE
absl::core_headers
absl::strings
sandbox2::config
sandbox2::strerror
sandbox2::syscall
sandbox2::violation_proto
@ -72,6 +83,7 @@ target_link_libraries(sandbox2_result PRIVATE
absl::base
absl::memory
absl::strings
sandbox2::config
sandbox2::regs
sandbox2::syscall
sandbox2::util
@ -271,6 +283,8 @@ target_link_libraries(sandbox2_sandbox2
absl::flat_hash_set
absl::memory
absl::optional
absl::status
absl::statusor
absl::str_format
absl::strings
absl::synchronization
@ -278,6 +292,7 @@ target_link_libraries(sandbox2_sandbox2
sandbox2::bpf_helper
sandbox2::client
sandbox2::comms
sandbox2::config
sandbox2::executor
sandbox2::file_base
sandbox2::fileops
@ -300,7 +315,6 @@ target_link_libraries(sandbox2_sandbox2
sandbox2::util
sandbox2::violation_proto
sapi::base
sapi::statusor
PUBLIC sapi::flags
sapi::status
sandbox2::logsink
@ -351,6 +365,8 @@ add_library(sandbox2_forkserver STATIC
add_library(sandbox2::forkserver ALIAS sandbox2_forkserver)
target_link_libraries(sandbox2_forkserver PRIVATE
absl::memory
absl::status
absl::statusor
absl::str_format
absl::strings
libcap::libcap
@ -369,7 +385,6 @@ target_link_libraries(sandbox2_forkserver PRIVATE
sandbox2::util
sapi::base
sapi::raw_logging
sapi::statusor
)
# sandboxed_api/sandbox2:fork_client
@ -397,9 +412,11 @@ target_link_libraries(sandbox2_mounts PRIVATE
absl::core_headers
absl::flat_hash_set
absl::status
absl::statusor
absl::str_format
absl::strings
protobuf::libprotobuf
sandbox2::config
sandbox2::file_base
sandbox2::fileops
sandbox2::minielf
@ -408,7 +425,6 @@ target_link_libraries(sandbox2_mounts PRIVATE
sapi::base
sapi::raw_logging
sapi::status
sapi::statusor
)
# sandboxed_api/sandbox2:namespace
@ -458,13 +474,14 @@ target_link_libraries(sandbox2_util
PRIVATE absl::core_headers
absl::str_format
absl::strings
sandbox2::config
sandbox2::file_base
sandbox2::fileops
sandbox2::strerror
sapi::base
sapi::raw_logging
sapi::statusor
PUBLIC absl::status
absl::statusor
)
target_compile_options(sandbox2_util PRIVATE
# The default is 16384, however we need to do a clone with a
@ -482,12 +499,13 @@ add_library(sandbox2::buffer ALIAS sandbox2_buffer)
target_link_libraries(sandbox2_buffer PRIVATE
absl::core_headers
absl::memory
absl::status
absl::statusor
absl::strings
sandbox2::strerror
sandbox2::util
sapi::base
sapi::status
sapi::statusor
)
# sandboxed_api/sandbox2:forkserver_proto
@ -527,6 +545,8 @@ add_library(sandbox2_comms STATIC
add_library(sandbox2::comms ALIAS sandbox2_comms)
target_link_libraries(sandbox2_comms
PRIVATE absl::memory
absl::status
absl::statusor
absl::str_format
absl::strings
sandbox2::strerror
@ -534,7 +554,6 @@ target_link_libraries(sandbox2_comms
sapi::base
sapi::raw_logging
sapi::status_proto
sapi::statusor
PUBLIC absl::core_headers
absl::status
absl::synchronization
@ -566,6 +585,7 @@ if(SAPI_ENABLE_TESTS)
)
target_link_libraries(syscall_test PRIVATE
absl::strings
sandbox2::config
sandbox2::syscall
sapi::test_main
)
@ -604,6 +624,7 @@ if(SAPI_ENABLE_TESTS)
absl::memory
absl::strings
sandbox2::comms
sandbox2::config
sandbox2::fileops
sandbox2::namespace
sandbox2::sandbox2
@ -628,6 +649,7 @@ if(SAPI_ENABLE_TESTS)
absl::memory
sandbox2::buffer
sandbox2::comms
sandbox2::config
sandbox2::sandbox2
sandbox2::testing
sapi::status_matchers
@ -702,6 +724,7 @@ if(SAPI_ENABLE_TESTS)
target_link_libraries(limits_test PRIVATE
absl::memory
sandbox2::bpf_helper
sandbox2::config
sandbox2::limits
sandbox2::sandbox2
sandbox2::testing
@ -751,6 +774,7 @@ if(SAPI_ENABLE_TESTS)
absl::memory
absl::strings
sandbox2::bpf_helper
sandbox2::config
sandbox2::limits
sandbox2::regs
sandbox2::sandbox2
@ -776,6 +800,7 @@ if(SAPI_ENABLE_TESTS)
absl::memory
absl::strings
sandbox2::bpf_helper
sandbox2::config
sandbox2::sandbox2
sandbox2::testing
sapi::status_matchers
@ -832,6 +857,7 @@ if(SAPI_ENABLE_TESTS)
)
target_link_libraries(stack_trace_test PRIVATE
absl::memory
absl::status
absl::strings
sandbox2::bpf_helper
sandbox2::fileops

View File

@ -21,6 +21,7 @@
#include <cerrno>
#include "absl/memory/memory.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "sandboxed_api/sandbox2/util.h"
#include "sandboxed_api/sandbox2/util/strerror.h"
@ -28,7 +29,7 @@
namespace sandbox2 {
// Creates a new Buffer that is backed by the specified file descriptor.
sapi::StatusOr<std::unique_ptr<Buffer>> Buffer::CreateFromFd(int fd) {
absl::StatusOr<std::unique_ptr<Buffer>> Buffer::CreateFromFd(int fd) {
auto buffer = absl::WrapUnique(new Buffer{});
struct stat stat_buf;
@ -53,7 +54,7 @@ sapi::StatusOr<std::unique_ptr<Buffer>> Buffer::CreateFromFd(int fd) {
// Creates a new Buffer of the specified size, backed by a temporary file that
// will be immediately deleted.
sapi::StatusOr<std::unique_ptr<Buffer>> Buffer::CreateWithSize(int64_t size) {
absl::StatusOr<std::unique_ptr<Buffer>> Buffer::CreateWithSize(int64_t size) {
int fd;
if (!util::CreateMemFd(&fd)) {
return absl::InternalError("Could not create buffer temp file");

View File

@ -19,7 +19,7 @@
#include <cstdint>
#include <memory>
#include "sandboxed_api/util/statusor.h"
#include "absl/status/statusor.h"
namespace sandbox2 {
@ -37,11 +37,11 @@ class Buffer final {
// Creates a new Buffer that is backed by the specified file descriptor.
// The Buffer takes ownership of the descriptor and will close it when
// destroyed.
static sapi::StatusOr<std::unique_ptr<Buffer>> CreateFromFd(int fd);
static absl::StatusOr<std::unique_ptr<Buffer>> CreateFromFd(int fd);
// Creates a new Buffer of the specified size, backed by a temporary file that
// will be immediately deleted.
static sapi::StatusOr<std::unique_ptr<Buffer>> CreateWithSize(int64_t size);
static absl::StatusOr<std::unique_ptr<Buffer>> CreateWithSize(int64_t size);
// Returns a pointer to the buffer, which is read/write.
uint8_t* data() const { return buf_; }

View File

@ -29,6 +29,7 @@
#include "gtest/gtest.h"
#include "absl/memory/memory.h"
#include "sandboxed_api/sandbox2/comms.h"
#include "sandboxed_api/sandbox2/config.h"
#include "sandboxed_api/sandbox2/executor.h"
#include "sandboxed_api/sandbox2/ipc.h"
#include "sandboxed_api/sandbox2/policy.h"
@ -83,19 +84,20 @@ std::unique_ptr<Policy> BufferTestcasePolicy() {
.AllowSyscall(__NR_lseek)
.AllowSyscall(__NR_close)
.BlockSyscallWithErrno(__NR_prlimit64, EPERM)
#ifdef __NR_open
.BlockSyscallWithErrno(__NR_open, ENOENT)
#endif
.BlockSyscallWithErrno(__NR_openat, ENOENT)
#ifdef __NR_access
// On Debian, even static binaries check existence of
// /etc/ld.so.nohwcap.
.BlockSyscallWithErrno(__NR_access, ENOENT)
#endif
#ifdef __NR_faccessat
.BlockSyscallWithErrno(__NR_faccessat, ENOENT)
#endif
.BuildOrDie();
#if defined(__powerpc64__)
s2p->AllowUnsafeMmapFiles();
s2p->AllowUnsafeMmapShared();
#endif /* defined(__powerpc64__) */
return s2p;
}

View File

@ -36,6 +36,7 @@
#include "google/protobuf/message.h"
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/synchronization/mutex.h"
@ -44,7 +45,6 @@
#include "sandboxed_api/util/raw_logging.h"
#include "sandboxed_api/util/status.h"
#include "sandboxed_api/util/status_macros.h"
#include "sandboxed_api/util/statusor.h"
#ifdef MEMORY_SANITIZER
#include "base/dynamic_annotations.h"
@ -347,7 +347,7 @@ bool Comms::RecvFD(int* fd) {
const auto op = [&msg](int fd) -> ssize_t {
PotentiallyBlockingRegion region;
// Use syscall, otherwise we would need to whitelist socketcall() on PPC.
// Use syscall, otherwise we would need to allow socketcall() on PPC.
return TEMP_FAILURE_RETRY(
util::Syscall(__NR_recvmsg, fd, reinterpret_cast<uintptr_t>(&msg), 0));
};

View File

@ -0,0 +1,85 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SANDBOXED_API_SANDBOX2_CONFIG_H_
#define SANDBOXED_API_SANDBOX2_CONFIG_H_
#include <cstdint>
#include "absl/base/config.h"
// GCC/Clang define __x86_64__, Visual Studio uses _M_X64
#if defined(__x86_64__) || defined(_M_X64)
#define SAPI_X86_64 1
// Check various spellings for 64-bit POWER. Not checking for Visual Studio, as
// it does not support 64-bit POWER.
#elif (defined(__PPC64__) || defined(__powerpc64__) || defined(__ppc64__)) && \
defined(ABSL_IS_LITTLE_ENDIAN)
#define SAPI_PPC64_LE 1
// Spellings for AArch64
#elif defined(__aarch64__) || defined(_M_ARM64)
#define SAPI_ARM64 1
#endif
namespace sandbox2 {
namespace cpu {
// CPU architectures known to Sandbox2
enum Architecture : uint16_t {
// Linux: Use a magic value, so it can be easily spotted in the seccomp-bpf
// bytecode decompilation stream. Must be < (1<<15), as/ that's the size of
// data which can be returned by BPF.
kUnknown = 0xCAF0,
kX8664,
kX86,
kPPC64LE,
kArm64,
};
} // namespace cpu
namespace host_cpu {
// Returns the current host CPU architecture if supported. If not supported,
// returns cpu::kUnknown.
constexpr cpu::Architecture Architecture() {
#if defined(SAPI_X86_64)
return cpu::kX8664;
#elif defined(SAPI_PPC64_LE)
return cpu::kPPC64LE;
#elif defined(SAPI_ARM64)
return cpu::kArm64;
#else
return cpu::kUnknown;
#endif
}
constexpr bool IsX8664() { return Architecture() == cpu::kX8664; }
constexpr bool IsPPC64LE() { return Architecture() == cpu::kPPC64LE; }
constexpr bool IsArm64() { return Architecture() == cpu::kArm64; }
} // namespace host_cpu
static_assert(host_cpu::Architecture() != cpu::kUnknown,
"Host CPU architecture is not supported: One of x86-64, POWER64 "
"(little endian) or AArch64 is required.");
} // namespace sandbox2
#endif // SANDBOXED_API_SANDBOX2_CONFIG_H_

View File

@ -27,7 +27,6 @@ cc_binary(
deps = [
"//sandboxed_api/sandbox2",
"//sandboxed_api/sandbox2:comms",
"//sandboxed_api/sandbox2/network_proxy:filtering",
"//sandboxed_api/sandbox2/util:bpf_helper",
"//sandboxed_api/sandbox2/util:fileops",
"//sandboxed_api/sandbox2/util:runfiles",
@ -48,7 +47,9 @@ cc_binary(
"//sandboxed_api/sandbox2/util:strerror",
"//sandboxed_api/util:flags",
"//sandboxed_api/util:status",
"//sandboxed_api/util:statusor",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
],
)

View File

@ -31,13 +31,14 @@ target_link_libraries(sandbox2_networkproxy_sandbox PRIVATE
sapi::flags
)
# sandboxed_api/sandbox2/examples/networkproxy:networkproxy_bin
add_executable(sandbox2_networkproxy_bin
networkproxy_bin.cc
)
add_executable(sandbox2::networkproxy_bin ALIAS sandbox2_networkproxy_bin)
target_link_libraries(sandbox2_networkproxy_bin PRIVATE
absl::status
absl::statusor
absl::str_format
glog::glog
gflags::gflags
@ -48,6 +49,4 @@ target_link_libraries(sandbox2_networkproxy_bin PRIVATE
sapi::base
sapi::flags
sapi::status
sapi::statusor
)

View File

@ -12,15 +12,16 @@
#include <cstring>
#include "sandboxed_api/util/flag.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "sandboxed_api/sandbox2/client.h"
#include "sandboxed_api/sandbox2/comms.h"
#include "sandboxed_api/sandbox2/network_proxy/client.h"
#include "sandboxed_api/sandbox2/util/fileops.h"
#include "sandboxed_api/sandbox2/util/strerror.h"
#include "sandboxed_api/util/status.h"
#include "sandboxed_api/util/status_macros.h"
#include "sandboxed_api/util/statusor.h"
ABSL_FLAG(bool, connect_with_handler, true, "Connect using automatic mode.");
@ -58,7 +59,7 @@ absl::Status CommunicationTest(int sock) {
return absl::OkStatus();
}
sapi::StatusOr<struct sockaddr_in6> CreateAddres(int port) {
absl::StatusOr<struct sockaddr_in6> CreateAddres(int port) {
static struct sockaddr_in6 saddr {};
saddr.sin6_family = AF_INET6;
saddr.sin6_port = htons(port);
@ -86,7 +87,7 @@ absl::Status ConnectWithHandler(int s, const struct sockaddr_in6& saddr) {
return absl::OkStatus();
}
sapi::StatusOr<int> ConnectToServer(int port) {
absl::StatusOr<int> ConnectToServer(int port) {
SAPI_ASSIGN_OR_RETURN(struct sockaddr_in6 saddr, CreateAddres(port));
sandbox2::file_util::fileops::FDCloser s(socket(AF_INET6, SOCK_STREAM, 0));
@ -134,7 +135,7 @@ int main(int argc, char** argv) {
return 2;
}
sapi::StatusOr<int> sock_s = ConnectToServer(port);
absl::StatusOr<int> sock_s = ConnectToServer(port);
if (!sock_s.ok()) {
LOG(ERROR) << sock_s.status().message();
return 3;

View File

@ -52,8 +52,10 @@ std::unique_ptr<sandbox2::Policy> GetPolicy() {
// Allow the getpid() syscall.
.AllowSyscall(__NR_getpid)
#ifdef __NR_access
// On Debian, even static binaries check existence of /etc/ld.so.nohwcap.
.BlockSyscallWithErrno(__NR_access, ENOENT)
#endif
// Examples for AddPolicyOnSyscall:
.AddPolicyOnSyscall(__NR_write,

View File

@ -86,7 +86,7 @@ pid_t Executor::StartSubProcess(int32_t clone_flags, const Namespace* ns,
if (!path_.empty()) {
exec_fd_ = open(path_.c_str(), O_PATH);
if (exec_fd_ < 0) {
LOG(ERROR) << "Could not open file " << path_;
PLOG(ERROR) << "Could not open file " << path_;
return -1;
}
}

View File

@ -36,6 +36,7 @@
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
@ -55,7 +56,6 @@
#include "sandboxed_api/sandbox2/util/fileops.h"
#include "sandboxed_api/sandbox2/util/strerror.h"
#include "sandboxed_api/util/raw_logging.h"
#include "sandboxed_api/util/statusor.h"
namespace {
// "Moves" the old FD to the new FD number.
@ -142,7 +142,7 @@ absl::Status SendPid(int signaling_fd) {
return absl::OkStatus();
}
sapi::StatusOr<pid_t> ReceivePid(int signaling_fd) {
absl::StatusOr<pid_t> ReceivePid(int signaling_fd) {
union {
struct cmsghdr cmh;
char ctrl[CMSG_SPACE(sizeof(struct ucred))];

View File

@ -23,6 +23,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/memory/memory.h"
#include "sandboxed_api/sandbox2/config.h"
#include "sandboxed_api/sandbox2/executor.h"
#include "sandboxed_api/sandbox2/policy.h"
#include "sandboxed_api/sandbox2/policybuilder.h"

View File

@ -49,6 +49,7 @@
#include "absl/time/time.h"
#include "sandboxed_api/sandbox2/client.h"
#include "sandboxed_api/sandbox2/comms.h"
#include "sandboxed_api/sandbox2/config.h"
#include "sandboxed_api/sandbox2/executor.h"
#include "sandboxed_api/sandbox2/limits.h"
#include "sandboxed_api/sandbox2/mounts.h"
@ -761,7 +762,7 @@ void Monitor::LogSyscallViolation(const Syscall& syscall) const {
void Monitor::EventPtraceSeccomp(pid_t pid, int event_msg) {
// If the seccomp-policy is using RET_TRACE, we request that it returns the
// syscall architecture identifier in the SECCOMP_RET_DATA.
const auto syscall_arch = static_cast<Syscall::CpuArch>(event_msg);
const auto syscall_arch = static_cast<cpu::Architecture>(event_msg);
Regs regs(pid);
auto status = regs.Fetch();
if (!status.ok()) {

View File

@ -27,19 +27,20 @@
#include "google/protobuf/util/message_differencer.h"
#include "absl/container/flat_hash_set.h"
#include "absl/status/statusor.h"
#include "absl/strings/ascii.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "sandboxed_api/sandbox2/config.h"
#include "sandboxed_api/sandbox2/util/fileops.h"
#include "sandboxed_api/sandbox2/util/minielf.h"
#include "sandboxed_api/sandbox2/util/path.h"
#include "sandboxed_api/sandbox2/util/strerror.h"
#include "sandboxed_api/util/raw_logging.h"
#include "sandboxed_api/util/status_macros.h"
#include "sandboxed_api/util/statusor.h"
namespace sandbox2 {
namespace {
@ -97,7 +98,7 @@ absl::string_view GetOutsidePath(const MountTree::Node& node) {
}
}
sapi::StatusOr<std::string> ExistingPathInsideDir(
absl::StatusOr<std::string> ExistingPathInsideDir(
absl::string_view dir_path, absl::string_view relative_path) {
auto path = file::CleanPath(file::JoinPath(dir_path, relative_path));
if (file_util::fileops::StripBasename(path) != dir_path) {
@ -112,6 +113,8 @@ sapi::StatusOr<std::string> ExistingPathInsideDir(
absl::Status ValidateInterpreter(absl::string_view interpreter) {
const absl::flat_hash_set<std::string> allowed_interpreters = {
"/lib64/ld-linux-x86-64.so.2",
"/lib64/ld64.so.2", // PPC64
"/lib/ld-linux-aarch64.so.1", // AArch64
};
if (!allowed_interpreters.contains(interpreter)) {
@ -132,15 +135,21 @@ std::string ResolveLibraryPath(absl::string_view lib_name,
return "";
}
constexpr absl::string_view GetPlatformCPUName() {
switch (host_cpu::Architecture()) {
case cpu::kX8664:
return "x86_64";
case cpu::kPPC64LE:
return "ppc64";
case cpu::kArm64:
return "aarch64";
default:
return "unknown";
}
}
std::string GetPlatform(absl::string_view interpreter) {
#if defined(__x86_64__)
constexpr absl::string_view kCpuPlatform = "x86_64";
#elif defined(__powerpc64__)
constexpr absl::string_view kCpuPlatform = "ppc64";
#else
constexpr absl::string_view kCpuPlatform = "unknown";
#endif
return absl::StrCat(kCpuPlatform, "-linux-gnu");
return absl::StrCat(GetPlatformCPUName(), "-linux-gnu");
}
} // namespace
@ -496,7 +505,7 @@ std::string MountFlagsToString(uint64_t flags) {
SAPI_MAP(MS_POSIXACL),
SAPI_MAP(MS_UNBINDABLE),
SAPI_MAP(MS_PRIVATE),
SAPI_MAP(MS_SLAVE),
SAPI_MAP(MS_SLAVE), // Inclusive language: system constant
SAPI_MAP(MS_SHARED),
SAPI_MAP(MS_RELATIME),
SAPI_MAP(MS_KERNMOUNT),

View File

@ -28,6 +28,7 @@
#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"
#include "sandboxed_api/sandbox2/comms.h"
#include "sandboxed_api/sandbox2/config.h"
#include "sandboxed_api/sandbox2/executor.h"
#include "sandboxed_api/sandbox2/policy.h"
#include "sandboxed_api/sandbox2/policybuilder.h"

View File

@ -30,6 +30,7 @@ cc_library(
"//sandboxed_api/sandbox2:comms",
"//sandboxed_api/sandbox2/util:fileops",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_glog//:glog",
],
@ -43,9 +44,11 @@ cc_library(
visibility = ["//visibility:public"],
deps = [
"//sandboxed_api/sandbox2:comms",
"//sandboxed_api/sandbox2:config",
"//sandboxed_api/sandbox2/util:strerror",
"//sandboxed_api/util:status",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/synchronization",
"@com_google_glog//:glog",
@ -61,7 +64,8 @@ cc_library(
"//sandboxed_api/sandbox2:comms",
"//sandboxed_api/sandbox2/util:strerror",
"//sandboxed_api/util:status",
"//sandboxed_api/util:statusor",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_glog//:glog",
],

View File

@ -33,14 +33,14 @@ add_library(sandbox2_network_proxy_filtering STATIC
filtering.h
)
add_library(sandbox2::network_proxy_filtering ALIAS sandbox2_network_proxy_filtering)
target_link_libraries(sandbox2_network_proxy_filtering PRIVATE
absl::memory
glog::glog
sandbox2::comms
sandbox2::fileops
sapi::base
target_link_libraries(sandbox2_network_proxy_filtering
PRIVATE absl::memory
absl::status
glog::glog
sandbox2::comms
sandbox2::fileops
sapi::base
PUBLIC sapi::status
sapi::statusor
)
# sandboxed_api/sandbox2/network_proxy:client
@ -54,6 +54,7 @@ target_link_libraries(sandbox2_network_proxy_client PRIVATE
absl::synchronization
glog::glog
sandbox2::comms
sandbox2::config
sandbox2::strerror
sapi::base
sapi::status

View File

@ -25,9 +25,10 @@
#include <glog/logging.h>
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "sandboxed_api/sandbox2/config.h"
#include "sandboxed_api/sandbox2/util/strerror.h"
#include "sandboxed_api/util/status.h"
#include "sandboxed_api/util/status_macros.h"
namespace sandbox2 {
@ -36,23 +37,26 @@ namespace sandbox2 {
constexpr int SYS_SECCOMP = 1;
#endif
#if defined(__x86_64__)
#if defined(SAPI_X86_64)
constexpr int kRegResult = REG_RAX;
constexpr int kRegSyscall = REG_RAX;
constexpr int kRegArg0 = REG_RDI;
constexpr int kRegArg1 = REG_RSI;
constexpr int kRegArg2 = REG_RDX;
#endif
#if defined(__powerpc64__)
#elif defined(SAPI_PPC64_LE)
constexpr int kRegResult = 3;
constexpr int kRegSyscall = 0;
constexpr int kRegArg0 = 3;
constexpr int kRegArg1 = 4;
constexpr int kRegArg2 = 5;
#elif defined(SAPI_ARM64)
constexpr int kRegResult = 0;
constexpr int kRegSyscall = 8;
constexpr int kRegArg0 = 0;
constexpr int kRegArg1 = 1;
constexpr int kRegArg2 = 2;
#endif
constexpr char NetworkProxyClient::kFDName[];
int NetworkProxyClient::ConnectHandler(int sockfd, const struct sockaddr* addr,
socklen_t addrlen) {
absl::Status status = Connect(sockfd, addr, addrlen);
@ -154,20 +158,22 @@ void NetworkProxyHandler::InvokeOldAct(int nr, siginfo_t* info,
void NetworkProxyHandler::ProcessSeccompTrap(int nr, siginfo_t* info,
void* void_context) {
ucontext_t* ctx = (ucontext_t*)(void_context);
if (info->si_code != SYS_SECCOMP) {
InvokeOldAct(nr, info, void_context);
return;
}
if (!ctx) return;
auto* ctx = static_cast<ucontext_t*>(void_context);
if (!ctx) {
return;
}
#if defined(__x86_64__)
#if defined(SAPI_X86_64)
auto* registers = ctx->uc_mcontext.gregs;
#elif defined(__powerpc64__)
#elif defined(SAPI_PPC64_LE)
auto* registers = ctx->uc_mcontext.gp_regs;
using ppc_gpreg_t = std::decay<decltype(registers[0])>::type;
#elif defined(SAPI_ARM64)
auto* registers = ctx->uc_mcontext.regs;
#endif
int syscall = registers[kRegSyscall];
int sockfd;
@ -178,14 +184,13 @@ void NetworkProxyHandler::ProcessSeccompTrap(int nr, siginfo_t* info,
sockfd = static_cast<int>(registers[kRegArg0]);
addr = reinterpret_cast<const struct sockaddr*>(registers[kRegArg1]);
addrlen = static_cast<socklen_t>(registers[kRegArg2]);
#if defined(__powerpc64__)
#if defined(SAPI_PPC64_LE)
} else if (syscall == __NR_socketcall &&
static_cast<int>(registers[kRegArg0]) == SYS_CONNECT) {
ppc_gpreg_t* args = reinterpret_cast<ppc_gpreg_t*>(registers[kRegArg1]);
sockfd = static_cast<int>(args[0]);
addr = reinterpret_cast<const struct sockaddr*>(args[1]);
addrlen = static_cast<socklen_t>(args[2]);
auto* connect_args = reinterpret_cast<uint64_t*>(registers[kRegArg1]);
sockfd = static_cast<int>(connect_args[0]);
addr = reinterpret_cast<const struct sockaddr*>(connect_args[1]);
addrlen = static_cast<socklen_t>(connect_args[2]);
#endif
} else {
InvokeOldAct(nr, info, void_context);

View File

@ -17,9 +17,9 @@
#include <netinet/in.h>
#include "absl/status/status.h"
#include "absl/synchronization/mutex.h"
#include "sandboxed_api/sandbox2/comms.h"
#include "sandboxed_api/util/status.h"
namespace sandbox2 {

View File

@ -17,16 +17,17 @@
#include <arpa/inet.h>
#include <glog/logging.h>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h"
#include "sandboxed_api/sandbox2/util/strerror.h"
#include "sandboxed_api/util/status.h"
#include "sandboxed_api/util/status_macros.h"
namespace sandbox2 {
static sapi::StatusOr<std::string> Addr6ToString(
static absl::StatusOr<std::string> Addr6ToString(
const struct sockaddr_in6* saddr) {
char addr[INET6_ADDRSTRLEN];
int port = htons(saddr->sin6_port);
@ -38,7 +39,7 @@ static sapi::StatusOr<std::string> Addr6ToString(
}
// Converts sockaddr_in structure into a string IPv4 representation.
static sapi::StatusOr<std::string> Addr4ToString(
static absl::StatusOr<std::string> Addr4ToString(
const struct sockaddr_in* saddr) {
char addr[INET_ADDRSTRLEN];
int port = htons(saddr->sin_port);
@ -50,7 +51,7 @@ static sapi::StatusOr<std::string> Addr4ToString(
}
// Converts sockaddr_in6 structure into a string IPv6 representation.
sapi::StatusOr<std::string> AddrToString(const struct sockaddr* saddr) {
absl::StatusOr<std::string> AddrToString(const struct sockaddr* saddr) {
switch (saddr->sa_family) {
case AF_INET:
return Addr4ToString(reinterpret_cast<const struct sockaddr_in*>(saddr));

View File

@ -19,14 +19,14 @@
#include <memory>
#include "absl/status/statusor.h"
#include "sandboxed_api/sandbox2/comms.h"
#include "sandboxed_api/util/statusor.h"
namespace sandbox2 {
// Converts sockaddr_in or sockaddr_in6 structure into a string
// representation.
sapi::StatusOr<std::string> AddrToString(const struct sockaddr* saddr);
absl::StatusOr<std::string> AddrToString(const struct sockaddr* saddr);
struct IPv4 {
in_addr_t ip;

View File

@ -26,6 +26,7 @@
#include <glog/logging.h>
#include "absl/memory/memory.h"
#include "absl/status/statusor.h"
#include "sandboxed_api/sandbox2/util/fileops.h"
namespace sandbox2 {
@ -104,7 +105,7 @@ void NetworkProxyServer::NotifySuccess() {
}
void NetworkProxyServer::NotifyViolation(const struct sockaddr* saddr) {
if (sapi::StatusOr<std::string> result = AddrToString(saddr); result.ok()) {
if (absl::StatusOr<std::string> result = AddrToString(saddr); result.ok()) {
violation_msg_ = std::move(result).value();
} else {
violation_msg_ = std::string(result.status().message());

View File

@ -49,8 +49,12 @@ std::unique_ptr<Policy> NotifyTestcasePolicy() {
.AllowWrite()
.AllowSyscall(__NR_close)
.AddPolicyOnSyscall(__NR_personality, {SANDBOX2_TRACE})
#ifdef __NR_open
.BlockSyscallWithErrno(__NR_open, ENOENT)
#endif
#ifdef __NR_access
.BlockSyscallWithErrno(__NR_access, ENOENT)
#endif
.BlockSyscallWithErrno(__NR_openat, ENOENT)
.BlockSyscallWithErrno(__NR_prlimit64, EPERM)
.BuildOrDie();

View File

@ -82,41 +82,41 @@ std::vector<sock_filter> Policy::GetDefaultPolicy() const {
bpf_labels l = {0};
std::vector<sock_filter> policy = {
// If compiled arch is different than the runtime one, inform the Monitor.
LOAD_ARCH,
JEQ32(Syscall::GetHostAuditArch(), JUMP(&l, past_arch_check_l)),
JEQ32(AUDIT_ARCH_X86_64, TRACE(Syscall::kX86_64)),
JEQ32(AUDIT_ARCH_I386, TRACE(Syscall::kX86_32)),
JEQ32(AUDIT_ARCH_PPC64LE, TRACE(Syscall::kPPC_64)),
TRACE(Syscall::kUnknown),
LABEL(&l, past_arch_check_l),
// If compiled arch is different than the runtime one, inform the Monitor.
LOAD_ARCH,
JEQ32(Syscall::GetHostAuditArch(), JUMP(&l, past_arch_check_l)),
#if defined(SAPI_X86_64)
JEQ32(AUDIT_ARCH_I386, TRACE(cpu::kX86)), // 32-bit sandboxee
#endif
TRACE(cpu::kUnknown),
LABEL(&l, past_arch_check_l),
// After the policy is uploaded, forkserver will execve the sandboxee. We
// need to allow this execve but not others. Since BPF does not have
// state, we need to inform the Monitor to decide, and for that we use a
// magic value in syscall args 5. Note that this value is not supposed to
// be secret, but just an optimization so that the monitor is not
// triggered on every call to execveat.
LOAD_SYSCALL_NR,
JNE32(__NR_execveat, JUMP(&l, past_execveat_l)),
ARG_32(4),
JNE32(AT_EMPTY_PATH, JUMP(&l, past_execveat_l)),
ARG_32(5),
JNE32(internal::kExecveMagic, JUMP(&l, past_execveat_l)),
SANDBOX2_TRACE,
LABEL(&l, past_execveat_l),
// After the policy is uploaded, forkserver will execve the sandboxee. We
// need to allow this execve but not others. Since BPF does not have
// state, we need to inform the Monitor to decide, and for that we use a
// magic value in syscall args 5. Note that this value is not supposed to
// be secret, but just an optimization so that the monitor is not
// triggered on every call to execveat.
LOAD_SYSCALL_NR,
JNE32(__NR_execveat, JUMP(&l, past_execveat_l)),
ARG_32(4),
JNE32(AT_EMPTY_PATH, JUMP(&l, past_execveat_l)),
ARG_32(5),
JNE32(internal::kExecveMagic, JUMP(&l, past_execveat_l)),
SANDBOX2_TRACE,
LABEL(&l, past_execveat_l),
// Forbid some syscalls because unsafe or too risky.
LOAD_SYSCALL_NR,
JEQ32(__NR_ptrace, DENY),
JEQ32(__NR_bpf, DENY),
// Forbid some syscalls because unsafe or too risky.
LOAD_SYSCALL_NR,
JEQ32(__NR_ptrace, DENY),
JEQ32(__NR_bpf, DENY),
// Disallow clone with CLONE_UNTRACED flag.
JNE32(__NR_clone, JUMP(&l, past_clone_untraced_l)),
// Regardless of arch, we only care about the lower 32-bits of the flags.
ARG_32(0),
JA32(CLONE_UNTRACED, DENY),
LABEL(&l, past_clone_untraced_l),
// Disallow clone with CLONE_UNTRACED flag.
JNE32(__NR_clone, JUMP(&l, past_clone_untraced_l)),
// Regardless of arch, we only care about the lower 32-bits of the flags.
ARG_32(0),
JA32(CLONE_UNTRACED, DENY),
LABEL(&l, past_clone_untraced_l),
};
if (bpf_resolve_jumps(&l, policy.data(), policy.size()) != 0) {
@ -129,11 +129,16 @@ std::vector<sock_filter> Policy::GetDefaultPolicy() const {
std::vector<sock_filter> Policy::GetTrackingPolicy() const {
return {
LOAD_ARCH,
JEQ32(AUDIT_ARCH_X86_64, TRACE(Syscall::kX86_64)),
JEQ32(AUDIT_ARCH_I386, TRACE(Syscall::kX86_32)),
JEQ32(AUDIT_ARCH_PPC64LE, TRACE(Syscall::kPPC_64)),
TRACE(Syscall::kUnknown),
LOAD_ARCH,
#if defined(SAPI_X86_64)
JEQ32(AUDIT_ARCH_X86_64, TRACE(cpu::kX8664)),
JEQ32(AUDIT_ARCH_I386, TRACE(cpu::kX86)),
#elif defined(SAPI_PPC64_LE)
JEQ32(AUDIT_ARCH_PPC64LE, TRACE(cpu::kPPC64LE)),
#elif defined(SAPI_ARM64)
JEQ32(AUDIT_ARCH_AARCH64, TRACE(cpu::kArm64)),
#endif
TRACE(cpu::kUnknown),
};
}

View File

@ -25,6 +25,7 @@
#include "gtest/gtest.h"
#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "sandboxed_api/sandbox2/config.h"
#include "sandboxed_api/sandbox2/executor.h"
#include "sandboxed_api/sandbox2/limits.h"
#include "sandboxed_api/sandbox2/policybuilder.h"
@ -49,14 +50,21 @@ std::unique_ptr<Policy> PolicyTestcasePolicy() {
.AllowSyscall(__NR_close)
.AllowSyscall(__NR_getppid)
.AllowTCGETS()
#ifdef __NR_open
.BlockSyscallWithErrno(__NR_open, ENOENT)
#endif
.BlockSyscallWithErrno(__NR_openat, ENOENT)
#ifdef __NR_access
.BlockSyscallWithErrno(__NR_access, ENOENT)
#endif
#ifdef __NR_faccessat
.BlockSyscallWithErrno(__NR_faccessat, ENOENT)
#endif
.BlockSyscallWithErrno(__NR_prlimit64, EPERM)
.BuildOrDie();
}
#if defined(__x86_64__)
#ifdef SAPI_X86_64
// Test that 32-bit syscalls from 64-bit are disallowed.
TEST(PolicyTest, AMD64Syscall32PolicyAllowed) {
SKIP_SANITIZERS_AND_COVERAGE;
@ -72,7 +80,7 @@ TEST(PolicyTest, AMD64Syscall32PolicyAllowed) {
ASSERT_THAT(result.final_status(), Eq(Result::VIOLATION));
EXPECT_THAT(result.reason_code(), Eq(1)); // __NR_exit in 32-bit
EXPECT_THAT(result.GetSyscallArch(), Eq(Syscall::kX86_32));
EXPECT_THAT(result.GetSyscallArch(), Eq(cpu::kX86));
}
// Test that 32-bit syscalls from 64-bit for FS checks are disallowed.
@ -90,9 +98,9 @@ TEST(PolicyTest, AMD64Syscall32FsAllowed) {
ASSERT_THAT(result.final_status(), Eq(Result::VIOLATION));
EXPECT_THAT(result.reason_code(),
Eq(33)); // __NR_access in 32-bit
EXPECT_THAT(result.GetSyscallArch(), Eq(Syscall::kX86_32));
EXPECT_THAT(result.GetSyscallArch(), Eq(cpu::kX86));
}
#endif // defined(__x86_64__)
#endif
// Test that ptrace(2) is disallowed.
TEST(PolicyTest, PtraceDisallowed) {
@ -161,7 +169,9 @@ std::unique_ptr<Policy> MinimalTestcasePolicy() {
.AllowStaticStartup()
.AllowExit()
.BlockSyscallWithErrno(__NR_prlimit64, EPERM)
#ifdef __NR_access
.BlockSyscallWithErrno(__NR_access, ENOENT)
#endif
.BuildOrDie();
}
@ -196,8 +206,10 @@ TEST(MinimalTest, MinimalSharedBinaryWorks) {
.AllowOpen()
.AllowExit()
.AllowMmap()
#ifdef __NR_access
// New glibc accesses /etc/ld.so.preload
.BlockSyscallWithErrno(__NR_access, ENOENT)
#endif
.BlockSyscallWithErrno(__NR_prlimit64, EPERM)
.AddLibrariesForBinary(path)
.BuildOrDie();
@ -222,7 +234,9 @@ TEST(MallocTest, SystemMallocWorks) {
.AllowSystemMalloc()
.AllowExit()
.BlockSyscallWithErrno(__NR_prlimit64, EPERM)
#ifdef __NR_access
.BlockSyscallWithErrno(__NR_access, ENOENT)
#endif
.BuildOrDie();
Sandbox2 s2(std::move(executor), std::move(policy));
@ -246,7 +260,9 @@ TEST(MultipleSyscalls, AddPolicyOnSyscallsWorks) {
auto policy =
PolicyBuilder()
#ifdef __NR_open
.BlockSyscallWithErrno(__NR_open, ENOENT)
#endif
.BlockSyscallWithErrno(__NR_openat, ENOENT)
.AllowStaticStartup()
.AllowTcMalloc()
@ -257,7 +273,9 @@ TEST(MultipleSyscalls, AddPolicyOnSyscallsWorks) {
.AddPolicyOnSyscalls({__NR_read, __NR_write}, {ERRNO(43)})
.AddPolicyOnSyscall(__NR_umask, {DENY})
.BlockSyscallWithErrno(__NR_prlimit64, EPERM)
#ifdef __NR_access
.BlockSyscallWithErrno(__NR_access, ENOENT)
#endif
.BuildOrDie();
Sandbox2 s2(std::move(executor), std::move(policy));

View File

@ -15,13 +15,7 @@
#include "sandboxed_api/sandbox2/policybuilder.h"
#include <asm/ioctls.h> // For TCGETS
#if defined(__x86_64__)
#include <asm/prctl.h>
#endif
#if defined(__powerpc64__)
#include <asm/termbits.h> // On PPC, TCGETS macro needs termios
#endif
#include <fcntl.h> // For the fcntl flags
#include <fcntl.h> // For the fcntl flags
#include <linux/futex.h>
#include <linux/net.h> // For SYS_CONNECT
#include <linux/random.h> // For GRND_NONBLOCK
@ -34,13 +28,21 @@
#include <utility>
#include "absl/memory/memory.h"
#include "absl/status/statusor.h"
#include "absl/strings/escaping.h"
#include "absl/strings/match.h"
#include "sandboxed_api/sandbox2/config.h"
#include "sandboxed_api/sandbox2/namespace.h"
#include "sandboxed_api/sandbox2/util/bpf_helper.h"
#include "sandboxed_api/sandbox2/util/path.h"
#include "sandboxed_api/util/status_macros.h"
#if defined(SAPI_X86_64)
#include <asm/prctl.h>
#elif defined(SAPI_PPC64_LE)
#include <asm/termbits.h> // On PPC, TCGETS macro needs termios
#endif
namespace sandbox2 {
namespace {
@ -510,7 +512,7 @@ PolicyBuilder& PolicyBuilder::AllowStaticStartup() {
JEQ32(SIG_UNBLOCK, ALLOW),
});
#if defined(__x86_64__)
#ifdef SAPI_X86_64
// The second argument is a pointer.
AddPolicyOnSyscall(__NR_arch_prctl, {
ARG_32(0),
@ -518,7 +520,12 @@ PolicyBuilder& PolicyBuilder::AllowStaticStartup() {
});
#endif
if constexpr (host_cpu::IsArm64()) {
BlockSyscallWithErrno(__NR_readlinkat, ENOENT);
}
#ifdef __NR_readlink
BlockSyscallWithErrno(__NR_readlink, ENOENT);
#endif
return *this;
}
@ -526,7 +533,11 @@ PolicyBuilder& PolicyBuilder::AllowStaticStartup() {
PolicyBuilder& PolicyBuilder::AllowDynamicStartup() {
AllowRead();
AllowStat();
AllowSyscalls({__NR_lseek, __NR_close, __NR_munmap});
AllowSyscalls({__NR_lseek,
#ifdef __NR__llseek
__NR__llseek, // Newer glibc on PPC
#endif
__NR_close, __NR_munmap});
AddPolicyOnSyscall(__NR_mprotect, {
ARG_32(2),
JEQ32(PROT_READ, ALLOW),
@ -656,7 +667,7 @@ PolicyBuilder& PolicyBuilder::DangerDefaultAllowAll() {
return *this;
}
sapi::StatusOr<std::string> PolicyBuilder::ValidateAbsolutePath(
absl::StatusOr<std::string> PolicyBuilder::ValidateAbsolutePath(
absl::string_view path) {
if (!file::IsAbsolutePath(path)) {
return absl::InvalidArgumentError(
@ -665,7 +676,7 @@ sapi::StatusOr<std::string> PolicyBuilder::ValidateAbsolutePath(
return ValidatePath(path);
}
sapi::StatusOr<std::string> PolicyBuilder::ValidatePath(
absl::StatusOr<std::string> PolicyBuilder::ValidatePath(
absl::string_view path) {
std::string fixed_path = file::CleanPath(path);
if (fixed_path != path) {
@ -686,7 +697,7 @@ std::vector<sock_filter> PolicyBuilder::ResolveBpfFunc(BpfFunc f) {
return policy;
}
sapi::StatusOr<std::unique_ptr<Policy>> PolicyBuilder::TryBuild() {
absl::StatusOr<std::unique_ptr<Policy>> PolicyBuilder::TryBuild() {
auto output = absl::WrapUnique(new Policy());
if (!last_status_.ok()) {
@ -879,7 +890,9 @@ PolicyBuilder& PolicyBuilder::AddNetworkProxyPolicy() {
AllowFutexOp(FUTEX_WAIT);
AllowFutexOp(FUTEX_WAIT_BITSET);
AllowSyscalls({
#ifdef __NR_dup2
__NR_dup2,
#endif
__NR_recvmsg,
__NR_close,
__NR_gettid,
@ -899,7 +912,7 @@ PolicyBuilder& PolicyBuilder::AddNetworkProxyPolicy() {
LABEL(&labels, getsockopt_end),
};
});
#if defined(__powerpc64__)
#ifdef SAPI_PPC64_LE
AddPolicyOnSyscall(__NR_socketcall, {
ARG_32(0),
JEQ32(SYS_SOCKET, ALLOW),
@ -925,7 +938,7 @@ PolicyBuilder& PolicyBuilder::AddNetworkProxyHandlerPolicy() {
});
AddPolicyOnSyscall(__NR_connect, {TRAP(0)});
#if defined(__powerpc64__)
#ifdef SAPI_PPC64_LE
AddPolicyOnSyscall(__NR_socketcall, {
ARG_32(0),
JEQ32(SYS_CONNECT, TRAP(0)),

View File

@ -29,18 +29,16 @@
#include <glog/logging.h>
#include "absl/base/macros.h"
#include "absl/memory/memory.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "sandboxed_api/sandbox2/mounts.h"
#include "sandboxed_api/sandbox2/network_proxy/filtering.h"
#include "sandboxed_api/sandbox2/policy.h"
#include "sandboxed_api/util/statusor.h"
struct bpf_labels;
namespace sandbox2 {
constexpr char kDefaultHostname[] = "sandbox2";
// PolicyBuilder is a helper class to simplify creation of policies. The builder
// uses fluent interface for convenience and increased readability of policies.
//
@ -91,6 +89,8 @@ constexpr char kDefaultHostname[] = "sandbox2";
// For a more complicated example, see examples/persistent/persistent_sandbox.cc
class PolicyBuilder final {
public:
static constexpr absl::string_view kDefaultHostname = "sandbox2";
using BpfInitializer = std::initializer_list<sock_filter>;
using BpfFunc = const std::function<std::vector<sock_filter>(bpf_labels&)>&;
using SyscallInitializer = std::initializer_list<unsigned int>;
@ -390,7 +390,7 @@ class PolicyBuilder final {
// Builds the policy returning a unique_ptr to it. This should only be called
// once.
sapi::StatusOr<std::unique_ptr<Policy>> TryBuild();
absl::StatusOr<std::unique_ptr<Policy>> TryBuild();
// Builds the policy returning a unique_ptr to it. This should only be called
// once.
@ -532,9 +532,9 @@ class PolicyBuilder final {
std::vector<sock_filter> ResolveBpfFunc(BpfFunc f);
static sapi::StatusOr<std::string> ValidateAbsolutePath(
static absl::StatusOr<std::string> ValidateAbsolutePath(
absl::string_view path);
static sapi::StatusOr<std::string> ValidatePath(absl::string_view path);
static absl::StatusOr<std::string> ValidatePath(absl::string_view path);
void StoreDescription(PolicyBuilderDescription* pb_description);
@ -542,7 +542,7 @@ class PolicyBuilder final {
bool use_namespaces_ = true;
bool requires_namespaces_ = false;
bool allow_unrestricted_networking_ = false;
std::string hostname_ = kDefaultHostname;
std::string hostname_ = std::string(kDefaultHostname);
bool collect_stacktrace_on_violation_ = true;
bool collect_stacktrace_on_signal_ = true;

View File

@ -24,6 +24,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/memory/memory.h"
#include "absl/status/statusor.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h"
@ -57,7 +58,7 @@ class PolicyBuilderPeer {
int policy_size() const { return builder_->user_policy_.size(); }
static sapi::StatusOr<std::string> ValidateAbsolutePath(
static absl::StatusOr<std::string> ValidateAbsolutePath(
absl::string_view path) {
return PolicyBuilder::ValidateAbsolutePath(path);
}
@ -100,7 +101,7 @@ TEST_F(PolicyBuilderTest, Testpolicy_size) {
builder.AllowSystemMalloc(); assert_increased();
builder.AllowSyscall(__NR_munmap); assert_same();
builder.BlockSyscallWithErrno(__NR_munmap, 1); assert_same();
builder.BlockSyscallWithErrno(__NR_open, 1);
builder.BlockSyscallWithErrno(__NR_openat, 1);
assert_increased();
builder.AllowTCGETS(); assert_increased();

View File

@ -23,65 +23,108 @@
#include <cerrno>
#include "absl/base/macros.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "sandboxed_api/sandbox2/config.h"
#include "sandboxed_api/sandbox2/util/strerror.h"
namespace sandbox2 {
absl::Status Regs::Fetch() {
#if defined(__powerpc64__)
iovec pt_iov = {&user_regs_, sizeof(user_regs_)};
#ifndef NT_ARM_SYSTEM_CALL
#define NT_ARM_SYSTEM_CALL 0x404
#endif
if (ptrace(PTRACE_GETREGSET, pid_, NT_PRSTATUS, &pt_iov) == -1L) {
return absl::InternalError(absl::StrCat(
"ptrace(PTRACE_GETREGSET, pid=", pid_, ") failed: ", StrError(errno)));
}
if (pt_iov.iov_len != sizeof(user_regs_)) {
return absl::InternalError(absl::StrCat(
"ptrace(PTRACE_GETREGSET, pid=", pid_,
") size returned: ", pt_iov.iov_len,
" different than sizeof(user_regs_): ", sizeof(user_regs_)));
}
#else
absl::Status Regs::Fetch() {
#ifdef SAPI_X86_64
if (ptrace(PTRACE_GETREGS, pid_, 0, &user_regs_) == -1L) {
return absl::InternalError(absl::StrCat("ptrace(PTRACE_GETREGS, pid=", pid_,
") failed: ", StrError(errno)));
}
#endif
if constexpr (host_cpu::IsPPC64LE() || host_cpu::IsArm64()) {
iovec pt_iov = {&user_regs_, sizeof(user_regs_)};
if (ptrace(PTRACE_GETREGSET, pid_, NT_PRSTATUS, &pt_iov) == -1L) {
return absl::InternalError(
absl::StrCat("ptrace(PTRACE_GETREGSET, pid=", pid_,
") failed: ", StrError(errno)));
}
if (pt_iov.iov_len != sizeof(user_regs_)) {
return absl::InternalError(absl::StrCat(
"ptrace(PTRACE_GETREGSET, pid=", pid_,
") size returned: ", pt_iov.iov_len,
" different than sizeof(user_regs_): ", sizeof(user_regs_)));
}
// On AArch64, we are not done yet. Read the syscall number.
if constexpr (host_cpu::IsArm64()) {
iovec sys_iov = {&syscall_number_, sizeof(syscall_number_)};
if (ptrace(PTRACE_GETREGSET, pid_, NT_ARM_SYSTEM_CALL, &sys_iov) == -1L) {
return absl::InternalError(
absl::StrCat("ptrace(PTRACE_GETREGSET, pid=", pid_,
", NT_ARM_SYSTEM_CALL) failed: ", StrError(errno)));
}
if (sys_iov.iov_len != sizeof(syscall_number_)) {
return absl::InternalError(absl::StrCat(
"ptrace(PTRACE_GETREGSET, pid=", pid_,
", NT_ARM_SYSTEM_CALL) size returned: ", sys_iov.iov_len,
" different than sizeof(syscall_number_): ",
sizeof(syscall_number_)));
}
}
}
return absl::OkStatus();
}
absl::Status Regs::Store() {
#if defined(__powerpc64__)
iovec pt_iov = {&user_regs_, sizeof(user_regs_)};
if (ptrace(PTRACE_SETREGSET, pid_, NT_PRSTATUS, &pt_iov) == -1L) {
return absl::InternalError(absl::StrCat(
"ptrace(PTRACE_SETREGSET, pid=", pid_, ") failed: ", StrError(errno)));
}
#else
#ifdef SAPI_X86_64
if (ptrace(PTRACE_SETREGS, pid_, 0, &user_regs_) == -1) {
return absl::InternalError(absl::StrCat("ptrace(PTRACE_SETREGS, pid=", pid_,
") failed: ", StrError(errno)));
}
#endif
if constexpr (host_cpu::IsPPC64LE() || host_cpu::IsArm64()) {
iovec pt_iov = {&user_regs_, sizeof(user_regs_)};
if (ptrace(PTRACE_SETREGSET, pid_, NT_PRSTATUS, &pt_iov) == -1L) {
return absl::InternalError(
absl::StrCat("ptrace(PTRACE_SETREGSET, pid=", pid_,
") failed: ", StrError(errno)));
}
// Store syscall number on AArch64.
if constexpr (host_cpu::IsArm64()) {
iovec sys_iov = {&syscall_number_, sizeof(syscall_number_)};
if (ptrace(PTRACE_SETREGSET, pid_, NT_ARM_SYSTEM_CALL, &sys_iov) == -1L) {
return absl::InternalError(
absl::StrCat("ptrace(PTRACE_SETREGSET, pid=", pid_,
", NT_ARM_SYSTEM_CALL) failed: ", StrError(errno)));
}
}
}
return absl::OkStatus();
}
absl::Status Regs::SkipSyscallReturnValue(uint64_t value) {
#if defined(__x86_64__)
#if defined(SAPI_X86_64)
user_regs_.orig_rax = -1;
user_regs_.rax = value;
#elif defined(__powerpc64__)
#elif defined(SAPI_PPC64_LE)
user_regs_.gpr[0] = -1;
user_regs_.gpr[3] = value;
#elif defined(SAPI_ARM64)
user_regs_.regs[0] = -1;
syscall_number_ = value;
#endif
return Store();
}
Syscall Regs::ToSyscall(Syscall::CpuArch syscall_arch) const {
#if defined(__x86_64__)
if (ABSL_PREDICT_TRUE(syscall_arch == Syscall::kX86_64)) {
Syscall Regs::ToSyscall(cpu::Architecture syscall_arch) const {
#if defined(SAPI_X86_64)
if (ABSL_PREDICT_TRUE(syscall_arch == cpu::kX8664)) {
auto syscall = user_regs_.orig_rax;
Syscall::Args args = {user_regs_.rdi, user_regs_.rsi, user_regs_.rdx,
user_regs_.r10, user_regs_.r8, user_regs_.r9};
@ -89,7 +132,7 @@ Syscall Regs::ToSyscall(Syscall::CpuArch syscall_arch) const {
auto ip = user_regs_.rip;
return Syscall(syscall_arch, syscall, args, pid_, sp, ip);
}
if (syscall_arch == Syscall::kX86_32) {
if (syscall_arch == cpu::kX86) {
auto syscall = user_regs_.orig_rax & 0xFFFFFFFF;
Syscall::Args args = {
user_regs_.rbx & 0xFFFFFFFF, user_regs_.rcx & 0xFFFFFFFF,
@ -99,8 +142,8 @@ Syscall Regs::ToSyscall(Syscall::CpuArch syscall_arch) const {
auto ip = user_regs_.rip & 0xFFFFFFFF;
return Syscall(syscall_arch, syscall, args, pid_, sp, ip);
}
#elif defined(__powerpc64__)
if (ABSL_PREDICT_TRUE(syscall_arch == Syscall::kPPC_64)) {
#elif defined(SAPI_PPC64_LE)
if (ABSL_PREDICT_TRUE(syscall_arch == cpu::kPPC64LE)) {
auto syscall = user_regs_.gpr[0];
Syscall::Args args = {user_regs_.orig_gpr3, user_regs_.gpr[4],
user_regs_.gpr[5], user_regs_.gpr[6],
@ -109,12 +152,28 @@ Syscall Regs::ToSyscall(Syscall::CpuArch syscall_arch) const {
auto ip = user_regs_.nip;
return Syscall(syscall_arch, syscall, args, pid_, sp, ip);
}
#elif defined(SAPI_ARM64)
if (ABSL_PREDICT_TRUE(syscall_arch == cpu::kArm64)) {
Syscall::Args args = {
// First argument should be orig_x0, which is not available to ptrace on
// AArch64 (see
// https://undo.io/resources/arm64-vs-arm32-whats-different-linux-programmers/),
// as it will have been overwritten. For our use case, though, using
// regs[0] is fine, as we are always called on syscall entry and never
// on exit.
user_regs_.regs[0], user_regs_.regs[1], user_regs_.regs[2],
user_regs_.regs[3], user_regs_.regs[4], user_regs_.regs[5],
};
auto sp = user_regs_.sp;
auto ip = user_regs_.pc;
return Syscall(syscall_arch, syscall_number_, args, pid_, sp, ip);
}
#endif
return Syscall(pid_);
}
void Regs::StoreRegisterValuesInProtobuf(RegisterValues* values) const {
#if defined(__x86_64__)
#if defined(SAPI_X86_64)
RegisterX8664* regs = values->mutable_register_x86_64();
regs->set_r15(user_regs_.r15);
regs->set_r14(user_regs_.r14);
@ -143,7 +202,7 @@ void Regs::StoreRegisterValuesInProtobuf(RegisterValues* values) const {
regs->set_es(user_regs_.es);
regs->set_fs(user_regs_.fs);
regs->set_gs(user_regs_.gs);
#elif defined(__powerpc64__)
#elif defined(SAPI_PPC64_LE)
RegisterPowerpc64* regs = values->mutable_register_powerpc64();
for (int i = 0; i < ABSL_ARRAYSIZE(user_regs_.gpr); ++i) {
regs->add_gpr(user_regs_.gpr[i]);
@ -164,6 +223,14 @@ void Regs::StoreRegisterValuesInProtobuf(RegisterValues* values) const {
regs->set_zero1(user_regs_.zero1);
regs->set_zero2(user_regs_.zero2);
regs->set_zero3(user_regs_.zero3);
#elif defined(SAPI_ARM64)
RegisterAarch64* regs = values->mutable_register_aarch64();
for (int i = 0; i < ABSL_ARRAYSIZE(user_regs_.regs); ++i) {
regs->add_regs(user_regs_.regs[i]);
}
regs->set_sp(user_regs_.sp);
regs->set_pc(user_regs_.pc);
regs->set_pstate(user_regs_.pstate);
#endif
}

View File

@ -24,6 +24,7 @@
#include <string>
#include "absl/status/status.h"
#include "sandboxed_api/sandbox2/config.h"
#include "sandboxed_api/sandbox2/syscall.h"
#include "sandboxed_api/sandbox2/violation.pb.h"
@ -33,10 +34,6 @@ namespace sandbox2 {
// assumes the process is already attached.
class Regs {
public:
#if !defined(__x86_64__) && !defined(__powerpc64__)
static_assert(false, "No support for the current CPU architecture");
#endif
explicit Regs(pid_t pid) : pid_(pid) {}
// Copies register values from the process
@ -49,7 +46,7 @@ class Regs {
absl::Status SkipSyscallReturnValue(uint64_t value);
// Converts raw register values obtained on syscall entry to syscall info
Syscall ToSyscall(Syscall::CpuArch syscall_arch) const;
Syscall ToSyscall(cpu::Architecture syscall_arch) const;
pid_t pid() const { return pid_; }
@ -60,7 +57,7 @@ class Regs {
friend class StackTracePeer;
struct PtraceRegisters {
#if defined(__x86_64__)
#if defined(SAPI_X86_64)
uint64_t r15;
uint64_t r14;
uint64_t r13;
@ -88,7 +85,7 @@ class Regs {
uint64_t es;
uint64_t fs;
uint64_t gs;
#elif defined(__powerpc64__)
#elif defined(SAPI_PPC64_LE)
uint64_t gpr[32];
uint64_t nip;
uint64_t msr;
@ -108,6 +105,13 @@ class Regs {
uint64_t zero1;
uint64_t zero2;
uint64_t zero3;
#elif defined(SAPI_ARM64)
uint64_t regs[31];
uint64_t sp;
uint64_t pc;
uint64_t pstate;
#else
static_assert(false, "Host CPU architecture not supported, see config.h");
#endif
};
@ -116,6 +120,9 @@ class Regs {
// Registers fetched with ptrace(PR_GETREGS/GETREGSET, pid).
PtraceRegisters user_regs_ = {};
// On AArch64, obtaining the syscall number needs a specific call to ptrace()
int syscall_number_ = 0;
};
} // namespace sandbox2

View File

@ -28,6 +28,7 @@
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "sandboxed_api/sandbox2/config.h"
#include "sandboxed_api/sandbox2/regs.h"
#include "sandboxed_api/sandbox2/syscall.h"
@ -131,8 +132,8 @@ class Result {
// Returns the current syscall architecture.
// Client architecture when final_status_ == VIOLATION, might be different
// from the host architecture (32-bit vs 64-bit syscalls).
Syscall::CpuArch GetSyscallArch() const {
return syscall_ ? syscall_->arch() : Syscall::kUnknown;
cpu::Architecture GetSyscallArch() const {
return syscall_ ? syscall_->arch() : cpu::kUnknown;
}
const std::vector<std::string> stack_trace() { return stack_trace_; }

View File

@ -21,6 +21,7 @@
#include <string>
#include "absl/memory/memory.h"
#include "absl/status/statusor.h"
#include "absl/time/time.h"
#include "sandboxed_api/sandbox2/monitor.h"
#include "sandboxed_api/sandbox2/result.h"
@ -33,7 +34,7 @@ Sandbox2::~Sandbox2() {
}
}
sapi::StatusOr<Result> Sandbox2::AwaitResultWithTimeout(
absl::StatusOr<Result> Sandbox2::AwaitResultWithTimeout(
absl::Duration timeout) {
CHECK(monitor_ != nullptr) << "Sandbox was not launched yet";
CHECK(monitor_thread_ != nullptr) << "Sandbox was already waited on";

View File

@ -26,6 +26,7 @@
#include <glog/logging.h>
#include "absl/base/macros.h"
#include "absl/memory/memory.h"
#include "absl/status/statusor.h"
#include "sandboxed_api/sandbox2/comms.h"
#include "sandboxed_api/sandbox2/executor.h"
#include "sandboxed_api/sandbox2/ipc.h"
@ -33,7 +34,6 @@
#include "sandboxed_api/sandbox2/notify.h"
#include "sandboxed_api/sandbox2/policy.h"
#include "sandboxed_api/sandbox2/result.h"
#include "sandboxed_api/util/statusor.h"
namespace sandbox2 {
@ -76,7 +76,7 @@ class Sandbox2 final {
// Waits for sandbox execution to finish within the timeout.
// Returns execution result or a DeadlineExceededError if the sandboxee does
// not finish in time.
sapi::StatusOr<Result> AwaitResultWithTimeout(absl::Duration timeout);
absl::StatusOr<Result> AwaitResultWithTimeout(absl::Duration timeout);
// Requests termination of the sandboxee.
// Sandbox should still waited with AwaitResult(), as it may finish for other

View File

@ -26,6 +26,7 @@
#include "gtest/gtest.h"
#include "absl/memory/memory.h"
#include "absl/strings/str_cat.h"
#include "sandboxed_api/sandbox2/config.h"
#include "sandboxed_api/sandbox2/executor.h"
#include "sandboxed_api/sandbox2/policy.h"
#include "sandboxed_api/sandbox2/policybuilder.h"

View File

@ -31,6 +31,7 @@
#include "absl/strings/strip.h"
#include "libcap/include/sys/capability.h"
#include "sandboxed_api/sandbox2/comms.h"
#include "sandboxed_api/sandbox2/config.h"
#include "sandboxed_api/sandbox2/executor.h"
#include "sandboxed_api/sandbox2/ipc.h"
#include "sandboxed_api/sandbox2/limits.h"
@ -85,6 +86,9 @@ std::unique_ptr<Policy> StackTracePeer::GetPolicy(pid_t target_pid,
// libunwind
.AllowSyscall(__NR_fstat)
.AllowSyscall(__NR_lseek)
#ifdef __NR__llseek
.AllowSyscall(__NR__llseek) // Newer glibc on PPC
#endif
.AllowSyscall(__NR_mincore)
.AllowSyscall(__NR_mprotect)
.AllowSyscall(__NR_munmap)
@ -270,6 +274,9 @@ bool StackTracePeer::LaunchLibunwindSandbox(const Regs* regs,
}
std::vector<std::string> GetStackTrace(const Regs* regs, const Mounts& mounts) {
if constexpr (host_cpu::IsArm64()) {
return {"[Stack traces unavailable]"};
}
if (absl::GetFlag(FLAGS_sandbox_disable_all_stack_traces)) {
return {"[Stacktraces disabled]"};
}

View File

@ -12,12 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// Implementation of the sandbox2::Syscall class.
#include "sandboxed_api/sandbox2/syscall.h"
#include <linux/audit.h>
#include <linux/elf-em.h>
#include <climits>
#include <csignal>
#include <cstring>
@ -26,6 +25,7 @@
#include <glog/logging.h>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include "sandboxed_api/sandbox2/config.h"
#include "sandboxed_api/sandbox2/syscall_defs.h"
#ifndef AUDIT_ARCH_PPC64LE
@ -34,46 +34,43 @@
namespace sandbox2 {
std::string Syscall::GetArchDescription(CpuArch arch) {
std::string Syscall::GetArchDescription(cpu::Architecture arch) {
switch (arch) {
case kX86_64:
case cpu::kX8664:
return "[X86-64]";
case kX86_32:
case cpu::kX86:
return "[X86-32]";
case kPPC_64:
case cpu::kPPC64LE:
return "[PPC-64]";
case cpu::kArm64:
return "[Arm-64]";
default:
LOG(ERROR) << "Unknown CPU architecture: " << arch;
return absl::StrFormat("[UNKNOWN_ARCH:%d]", arch);
}
}
Syscall::CpuArch Syscall::GetHostArch() {
#if defined(__x86_64__)
return kX86_64;
#elif defined(__i386__)
return kX86_32;
#elif defined(__powerpc64__)
return kPPC_64;
#endif
}
uint32_t Syscall::GetHostAuditArch() {
#if defined(__x86_64__)
return AUDIT_ARCH_X86_64;
#elif defined(__i386__)
return AUDIT_ARCH_I386;
#elif defined(__powerpc64__)
return AUDIT_ARCH_PPC64LE;
#endif
switch (host_cpu::Architecture()) {
case cpu::kX8664:
return AUDIT_ARCH_X86_64;
case cpu::kPPC64LE:
return AUDIT_ARCH_PPC64LE;
case cpu::kArm64:
return AUDIT_ARCH_AARCH64;
default:
// The static_assert() in config.h should prevent us from ever getting
// here.
return 0; // Not reached
}
}
std::string Syscall::GetName() const {
absl::string_view name = SyscallTable::get(arch_).GetName(nr_);
if (name.empty()) {
return absl::StrFormat("UNKNOWN[%d/0x%x]", nr_, nr_);
if (absl::string_view name = SyscallTable::get(arch_).GetName(nr_);
!name.empty()) {
return std::string(name);
}
return std::string(name);
return absl::StrFormat("UNKNOWN[%d/0x%x]", nr_, nr_);
}
std::vector<std::string> Syscall::GetArgumentsDescription() const {

View File

@ -13,7 +13,7 @@
// limitations under the License.
// The sandbox2::Syscalls class defines mostly static helper methods which
// are used to analyze status of the ptraced process
// are used to analyze the status of the sandboxed process.
#ifndef SANDBOXED_API_SANDBOX2_SYSCALL_H__
#define SANDBOXED_API_SANDBOX2_SYSCALL_H__
@ -26,40 +26,34 @@
#include <string>
#include <vector>
#include "sandboxed_api/sandbox2/config.h"
namespace sandbox2 {
class Syscall {
public:
// Supported CPU architectures.
// Linux: Use a magic value, so it can be easily spotted in the seccomp-bpf
// bytecode decompilation stream. Must be < (1<<15), as/ that's the size of
// data which can be returned by BPF.
enum CpuArch {
kUnknown = 0xCAF0,
kX86_64,
kX86_32,
kPPC_64,
};
// Maximum number of syscall arguments
static constexpr size_t kMaxArgs = 6;
using Args = std::array<uint64_t, kMaxArgs>;
// Returns the host architecture, according to CpuArch.
static CpuArch GetHostArch();
static constexpr cpu::Architecture GetHostArch() {
return host_cpu::Architecture();
}
// Returns the host architecture, according to <linux/audit.h>.
static uint32_t GetHostAuditArch();
// Returns a description of the architecture.
static std::string GetArchDescription(CpuArch arch);
static std::string GetArchDescription(cpu::Architecture arch);
Syscall() = default;
Syscall(CpuArch arch, uint64_t nr, Args args = {})
Syscall(cpu::Architecture arch, uint64_t nr, Args args = {})
: arch_(arch), nr_(nr), args_(args) {}
pid_t pid() const { return pid_; }
uint64_t nr() const { return nr_; }
CpuArch arch() const { return arch_; }
cpu::Architecture arch() const { return arch_; }
const Args& args() const { return args_; }
uint64_t stack_pointer() const { return sp_; }
uint64_t instruction_pointer() const { return ip_; }
@ -72,12 +66,12 @@ class Syscall {
private:
friend class Regs;
Syscall(pid_t pid) : pid_(pid) {}
Syscall(CpuArch arch, uint64_t nr, Args args, pid_t pid, uint64_t sp,
uint64_t ip)
explicit Syscall(pid_t pid) : pid_(pid) {}
Syscall(cpu::Architecture arch, uint64_t nr, Args args, pid_t pid,
uint64_t sp, uint64_t ip)
: arch_(arch), nr_(nr), args_(args), pid_(pid), sp_(sp), ip_(ip) {}
CpuArch arch_ = kUnknown;
cpu::Architecture arch_ = cpu::kUnknown;
uint64_t nr_ = -1;
Args args_ = {};
pid_t pid_ = -1;

View File

@ -7,6 +7,7 @@
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "sandboxed_api/sandbox2/config.h"
#include "sandboxed_api/sandbox2/util.h"
namespace sandbox2 {
@ -128,7 +129,6 @@ std::vector<std::string> SyscallTable::GetArgumentsDescription(
#define SYSCALLS_UNUSED00_99(prefix) \
SYSCALLS_UNUSED00_49(prefix), SYSCALLS_UNUSED50_99(prefix)
#if defined(__x86_64__)
// Syscall description table for Linux x86_64
constexpr SyscallTable::Entry kSyscallDataX8664[] = {
MakeEntry("read", kInt, kHex, kInt), // 0
@ -824,12 +824,10 @@ constexpr SyscallTable::Entry kSyscallDataX8632[] = {
MakeEntry("bpf", kHex, kHex, kHex, kHex, kHex, kHex), // 357
};
#elif defined(__powerpc64__)
// http://lxr.free-electrons.com/source/arch/powerpc/include/uapi/asm/unistd.h
// Note: PPC64 syscalls can have up to 7 register arguments, but nobody is
// using the 7th argument - probably for x64 compatibility reasons.
constexpr SyscallTable::Entry kSyscallDataPPC64[] = {
constexpr SyscallTable::Entry kSyscallDataPPC64LE[] = {
MakeEntry("restart_syscall", kGen, kGen, kGen, kGen, kGen, kGen), // 0
MakeEntry("exit", kInt, kGen, kGen, kGen, kGen, kGen), // 1
MakeEntry("fork", kGen, kGen, kGen, kGen, kGen, kGen), // 2
@ -1218,7 +1216,290 @@ constexpr SyscallTable::Entry kSyscallDataPPC64[] = {
MakeEntry("pwritev2", kHex, kHex, kHex, kHex, kHex, kHex), // 381
};
#endif
// TODO(cblichmann): Confirm the entries in this list.
// https://github.com/torvalds/linux/blob/v5.8/include/uapi/asm-generic/unistd.h
constexpr SyscallTable::Entry kSyscallDataArm64[] = {
MakeEntry("io_setup", UnknownArguments()), // 0
MakeEntry("io_destroy", UnknownArguments()), // 1
MakeEntry("io_submit", UnknownArguments()), // 2
MakeEntry("io_cancel", UnknownArguments()), // 3
MakeEntry("io_getevents", UnknownArguments()), // 4
MakeEntry("setxattr", kPath, kString, kGen, kInt, kHex, kGen), // 5
MakeEntry("lsetxattr", kPath, kString, kGen, kInt, kHex, kGen), // 6
MakeEntry("fsetxattr", UnknownArguments()), // 7
MakeEntry("getxattr", kPath, kString, kGen, kInt, kGen, kGen), // 8
MakeEntry("lgetxattr", kPath, kString, kGen, kInt, kGen, kGen), // 9
MakeEntry("fgetxattr", UnknownArguments()), // 10
MakeEntry("listxattr", kPath, kGen, kInt, kGen, kGen, kGen), // 11
MakeEntry("llistxattr", kPath, kGen, kInt, kGen, kGen, kGen), // 12
MakeEntry("flistxattr", UnknownArguments()), // 13
MakeEntry("removexattr", kPath, kString, kGen, kGen, kGen, kGen), // 14
MakeEntry("lremovexattr", UnknownArguments()), // 15
MakeEntry("fremovexattr", UnknownArguments()), // 16
MakeEntry("getcwd", UnknownArguments()), // 17
MakeEntry("lookup_dcookie", UnknownArguments()), // 18
MakeEntry("eventfd2", UnknownArguments()), // 19
MakeEntry("epoll_create1", UnknownArguments()), // 20
MakeEntry("epoll_ctl", UnknownArguments()), // 21
MakeEntry("epoll_pwait", UnknownArguments()), // 22
MakeEntry("dup", UnknownArguments()), // 23
MakeEntry("dup3", UnknownArguments()), // 24
MakeEntry("fcntl", UnknownArguments()), // 25
MakeEntry("inotify_init1", UnknownArguments()), // 26
MakeEntry("inotify_add_watch", UnknownArguments()), // 27
MakeEntry("inotify_rm_watch", UnknownArguments()), // 28
MakeEntry("ioctl", UnknownArguments()), // 29
MakeEntry("ioprio_set", UnknownArguments()), // 30
MakeEntry("ioprio_get", UnknownArguments()), // 31
MakeEntry("flock", UnknownArguments()), // 32
MakeEntry("mknodat", kGen, kPath, kGen, kGen, kGen, kGen), // 33
MakeEntry("mkdirat", kGen, kPath, kGen, kGen, kGen, kGen), // 34
MakeEntry("unlinkat", kGen, kPath, kGen, kGen, kGen, kGen), // 35
MakeEntry("symlinkat", kPath, kGen, kPath, kGen, kGen, kGen), // 36
MakeEntry("linkat", kGen, kPath, kGen, kPath, kGen, kGen), // 37
MakeEntry("renameat", kGen, kPath, kGen, kPath, kGen, kGen), // 38
MakeEntry("umount2", kPath, kHex, kGen, kGen, kGen, kGen), // 39
MakeEntry("mount", kPath, kPath, kString, kHex, kGen, kGen), // 40
MakeEntry("pivot_root", kPath, kPath, kGen, kGen, kGen, kGen), // 41
MakeEntry("nfsservctl", UnknownArguments()), // 42
MakeEntry("statfs", kPath, kGen, kGen, kGen, kGen, kGen), // 43
MakeEntry("fstatfs", UnknownArguments()), // 44
MakeEntry("truncate", kPath, kInt, kGen, kGen, kGen, kGen), // 45
MakeEntry("ftruncate", UnknownArguments()), // 46
MakeEntry("fallocate", UnknownArguments()), // 47
MakeEntry("faccessat", kGen, kPath, kGen, kGen, kGen, kGen), // 48
MakeEntry("chdir", kPath, kGen, kGen, kGen, kGen, kGen), // 49
MakeEntry("fchdir", UnknownArguments()), // 50
MakeEntry("chroot", kPath, kGen, kGen, kGen, kGen, kGen), // 51
MakeEntry("fchmod", UnknownArguments()), // 52
MakeEntry("fchmodat", kGen, kPath, kGen, kGen, kGen, kGen), // 53
MakeEntry("fchownat", kGen, kPath, kGen, kGen, kGen, kGen), // 54
MakeEntry("fchown", UnknownArguments()), // 55
MakeEntry("openat", kGen, kPath, kOct, kHex, kGen, kGen), // 56
MakeEntry("close", kInt, kGen, kGen, kGen, kGen, kGen), // 57
MakeEntry("vhangup", UnknownArguments()), // 58
MakeEntry("pipe2", UnknownArguments()), // 59
MakeEntry("quotactl", kInt, kPath, kInt, kGen, kGen, kGen), // 60
MakeEntry("getdents64", UnknownArguments()), // 61
MakeEntry("lseek", UnknownArguments()), // 62
MakeEntry("read", kInt, kHex, kInt, kGen, kGen, kGen), // 63
MakeEntry("write", kInt, kHex, kInt, kGen, kGen, kGen), // 64
MakeEntry("readv", UnknownArguments()), // 65
MakeEntry("writev", UnknownArguments()), // 66
MakeEntry("pread64", UnknownArguments()), // 67
MakeEntry("pwrite64", UnknownArguments()), // 68
MakeEntry("preadv", UnknownArguments()), // 69
MakeEntry("pwritev", UnknownArguments()), // 70
MakeEntry("sendfile", UnknownArguments()), // 71
MakeEntry("pselect6", UnknownArguments()), // 72
MakeEntry("ppoll", UnknownArguments()), // 73
MakeEntry("signalfd4", UnknownArguments()), // 74
MakeEntry("vmsplice", UnknownArguments()), // 75
MakeEntry("splice", UnknownArguments()), // 76
MakeEntry("tee", UnknownArguments()), // 77
MakeEntry("readlinkat", kGen, kPath, kGen, kGen, kGen, kGen), // 78
MakeEntry("newfstatat", kGen, kPath, kGen, kGen, kGen, kGen), // 79
MakeEntry("fstat", kInt, kHex, kGen, kGen, kGen, kGen), // 80
MakeEntry("sync", UnknownArguments()), // 81
MakeEntry("fsync", UnknownArguments()), // 82
MakeEntry("fdatasync", UnknownArguments()), // 83
MakeEntry("sync_file_range", UnknownArguments()), // 84
MakeEntry("timerfd_create", UnknownArguments()), // 85
MakeEntry("timerfd_settime", UnknownArguments()), // 86
MakeEntry("timerfd_gettime", UnknownArguments()), // 87
MakeEntry("utimensat", UnknownArguments()), // 88
MakeEntry("acct", kPath, kGen, kGen, kGen, kGen, kGen), // 89
MakeEntry("capget", UnknownArguments()), // 90
MakeEntry("capset", UnknownArguments()), // 91
MakeEntry("personality", UnknownArguments()), // 92
MakeEntry("exit", kInt, kGen, kGen, kGen, kGen, kGen), // 93
MakeEntry("exit_group", kInt, kGen, kGen, kGen, kGen, kGen), // 94
MakeEntry("waitid", UnknownArguments()), // 95
MakeEntry("set_tid_address", kHex, kGen, kGen, kGen, kGen, kGen), // 96
MakeEntry("unshare", UnknownArguments()), // 97
MakeEntry("futex", UnknownArguments()), // 98
MakeEntry("set_robust_list", UnknownArguments()), // 99
MakeEntry("get_robust_list", UnknownArguments()), // 100
MakeEntry("nanosleep", kHex, kHex, kGen, kGen, kGen, kGen), // 101
MakeEntry("getitimer", UnknownArguments()), // 102
MakeEntry("setitimer", UnknownArguments()), // 103
MakeEntry("kexec_load", UnknownArguments()), // 104
MakeEntry("init_module", UnknownArguments()), // 105
MakeEntry("delete_module", UnknownArguments()), // 106
MakeEntry("timer_create", UnknownArguments()), // 107
MakeEntry("timer_gettime", UnknownArguments()), // 108
MakeEntry("timer_getoverrun", UnknownArguments()), // 109
MakeEntry("timer_settime", UnknownArguments()), // 110
MakeEntry("timer_delete", UnknownArguments()), // 111
MakeEntry("clock_settime", UnknownArguments()), // 112
MakeEntry("clock_gettime", UnknownArguments()), // 113
MakeEntry("clock_getres", UnknownArguments()), // 114
MakeEntry("clock_nanosleep", UnknownArguments()), // 115
MakeEntry("syslog", UnknownArguments()), // 116
MakeEntry("ptrace", UnknownArguments()), // 117
MakeEntry("sched_setparam", UnknownArguments()), // 118
MakeEntry("sched_setscheduler", UnknownArguments()), // 119
MakeEntry("sched_getscheduler", UnknownArguments()), // 120
MakeEntry("sched_getparam", UnknownArguments()), // 121
MakeEntry("sched_setaffinity", UnknownArguments()), // 122
MakeEntry("sched_getaffinity", UnknownArguments()), // 123
MakeEntry("sched_yield", UnknownArguments()), // 124
MakeEntry("sched_get_priority_max", UnknownArguments()), // 125
MakeEntry("sched_get_priority_min", UnknownArguments()), // 126
MakeEntry("sched_rr_get_interval", UnknownArguments()), // 127
MakeEntry("restart_syscall", UnknownArguments()), // 128
MakeEntry("kill", kInt, kSignal, kGen, kGen, kGen, kGen), // 129
MakeEntry("tkill", kInt, kSignal, kGen, kGen, kGen, kGen), // 130
MakeEntry("tgkill", kInt, kInt, kSignal, kGen, kGen, kGen), // 131
MakeEntry("sigaltstack", UnknownArguments()), // 132
MakeEntry("rt_sigsuspend", UnknownArguments()), // 133
MakeEntry("rt_sigaction", kSignal, kHex, kHex, kInt, kGen, kGen), // 134
MakeEntry("rt_sigprocmask", UnknownArguments()), // 135
MakeEntry("rt_sigpending", UnknownArguments()), // 136
MakeEntry("rt_sigtimedwait", UnknownArguments()), // 137
MakeEntry("rt_sigqueueinfo", UnknownArguments()), // 138
MakeEntry("rt_sigreturn", UnknownArguments()), // 139
MakeEntry("setpriority", UnknownArguments()), // 140
MakeEntry("getpriority", UnknownArguments()), // 141
MakeEntry("reboot", UnknownArguments()), // 142
MakeEntry("setregid", UnknownArguments()), // 143
MakeEntry("setgid", UnknownArguments()), // 144
MakeEntry("setreuid", UnknownArguments()), // 145
MakeEntry("setuid", UnknownArguments()), // 146
MakeEntry("setresuid", UnknownArguments()), // 147
MakeEntry("getresuid", UnknownArguments()), // 148
MakeEntry("setresgid", UnknownArguments()), // 149
MakeEntry("getresgid", UnknownArguments()), // 150
MakeEntry("setfsuid", UnknownArguments()), // 151
MakeEntry("setfsgid", UnknownArguments()), // 152
MakeEntry("times", UnknownArguments()), // 153
MakeEntry("setpgid", UnknownArguments()), // 154
MakeEntry("getpgid", UnknownArguments()), // 155
MakeEntry("getsid", UnknownArguments()), // 156
MakeEntry("setsid", UnknownArguments()), // 157
MakeEntry("getgroups", UnknownArguments()), // 158
MakeEntry("setgroups", UnknownArguments()), // 159
MakeEntry("uname", UnknownArguments()), // 160
MakeEntry("sethostname", UnknownArguments()), // 161
MakeEntry("setdomainname", UnknownArguments()), // 162
MakeEntry("getrlimit", UnknownArguments()), // 163
MakeEntry("setrlimit", UnknownArguments()), // 164
MakeEntry("getrusage", UnknownArguments()), // 165
MakeEntry("umask", kHex, kGen, kGen, kGen, kGen, kGen), // 166
MakeEntry("prctl", kInt, kHex, kHex, kHex, kHex, kGen), // 167
MakeEntry("getcpu", kHex, kHex, kHex, kGen, kGen, kGen), // 168
MakeEntry("gettimeofday", kHex, kHex, kGen, kGen, kGen, kGen), // 169
MakeEntry("settimeofday", kHex, kHex, kGen, kGen, kGen, kGen), // 170
MakeEntry("adjtimex", UnknownArguments()), // 171
MakeEntry("getpid", UnknownArguments()), // 172
MakeEntry("getppid", UnknownArguments()), // 173
MakeEntry("getuid", UnknownArguments()), // 174
MakeEntry("geteuid", UnknownArguments()), // 175
MakeEntry("getgid", UnknownArguments()), // 176
MakeEntry("getegid", UnknownArguments()), // 177
MakeEntry("gettid", UnknownArguments()), // 178
MakeEntry("sysinfo", UnknownArguments()), // 179
MakeEntry("mq_open", UnknownArguments()), // 180
MakeEntry("mq_unlink", UnknownArguments()), // 181
MakeEntry("mq_timedsend", UnknownArguments()), // 182
MakeEntry("mq_timedreceive", UnknownArguments()), // 183
MakeEntry("mq_notify", UnknownArguments()), // 184
MakeEntry("mq_getsetattr", UnknownArguments()), // 185
MakeEntry("msgget", UnknownArguments()), // 186
MakeEntry("msgctl", UnknownArguments()), // 187
MakeEntry("msgrcv", UnknownArguments()), // 188
MakeEntry("msgsnd", UnknownArguments()), // 189
MakeEntry("semget", UnknownArguments()), // 190
MakeEntry("semctl", UnknownArguments()), // 191
MakeEntry("semtimedop", UnknownArguments()), // 192
MakeEntry("semop", UnknownArguments()), // 193
MakeEntry("shmget", UnknownArguments()), // 194
MakeEntry("shmctl", UnknownArguments()), // 195
MakeEntry("shmat", UnknownArguments()), // 196
MakeEntry("shmdt", UnknownArguments()), // 197
MakeEntry("socket", kAddressFamily, kInt, kInt, kGen, kGen, kGen), // 198
MakeEntry("socketpair", UnknownArguments()), // 199
MakeEntry("bind", UnknownArguments()), // 200
MakeEntry("listen", UnknownArguments()), // 201
MakeEntry("accept", UnknownArguments()), // 202
MakeEntry("connect", kInt, kSockaddr, kInt, kGen, kGen, kGen), // 203
MakeEntry("getsockname", UnknownArguments()), // 204
MakeEntry("getpeername", UnknownArguments()), // 205
MakeEntry("sendto", kInt, kGen, kInt, kHex, kSockaddr, kInt), // 206
MakeEntry("recvfrom", UnknownArguments()), // 207
MakeEntry("setsockopt", UnknownArguments()), // 208
MakeEntry("getsockopt", UnknownArguments()), // 209
MakeEntry("shutdown", UnknownArguments()), // 210
MakeEntry("sendmsg", kInt, kSockmsghdr, kHex, kGen, kGen, kGen), // 211
MakeEntry("recvmsg", UnknownArguments()), // 212
MakeEntry("readahead", UnknownArguments()), // 213
MakeEntry("brk", kHex, kGen, kGen, kGen, kGen, kGen), // 214
MakeEntry("munmap", kHex, kHex, kGen, kGen, kGen, kGen), // 215
MakeEntry("mremap", UnknownArguments()), // 216
MakeEntry("add_key", UnknownArguments()), // 217
MakeEntry("request_key", UnknownArguments()), // 218
MakeEntry("keyctl", UnknownArguments()), // 219
MakeEntry("clone", kCloneFlag, kHex, kHex, kHex, kHex, kGen), // 220
MakeEntry("execve", kPath, kHex, kHex, kGen, kGen, kGen), // 221
MakeEntry("mmap", kHex, kInt, kHex, kHex, kInt, kInt), // 222
MakeEntry("fadvise64", UnknownArguments()), // 223
MakeEntry("swapon", kPath, kHex, kGen, kGen, kGen, kGen), // 224
MakeEntry("swapoff", kPath, kGen, kGen, kGen, kGen, kGen), // 225
MakeEntry("mprotect", kHex, kHex, kHex, kGen, kGen, kGen), // 226
MakeEntry("msync", UnknownArguments()), // 227
MakeEntry("mlock", UnknownArguments()), // 228
MakeEntry("munlock", UnknownArguments()), // 229
MakeEntry("mlockall", UnknownArguments()), // 230
MakeEntry("munlockall", UnknownArguments()), // 231
MakeEntry("mincore", UnknownArguments()), // 232
MakeEntry("madvise", UnknownArguments()), // 233
MakeEntry("remap_file_pages", UnknownArguments()), // 234
MakeEntry("mbind", UnknownArguments()), // 235
MakeEntry("get_mempolicy", UnknownArguments()), // 236
MakeEntry("set_mempolicy", UnknownArguments()), // 237
MakeEntry("migrate_pages", UnknownArguments()), // 238
MakeEntry("move_pages", UnknownArguments()), // 239
MakeEntry("rt_tgsigqueueinfo", UnknownArguments()), // 240
MakeEntry("perf_event_open", UnknownArguments()), // 241
MakeEntry("accept4", UnknownArguments()), // 242
MakeEntry("recvmmsg", kInt, kHex, kHex, kHex, kGen, kGen), // 243
SYSCALLS_UNUSED("UNUSED244"), // 244
SYSCALLS_UNUSED("UNUSED245"), // 245
SYSCALLS_UNUSED("UNUSED246"), // 246
SYSCALLS_UNUSED("UNUSED247"), // 247
SYSCALLS_UNUSED("UNUSED248"), // 248
SYSCALLS_UNUSED("UNUSED249"), // 249
SYSCALLS_UNUSED("UNUSED250"), // 250
SYSCALLS_UNUSED("UNUSED251"), // 251
SYSCALLS_UNUSED("UNUSED252"), // 252
SYSCALLS_UNUSED("UNUSED253"), // 253
SYSCALLS_UNUSED("UNUSED254"), // 254
SYSCALLS_UNUSED("UNUSED255"), // 255
SYSCALLS_UNUSED("UNUSED256"), // 256
SYSCALLS_UNUSED("UNUSED257"), // 257
SYSCALLS_UNUSED("UNUSED258"), // 258
SYSCALLS_UNUSED("UNUSED259"), // 259
MakeEntry("wait4", kInt, kHex, kHex, kHex, kGen, kGen), // 260
MakeEntry("prlimit64", kInt, kInt, kHex, kHex, kGen, kGen), // 261
MakeEntry("fanotify_init", kHex, kHex, kInt, kGen, kGen, kGen), // 262
MakeEntry("fanotify_mark", kInt, kHex, kInt, kPath, kGen, kGen), // 263
MakeEntry("name_to_handle_at", kInt, kGen, kHex, kHex, kHex, kGen), // 264
MakeEntry("open_by_handle_at", kInt, kHex, kHex, kGen, kGen, kGen), // 265
MakeEntry("clock_adjtime", kInt, kHex, kGen, kGen, kGen, kGen), // 266
MakeEntry("syncfs", kInt, kGen, kGen, kGen, kGen, kGen), // 267
MakeEntry("setns", kInt, kHex, kGen, kGen, kGen, kGen), // 268
MakeEntry("sendmmsg", kInt, kHex, kInt, kHex, kGen, kGen), // 269
MakeEntry("process_vm_readv", kInt, kHex, kInt, kHex, kInt, kInt), // 270
MakeEntry("process_vm_writev", kInt, kHex, kInt, kHex, kInt, kInt), // 271
MakeEntry("kcmp", kInt, kInt, kInt, kHex, kHex, kGen), // 272
MakeEntry("finit_module", kInt, kPath, kHex, kGen, kGen, kGen), // 273
MakeEntry("sched_setattr", UnknownArguments()), // 274
MakeEntry("sched_getattr", UnknownArguments()), // 275
MakeEntry("renameat2", kGen, kPath, kGen, kPath, kGen, kGen), // 276
MakeEntry("seccomp", UnknownArguments()), // 277
MakeEntry("getrandom", UnknownArguments()), // 278
MakeEntry("memfd_create", UnknownArguments()), // 279
};
#undef SYSCALLS_UNUSED00_99
#undef SYSCALLS_UNUSED50_99
@ -1226,17 +1507,16 @@ constexpr SyscallTable::Entry kSyscallDataPPC64[] = {
#undef SYSCALLS_UNUSED0_9
#undef SYSCALLS_UNUSED
SyscallTable SyscallTable::get(Syscall::CpuArch arch) {
switch (arch) {
#if defined(__x86_64__)
case Syscall::kX86_64:
SyscallTable SyscallTable::get(cpu::Architecture arch) {
switch (host_cpu::Architecture()) {
case cpu::kX8664:
return SyscallTable(kSyscallDataX8664);
case Syscall::kX86_32:
case cpu::kX86:
return SyscallTable(kSyscallDataX8632);
#elif defined(__powerpc64__)
case Syscall::kPPC_64:
return SyscallTable(kSyscallDataPPC64);
#endif
case cpu::kPPC64LE:
return SyscallTable(kSyscallDataPPC64LE);
case cpu::kArm64:
return SyscallTable(kSyscallDataArm64);
default:
return SyscallTable();
}

View File

@ -9,6 +9,7 @@
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "sandboxed_api/sandbox2/config.h"
#include "sandboxed_api/sandbox2/syscall.h"
namespace sandbox2 {
@ -23,7 +24,7 @@ class SyscallTable {
struct Entry;
// Returns the syscall table for the architecture.
static SyscallTable get(Syscall::CpuArch arch);
static SyscallTable get(cpu::Architecture arch);
int size() { return data_.size(); }

View File

@ -19,6 +19,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/strings/str_cat.h"
#include "sandboxed_api/sandbox2/config.h"
using ::testing::Eq;
using ::testing::StartsWith;
@ -45,7 +46,7 @@ TEST(SyscallTest, Basic) {
EXPECT_THAT(arg_desc[2], Eq("0x5 [5]"));
EXPECT_THAT(
syscall.GetDescription(),
Eq(absl::StrCat(Syscall::GetArchDescription(Syscall::GetHostArch()),
Eq(absl::StrCat(Syscall::GetArchDescription(host_cpu::Architecture()),
" read [", __NR_read,
"](0x1 [1], 0xbadbeef, 0x5 [5]) IP: 0, STACK: 0")));
}
@ -53,7 +54,7 @@ TEST(SyscallTest, Basic) {
TEST(SyscallTest, Empty) {
Syscall syscall;
EXPECT_THAT(syscall.arch(), Eq(Syscall::kUnknown));
EXPECT_THAT(syscall.arch(), Eq(cpu::kUnknown));
EXPECT_THAT(syscall.GetName(), StartsWith("UNKNOWN"));
EXPECT_THAT(syscall.GetArgumentsDescription().size(), Eq(Syscall::kMaxArgs));
}

View File

@ -41,7 +41,12 @@ STATIC_LINKOPTS = [
]
# TODO(https://github.com/bazelbuild/bazel/issues/8672): Remove this workaround
EXTRA_FULLY_STATIC_LINKOPTS = ["-l:libstdc++.a"]
# Change is scheduled for Bazel 4.0. Specifying
# `--incompatible_linkopts_to_linklibs` also works
EXTRA_FULLY_STATIC_LINKOPTS = [
"-l:libstdc++.a",
"-l:libm.a",
]
cc_binary(
name = "abort",
@ -173,6 +178,7 @@ cc_binary(
"fully_static_link", # link libc statically
],
linkstatic = 1, # prefer static libraries
deps = ["//sandboxed_api/sandbox2:config"],
)
# security: disable=cc-static-no-pie

View File

@ -159,6 +159,7 @@ set_target_properties(policy PROPERTIES
)
target_link_libraries(policy PRIVATE
sapi::base
sandbox2::config
${_sandbox2_fully_static_linkopts}
)

View File

@ -23,7 +23,9 @@
#include <cstdio>
#include <cstdlib>
#if defined(__x86_64__)
#include "sandboxed_api/sandbox2/config.h"
#ifdef SAPI_X86_64
void TestAMD64SyscallMismatch() {
int64_t result;
@ -53,7 +55,7 @@ void TestAMD64SyscallMismatchFs() {
: "rax", "rbx", "rcx");
exit(-result);
}
#endif // defined(__x86_64__)
#endif
void TestPtrace() {
ptrace(PTRACE_SEIZE, getppid(), 0, 0);
@ -97,14 +99,14 @@ int main(int argc, char** argv) {
int testno = atoi(argv[1]); // NOLINT
switch (testno) {
#if defined(__x86_64__)
#ifdef SAPI_X86_64
case 1:
TestAMD64SyscallMismatch();
break;
case 2:
TestAMD64SyscallMismatchFs();
break;
#endif // defined(__x86_64__)
#endif
case 3:
TestPtrace();
break;

View File

@ -39,13 +39,13 @@
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "sandboxed_api/sandbox2/config.h"
#include "sandboxed_api/sandbox2/util/fileops.h"
#include "sandboxed_api/sandbox2/util/path.h"
#include "sandboxed_api/sandbox2/util/strerror.h"
#include "sandboxed_api/util/raw_logging.h"
namespace sandbox2 {
namespace util {
namespace sandbox2::util {
void CharPtrArrToVecString(char* const* arr, std::vector<std::string>* vec) {
for (int i = 0; arr[i]; ++i) {
@ -126,13 +126,11 @@ ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS
ABSL_ATTRIBUTE_NOINLINE
pid_t CloneAndJump(int flags, jmp_buf* env_ptr) {
uint8_t stack_buf[PTHREAD_STACK_MIN] ABSL_CACHELINE_ALIGNED;
#if defined(__x86_64__) || defined(__x86__) || defined(__i386__) || \
defined(__powerpc64__)
static_assert(
host_cpu::IsX8664() || host_cpu::IsPPC64LE() || host_cpu::IsArm64(),
"Host CPU architecture not supported, see config.h");
// Stack grows down.
void* stack = stack_buf + sizeof(stack_buf);
#else
#error "Architecture is not supported"
#endif
int r;
{
r = clone(&ChildFunc, stack, flags, env_ptr, nullptr, nullptr, nullptr);
@ -182,9 +180,9 @@ bool CreateMemFd(int* fd, const char* name) {
return true;
}
sapi::StatusOr<int> Communicate(const std::vector<std::string>& argv,
const std::vector<std::string>& envv,
std::string* output) {
absl::StatusOr<int> Communicate(const std::vector<std::string>& argv,
const std::vector<std::string>& envv,
std::string* output) {
int cout_pipe[2];
posix_spawn_file_actions_t action;
@ -280,7 +278,7 @@ std::string GetRlimitName(int resource) {
}
}
sapi::StatusOr<std::string> ReadCPathFromPid(pid_t pid, uintptr_t ptr) {
absl::StatusOr<std::string> ReadCPathFromPid(pid_t pid, uintptr_t ptr) {
std::string path(PATH_MAX, '\0');
iovec local_iov[] = {{&path[0], path.size()}};
@ -321,5 +319,4 @@ sapi::StatusOr<std::string> ReadCPathFromPid(pid_t pid, uintptr_t ptr) {
return path;
}
} // namespace util
} // namespace sandbox2
} // namespace sandbox2::util

View File

@ -25,7 +25,7 @@
#include <vector>
#include "absl/base/macros.h"
#include "sandboxed_api/util/statusor.h"
#include "absl/status/statusor.h"
namespace sandbox2 {
namespace util {
@ -62,9 +62,9 @@ bool CreateMemFd(int* fd, const char* name = "buffer_file");
// Executes a the program given by argv and the specified environment and
// captures any output to stdout/stderr.
sapi::StatusOr<int> Communicate(const std::vector<std::string>& argv,
const std::vector<std::string>& envv,
std::string* output);
absl::StatusOr<int> Communicate(const std::vector<std::string>& argv,
const std::vector<std::string>& envv,
std::string* output);
// Returns signal description.
std::string GetSignalName(int signo);
@ -74,7 +74,7 @@ std::string GetRlimitName(int resource);
// Reads a path string (NUL-terminated, shorter than PATH_MAX) from another
// process memory
sapi::StatusOr<std::string> ReadCPathFromPid(pid_t pid, uintptr_t ptr);
absl::StatusOr<std::string> ReadCPathFromPid(pid_t pid, uintptr_t ptr);
} // namespace util
} // namespace sandbox2

View File

@ -139,9 +139,9 @@ cc_library(
"//sandboxed_api/sandbox2:util",
"//sandboxed_api/util:raw_logging",
"//sandboxed_api/util:status",
"//sandboxed_api/util:statusor",
"@com_google_absl//absl/base:endian",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
],
)
@ -173,8 +173,8 @@ cc_library(
deps = [
":fileops",
":strerror",
"//sandboxed_api/util:statusor",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
],
)
@ -199,8 +199,8 @@ cc_library(
hdrs = ["maps_parser.h"],
copts = sapi_platform_copts(),
deps = [
"//sandboxed_api/util:statusor",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
],
)

View File

@ -80,7 +80,6 @@ target_link_libraries(sandbox2_util_minielf PRIVATE
sandbox2::util
sapi::base
sapi::raw_logging
sapi::statusor
)
# sandboxed_api/sandbox2/util:temp_file
@ -95,7 +94,7 @@ target_link_libraries(sandbox2_util_temp_file
sandbox2::strerror
sapi::base
PUBLIC absl::status
sapi::statusor
absl::statusor
)
# sandboxed_api/sandbox2/util:maps_parser
@ -106,9 +105,9 @@ add_library(sandbox2_util_maps_parser STATIC
add_library(sandbox2::maps_parser ALIAS sandbox2_util_maps_parser)
target_link_libraries(sandbox2_util_maps_parser PRIVATE
absl::status
absl::statusor
absl::strings
sapi::base
sapi::statusor
)
# sandboxed_api/sandbox2/util:runfiles

View File

@ -15,11 +15,12 @@
#include "sandboxed_api/sandbox2/util/maps_parser.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_split.h"
namespace sandbox2 {
sapi::StatusOr<std::vector<MapsEntry>> ParseProcMaps(
absl::StatusOr<std::vector<MapsEntry>> ParseProcMaps(
const std::string& contents) {
// Note: The format string
// https://github.com/torvalds/linux/blob/v4.14/fs/proc/task_mmu.c#L289

View File

@ -19,7 +19,7 @@
#include <string>
#include <vector>
#include "sandboxed_api/util/statusor.h"
#include "absl/status/statusor.h"
namespace sandbox2 {
@ -37,7 +37,7 @@ struct MapsEntry {
std::string path;
};
sapi::StatusOr<std::vector<MapsEntry>> ParseProcMaps(
absl::StatusOr<std::vector<MapsEntry>> ParseProcMaps(
const std::string& contents);
} // namespace sandbox2

View File

@ -95,7 +95,7 @@ class ElfParser {
static constexpr size_t kMaxInterpreterSize = 1000;
ElfParser() = default;
sapi::StatusOr<ElfFile> Parse(FILE* elf, uint32_t features);
absl::StatusOr<ElfFile> Parse(FILE* elf, uint32_t features);
private:
// Endianess support functions
@ -133,16 +133,16 @@ class ElfParser {
// Reads elf header.
absl::Status ReadFileHeader();
// Reads a single elf program header.
sapi::StatusOr<Elf64_Phdr> ReadProgramHeader(absl::string_view src);
absl::StatusOr<Elf64_Phdr> ReadProgramHeader(absl::string_view src);
// Reads all elf program headers.
absl::Status ReadProgramHeaders();
// Reads a single elf section header.
sapi::StatusOr<Elf64_Shdr> ReadSectionHeader(absl::string_view src);
absl::StatusOr<Elf64_Shdr> ReadSectionHeader(absl::string_view src);
// Reads all elf section headers.
absl::Status ReadSectionHeaders();
// Reads contents of an elf section.
sapi::StatusOr<std::string> ReadSectionContents(int idx);
sapi::StatusOr<std::string> ReadSectionContents(
absl::StatusOr<std::string> ReadSectionContents(int idx);
absl::StatusOr<std::string> ReadSectionContents(
const Elf64_Shdr& section_header);
// Reads all symbols from symtab section.
absl::Status ReadSymbolsFromSymtab(const Elf64_Shdr& symtab);
@ -219,8 +219,7 @@ absl::Status ElfParser::ReadFileHeader() {
return absl::OkStatus();
}
sapi::StatusOr<Elf64_Shdr> ElfParser::ReadSectionHeader(
absl::string_view src) {
absl::StatusOr<Elf64_Shdr> ElfParser::ReadSectionHeader(absl::string_view src) {
if (src.size() < sizeof(Elf64_Shdr)) {
return absl::FailedPreconditionError(
absl::StrCat("invalid section header data: got ", src.size(),
@ -267,7 +266,7 @@ absl::Status ElfParser::ReadSectionHeaders() {
return absl::OkStatus();
}
sapi::StatusOr<std::string> ElfParser::ReadSectionContents(int idx) {
absl::StatusOr<std::string> ElfParser::ReadSectionContents(int idx) {
if (idx < 0 || idx >= section_headers_.size()) {
return absl::FailedPreconditionError(
absl::StrCat("invalid section header index: ", idx));
@ -275,7 +274,7 @@ sapi::StatusOr<std::string> ElfParser::ReadSectionContents(int idx) {
return ReadSectionContents(section_headers_.at(idx));
}
sapi::StatusOr<std::string> ElfParser::ReadSectionContents(
absl::StatusOr<std::string> ElfParser::ReadSectionContents(
const Elf64_Shdr& section_header) {
auto offset = section_header.sh_offset;
if (offset > file_size_) {
@ -293,8 +292,7 @@ sapi::StatusOr<std::string> ElfParser::ReadSectionContents(
return rv;
}
sapi::StatusOr<Elf64_Phdr> ElfParser::ReadProgramHeader(
absl::string_view src) {
absl::StatusOr<Elf64_Phdr> ElfParser::ReadProgramHeader(absl::string_view src) {
if (src.size() < sizeof(Elf64_Phdr)) {
return absl::FailedPreconditionError(
absl::StrCat("invalid program header data: got ", src.size(),
@ -456,7 +454,7 @@ absl::Status ElfParser::ReadImportedLibrariesFromDynamic(
return absl::OkStatus();
}
sapi::StatusOr<ElfFile> ElfParser::Parse(FILE* elf, uint32_t features) {
absl::StatusOr<ElfFile> ElfParser::Parse(FILE* elf, uint32_t features) {
elf_ = elf;
// Basic sanity check.
if (features & ~(ElfFile::kAll)) {
@ -513,8 +511,8 @@ sapi::StatusOr<ElfFile> ElfParser::Parse(FILE* elf, uint32_t features) {
return std::move(result_);
}
sapi::StatusOr<ElfFile> ElfFile::ParseFromFile(const std::string& filename,
uint32_t features) {
absl::StatusOr<ElfFile> ElfFile::ParseFromFile(const std::string& filename,
uint32_t features) {
std::unique_ptr<FILE, void (*)(FILE*)> elf{fopen(filename.c_str(), "r"),
[](FILE* f) { fclose(f); }};
if (!elf) {

View File

@ -20,7 +20,7 @@
#include <string>
#include <vector>
#include "sandboxed_api/util/statusor.h"
#include "absl/status/statusor.h"
namespace sandbox2 {
@ -33,8 +33,8 @@ class ElfFile {
std::string name;
};
static sapi::StatusOr<ElfFile> ParseFromFile(const std::string& filename,
uint32_t features);
static absl::StatusOr<ElfFile> ParseFromFile(const std::string& filename,
uint32_t features);
int64_t file_size() const { return file_size_; }
const std::string& interpreter() const { return interpreter_; }

View File

@ -22,6 +22,7 @@
#include <cstdlib>
#include <vector>
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "sandboxed_api/sandbox2/util/fileops.h"
#include "sandboxed_api/sandbox2/util/strerror.h"
@ -32,7 +33,7 @@ namespace {
constexpr absl::string_view kMktempSuffix = "XXXXXX";
} // namespace
sapi::StatusOr<std::pair<std::string, int>> CreateNamedTempFile(
absl::StatusOr<std::pair<std::string, int>> CreateNamedTempFile(
absl::string_view prefix) {
std::string name_template = absl::StrCat(prefix, kMktempSuffix);
int fd = mkstemp(&name_template[0]);
@ -42,7 +43,7 @@ sapi::StatusOr<std::pair<std::string, int>> CreateNamedTempFile(
return std::pair<std::string, int>{std::move(name_template), fd};
}
sapi::StatusOr<std::string> CreateNamedTempFileAndClose(
absl::StatusOr<std::string> CreateNamedTempFileAndClose(
absl::string_view prefix) {
auto result_or = CreateNamedTempFile(prefix);
if (result_or.ok()) {
@ -55,7 +56,7 @@ sapi::StatusOr<std::string> CreateNamedTempFileAndClose(
return result_or.status();
}
sapi::StatusOr<std::string> CreateTempDir(absl::string_view prefix) {
absl::StatusOr<std::string> CreateTempDir(absl::string_view prefix) {
std::string name_template = absl::StrCat(prefix, kMktempSuffix);
if (mkdtemp(&name_template[0]) == nullptr) {
return absl::UnknownError(absl::StrCat("mkdtemp():", StrError(errno)));

View File

@ -17,24 +17,24 @@
#include <string>
#include "sandboxed_api/util/statusor.h"
#include "absl/status/statusor.h"
namespace sandbox2 {
// Creates a temporary file under a path starting with prefix. File is not
// unlinked and its path is returned together with an open fd.
sapi::StatusOr<std::pair<std::string, int>> CreateNamedTempFile(
absl::StatusOr<std::pair<std::string, int>> CreateNamedTempFile(
absl::string_view prefix);
// Creates a temporary file under a path starting with prefix. File is not
// unlinked and its path is returned. FD of the created file is closed just
// after creation.
sapi::StatusOr<std::string> CreateNamedTempFileAndClose(
absl::StatusOr<std::string> CreateNamedTempFileAndClose(
absl::string_view prefix);
// Creates a temporary directory under a path starting with prefix.
// Returns the path of the created directory.
sapi::StatusOr<std::string> CreateTempDir(absl::string_view prefix);
absl::StatusOr<std::string> CreateTempDir(absl::string_view prefix);
} // namespace sandbox2

View File

@ -23,8 +23,8 @@
#include "sandboxed_api/sandbox2/testing.h"
#include "sandboxed_api/sandbox2/util/path.h"
using testing::Gt;
using testing::IsTrue;
using ::testing::Gt;
using ::testing::IsTrue;
namespace sandbox2 {
namespace util {

View File

@ -25,7 +25,6 @@ enum PBViolationType {
SYSCALL_ARCHITECTURE_MISMATCH = 3;
}
// X86_64 not allowed (naming convention...)
message RegisterX8664 {
uint64 r15 = 1;
uint64 r14 = 2;
@ -77,7 +76,6 @@ message RegisterPowerpc64 {
uint64 zero3 = 17;
}
// Deprecated.
message RegisterAarch64 {
repeated uint64 regs = 1;
uint64 sp = 2;
@ -90,7 +88,7 @@ message RegisterValues {
oneof register_values {
RegisterX8664 register_x86_64 = 2;
RegisterPowerpc64 register_powerpc64 = 3;
RegisterAarch64 register_aarch64 = 4; // Deprecated.
RegisterAarch64 register_aarch64 = 4;
}
}
@ -105,10 +103,10 @@ message SyscallDescription {
}
message FsDescription {
repeated string file_whitelist = 1;
repeated string symlink_whitelist = 2;
repeated string file_allowlist = 1;
repeated string symlink_allowlist = 2;
repeated string file_greylist = 3;
repeated string file_blacklist = 4;
repeated string file_denylist = 4;
}
message PolicyBuilderDescription {
@ -125,7 +123,7 @@ message NamespaceDescription {
message PolicyDescription {
bytes user_bpf_policy = 1;
reserved 2 to 5;
// This requires additional fields. (e.g. whitelisted syscall #s)
// This requires additional fields. (e.g. allowed syscall numbers)
PolicyBuilderDescription policy_builder_description = 6;
// namespace

View File

@ -15,6 +15,7 @@
#include "sandboxed_api/tools/clang_generator/emitter.h"
#include "absl/random/random.h"
#include "absl/status/statusor.h"
#include "absl/strings/ascii.h"
#include "absl/strings/escaping.h"
#include "absl/strings/match.h"
@ -46,10 +47,10 @@ constexpr absl::string_view kHeaderProlog =
#include "absl/base/macros.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "sandboxed_api/sandbox.h"
#include "sandboxed_api/vars.h"
#include "sandboxed_api/util/status_macros.h"
#include "sandboxed_api/util/statusor.h"
)";
constexpr absl::string_view kHeaderEpilog =
@ -196,7 +197,7 @@ std::string PrintFunctionPrototype(const clang::FunctionDecl* decl) {
return out;
}
sapi::StatusOr<std::string> EmitFunction(const clang::FunctionDecl* decl) {
absl::StatusOr<std::string> EmitFunction(const clang::FunctionDecl* decl) {
std::string out;
absl::StrAppend(&out, "\n// ", PrintFunctionPrototype(decl), "\n");
const std::string function_name = decl->getNameAsString();
@ -248,7 +249,7 @@ sapi::StatusOr<std::string> EmitFunction(const clang::FunctionDecl* decl) {
return out;
}
sapi::StatusOr<std::string> EmitHeader(
absl::StatusOr<std::string> EmitHeader(
std::vector<clang::FunctionDecl*> functions, const QualTypeSet& types,
const GeneratorOptions& options) {
std::string out;

View File

@ -18,12 +18,12 @@
#include <string>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Type.h"
#include "sandboxed_api/tools/clang_generator/generator.h"
#include "sandboxed_api/tools/clang_generator/types.h"
#include "sandboxed_api/util/statusor.h"
namespace sapi {
@ -36,7 +36,7 @@ namespace sapi {
std::string GetIncludeGuard(absl::string_view filename);
// Outputs a formatted header for a list of functions and their related types.
sapi::StatusOr<std::string> EmitHeader(
absl::StatusOr<std::string> EmitHeader(
std::vector<clang::FunctionDecl*> functions, const QualTypeSet& types,
const GeneratorOptions& options);

View File

@ -18,12 +18,12 @@
#include <iostream>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "clang/Format/Format.h"
#include "sandboxed_api/sandbox2/util/fileops.h"
#include "sandboxed_api/tools/clang_generator/diagnostics.h"
#include "sandboxed_api/tools/clang_generator/emitter.h"
#include "sandboxed_api/util/status_macros.h"
#include "sandboxed_api/util/statusor.h"
namespace sapi {
namespace {
@ -67,8 +67,8 @@ bool GeneratorASTVisitor::VisitFunctionDecl(clang::FunctionDecl* decl) {
namespace internal {
sapi::StatusOr<std::string> ReformatGoogleStyle(const std::string& filename,
const std::string& code) {
absl::StatusOr<std::string> ReformatGoogleStyle(const std::string& filename,
const std::string& code) {
// Configure code style based on Google style, but enforce pointer alignment
clang::format::FormatStyle style =
clang::format::getGoogleStyle(clang::format::FormatStyle::LK_Cpp);

View File

@ -20,13 +20,13 @@
#include "absl/container/flat_hash_set.h"
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Tooling/Tooling.h"
#include "sandboxed_api/tools/clang_generator/types.h"
#include "sandboxed_api/util/statusor.h"
namespace sapi {
@ -66,8 +66,8 @@ class GeneratorASTVisitor
namespace internal {
sapi::StatusOr<std::string> ReformatGoogleStyle(const std::string& filename,
const std::string& code);
absl::StatusOr<std::string> ReformatGoogleStyle(const std::string& filename,
const std::string& code);
} // namespace internal

View File

@ -208,7 +208,7 @@ std::string MapQualTypeReturn(const clang::ASTContext& context,
return "absl::Status";
}
// Remove const qualifier like in MapQualType().
return absl::StrCat("::sapi::StatusOr<",
return absl::StrCat("absl::StatusOr<",
MaybeRemoveConst(context, qual).getAsString(), ">");
}

View File

@ -68,7 +68,7 @@ std::string MapQualTypeParameter(const clang::ASTContext& context,
// Maps a qualified type used as a function return type to a type name
// compatible with the generated Sandboxed API. Uses MapQualTypeParameter() and
// wraps the type in a sapi::StatusOr<> if qual is non-void. Otherwise returns
// wraps the type in an absl::StatusOr<> if qual is non-void. Otherwise returns
// absl::Status.
std::string MapQualTypeReturn(const clang::ASTContext& context,
clang::QualType qual);

View File

@ -461,7 +461,7 @@ class ReturnType(ArgumentType):
"""Class representing function return type.
Attributes:
return_type: sapi::StatusOr<T> where T is original return type, or
return_type: absl::StatusOr<T> where T is original return type, or
absl::Status for functions returning void
"""
@ -474,7 +474,7 @@ class ReturnType(ArgumentType):
"""Returns function return type prepared from the type."""
# TODO(szwl): const ptrs do not play well with SAPI C++ API...
spelling = self._clang_type.spelling.replace('const', '')
return_type = 'sapi::StatusOr<{}>'.format(spelling)
return_type = 'absl::StatusOr<{}>'.format(spelling)
return_type = 'absl::Status' if self.is_void() else return_type
return return_type

View File

@ -32,7 +32,7 @@ class TestApi {
::sapi::Sandbox* sandbox() const { return sandbox_; }
// int function_a(int, int)
sapi::StatusOr<int> function_a(int x, int y) {
absl::StatusOr<int> function_a(int x, int y) {
::sapi::v::Int ret;
::sapi::v::Int x_((x));
::sapi::v::Int y_((y));
@ -42,7 +42,7 @@ class TestApi {
}
// int types_1(bool, unsigned char, char, unsigned short, short)
sapi::StatusOr<int> types_1(bool a0, unsigned char a1, char a2, unsigned short a3, short a4) {
absl::StatusOr<int> types_1(bool a0, unsigned char a1, char a2, unsigned short a3, short a4) {
::sapi::v::Int ret;
::sapi::v::Bool a0_((a0));
::sapi::v::UChar a1_((a1));
@ -55,7 +55,7 @@ class TestApi {
}
// int types_2(int, unsigned int, long, unsigned long)
sapi::StatusOr<int> types_2(int a0, unsigned int a1, long a2, unsigned long a3) {
absl::StatusOr<int> types_2(int a0, unsigned int a1, long a2, unsigned long a3) {
::sapi::v::Int ret;
::sapi::v::Int a0_((a0));
::sapi::v::UInt a1_((a1));
@ -67,7 +67,7 @@ class TestApi {
}
// int types_3(long long, unsigned long long, float, double)
sapi::StatusOr<int> types_3(long long a0, unsigned long long a1, float a2, double a3) {
absl::StatusOr<int> types_3(long long a0, unsigned long long a1, float a2, double a3) {
::sapi::v::Int ret;
::sapi::v::LLong a0_((a0));
::sapi::v::ULLong a1_((a1));
@ -79,7 +79,7 @@ class TestApi {
}
// int types_4(signed char, short, int, long)
sapi::StatusOr<int> types_4(signed char a0, short a1, int a2, long a3) {
absl::StatusOr<int> types_4(signed char a0, short a1, int a2, long a3) {
::sapi::v::Int ret;
::sapi::v::SChar a0_((a0));
::sapi::v::Short a1_((a1));
@ -91,7 +91,7 @@ class TestApi {
}
// int types_5(long long, long double)
sapi::StatusOr<int> types_5(long long a0, long double a1) {
absl::StatusOr<int> types_5(long long a0, long double a1) {
::sapi::v::Int ret;
::sapi::v::LLong a0_((a0));
::sapi::v::Reg<long double> a1_((a1));
@ -136,7 +136,7 @@ class TestApi {
::sapi::Sandbox* sandbox() const { return sandbox_; }
// uint function(uintp)
sapi::StatusOr<uint> function(::sapi::v::Ptr* a) {
absl::StatusOr<uint> function(::sapi::v::Ptr* a) {
::sapi::v::UInt ret;
SAPI_RETURN_IF_ERROR(sandbox_->Call("function", &ret, a));
@ -173,7 +173,7 @@ class TestApi {
::sapi::Sandbox* sandbox() const { return sandbox_; }
// ProcessStatus ProcessDatapoint(ProcessStatus)
sapi::StatusOr<ProcessStatus> ProcessDatapoint(ProcessStatus status) {
absl::StatusOr<ProcessStatus> ProcessDatapoint(ProcessStatus status) {
::sapi::v::IntBase<ProcessStatus> ret;
::sapi::v::IntBase<ProcessStatus> status_((status));

View File

@ -45,20 +45,15 @@ cc_library(
cc_library(
name = "statusor",
hdrs = ["statusor.h"],
copts = sapi_platform_copts(),
visibility = ["//visibility:public"],
deprecation = "Migrate to `absl::StatusOr<T>`",
deps = [
":raw_logging",
":status",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/base:log_severity",
"@com_google_absl//absl/status",
"@com_google_absl//absl/types:variant",
"@com_google_absl//absl/status:statusor",
],
)
# gMock matchers for absl::Status and sapi::StatusOr<T> and a gUnit printer
# extension for sapi::StatusOr<T>.
# gMock matchers for absl::Status and absl::StatusOr<T> and a gUnit printer
# extension. Adapted from the version in Asylo.
cc_library(
name = "status_matchers",
testonly = 1,
@ -67,8 +62,8 @@ cc_library(
visibility = ["//visibility:public"],
deps = [
":status",
":statusor",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/types:optional",
"@com_google_googletest//:gtest",
],
@ -87,19 +82,6 @@ cc_test(
],
)
# Tests for the StatusOr template class.
cc_test(
name = "statusor_test",
srcs = ["statusor_test.cc"],
copts = sapi_platform_copts(),
deps = [
":status",
":status_matchers",
":statusor",
"@com_google_googletest//:gtest_main",
],
)
# Tests for the Status macros.
cc_test(
name = "status_macros_test",
@ -108,9 +90,9 @@ cc_test(
deps = [
":status",
":status_matchers",
":statusor",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_googletest//:gtest_main",
],

View File

@ -48,11 +48,10 @@ add_library(sapi_util_statusor STATIC
)
add_library(sapi::statusor ALIAS sapi_util_statusor)
target_link_libraries(sapi_util_statusor PRIVATE
absl::base
absl::core_headers
absl::variant
sapi::raw_logging
sapi::status
absl::status
absl::statusor
sapi::base
)
# sandboxed_api/util:flag
@ -90,7 +89,6 @@ if(SAPI_ENABLE_TESTS)
sapi::base
PUBLIC absl::status
sapi::status
sapi::statusor
)
# sandboxed_api/util:status_test
@ -98,20 +96,24 @@ if(SAPI_ENABLE_TESTS)
status_test.cc
)
target_link_libraries(status_test PRIVATE
sapi::status
sapi::status_matchers
sapi::test_main
absl::status
absl::type_traits
)
gtest_discover_tests(status_test)
# sandboxed_api/util:statusor_test
add_executable(statusor_test
statusor_test.cc
# sandboxed_api/util:status_macros_test
add_executable(status_macros_test
status_macros_test.cc
)
target_link_libraries(statusor_test PRIVATE
target_link_libraries(status_macros_test PRIVATE
sapi::status_matchers
sapi::test_main
absl::status
absl::statusor
absl::type_traits
)
gtest_discover_tests(statusor_test)
gtest_discover_tests(status_macros_test)
endif()

View File

@ -12,10 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// This file and it's implementation provide a custom fork of
// util/task/status.h. This will become obsolete and will be replaced once
// Abseil releases absl::Status.
#ifndef THIRD_PARTY_SAPI_UTIL_STATUS_H_
#define THIRD_PARTY_SAPI_UTIL_STATUS_H_

View File

@ -42,6 +42,6 @@
if (ABSL_PREDICT_FALSE(!statusor.ok())) { \
return statusor.status(); \
} \
lhs = std::move(statusor).ValueOrDie();
lhs = std::move(statusor).value();
#endif // THIRD_PARTY_SAPI_UTIL_STATUS_MACROS_H_

View File

@ -20,10 +20,10 @@
#include "gtest/gtest.h"
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "sandboxed_api/util/status.h"
#include "sandboxed_api/util/status_matchers.h"
#include "sandboxed_api/util/statusor.h"
namespace sapi {
namespace {
@ -52,17 +52,17 @@ TEST(ReturnIfError, ReturnsOnErrorFromLambda) {
TEST(AssignOrReturn, AssignsMultipleVariablesInSequence) {
auto func = []() -> absl::Status {
int value1;
SAPI_ASSIGN_OR_RETURN(value1, StatusOr<int>(1));
SAPI_ASSIGN_OR_RETURN(value1, absl::StatusOr<int>(1));
EXPECT_EQ(1, value1);
int value2;
SAPI_ASSIGN_OR_RETURN(value2, StatusOr<int>(2));
SAPI_ASSIGN_OR_RETURN(value2, absl::StatusOr<int>(2));
EXPECT_EQ(2, value2);
int value3;
SAPI_ASSIGN_OR_RETURN(value3, StatusOr<int>(3));
SAPI_ASSIGN_OR_RETURN(value3, absl::StatusOr<int>(3));
EXPECT_EQ(3, value3);
int value4;
SAPI_ASSIGN_OR_RETURN(value4,
StatusOr<int>(absl::UnknownError("EXPECTED")));
absl::StatusOr<int>(absl::UnknownError("EXPECTED")));
return absl::UnknownError(absl::StrCat("ERROR: assigned value ", value4));
};
@ -72,11 +72,12 @@ TEST(AssignOrReturn, AssignsMultipleVariablesInSequence) {
TEST(AssignOrReturn, AssignsRepeatedlyToSingleVariable) {
auto func = []() -> absl::Status {
int value = 1;
SAPI_ASSIGN_OR_RETURN(value, StatusOr<int>(2));
SAPI_ASSIGN_OR_RETURN(value, absl::StatusOr<int>(2));
EXPECT_EQ(2, value);
SAPI_ASSIGN_OR_RETURN(value, StatusOr<int>(3));
SAPI_ASSIGN_OR_RETURN(value, absl::StatusOr<int>(3));
EXPECT_EQ(3, value);
SAPI_ASSIGN_OR_RETURN(value, StatusOr<int>(absl::UnknownError("EXPECTED")));
SAPI_ASSIGN_OR_RETURN(value,
absl::StatusOr<int>(absl::UnknownError("EXPECTED")));
return absl::UnknownError("ERROR");
};
@ -87,7 +88,7 @@ TEST(AssignOrReturn, MovesUniquePtr) {
auto func = []() -> absl::Status {
std::unique_ptr<int> ptr;
SAPI_ASSIGN_OR_RETURN(
ptr, StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(1)));
ptr, absl::StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(1)));
EXPECT_EQ(*ptr, 1);
return absl::UnknownError("EXPECTED");
};
@ -98,8 +99,8 @@ TEST(AssignOrReturn, MovesUniquePtr) {
TEST(AssignOrReturn, DoesNotAssignUniquePtrOnErrorStatus) {
auto func = []() -> absl::Status {
std::unique_ptr<int> ptr;
SAPI_ASSIGN_OR_RETURN(
ptr, StatusOr<std::unique_ptr<int>>(absl::UnknownError("EXPECTED")));
SAPI_ASSIGN_OR_RETURN(ptr, absl::StatusOr<std::unique_ptr<int>>(
absl::UnknownError("EXPECTED")));
EXPECT_EQ(ptr, nullptr);
return absl::OkStatus();
};
@ -111,10 +112,10 @@ TEST(AssignOrReturn, MovesUniquePtrRepeatedlyToSingleVariable) {
auto func = []() -> absl::Status {
std::unique_ptr<int> ptr;
SAPI_ASSIGN_OR_RETURN(
ptr, StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(1)));
ptr, absl::StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(1)));
EXPECT_EQ(*ptr, 1);
SAPI_ASSIGN_OR_RETURN(
ptr, StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(2)));
ptr, absl::StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(2)));
EXPECT_EQ(*ptr, 2);
return absl::UnknownError("EXPECTED");
};

View File

@ -19,9 +19,9 @@
#include "gmock/gmock.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/types/optional.h"
#include "sandboxed_api/util/status_macros.h"
#include "sandboxed_api/util/statusor.h"
#define SAPI_ASSERT_OK_AND_ASSIGN(lhs, rexpr) \
SAPI_ASSERT_OK_AND_ASSIGN_IMPL( \

View File

@ -12,220 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// This file and it's implementation provide a custom fork of
// util/task/statusor.h. This will become obsolete and will be replaced once
// Abseil releases absl::Status.
#ifndef THIRD_PARTY_SAPI_UTIL_STATUSOR_H_
#define THIRD_PARTY_SAPI_UTIL_STATUSOR_H_
#include <initializer_list>
#include <utility>
#include "absl/base/internal/raw_logging.h"
#include "absl/base/attributes.h"
#include "absl/base/log_severity.h"
#include "absl/status/status.h"
#include "absl/types/variant.h"
#include "sandboxed_api/util/raw_logging.h"
#include "absl/status/statusor.h"
namespace sapi {
template <typename T>
class ABSL_MUST_USE_RESULT StatusOr {
template <typename U>
friend class StatusOr;
public:
using element_type = T;
explicit StatusOr() : variant_(absl::UnknownError("")) {}
StatusOr(const StatusOr&) = default;
StatusOr& operator=(const StatusOr&) = default;
StatusOr(StatusOr&&) = default;
StatusOr& operator=(StatusOr&&) = default;
// Not implemented:
// template <typename U> StatusOr(const StatusOr<U>& other)
// template <typename U> StatusOr(StatusOr<U>&& other)
template <typename U>
StatusOr& operator=(const StatusOr<U>& other) {
if (other.ok()) {
variant_ = other.value();
} else {
variant_ = other.status();
}
return *this;
}
template <typename U>
StatusOr& operator=(StatusOr<U>&& other) {
if (other.ok()) {
variant_ = std::move(other).value();
} else {
variant_ = std::move(other).status();
}
return *this;
}
StatusOr(const T& value) : variant_(value) {}
StatusOr(const absl::Status& status) : variant_(status) { EnsureNotOk(); }
// Not implemented:
// template <typename U = T> StatusOr& operator=(U&& value)
StatusOr(T&& value) : variant_(std::move(value)) {}
StatusOr(absl::Status&& value) : variant_(std::move(value)) {}
StatusOr& operator=(absl::Status&& status) {
variant_ = std::move(status);
EnsureNotOk();
}
template <typename... Args>
explicit StatusOr(absl::in_place_t, Args&&... args)
: StatusOr(T(std::forward<Args>(args)...)) {}
template <typename U, typename... Args>
explicit StatusOr(absl::in_place_t, std::initializer_list<U> ilist,
Args&&... args)
: StatusOr(ilist, U(std::forward<Args>(args)...)) {}
explicit operator bool() const { return ok(); }
ABSL_MUST_USE_RESULT bool ok() const {
return absl::holds_alternative<T>(variant_);
}
const absl::Status& status() const& {
static const auto* ok_status = new absl::Status();
return ok() ? *ok_status : absl::get<absl::Status>(variant_);
}
absl::Status status() && {
return ok() ? absl::OkStatus()
: std::move(absl::get<absl::Status>(variant_));
}
const T& value() const& {
EnsureOk();
return absl::get<T>(variant_);
}
T& value() & {
EnsureOk();
return absl::get<T>(variant_);
}
const T&& value() const&& {
EnsureOk();
return absl::get<T>(std::move(variant_));
}
T&& value() && {
EnsureOk();
return absl::get<T>(std::move(variant_));
}
const T& ValueOrDie() const& {
EnsureOk();
return absl::get<T>(variant_);
}
T& ValueOrDie() & {
EnsureOk();
return absl::get<T>(variant_);
}
T&& ValueOrDie() && {
EnsureOk();
return absl::get<T>(std::move(variant_));
}
const T& operator*() const& {
EnsureOk();
return absl::get<T>(variant_);
}
T& operator*() & {
EnsureOk();
return absl::get<T>(variant_);
}
const T&& operator*() const&& {
EnsureOk();
return absl::get<T>(std::move(variant_));
}
T&& operator*() && {
EnsureOk();
return absl::get<T>(std::move(variant_));
}
const T* operator->() const {
EnsureOk();
return &absl::get<T>(variant_);
}
T* operator->() {
EnsureOk();
return &absl::get<T>(variant_);
}
template <typename U>
T value_or(U&& default_value) const& {
if (ok()) {
return absl::get<T>(variant_);
}
return std::forward<U>(default_value);
}
template <typename U>
T value_or(U&& default_value) && {
if (ok()) {
return absl::get<T>(std::move(variant_));
}
return std::forward<U>(default_value);
}
void IgnoreError() const { /* no-op */
}
template <typename... Args>
T& emplace(Args&&... args) {
return variant_.template emplace<T>(std::forward<Args>(args)...);
}
template <typename U, typename... Args>
T& emplace(std::initializer_list<U> ilist, Args&&... args) {
return variant_.template emplace<T>(ilist, std::forward<Args>(args)...);
}
private:
void EnsureOk() const {
if (!ok()) {
// GoogleTest needs this exact error message for death tests to work.
SAPI_RAW_LOG(FATAL,
"Attempting to fetch value instead of handling error %s",
status().message());
}
}
void EnsureNotOk() const {
if (ok()) {
SAPI_RAW_LOG(
FATAL,
"An OK status is not a valid constructor argument to StatusOr<T>");
}
}
absl::variant<absl::Status, T> variant_;
};
using StatusOr ABSL_DEPRECATED("Use absl::StatusOr instead") =
absl::StatusOr<T>;
} // namespace sapi

View File

@ -1,407 +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.
// This file is a custom fork of the version in Asylo. This will become obsolete
// and will be replaced once Abseil releases absl::Status.
#include "sandboxed_api/util/statusor.h"
#include <memory>
#include <string>
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "sandboxed_api/util/status_matchers.h"
using ::testing::Eq;
using ::testing::IsFalse;
using ::testing::Not;
using ::testing::Pointee;
namespace sapi {
namespace {
constexpr auto kErrorCode = absl::StatusCode::kInvalidArgument;
constexpr char kErrorMessage[] = "Invalid argument";
const int kIntElement = 47;
constexpr char kStringElement[] = "47 is 42, corrected for inflation";
// A data type without a default constructor.
struct Foo {
int bar;
std::string baz;
explicit Foo(int value) : bar(value), baz(kStringElement) {}
};
// A data type with dynamically-allocated data.
struct HeapAllocatedObject {
int* value;
HeapAllocatedObject() {
value = new int;
*value = kIntElement;
}
HeapAllocatedObject(const HeapAllocatedObject& other) { *this = other; }
HeapAllocatedObject& operator=(const HeapAllocatedObject& other) {
value = new int;
*value = *other.value;
return *this;
}
HeapAllocatedObject(HeapAllocatedObject&& other) { *this = std::move(other); }
HeapAllocatedObject& operator=(HeapAllocatedObject&& other) {
value = other.value;
other.value = nullptr;
return *this;
}
~HeapAllocatedObject() { delete value; }
};
// Constructs a Foo.
struct FooCtor {
using value_type = Foo;
Foo operator()() { return Foo(kIntElement); }
};
// Constructs a HeapAllocatedObject.
struct HeapAllocatedObjectCtor {
using value_type = HeapAllocatedObject;
HeapAllocatedObject operator()() { return HeapAllocatedObject(); }
};
// Constructs an integer.
struct IntCtor {
using value_type = int;
int operator()() { return kIntElement; }
};
// Constructs a string.
struct StringCtor {
using value_type = std::string;
std::string operator()() { return std::string(kStringElement); }
};
// Constructs a vector of strings.
struct StringVectorCtor {
using value_type = std::vector<std::string>;
std::vector<std::string> operator()() {
return {kStringElement, kErrorMessage};
}
};
bool operator==(const Foo& lhs, const Foo& rhs) {
return (lhs.bar == rhs.bar) && (lhs.baz == rhs.baz);
}
bool operator==(const HeapAllocatedObject& lhs,
const HeapAllocatedObject& rhs) {
return *lhs.value == *rhs.value;
}
// Returns an rvalue reference to the StatusOr<T> object pointed to by
// |statusor|.
template <typename T>
StatusOr<T>&& MoveStatusOr(StatusOr<T>* statusor) {
return std::move(*statusor);
}
// A test fixture is required for typed tests.
template <typename T>
class StatusOrTest : public ::testing::Test {};
using TestTypes = ::testing::Types<IntCtor, FooCtor, StringCtor,
StringVectorCtor, HeapAllocatedObjectCtor>;
TYPED_TEST_SUITE(StatusOrTest, TestTypes);
// Verify that the default constructor for StatusOr constructs an object with a
// non-ok status.
TYPED_TEST(StatusOrTest, ConstructorDefault) {
StatusOr<typename TypeParam::value_type> statusor;
EXPECT_THAT(statusor.ok(), IsFalse());
EXPECT_THAT(statusor.status().code(), Eq(absl::StatusCode::kUnknown));
}
// Verify that StatusOr can be constructed from a Status object.
TYPED_TEST(StatusOrTest, ConstructorStatus) {
StatusOr<typename TypeParam::value_type> statusor(
absl::Status(kErrorCode, kErrorMessage));
EXPECT_THAT(statusor.ok(), IsFalse());
EXPECT_THAT(statusor.status().ok(), IsFalse());
EXPECT_THAT(statusor.status(), Eq(absl::Status(kErrorCode, kErrorMessage)));
}
// Verify that StatusOr can be constructed from an object of its element type.
TYPED_TEST(StatusOrTest, ConstructorElementConstReference) {
auto value = TypeParam()();
StatusOr<typename TypeParam::value_type> statusor{value};
ASSERT_THAT(statusor, IsOk());
ASSERT_THAT(statusor.status(), IsOk());
EXPECT_THAT(statusor.ValueOrDie(), Eq(value));
}
// Verify that StatusOr can be constructed from an rvalue reference of an object
// of its element type.
TYPED_TEST(StatusOrTest, ConstructorElementRValue) {
auto value = TypeParam()();
auto value_copy(value);
StatusOr<typename TypeParam::value_type> statusor(std::move(value));
ASSERT_THAT(statusor, IsOk());
ASSERT_THAT(statusor.status(), IsOk());
// Compare to a copy of the original value, since the original was moved.
EXPECT_THAT(statusor.ValueOrDie(), Eq(value_copy));
}
// Verify that StatusOr can be copy-constructed from a StatusOr with a non-ok
// status.
TYPED_TEST(StatusOrTest, CopyConstructorNonOkStatus) {
StatusOr<typename TypeParam::value_type> statusor1 =
absl::Status(kErrorCode, kErrorMessage);
StatusOr<typename TypeParam::value_type> statusor2(statusor1);
EXPECT_THAT(statusor1.ok(), Eq(statusor2.ok()));
EXPECT_THAT(statusor1.status(), Eq(statusor2.status()));
}
// Verify that StatusOr can be copy-constructed from a StatusOr with an ok
// status.
TYPED_TEST(StatusOrTest, CopyConstructorOkStatus) {
StatusOr<typename TypeParam::value_type> statusor1{TypeParam()()};
StatusOr<typename TypeParam::value_type> statusor2{statusor1};
EXPECT_THAT(statusor1.ok(), Eq(statusor2.ok()));
ASSERT_THAT(statusor2, IsOk());
EXPECT_THAT(statusor1.ValueOrDie(), Eq(statusor2.ValueOrDie()));
}
// Verify that copy-assignment of a StatusOr with a non-ok is working as
// expected.
TYPED_TEST(StatusOrTest, CopyAssignmentNonOkStatus) {
StatusOr<typename TypeParam::value_type> statusor1{
absl::Status(kErrorCode, kErrorMessage)};
StatusOr<typename TypeParam::value_type> statusor2{TypeParam()()};
// Invoke the copy-assignment operator.
statusor2 = statusor1;
EXPECT_THAT(statusor1.ok(), Eq(statusor2.ok()));
EXPECT_THAT(statusor1.status(), Eq(statusor2.status()));
}
// Verify that copy-assignment of a StatusOr with an ok status is working as
// expected.
TYPED_TEST(StatusOrTest, CopyAssignmentOkStatus) {
StatusOr<typename TypeParam::value_type> statusor1{TypeParam()()};
StatusOr<typename TypeParam::value_type> statusor2{
absl::Status(kErrorCode, kErrorMessage)};
// Invoke the copy-assignment operator.
statusor2 = statusor1;
EXPECT_THAT(statusor1.ok(), Eq(statusor2.ok()));
ASSERT_THAT(statusor2, IsOk());
EXPECT_THAT(statusor1.ValueOrDie(), Eq(statusor2.ValueOrDie()));
}
// Verify that StatusOr can be move-constructed from a StatusOr with a non-ok
// status.
TYPED_TEST(StatusOrTest, MoveConstructorNonOkStatus) {
absl::Status status(kErrorCode, kErrorMessage);
StatusOr<typename TypeParam::value_type> statusor1(status);
StatusOr<typename TypeParam::value_type> statusor2(std::move(statusor1));
// Verify that the status of the donor object was updated.
EXPECT_THAT(statusor1.ok(), IsFalse()); // NOLINT
EXPECT_THAT(statusor1.status(), StatusIs(absl::StatusCode::kInternal));
// Verify that the destination object contains the status previously held by
// the donor.
EXPECT_THAT(statusor2.ok(), IsFalse());
EXPECT_THAT(statusor2.status(), Eq(status));
}
// Verify that StatusOr can be move-constructed from a StatusOr with an ok
// status.
TYPED_TEST(StatusOrTest, MoveConstructorOkStatus) {
auto value = TypeParam()();
StatusOr<typename TypeParam::value_type> statusor1(value);
StatusOr<typename TypeParam::value_type> statusor2(std::move(statusor1));
// The destination object should possess the value previously held by the
// donor.
ASSERT_THAT(statusor2, IsOk());
EXPECT_THAT(statusor2.ValueOrDie(), Eq(value));
}
// Verify that move-assignment from a StatusOr with a non-ok status is working
// as expected.
TYPED_TEST(StatusOrTest, MoveAssignmentOperatorNonOkStatus) {
absl::Status status(kErrorCode, kErrorMessage);
StatusOr<typename TypeParam::value_type> statusor1(status);
StatusOr<typename TypeParam::value_type> statusor2{TypeParam()()};
// Invoke the move-assignment operator.
statusor2 = std::move(statusor1);
// Verify that the status of the donor object was updated.
EXPECT_THAT(statusor1.ok(), IsFalse()); // NOLINT
EXPECT_THAT(statusor1.status(), StatusIs(absl::StatusCode::kInternal));
// Verify that the destination object contains the status previously held by
// the donor.
EXPECT_THAT(statusor2.ok(), IsFalse());
EXPECT_THAT(statusor2.status(), Eq(status));
}
// Verify that move-assignment from a StatusOr with an ok status is working as
// expected.
TYPED_TEST(StatusOrTest, MoveAssignmentOperatorOkStatus) {
auto value = TypeParam()();
StatusOr<typename TypeParam::value_type> statusor1(value);
StatusOr<typename TypeParam::value_type> statusor2(
absl::Status(kErrorCode, kErrorMessage));
// Invoke the move-assignment operator.
statusor2 = std::move(statusor1);
// The destination object should possess the value previously held by the
// donor.
ASSERT_THAT(statusor2, IsOk());
EXPECT_THAT(statusor2.ValueOrDie(), Eq(value));
}
// Verify that the sapi::IsOk() gMock matcher works with StatusOr<T>.
TYPED_TEST(StatusOrTest, IsOkMatcher) {
auto value = TypeParam()();
StatusOr<typename TypeParam::value_type> statusor(value);
EXPECT_THAT(statusor, IsOk());
statusor = StatusOr<typename TypeParam::value_type>(
absl::Status(kErrorCode, kErrorMessage));
EXPECT_THAT(statusor, Not(IsOk()));
}
// Tests for move-only types. These tests use std::unique_ptr<> as the
// test type, since it is valuable to support this type in the Asylo infra.
// These tests are not part of the typed test suite for the following reasons:
// * std::unique_ptr<> cannot be used as a type in tests that expect
// the test type to support copy operations.
// * std::unique_ptr<> provides an equality operator that checks equality of
// the underlying ptr. Consequently, it is difficult to generalize existing
// tests that verify ValueOrDie() functionality using equality comparisons.
// Verify that a StatusOr object can be constructed from a move-only type.
TEST(StatusOrTest, InitializationMoveOnlyType) {
auto* str = new std::string(kStringElement);
std::unique_ptr<std::string> value(str);
StatusOr<std::unique_ptr<std::string>> statusor(std::move(value));
ASSERT_THAT(statusor, IsOk());
EXPECT_THAT(statusor.ValueOrDie().get(), Eq(str));
}
// Verify that a StatusOr object can be move-constructed from a move-only type.
TEST(StatusOrTest, MoveConstructorMoveOnlyType) {
auto* str = new std::string(kStringElement);
std::unique_ptr<std::string> value(str);
StatusOr<std::unique_ptr<std::string>> statusor1(std::move(value));
StatusOr<std::unique_ptr<std::string>> statusor2(std::move(statusor1));
// The destination object should possess the value previously held by the
// donor.
ASSERT_THAT(statusor2, IsOk());
EXPECT_THAT(statusor2.ValueOrDie().get(), Eq(str));
}
// Verify that a StatusOr object can be move-assigned to from a StatusOr object
// containing a move-only type.
TEST(StatusOrTest, MoveAssignmentMoveOnlyType) {
auto* str = new std::string(kStringElement);
std::unique_ptr<std::string> value(str);
StatusOr<std::unique_ptr<std::string>> statusor1(std::move(value));
StatusOr<std::unique_ptr<std::string>> statusor2(
absl::Status(kErrorCode, kErrorMessage));
// Invoke the move-assignment operator.
statusor2 = std::move(statusor1);
// The destination object should possess the value previously held by the
// donor.
ASSERT_THAT(statusor2, IsOk());
EXPECT_THAT(statusor2.ValueOrDie().get(), Eq(str));
}
// Verify that a value can be moved out of a StatusOr object via ValueOrDie().
TEST(StatusOrTest, ValueOrDieMovedValue) {
auto* str = new std::string(kStringElement);
std::unique_ptr<std::string> value(str);
StatusOr<std::unique_ptr<std::string>> statusor(std::move(value));
std::unique_ptr<std::string> moved_value = std::move(statusor).ValueOrDie();
EXPECT_THAT(moved_value.get(), Eq(str));
EXPECT_THAT(*moved_value, Eq(kStringElement));
}
TEST(StatusOrTest, MapToStatusOrUniquePtr) {
// A reduced version of a problematic type found in the wild. All of the
// operations below should compile.
using MapType = std::map<std::string, StatusOr<std::unique_ptr<int>>>;
MapType a;
// Move-construction
MapType b(std::move(a));
// Move-assignment
a = std::move(b);
}
TEST(StatusOrTest, ValueOrOk) {
const StatusOr<int> status_or = 0;
EXPECT_EQ(status_or.value_or(-1), 0);
}
TEST(StatusOrTest, ValueOrDefault) {
const StatusOr<int> status_or = absl::CancelledError();
EXPECT_EQ(status_or.value_or(-1), -1);
}
TEST(StatusOrTest, MoveOnlyValueOrOk) {
EXPECT_THAT(StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(0))
.value_or(absl::make_unique<int>(-1)),
Pointee(0));
}
TEST(StatusOr, MoveOnlyValueOrDefault) {
EXPECT_THAT(StatusOr<std::unique_ptr<int>>(absl::CancelledError())
.value_or(absl::make_unique<int>(-1)),
Pointee(-1));
}
} // namespace
} // namespace sapi

View File

@ -41,7 +41,7 @@ class Proto : public Pointable, public Var {
explicit Proto(const T& proto)
: wrapped_var_(SerializeProto(proto).value()) {}
static sapi::StatusOr<Proto<T>> FromMessage(const T& proto) {
static absl::StatusOr<Proto<T>> FromMessage(const T& proto) {
SAPI_ASSIGN_OR_RETURN(std::vector<uint8_t> len_val, SerializeProto(proto));
return Proto(len_val);
}
@ -59,7 +59,7 @@ class Proto : public Pointable, public Var {
void* GetLocal() const override { return wrapped_var_.GetLocal(); }
// Returns a copy of the stored protobuf object.
sapi::StatusOr<T> GetMessage() const {
absl::StatusOr<T> GetMessage() const {
return DeserializeProto<T>(
reinterpret_cast<const char*>(wrapped_var_.GetData()),
wrapped_var_.GetDataSize());