Merge branch 'master' into jsonnet
commit
73522f4844
|
@ -1,4 +1,6 @@
|
|||
---
|
||||
Language: Cpp
|
||||
BasedOnStyle: Google
|
||||
Language: Cpp
|
||||
BasedOnStyle: Google
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Left
|
||||
...
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
[submodule "oss-internship-2020/jsonnet/jsonnet"]
|
||||
path = oss-internship-2020/jsonnet/jsonnet
|
||||
url = https://github.com/google/jsonnet.git
|
||||
[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/
|
||||
|
|
|
@ -132,7 +132,6 @@ function(add_sapi_library)
|
|||
set(_sapi_embed_dir "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
set(_sapi_embed_name "${_sapi_NAME}")
|
||||
endif()
|
||||
# TODO(cblichmann): Implement sapi_isystem
|
||||
if(SAPI_ENABLE_GENERATOR)
|
||||
add_custom_command(
|
||||
OUTPUT "${_sapi_gen_header}"
|
||||
|
@ -149,9 +148,14 @@ function(add_sapi_library)
|
|||
VERBATIM
|
||||
)
|
||||
else()
|
||||
set(_sapi_isystem "${_sapi_NAME}.isystem")
|
||||
list_join(_sapi_full_inputs "," _sapi_full_inputs)
|
||||
add_custom_command(
|
||||
OUTPUT "${_sapi_gen_header}"
|
||||
OUTPUT "${_sapi_gen_header}" "${_sapi_isystem}"
|
||||
COMMAND sh -c
|
||||
"${CMAKE_CXX_COMPILER} -E -x c++ -v /dev/null 2>&1 | \
|
||||
awk '/> search starts here:/{f=1;next}/^End of search/{f=0}f{print $1}' \
|
||||
> \"${_sapi_isystem}\""
|
||||
COMMAND "${SAPI_PYTHON3_EXECUTABLE}" -B
|
||||
"${SAPI_SOURCE_DIR}/sandboxed_api/tools/generator2/sapi_generator.py"
|
||||
"--sapi_name=${_sapi_LIBRARY_NAME}"
|
||||
|
@ -160,8 +164,10 @@ function(add_sapi_library)
|
|||
"--sapi_embed_name=${_sapi_embed_name}"
|
||||
"--sapi_functions=${_sapi_funcs}"
|
||||
"--sapi_ns=${_sapi_NAMESPACE}"
|
||||
"--sapi_isystem=${_sapi_isystem}"
|
||||
"--sapi_in=${_sapi_full_inputs}"
|
||||
COMMENT "Generating interface"
|
||||
VERBATIM
|
||||
)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -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 ""
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
# Build in C++17 mode without a custom CROSSTOOL
|
||||
build --cxxopt=-std=c++17
|
|
@ -0,0 +1,83 @@
|
|||
# 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.
|
||||
|
||||
load(
|
||||
"@com_google_sandboxed_api//sandboxed_api/bazel:sapi.bzl",
|
||||
"sapi_library",
|
||||
)
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
cc_library(
|
||||
name = "guetzli_wrapper",
|
||||
srcs = ["guetzli_entry_points.cc"],
|
||||
hdrs = ["guetzli_entry_points.h"],
|
||||
deps = [
|
||||
"@com_google_sandboxed_api//sandboxed_api:lenval_core",
|
||||
"@com_google_sandboxed_api//sandboxed_api:vars",
|
||||
"@guetzli//:guetzli_lib",
|
||||
"@png_archive//:png",
|
||||
],
|
||||
)
|
||||
|
||||
sapi_library(
|
||||
name = "guetzli_sapi",
|
||||
srcs = ["guetzli_transaction.cc"],
|
||||
hdrs = [
|
||||
"guetzli_sandbox.h",
|
||||
"guetzli_transaction.h",
|
||||
],
|
||||
functions = [
|
||||
"ProcessJpeg",
|
||||
"ProcessRgb",
|
||||
"WriteDataToFd",
|
||||
],
|
||||
input_files = ["guetzli_entry_points.h"],
|
||||
lib = ":guetzli_wrapper",
|
||||
lib_name = "Guetzli",
|
||||
namespace = "guetzli::sandbox",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "guetzli_sandboxed",
|
||||
srcs = ["guetzli_sandboxed.cc"],
|
||||
deps = [
|
||||
":guetzli_sapi",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "transaction_tests",
|
||||
size = "large",
|
||||
srcs = ["guetzli_transaction_test.cc"],
|
||||
data = glob(["testdata/*"]),
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//:guetzli_sapi",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "sapi_lib_tests",
|
||||
size = "large",
|
||||
srcs = ["guetzli_sapi_test.cc"],
|
||||
data = glob(["testdata/*"]),
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//:guetzli_sapi",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
|
@ -0,0 +1,32 @@
|
|||
# Guetzli Sandbox
|
||||
This is an example implementation of a sandbox for the [Guetzli](https://github.com/google/guetzli) library using [Sandboxed API](https://github.com/google/sandboxed-api).
|
||||
Please read Guetzli's [documentation](https://github.com/google/guetzli#introduction) to learn more about it.
|
||||
|
||||
## Implementation details
|
||||
Because Guetzli provides a C++ API and SAPI requires functions to be `extern "C"`, a wrapper library has been written for the compatibility. SAPI provides a Transaction class, which is a convenient way to create a wrapper for your sandboxed API that handles internal errors. The original Guetzli has a command-line utility to encode images, so a fully compatible utility that uses sandboxed Guetzli is provided.
|
||||
|
||||
The wrapper around Guetzli uses file descriptors to pass data to the sandbox. This approach restricts the sandbox from using the `open()` syscall and also helps to prevent making copies of data, because you need to synchronize it between processes.
|
||||
|
||||
## Build Guetzli Sandboxed
|
||||
Right now Sandboxed API support only Linux systems, so you need one to build it. Guetzli sandboxed uses [Bazel](https://bazel.build/) as a build system so you need to [install it](https://docs.bazel.build/versions/3.4.0/install.html) before building.
|
||||
|
||||
To build Guetzli sandboxed encoding utility you can use this command:
|
||||
`bazel build //:guetzli_sandboxed`
|
||||
|
||||
Then you can use it in this way:
|
||||
```
|
||||
guetzli_sandboxed [--quality Q] [--verbose] original.png output.jpg
|
||||
guetzli_sandboxed [--quality Q] [--verbose] original.jpg output.jpg
|
||||
```
|
||||
Refer to Guetzli's [documentation](https://github.com/google/guetzli#using) to read more about usage.
|
||||
|
||||
## Examples
|
||||
There are two different sets of unit tests which demonstrate how to use different parts of Guetzli sandboxed:
|
||||
* `tests/guetzli_sapi_test.cc` - example usage of Guetzli sandboxed API.
|
||||
* `tests/guetzli_transaction_test.cc` - example usage of Guetzli transaction.
|
||||
|
||||
To run tests use the following command:
|
||||
`bazel test ...`
|
||||
|
||||
Also, there is an example of custom security policy for your sandbox in
|
||||
`guetzli_sandbox.h`
|
|
@ -0,0 +1,100 @@
|
|||
# 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.
|
||||
|
||||
workspace(name = "guetzli_sandboxed")
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
|
||||
|
||||
# Include the Sandboxed API dependency if it does not already exist in this
|
||||
# project. This ensures that this workspace plays well with other external
|
||||
# dependencies that might use Sandboxed API.
|
||||
maybe(
|
||||
git_repository,
|
||||
name = "com_google_sandboxed_api",
|
||||
# This example depends on the latest master. In an embedding project, it
|
||||
# is advisable to pin Sandboxed API to a specific revision instead.
|
||||
# commit = "ba47adc21d4c9bc316f3c7c32b0faaef952c111e", # 2020-05-15
|
||||
branch = "master",
|
||||
remote = "https://github.com/google/sandboxed-api.git",
|
||||
)
|
||||
|
||||
# From here on, Sandboxed API files are available. The statements below setup
|
||||
# transitive dependencies such as Abseil. Like above, those will only be
|
||||
# included if they don't already exist in the project.
|
||||
load(
|
||||
"@com_google_sandboxed_api//sandboxed_api/bazel:sapi_deps.bzl",
|
||||
"sapi_deps",
|
||||
)
|
||||
|
||||
sapi_deps()
|
||||
|
||||
# Need to separately setup Protobuf dependencies in order for the build rules
|
||||
# to work.
|
||||
load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
|
||||
|
||||
protobuf_deps()
|
||||
|
||||
http_archive(
|
||||
name = "guetzli",
|
||||
build_file = "guetzli.BUILD",
|
||||
sha256 = "39632357e49db83d9560bf0de560ad833352f36d23b109b0e995b01a37bddb57",
|
||||
strip_prefix = "guetzli-master",
|
||||
url = "https://github.com/google/guetzli/archive/master.zip",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "butteraugli",
|
||||
build_file = "butteraugli.BUILD",
|
||||
sha256 = "39632357e49db83d9560bf0de560ad833352f36d23b109b0e995b01a37bddb57",
|
||||
strip_prefix = "guetzli-master/third_party/butteraugli",
|
||||
url = "https://github.com/google/guetzli/archive/master.zip",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "png_archive",
|
||||
build_file = "png.BUILD",
|
||||
sha256 = "a941dc09ca00148fe7aaf4ecdd6a67579c293678ed1e1cf633b5ffc02f4f8cf7",
|
||||
strip_prefix = "libpng-1.2.57",
|
||||
url = "http://github.com/glennrp/libpng/archive/v1.2.57.zip",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "jpeg_archive",
|
||||
build_file = "jpeg.BUILD",
|
||||
sha256 = "240fd398da741669bf3c90366f58452ea59041cacc741a489b99f2f6a0bad052",
|
||||
strip_prefix = "jpeg-9b",
|
||||
url = "http://www.ijg.org/files/jpegsrc.v9b.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "net_zlib",
|
||||
build_file = "zlib.BUILD",
|
||||
sha256 = "c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1", # 2020-04-23
|
||||
strip_prefix = "zlib-1.2.11",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/zlib.net/zlib-1.2.11.tar.gz",
|
||||
"https://www.zlib.net/zlib-1.2.11.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
# GoogleTest/GoogleMock
|
||||
maybe(
|
||||
http_archive,
|
||||
name = "com_google_googletest",
|
||||
sha256 = "a6ab7c7d6fd4dd727f6012b5d85d71a73d3aa1274f529ecd4ad84eb9ec4ff767", # 2020-04-16
|
||||
strip_prefix = "googletest-dcc92d0ab6c4ce022162a23566d44f673251eee4",
|
||||
urls = ["https://github.com/google/googletest/archive/dcc92d0ab6c4ce022162a23566d44f673251eee4.zip"],
|
||||
)
|
|
@ -0,0 +1,28 @@
|
|||
# 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.
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
cc_library(
|
||||
name = "butteraugli",
|
||||
srcs = [
|
||||
"butteraugli/butteraugli.cc",
|
||||
"butteraugli/butteraugli.h",
|
||||
],
|
||||
hdrs = [
|
||||
"butteraugli/butteraugli.h",
|
||||
],
|
||||
copts = ["-Wno-sign-compare"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
|
@ -0,0 +1,32 @@
|
|||
# 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.
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
cc_library(
|
||||
name = "guetzli_lib",
|
||||
srcs = glob(
|
||||
[
|
||||
"guetzli/*.h",
|
||||
"guetzli/*.cc",
|
||||
"guetzli/*.inc",
|
||||
],
|
||||
exclude = ["guetzli/guetzli.cc"],
|
||||
),
|
||||
copts = [ "-Wno-sign-compare" ],
|
||||
visibility= [ "//visibility:public" ],
|
||||
deps = [
|
||||
"@butteraugli//:butteraugli",
|
||||
],
|
||||
)
|
|
@ -0,0 +1,89 @@
|
|||
# Description:
|
||||
# The Independent JPEG Group's JPEG runtime library.
|
||||
|
||||
licenses(["notice"]) # custom notice-style license, see LICENSE
|
||||
|
||||
cc_library(
|
||||
name = "jpeg",
|
||||
srcs = [
|
||||
"cderror.h",
|
||||
"cdjpeg.h",
|
||||
"jaricom.c",
|
||||
"jcapimin.c",
|
||||
"jcapistd.c",
|
||||
"jcarith.c",
|
||||
"jccoefct.c",
|
||||
"jccolor.c",
|
||||
"jcdctmgr.c",
|
||||
"jchuff.c",
|
||||
"jcinit.c",
|
||||
"jcmainct.c",
|
||||
"jcmarker.c",
|
||||
"jcmaster.c",
|
||||
"jcomapi.c",
|
||||
"jconfig.h",
|
||||
"jcparam.c",
|
||||
"jcprepct.c",
|
||||
"jcsample.c",
|
||||
"jctrans.c",
|
||||
"jdapimin.c",
|
||||
"jdapistd.c",
|
||||
"jdarith.c",
|
||||
"jdatadst.c",
|
||||
"jdatasrc.c",
|
||||
"jdcoefct.c",
|
||||
"jdcolor.c",
|
||||
"jdct.h",
|
||||
"jddctmgr.c",
|
||||
"jdhuff.c",
|
||||
"jdinput.c",
|
||||
"jdmainct.c",
|
||||
"jdmarker.c",
|
||||
"jdmaster.c",
|
||||
"jdmerge.c",
|
||||
"jdpostct.c",
|
||||
"jdsample.c",
|
||||
"jdtrans.c",
|
||||
"jerror.c",
|
||||
"jfdctflt.c",
|
||||
"jfdctfst.c",
|
||||
"jfdctint.c",
|
||||
"jidctflt.c",
|
||||
"jidctfst.c",
|
||||
"jidctint.c",
|
||||
"jinclude.h",
|
||||
"jmemmgr.c",
|
||||
"jmemnobs.c",
|
||||
"jmemsys.h",
|
||||
"jmorecfg.h",
|
||||
"jquant1.c",
|
||||
"jquant2.c",
|
||||
"jutils.c",
|
||||
"jversion.h",
|
||||
"transupp.h",
|
||||
],
|
||||
hdrs = [
|
||||
"jerror.h",
|
||||
"jpegint.h",
|
||||
"jpeglib.h",
|
||||
],
|
||||
includes = ["."],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
genrule(
|
||||
name = "configure",
|
||||
outs = ["jconfig.h"],
|
||||
cmd = "cat <<EOF >$@\n" +
|
||||
"#define HAVE_PROTOTYPES 1\n" +
|
||||
"#define HAVE_UNSIGNED_CHAR 1\n" +
|
||||
"#define HAVE_UNSIGNED_SHORT 1\n" +
|
||||
"#define HAVE_STDDEF_H 1\n" +
|
||||
"#define HAVE_STDLIB_H 1\n" +
|
||||
"#ifdef WIN32\n" +
|
||||
"#define INLINE __inline\n" +
|
||||
"#else\n" +
|
||||
"#define INLINE __inline__\n" +
|
||||
"#endif\n" +
|
||||
"EOF\n",
|
||||
)
|
|
@ -0,0 +1,33 @@
|
|||
# Description:
|
||||
# libpng is the official PNG reference library.
|
||||
|
||||
licenses(["notice"]) # BSD/MIT-like license
|
||||
|
||||
cc_library(
|
||||
name = "png",
|
||||
srcs = [
|
||||
"png.c",
|
||||
"pngerror.c",
|
||||
"pngget.c",
|
||||
"pngmem.c",
|
||||
"pngpread.c",
|
||||
"pngread.c",
|
||||
"pngrio.c",
|
||||
"pngrtran.c",
|
||||
"pngrutil.c",
|
||||
"pngset.c",
|
||||
"pngtrans.c",
|
||||
"pngwio.c",
|
||||
"pngwrite.c",
|
||||
"pngwtran.c",
|
||||
"pngwutil.c",
|
||||
],
|
||||
hdrs = [
|
||||
"png.h",
|
||||
"pngconf.h",
|
||||
],
|
||||
includes = ["."],
|
||||
linkopts = ["-lm"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["@net_zlib//:zlib"],
|
||||
)
|
|
@ -0,0 +1,56 @@
|
|||
# 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.
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
cc_library(
|
||||
name = "zlib",
|
||||
srcs = [
|
||||
"adler32.c",
|
||||
"compress.c",
|
||||
"crc32.c",
|
||||
"deflate.c",
|
||||
"gzclose.c",
|
||||
"gzlib.c",
|
||||
"gzread.c",
|
||||
"gzwrite.c",
|
||||
"infback.c",
|
||||
"inffast.c",
|
||||
"inflate.c",
|
||||
"inflate.h",
|
||||
"inftrees.c",
|
||||
"trees.c",
|
||||
"trees.h",
|
||||
"uncompr.c",
|
||||
"zutil.c",
|
||||
],
|
||||
hdrs = ["zlib.h"],
|
||||
# Use -Dverbose=-1 to turn off zlib's trace logging. (#3280)
|
||||
copts = [
|
||||
"-w",
|
||||
"-Dverbose=-1",
|
||||
],
|
||||
includes = ["."],
|
||||
textual_hdrs = [
|
||||
"crc32.h",
|
||||
"deflate.h",
|
||||
"gzguts.h",
|
||||
"inffast.h",
|
||||
"inffixed.h",
|
||||
"inftrees.h",
|
||||
"zconf.h",
|
||||
"zutil.h",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
|
@ -0,0 +1,293 @@
|
|||
// 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 "guetzli_entry_points.h" // NOLINT(build/include)
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "guetzli/jpeg_data_reader.h"
|
||||
#include "guetzli/quality.h"
|
||||
#include "png.h" // NOLINT(build/include)
|
||||
#include "sandboxed_api/sandbox2/util/fileops.h"
|
||||
#include "sandboxed_api/util/statusor.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int kBytesPerPixel = 350;
|
||||
constexpr int kLowestMemusageMB = 100;
|
||||
|
||||
struct GuetzliInitData {
|
||||
std::string in_data;
|
||||
guetzli::Params params;
|
||||
guetzli::ProcessStats stats;
|
||||
};
|
||||
|
||||
struct ImageData {
|
||||
int xsize;
|
||||
int ysize;
|
||||
std::vector<uint8_t> rgb;
|
||||
};
|
||||
|
||||
sapi::LenValStruct CreateLenValFromData(const void* data, size_t size) {
|
||||
void* new_data = malloc(size);
|
||||
memcpy(new_data, data, size);
|
||||
return {size, new_data};
|
||||
}
|
||||
|
||||
sapi::StatusOr<std::string> ReadFromFd(int fd) {
|
||||
struct stat file_data;
|
||||
int status = fstat(fd, &file_data);
|
||||
|
||||
if (status < 0) {
|
||||
return absl::FailedPreconditionError("Error reading input from fd");
|
||||
}
|
||||
|
||||
std::string result;
|
||||
result.resize(file_data.st_size);
|
||||
status = read(fd, result.data(), result.size());
|
||||
|
||||
if (status < 0) {
|
||||
return absl::FailedPreconditionError("Error reading input from fd");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
sapi::StatusOr<GuetzliInitData> PrepareDataForProcessing(
|
||||
const ProcessingParams& processing_params) {
|
||||
sapi::StatusOr<std::string> input = ReadFromFd(processing_params.remote_fd);
|
||||
|
||||
if (!input.ok()) {
|
||||
return input.status();
|
||||
}
|
||||
|
||||
guetzli::Params guetzli_params;
|
||||
guetzli_params.butteraugli_target = static_cast<float>(
|
||||
guetzli::ButteraugliScoreForQuality(processing_params.quality));
|
||||
|
||||
guetzli::ProcessStats stats;
|
||||
|
||||
if (processing_params.verbose) {
|
||||
stats.debug_output_file = stderr;
|
||||
}
|
||||
|
||||
return GuetzliInitData{std::move(input.value()), guetzli_params, stats};
|
||||
}
|
||||
|
||||
inline uint8_t BlendOnBlack(const uint8_t val, const uint8_t alpha) {
|
||||
return (static_cast<int>(val) * static_cast<int>(alpha) + 128) / 255;
|
||||
}
|
||||
|
||||
// Modified version of ReadPNG from original guetzli.cc
|
||||
sapi::StatusOr<ImageData> ReadPNG(const std::string& data) {
|
||||
std::vector<uint8_t> rgb;
|
||||
int xsize, ysize;
|
||||
png_structp png_ptr =
|
||||
png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!png_ptr) {
|
||||
return absl::FailedPreconditionError(
|
||||
"Error reading PNG data from input file");
|
||||
}
|
||||
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (!info_ptr) {
|
||||
png_destroy_read_struct(&png_ptr, nullptr, nullptr);
|
||||
return absl::FailedPreconditionError(
|
||||
"Error reading PNG data from input file");
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr)) != 0) {
|
||||
// Ok we are here because of the setjmp.
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
|
||||
return absl::FailedPreconditionError(
|
||||
"Error reading PNG data from input file");
|
||||
}
|
||||
|
||||
std::istringstream memstream(data, std::ios::in | std::ios::binary);
|
||||
png_set_read_fn(
|
||||
png_ptr, static_cast<void*>(&memstream),
|
||||
[](png_structp png_ptr, png_bytep outBytes, png_size_t byteCountToRead) {
|
||||
std::istringstream& memstream =
|
||||
*static_cast<std::istringstream*>(png_get_io_ptr(png_ptr));
|
||||
|
||||
memstream.read(reinterpret_cast<char*>(outBytes), byteCountToRead);
|
||||
|
||||
if (memstream.eof()) png_error(png_ptr, "unexpected end of data");
|
||||
if (memstream.fail()) png_error(png_ptr, "read from memory error");
|
||||
});
|
||||
|
||||
// The png_transforms flags are as follows:
|
||||
// packing == convert 1,2,4 bit images,
|
||||
// strip == 16 -> 8 bits / channel,
|
||||
// shift == use sBIT dynamics, and
|
||||
// expand == palettes -> rgb, grayscale -> 8 bit images, tRNS -> alpha.
|
||||
const unsigned int png_transforms =
|
||||
PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_STRIP_16;
|
||||
|
||||
png_read_png(png_ptr, info_ptr, png_transforms, nullptr);
|
||||
|
||||
png_bytep* row_pointers = png_get_rows(png_ptr, info_ptr);
|
||||
|
||||
xsize = png_get_image_width(png_ptr, info_ptr);
|
||||
ysize = png_get_image_height(png_ptr, info_ptr);
|
||||
rgb.resize(3 * xsize * ysize);
|
||||
|
||||
const int components = png_get_channels(png_ptr, info_ptr);
|
||||
switch (components) {
|
||||
case 1: {
|
||||
// GRAYSCALE
|
||||
for (int y = 0; y < ysize; ++y) {
|
||||
const uint8_t* row_in = row_pointers[y];
|
||||
uint8_t* row_out = &rgb[3 * y * xsize];
|
||||
for (int x = 0; x < xsize; ++x) {
|
||||
const uint8_t gray = row_in[x];
|
||||
row_out[3 * x + 0] = gray;
|
||||
row_out[3 * x + 1] = gray;
|
||||
row_out[3 * x + 2] = gray;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
// GRAYSCALE + ALPHA
|
||||
for (int y = 0; y < ysize; ++y) {
|
||||
const uint8_t* row_in = row_pointers[y];
|
||||
uint8_t* row_out = &rgb[3 * y * xsize];
|
||||
for (int x = 0; x < xsize; ++x) {
|
||||
const uint8_t gray = BlendOnBlack(row_in[2 * x], row_in[2 * x + 1]);
|
||||
row_out[3 * x + 0] = gray;
|
||||
row_out[3 * x + 1] = gray;
|
||||
row_out[3 * x + 2] = gray;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
// RGB
|
||||
for (int y = 0; y < ysize; ++y) {
|
||||
const uint8_t* row_in = row_pointers[y];
|
||||
uint8_t* row_out = &rgb[3 * y * xsize];
|
||||
memcpy(row_out, row_in, 3 * xsize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
// RGBA
|
||||
for (int y = 0; y < ysize; ++y) {
|
||||
const uint8_t* row_in = row_pointers[y];
|
||||
uint8_t* row_out = &rgb[3 * y * xsize];
|
||||
for (int x = 0; x < xsize; ++x) {
|
||||
const uint8_t alpha = row_in[4 * x + 3];
|
||||
row_out[3 * x + 0] = BlendOnBlack(row_in[4 * x + 0], alpha);
|
||||
row_out[3 * x + 1] = BlendOnBlack(row_in[4 * x + 1], alpha);
|
||||
row_out[3 * x + 2] = BlendOnBlack(row_in[4 * x + 2], alpha);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
|
||||
return absl::FailedPreconditionError(
|
||||
"Error reading PNG data from input file");
|
||||
}
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
|
||||
|
||||
return ImageData{xsize, ysize, std::move(rgb)};
|
||||
}
|
||||
|
||||
bool CheckMemoryLimitExceeded(int memlimit_mb, int xsize, int ysize) {
|
||||
double pixels = static_cast<double>(xsize) * ysize;
|
||||
return memlimit_mb != -1 &&
|
||||
(pixels * kBytesPerPixel / (1 << 20) > memlimit_mb ||
|
||||
memlimit_mb < kLowestMemusageMB);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" bool ProcessJpeg(const ProcessingParams* processing_params,
|
||||
sapi::LenValStruct* output) {
|
||||
auto processing_data = PrepareDataForProcessing(*processing_params);
|
||||
|
||||
if (!processing_data.ok()) {
|
||||
std::cerr << processing_data.status().ToString() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
guetzli::JPEGData jpg_header;
|
||||
if (!guetzli::ReadJpeg(processing_data->in_data, guetzli::JPEG_READ_HEADER,
|
||||
&jpg_header)) {
|
||||
std::cerr << "Error reading JPG data from input file" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CheckMemoryLimitExceeded(processing_params->memlimit_mb, jpg_header.width,
|
||||
jpg_header.height)) {
|
||||
std::cerr << "Memory limit would be exceeded" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string out_data;
|
||||
if (!guetzli::Process(processing_data->params, &processing_data->stats,
|
||||
processing_data->in_data, &out_data)) {
|
||||
std::cerr << "Guezli processing failed" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
*output = CreateLenValFromData(out_data.data(), out_data.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" bool ProcessRgb(const ProcessingParams* processing_params,
|
||||
sapi::LenValStruct* output) {
|
||||
auto processing_data = PrepareDataForProcessing(*processing_params);
|
||||
|
||||
if (!processing_data.ok()) {
|
||||
std::cerr << processing_data.status().ToString() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto png_data = ReadPNG(processing_data->in_data);
|
||||
if (!png_data.ok()) {
|
||||
std::cerr << "Error reading PNG data from input file" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CheckMemoryLimitExceeded(processing_params->memlimit_mb, png_data->xsize,
|
||||
png_data->ysize)) {
|
||||
std::cerr << "Memory limit would be exceeded" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string out_data;
|
||||
if (!guetzli::Process(processing_data->params, &processing_data->stats,
|
||||
png_data->rgb, png_data->xsize, png_data->ysize,
|
||||
&out_data)) {
|
||||
std::cerr << "Guetzli processing failed" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
*output = CreateLenValFromData(out_data.data(), out_data.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" bool WriteDataToFd(int fd, sapi::LenValStruct* data) {
|
||||
return sandbox2::file_util::fileops::WriteToFD(
|
||||
fd, static_cast<const char*>(data->data), data->size);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
// 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 GUETZLI_SANDBOXED_GUETZLI_ENTRY_POINTS_H_
|
||||
#define GUETZLI_SANDBOXED_GUETZLI_ENTRY_POINTS_H_
|
||||
|
||||
#include "guetzli/processor.h"
|
||||
#include "sandboxed_api/lenval_core.h"
|
||||
#include "sandboxed_api/vars.h"
|
||||
|
||||
struct ProcessingParams {
|
||||
int remote_fd = -1;
|
||||
int verbose = 0;
|
||||
int quality = 0;
|
||||
int memlimit_mb = 0;
|
||||
};
|
||||
|
||||
extern "C" bool ProcessJpeg(const ProcessingParams* processing_params,
|
||||
sapi::LenValStruct* output);
|
||||
extern "C" bool ProcessRgb(const ProcessingParams* processing_params,
|
||||
sapi::LenValStruct* output);
|
||||
extern "C" bool WriteDataToFd(int fd, sapi::LenValStruct* data);
|
||||
|
||||
#endif // GUETZLI_SANDBOXED_GUETZLI_ENTRY_POINTS_H_
|
|
@ -0,0 +1,45 @@
|
|||
// 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 GUETZLI_SANDBOXED_GUETZLI_SANDBOX_H_
|
||||
#define GUETZLI_SANDBOXED_GUETZLI_SANDBOX_H_
|
||||
|
||||
#include <syscall.h>
|
||||
|
||||
#include "guetzli_sapi.sapi.h" // NOLINT(build/include)
|
||||
|
||||
namespace guetzli::sandbox {
|
||||
|
||||
class GuetzliSapiSandbox : public GuetzliSandbox {
|
||||
public:
|
||||
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
||||
sandbox2::PolicyBuilder*) override {
|
||||
return sandbox2::PolicyBuilder()
|
||||
.AllowStaticStartup()
|
||||
.AllowRead()
|
||||
.AllowSystemMalloc()
|
||||
.AllowWrite()
|
||||
.AllowExit()
|
||||
.AllowStat()
|
||||
.AllowSyscalls({
|
||||
__NR_futex, __NR_close,
|
||||
__NR_recvmsg // To work with remote fd
|
||||
})
|
||||
.BuildOrDie();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace guetzli::sandbox
|
||||
|
||||
#endif // GUETZLI_SANDBOXED_GUETZLI_SANDBOX_H_
|
|
@ -0,0 +1,96 @@
|
|||
// 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 <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
#include "guetzli_transaction.h" // NOLINT(build/include)
|
||||
#include "sandboxed_api/sandbox2/util/fileops.h"
|
||||
#include "sandboxed_api/util/statusor.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int kDefaultJPEGQuality = 95;
|
||||
constexpr int kDefaultMemlimitMB = 6000;
|
||||
|
||||
void Usage() {
|
||||
fprintf(stderr,
|
||||
"Guetzli JPEG compressor. Usage: \n"
|
||||
"guetzli [flags] input_filename output_filename\n"
|
||||
"\n"
|
||||
"Flags:\n"
|
||||
" --verbose - Print a verbose trace of all attempts to standard "
|
||||
"output.\n"
|
||||
" --quality Q - Visual quality to aim for, expressed as a JPEG "
|
||||
"quality value.\n"
|
||||
" Default value is %d.\n"
|
||||
" --memlimit M - Memory limit in MB. Guetzli will fail if unable to "
|
||||
"stay under\n"
|
||||
" the limit. Default limit is %d MB.\n"
|
||||
" --nomemlimit - Do not limit memory usage.\n",
|
||||
kDefaultJPEGQuality, kDefaultMemlimitMB);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, const char** argv) {
|
||||
int verbose = 0;
|
||||
int quality = kDefaultJPEGQuality;
|
||||
int memlimit_mb = kDefaultMemlimitMB;
|
||||
|
||||
int opt_idx = 1;
|
||||
for (; opt_idx < argc; opt_idx++) {
|
||||
if (strnlen(argv[opt_idx], 2) < 2 || argv[opt_idx][0] != '-' ||
|
||||
argv[opt_idx][1] != '-')
|
||||
break;
|
||||
|
||||
if (!strcmp(argv[opt_idx], "--verbose")) {
|
||||
verbose = 1;
|
||||
} else if (!strcmp(argv[opt_idx], "--quality")) {
|
||||
opt_idx++;
|
||||
if (opt_idx >= argc) Usage();
|
||||
quality = atoi(argv[opt_idx]); // NOLINT(runtime/deprecated_fn)
|
||||
} else if (!strcmp(argv[opt_idx], "--memlimit")) {
|
||||
opt_idx++;
|
||||
if (opt_idx >= argc) Usage();
|
||||
memlimit_mb = atoi(argv[opt_idx]); // NOLINT(runtime/deprecated_fn)
|
||||
} else if (!strcmp(argv[opt_idx], "--nomemlimit")) {
|
||||
memlimit_mb = -1;
|
||||
} else if (!strcmp(argv[opt_idx], "--")) {
|
||||
opt_idx++;
|
||||
break;
|
||||
} else {
|
||||
fprintf(stderr, "Unknown commandline flag: %s\n", argv[opt_idx]);
|
||||
Usage();
|
||||
}
|
||||
}
|
||||
|
||||
if (argc - opt_idx != 2) {
|
||||
Usage();
|
||||
}
|
||||
|
||||
guetzli::sandbox::TransactionParams params = {
|
||||
argv[opt_idx], argv[opt_idx + 1], verbose, quality, memlimit_mb};
|
||||
|
||||
guetzli::sandbox::GuetzliTransaction transaction(std::move(params));
|
||||
auto result = transaction.Run();
|
||||
|
||||
if (!result.ok()) {
|
||||
std::cerr << result.ToString() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
// 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 <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <syscall.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
#include "guetzli_sandbox.h" // NOLINT(build/include)
|
||||
#include "gtest/gtest.h"
|
||||
#include "sandboxed_api/sandbox2/util/fileops.h"
|
||||
#include "sandboxed_api/vars.h"
|
||||
|
||||
namespace guetzli::sandbox::tests {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr absl::string_view kInPngFilename = "bees.png";
|
||||
constexpr absl::string_view kInJpegFilename = "nature.jpg";
|
||||
constexpr absl::string_view kPngReferenceFilename = "bees_reference.jpg";
|
||||
constexpr absl::string_view kJpegReferenceFIlename = "nature_reference.jpg";
|
||||
|
||||
constexpr int kDefaultQualityTarget = 95;
|
||||
constexpr int kDefaultMemlimitMb = 6000;
|
||||
|
||||
constexpr absl::string_view kRelativePathToTestdata =
|
||||
"/guetzli_sandboxed/testdata/";
|
||||
|
||||
std::string GetPathToInputFile(absl::string_view filename) {
|
||||
return absl::StrCat(getenv("TEST_SRCDIR"), kRelativePathToTestdata, filename);
|
||||
}
|
||||
|
||||
std::string ReadFromFile(const std::string& filename) {
|
||||
std::ifstream stream(filename, std::ios::binary);
|
||||
|
||||
if (!stream.is_open()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::stringstream result;
|
||||
result << stream.rdbuf();
|
||||
return result.str();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class GuetzliSapiTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
sandbox_ = std::make_unique<GuetzliSapiSandbox>();
|
||||
ASSERT_EQ(sandbox_->Init(), absl::OkStatus());
|
||||
api_ = std::make_unique<GuetzliApi>(sandbox_.get());
|
||||
}
|
||||
|
||||
std::unique_ptr<GuetzliSapiSandbox> sandbox_;
|
||||
std::unique_ptr<GuetzliApi> api_;
|
||||
};
|
||||
|
||||
// This test can take up to few minutes depending on your hardware
|
||||
TEST_F(GuetzliSapiTest, ProcessRGB) {
|
||||
sapi::v::Fd in_fd(open(GetPathToInputFile(kInPngFilename).c_str(), O_RDONLY));
|
||||
ASSERT_TRUE(in_fd.GetValue() != -1) << "Error opening input file";
|
||||
ASSERT_EQ(api_->sandbox()->TransferToSandboxee(&in_fd), absl::OkStatus())
|
||||
<< "Error transfering fd to sandbox";
|
||||
ASSERT_TRUE(in_fd.GetRemoteFd() != -1) << "Error opening remote fd";
|
||||
sapi::v::Struct<ProcessingParams> processing_params;
|
||||
*processing_params.mutable_data() = {
|
||||
in_fd.GetRemoteFd(), 0, kDefaultQualityTarget, kDefaultMemlimitMb};
|
||||
sapi::v::LenVal output(0);
|
||||
sapi::StatusOr<bool> processing_result =
|
||||
api_->ProcessRgb(processing_params.PtrBefore(), output.PtrBoth());
|
||||
ASSERT_TRUE(processing_result.value_or(false)) << "Error processing rgb data";
|
||||
std::string reference_data =
|
||||
ReadFromFile(GetPathToInputFile(kPngReferenceFilename));
|
||||
ASSERT_EQ(output.GetDataSize(), reference_data.size())
|
||||
<< "Incorrect result data size";
|
||||
ASSERT_EQ(
|
||||
std::string(output.GetData(), output.GetData() + output.GetDataSize()),
|
||||
reference_data)
|
||||
<< "Processed data doesn't match reference output";
|
||||
}
|
||||
|
||||
// This test can take up to few minutes depending on your hardware
|
||||
TEST_F(GuetzliSapiTest, ProcessJpeg) {
|
||||
sapi::v::Fd in_fd(
|
||||
open(GetPathToInputFile(kInJpegFilename).c_str(), O_RDONLY));
|
||||
ASSERT_TRUE(in_fd.GetValue() != -1) << "Error opening input file";
|
||||
ASSERT_EQ(api_->sandbox()->TransferToSandboxee(&in_fd), absl::OkStatus())
|
||||
<< "Error transfering fd to sandbox";
|
||||
ASSERT_TRUE(in_fd.GetRemoteFd() != -1) << "Error opening remote fd";
|
||||
sapi::v::Struct<ProcessingParams> processing_params;
|
||||
*processing_params.mutable_data() = {
|
||||
in_fd.GetRemoteFd(), 0, kDefaultQualityTarget, kDefaultMemlimitMb};
|
||||
sapi::v::LenVal output(0);
|
||||
sapi::StatusOr<bool> processing_result =
|
||||
api_->ProcessJpeg(processing_params.PtrBefore(), output.PtrBoth());
|
||||
ASSERT_TRUE(processing_result.value_or(false)) << "Error processing jpg data";
|
||||
std::string reference_data =
|
||||
ReadFromFile(GetPathToInputFile(kJpegReferenceFIlename));
|
||||
ASSERT_EQ(output.GetDataSize(), reference_data.size())
|
||||
<< "Incorrect result data size";
|
||||
ASSERT_EQ(
|
||||
std::string(output.GetData(), output.GetData() + output.GetDataSize()),
|
||||
reference_data)
|
||||
<< "Processed data doesn't match reference output";
|
||||
}
|
||||
|
||||
} // namespace guetzli::sandbox::tests
|
|
@ -0,0 +1,123 @@
|
|||
// 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 "guetzli_transaction.h" // NOLINT(build/include)
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
namespace guetzli::sandbox {
|
||||
|
||||
absl::Status GuetzliTransaction::Main() {
|
||||
sapi::v::Fd in_fd(open(params_.in_file, O_RDONLY));
|
||||
|
||||
if (in_fd.GetValue() < 0) {
|
||||
return absl::FailedPreconditionError("Error opening input file");
|
||||
}
|
||||
|
||||
SAPI_ASSIGN_OR_RETURN(image_type_, GetImageTypeFromFd(in_fd.GetValue()));
|
||||
SAPI_RETURN_IF_ERROR(sandbox()->TransferToSandboxee(&in_fd));
|
||||
|
||||
if (in_fd.GetRemoteFd() < 0) {
|
||||
return absl::FailedPreconditionError(
|
||||
"Error receiving remote FD: remote input fd is set to -1");
|
||||
}
|
||||
|
||||
GuetzliApi api(sandbox());
|
||||
sapi::v::LenVal output(0);
|
||||
|
||||
sapi::v::Struct<ProcessingParams> processing_params;
|
||||
*processing_params.mutable_data() = {in_fd.GetRemoteFd(), params_.verbose,
|
||||
params_.quality, params_.memlimit_mb};
|
||||
|
||||
auto result =
|
||||
image_type_ == ImageType::kJpeg
|
||||
? api.ProcessJpeg(processing_params.PtrBefore(), output.PtrBefore())
|
||||
: api.ProcessRgb(processing_params.PtrBefore(), output.PtrBefore());
|
||||
|
||||
if (!result.value_or(false)) {
|
||||
return absl::FailedPreconditionError(absl::StrCat(
|
||||
"Error processing ", (image_type_ == ImageType::kJpeg ? "jpeg" : "rgb"),
|
||||
" data"));
|
||||
}
|
||||
|
||||
sapi::v::Fd out_fd(open(".", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR));
|
||||
if (out_fd.GetValue() < 0) {
|
||||
return absl::FailedPreconditionError("Error creating temp output file");
|
||||
}
|
||||
|
||||
SAPI_RETURN_IF_ERROR(sandbox()->TransferToSandboxee(&out_fd));
|
||||
|
||||
if (out_fd.GetRemoteFd() < 0) {
|
||||
return absl::FailedPreconditionError(
|
||||
"Error receiving remote FD: remote output fd is set to -1");
|
||||
}
|
||||
|
||||
auto write_result = api.WriteDataToFd(out_fd.GetRemoteFd(), output.PtrNone());
|
||||
|
||||
if (!write_result.value_or(false)) {
|
||||
return absl::FailedPreconditionError("Error writing file inside sandbox");
|
||||
}
|
||||
|
||||
SAPI_RETURN_IF_ERROR(LinkOutFile(out_fd.GetValue()));
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status GuetzliTransaction::LinkOutFile(int out_fd) const {
|
||||
if (access(params_.out_file, F_OK) != -1) {
|
||||
if (remove(params_.out_file) < 0) {
|
||||
return absl::FailedPreconditionError(absl::StrCat(
|
||||
"Error deleting existing output file: ", params_.out_file));
|
||||
}
|
||||
}
|
||||
|
||||
std::string path = absl::StrCat("/proc/self/fd/", out_fd);
|
||||
|
||||
if (linkat(AT_FDCWD, path.c_str(), AT_FDCWD, params_.out_file,
|
||||
AT_SYMLINK_FOLLOW) < 0) {
|
||||
return absl::FailedPreconditionError(
|
||||
absl::StrCat("Error linking: ", params_.out_file));
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
sapi::StatusOr<ImageType> GuetzliTransaction::GetImageTypeFromFd(int fd) const {
|
||||
static const unsigned char kPNGMagicBytes[] = {
|
||||
0x89, 'P', 'N', 'G', '\r', '\n', 0x1a, '\n',
|
||||
};
|
||||
char read_buf[sizeof(kPNGMagicBytes)];
|
||||
|
||||
if (read(fd, read_buf, sizeof(kPNGMagicBytes)) != sizeof(kPNGMagicBytes)) {
|
||||
return absl::FailedPreconditionError(
|
||||
"Error determining type of the input file");
|
||||
}
|
||||
|
||||
if (lseek(fd, 0, SEEK_SET) != 0) {
|
||||
return absl::FailedPreconditionError(
|
||||
"Error returnig cursor to the beginning");
|
||||
}
|
||||
|
||||
return memcmp(read_buf, kPNGMagicBytes, sizeof(kPNGMagicBytes)) == 0
|
||||
? ImageType::kPng
|
||||
: ImageType::kJpeg;
|
||||
}
|
||||
|
||||
} // namespace guetzli::sandbox
|
|
@ -0,0 +1,59 @@
|
|||
// 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 GUETZLI_SANDBOXED_GUETZLI_TRANSACTION_H_
|
||||
#define GUETZLI_SANDBOXED_GUETZLI_TRANSACTION_H_
|
||||
|
||||
#include <syscall.h>
|
||||
|
||||
#include "guetzli_sandbox.h" // NOLINT(build/include)
|
||||
#include "sandboxed_api/transaction.h"
|
||||
#include "sandboxed_api/vars.h"
|
||||
|
||||
namespace guetzli::sandbox {
|
||||
|
||||
enum class ImageType { kJpeg, kPng };
|
||||
|
||||
struct TransactionParams {
|
||||
const char* in_file = nullptr;
|
||||
const char* out_file = nullptr;
|
||||
int verbose = 0;
|
||||
int quality = 0;
|
||||
int memlimit_mb = 0;
|
||||
};
|
||||
|
||||
// Instance of this transaction shouldn't be reused
|
||||
// Create a new one for each processing operation
|
||||
class GuetzliTransaction : public sapi::Transaction {
|
||||
public:
|
||||
explicit GuetzliTransaction(TransactionParams params, int retry_count = 0)
|
||||
: sapi::Transaction(std::make_unique<GuetzliSapiSandbox>()),
|
||||
params_(std::move(params)) {
|
||||
set_retry_count(retry_count);
|
||||
SetTimeLimit(absl::InfiniteDuration());
|
||||
}
|
||||
|
||||
private:
|
||||
absl::Status Main() final;
|
||||
|
||||
absl::Status LinkOutFile(int out_fd) const;
|
||||
sapi::StatusOr<ImageType> GetImageTypeFromFd(int fd) const;
|
||||
|
||||
const TransactionParams params_;
|
||||
ImageType image_type_ = ImageType::kJpeg;
|
||||
};
|
||||
|
||||
} // namespace guetzli::sandbox
|
||||
|
||||
#endif // GUETZLI_SANDBOXED_GUETZLI_TRANSACTION_H_
|
|
@ -0,0 +1,145 @@
|
|||
// 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 "guetzli_transaction.h" // NOLINT(build/include)
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "sandboxed_api/sandbox2/util/fileops.h"
|
||||
|
||||
namespace guetzli::sandbox::tests {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr absl::string_view kInPngFilename = "bees.png";
|
||||
constexpr absl::string_view kInJpegFilename = "nature.jpg";
|
||||
constexpr absl::string_view kOutJpegFilename = "out_jpeg.jpg";
|
||||
constexpr absl::string_view kOutPngFilename = "out_png.png";
|
||||
constexpr absl::string_view kPngReferenceFilename = "bees_reference.jpg";
|
||||
constexpr absl::string_view kJpegReferenceFIlename = "nature_reference.jpg";
|
||||
|
||||
constexpr int kPngExpectedSize = 38'625;
|
||||
constexpr int kJpegExpectedSize = 10'816;
|
||||
|
||||
constexpr int kDefaultQualityTarget = 95;
|
||||
constexpr int kDefaultMemlimitMb = 6000;
|
||||
|
||||
constexpr absl::string_view kRelativePathToTestdata =
|
||||
"/guetzli_sandboxed/testdata/";
|
||||
|
||||
std::string GetPathToFile(absl::string_view filename) {
|
||||
return absl::StrCat(getenv("TEST_SRCDIR"), kRelativePathToTestdata, filename);
|
||||
}
|
||||
|
||||
std::string ReadFromFile(const std::string& filename) {
|
||||
std::ifstream stream(filename, std::ios::binary);
|
||||
|
||||
if (!stream.is_open()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::stringstream result;
|
||||
result << stream.rdbuf();
|
||||
return result.str();
|
||||
}
|
||||
|
||||
// Helper class to delete file after opening
|
||||
class FileRemover {
|
||||
public:
|
||||
explicit FileRemover(const char* path)
|
||||
: path_(path), fd_(open(path, O_RDONLY)) {}
|
||||
|
||||
~FileRemover() {
|
||||
close(fd_);
|
||||
remove(path_);
|
||||
}
|
||||
|
||||
int get() const { return fd_; }
|
||||
|
||||
private:
|
||||
const char* path_;
|
||||
int fd_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(GuetzliTransactionTest, TestTransactionJpg) {
|
||||
std::string in_path = GetPathToFile(kInJpegFilename);
|
||||
std::string out_path = GetPathToFile(kOutJpegFilename);
|
||||
|
||||
TransactionParams params = {in_path.c_str(), out_path.c_str(), 0,
|
||||
kDefaultQualityTarget, kDefaultMemlimitMb};
|
||||
{
|
||||
GuetzliTransaction transaction(std::move(params));
|
||||
absl::Status result = transaction.Run();
|
||||
|
||||
ASSERT_TRUE(result.ok()) << result.ToString();
|
||||
}
|
||||
std::string reference_data =
|
||||
ReadFromFile(GetPathToFile(kJpegReferenceFIlename));
|
||||
FileRemover file_remover(out_path.c_str());
|
||||
ASSERT_TRUE(file_remover.get() != -1) << "Error opening output file";
|
||||
off_t output_size = lseek(file_remover.get(), 0, SEEK_END);
|
||||
ASSERT_EQ(reference_data.size(), output_size)
|
||||
<< "Different sizes of reference and returned data";
|
||||
ASSERT_EQ(lseek(file_remover.get(), 0, SEEK_SET), 0)
|
||||
<< "Error repositioning out file";
|
||||
|
||||
std::string output;
|
||||
output.resize(output_size);
|
||||
ssize_t status = read(file_remover.get(), output.data(), output_size);
|
||||
ASSERT_EQ(status, output_size) << "Error reading data from temp output file";
|
||||
|
||||
ASSERT_EQ(output, reference_data) << "Returned data doesn't match reference";
|
||||
}
|
||||
|
||||
TEST(GuetzliTransactionTest, TestTransactionPng) {
|
||||
std::string in_path = GetPathToFile(kInPngFilename);
|
||||
std::string out_path = GetPathToFile(kOutPngFilename);
|
||||
|
||||
TransactionParams params = {in_path.c_str(), out_path.c_str(), 0,
|
||||
kDefaultQualityTarget, kDefaultMemlimitMb};
|
||||
{
|
||||
GuetzliTransaction transaction(std::move(params));
|
||||
absl::Status result = transaction.Run();
|
||||
|
||||
ASSERT_TRUE(result.ok()) << result.ToString();
|
||||
}
|
||||
std::string reference_data =
|
||||
ReadFromFile(GetPathToFile(kPngReferenceFilename));
|
||||
FileRemover file_remover(out_path.c_str());
|
||||
ASSERT_TRUE(file_remover.get() != -1) << "Error opening output file";
|
||||
off_t output_size = lseek(file_remover.get(), 0, SEEK_END);
|
||||
ASSERT_EQ(reference_data.size(), output_size)
|
||||
<< "Different sizes of reference and returned data";
|
||||
ASSERT_EQ(lseek(file_remover.get(), 0, SEEK_SET), 0)
|
||||
<< "Error repositioning out file";
|
||||
|
||||
std::string output;
|
||||
output.resize(output_size);
|
||||
ssize_t status = read(file_remover.get(), output.data(), output_size);
|
||||
ASSERT_EQ(status, output_size) << "Error reading data from temp output file";
|
||||
|
||||
ASSERT_EQ(output, reference_data) << "Returned data doesn't match refernce";
|
||||
}
|
||||
|
||||
} // namespace guetzli::sandbox::tests
|
Binary file not shown.
After Width: | Height: | Size: 173 KiB |
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
|
@ -0,0 +1 @@
|
|||
build/
|
|
@ -0,0 +1,56 @@
|
|||
# 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(openjpeg-sapi C CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
# To override lib option -- else SAPI won't work
|
||||
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build OpenJPEG shared library and link executables against it." FORCE)
|
||||
add_subdirectory(openjpeg)
|
||||
|
||||
set(SAPI_ROOT "../.." CACHE PATH "Path to the Sandboxed API source tree")
|
||||
set(SAPI_ENABLE_EXAMPLES OFF CACHE BOOL "")
|
||||
set(SAPI_ENABLE_TESTS OFF CACHE BOOL "")
|
||||
set(EXECUTABLE_OUTPUT_PATH "" CACHE PATH "" FORCE)
|
||||
add_subdirectory("${SAPI_ROOT}"
|
||||
"${CMAKE_BINARY_DIR}/sandboxed-api-build"
|
||||
EXCLUDE_FROM_ALL)
|
||||
|
||||
add_sapi_library(openjp2_sapi
|
||||
FUNCTIONS opj_stream_destroy
|
||||
opj_stream_create_default_file_stream
|
||||
opj_create_decompress
|
||||
opj_image_destroy
|
||||
opj_setup_decoder
|
||||
opj_destroy_codec
|
||||
opj_read_header
|
||||
opj_decode
|
||||
opj_set_default_decoder_parameters
|
||||
opj_end_decompress
|
||||
|
||||
INPUTS ${CMAKE_CURRENT_SOURCE_DIR}/openjpeg/src/lib/openjp2/openjpeg.h
|
||||
LIBRARY openjp2
|
||||
LIBRARY_NAME Openjp2
|
||||
NAMESPACE ""
|
||||
)
|
||||
|
||||
target_include_directories(openjp2_sapi INTERFACE
|
||||
"${PROJECT_BINARY_DIR}"
|
||||
)
|
||||
|
||||
add_subdirectory(examples)
|
|
@ -0,0 +1,29 @@
|
|||
# OpenJPEG Sandboxed API
|
||||
|
||||
This library provides sandboxed version of the [OpenJPEG](https://github.com/uclouvain/openjpeg) library.
|
||||
|
||||
## Examples
|
||||
|
||||
The examples are sandboxed and simplified version of the main tools provided by the OpenJPEG library, namely (for now) `opj_decompress` from [here](https://github.com/uclouvain/openjpeg/blob/master/src/bin/jp2/opj_decompress.c).
|
||||
|
||||
In `decompress_example.cc` the library's sandboxed API is used to convert the _.jp2_ to _.pnm_ image format.
|
||||
|
||||
## Build
|
||||
|
||||
To build this example, after cloning the whole Sandbox API project, you also need to run
|
||||
|
||||
```
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
anywhere in the project tree in order to clone the `openjpeg` submodule.
|
||||
Then in the `sandboxed-api/oss-internship-2020/openjpeg` run
|
||||
```
|
||||
mkdir build && cd build
|
||||
cmake -G Ninja
|
||||
ninja
|
||||
```
|
||||
To run `decompress_sandboxed`:
|
||||
```
|
||||
cd examples
|
||||
./decompress_sandboxed absolute/path/to/the/file.jp2 absolute/path/to/the/file.pnm
|
||||
```
|
|
@ -0,0 +1,48 @@
|
|||
# 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.
|
||||
|
||||
# we need to use modified versions of some of the library tools
|
||||
|
||||
file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/gen_files")
|
||||
file(COPY "${PROJECT_SOURCE_DIR}/openjpeg/src/bin/jp2/convert.c" DESTINATION "${PROJECT_BINARY_DIR}/gen_files/")
|
||||
file(COPY "${PROJECT_SOURCE_DIR}/openjpeg/src/bin/jp2/convert.h" DESTINATION "${PROJECT_BINARY_DIR}/gen_files/")
|
||||
file(COPY "${PROJECT_SOURCE_DIR}/examples/convert.patch" DESTINATION "${PROJECT_BINARY_DIR}/gen_files/")
|
||||
file(COPY "${PROJECT_SOURCE_DIR}/examples/convert_h.patch" DESTINATION "${PROJECT_BINARY_DIR}/gen_files/")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${PROJECT_BINARY_DIR}/gen_files/convert.cc ${PROJECT_BINARY_DIR}/gen_files/convert.h
|
||||
COMMAND cd ${PROJECT_BINARY_DIR}/gen_files && patch < ${PROJECT_SOURCE_DIR}/examples/convert.patch > /dev/null
|
||||
COMMAND cd ${PROJECT_BINARY_DIR}/gen_files && patch < ${PROJECT_SOURCE_DIR}/examples/convert_h.patch > /dev/null
|
||||
COMMAND mv ${PROJECT_BINARY_DIR}/gen_files/convert.c ${PROJECT_BINARY_DIR}/gen_files/convert.cc
|
||||
)
|
||||
|
||||
add_library(convert_helper STATIC
|
||||
${PROJECT_BINARY_DIR}/gen_files/convert.cc
|
||||
${PROJECT_BINARY_DIR}/gen_files/convert.h
|
||||
)
|
||||
|
||||
add_executable(decompress_sandboxed
|
||||
decompress_example.cc
|
||||
)
|
||||
|
||||
target_link_libraries(decompress_sandboxed PRIVATE
|
||||
convert_helper
|
||||
openjp2_sapi
|
||||
sapi::sapi
|
||||
)
|
||||
|
||||
target_link_libraries(convert_helper PRIVATE
|
||||
openjp2_sapi
|
||||
sapi::sapi
|
||||
)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,135 @@
|
|||
--- convert.h 2020-08-27 15:46:45.028628305 +0000
|
||||
+++ convert_helper.h 2020-08-27 14:26:02.155455250 +0000
|
||||
@@ -1,126 +1,8 @@
|
||||
-/*
|
||||
- * The copyright in this software is being made available under the 2-clauses
|
||||
- * BSD License, included below. This software may be subject to other third
|
||||
- * party and contributor rights, including patent rights, and no such rights
|
||||
- * are granted under this license.
|
||||
- *
|
||||
- * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
|
||||
- * Copyright (c) 2002-2014, Professor Benoit Macq
|
||||
- * Copyright (c) 2001-2003, David Janssens
|
||||
- * Copyright (c) 2002-2003, Yannick Verschueren
|
||||
- * Copyright (c) 2003-2007, Francois-Olivier Devaux
|
||||
- * Copyright (c) 2003-2014, Antonin Descampe
|
||||
- * Copyright (c) 2005, Herve Drolon, FreeImage Team
|
||||
- * All rights reserved.
|
||||
- *
|
||||
- * Redistribution and use in source and binary forms, with or without
|
||||
- * modification, are permitted provided that the following conditions
|
||||
- * are met:
|
||||
- * 1. Redistributions of source code must retain the above copyright
|
||||
- * notice, this list of conditions and the following disclaimer.
|
||||
- * 2. Redistributions in binary form must reproduce the above copyright
|
||||
- * notice, this list of conditions and the following disclaimer in the
|
||||
- * documentation and/or other materials provided with the distribution.
|
||||
- *
|
||||
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
|
||||
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
- * POSSIBILITY OF SUCH DAMAGE.
|
||||
- */
|
||||
-#ifndef __J2K_CONVERT_H
|
||||
-#define __J2K_CONVERT_H
|
||||
+// imagetopnm and the two functions it calls internaly are patched
|
||||
+// versions of the library's tools; from openjpeg/src/bin/jp2/convert.c
|
||||
|
||||
-/**@name RAW component encoding parameters */
|
||||
-/*@{*/
|
||||
-typedef struct raw_comp_cparameters {
|
||||
- /** subsampling in X direction */
|
||||
- int dx;
|
||||
- /** subsampling in Y direction */
|
||||
- int dy;
|
||||
- /*@}*/
|
||||
-} raw_comp_cparameters_t;
|
||||
-
|
||||
-/**@name RAW image encoding parameters */
|
||||
-/*@{*/
|
||||
-typedef struct raw_cparameters {
|
||||
- /** width of the raw image */
|
||||
- int rawWidth;
|
||||
- /** height of the raw image */
|
||||
- int rawHeight;
|
||||
- /** number of components of the raw image */
|
||||
- int rawComp;
|
||||
- /** bit depth of the raw image */
|
||||
- int rawBitDepth;
|
||||
- /** signed/unsigned raw image */
|
||||
- OPJ_BOOL rawSigned;
|
||||
- /** raw components parameters */
|
||||
- raw_comp_cparameters_t *rawComps;
|
||||
- /*@}*/
|
||||
-} raw_cparameters_t;
|
||||
-
|
||||
-/* Component precision clipping */
|
||||
-void clip_component(opj_image_comp_t* component, OPJ_UINT32 precision);
|
||||
-/* Component precision scaling */
|
||||
-void scale_component(opj_image_comp_t* component, OPJ_UINT32 precision);
|
||||
-
|
||||
-/* planar / interleaved conversions */
|
||||
-typedef void (* convert_32s_CXPX)(const OPJ_INT32* pSrc, OPJ_INT32* const* pDst,
|
||||
- OPJ_SIZE_T length);
|
||||
-extern const convert_32s_CXPX convert_32s_CXPX_LUT[5];
|
||||
-typedef void (* convert_32s_PXCX)(OPJ_INT32 const* const* pSrc, OPJ_INT32* pDst,
|
||||
- OPJ_SIZE_T length, OPJ_INT32 adjust);
|
||||
-extern const convert_32s_PXCX convert_32s_PXCX_LUT[5];
|
||||
-/* bit depth conversions */
|
||||
-typedef void (* convert_XXx32s_C1R)(const OPJ_BYTE* pSrc, OPJ_INT32* pDst,
|
||||
- OPJ_SIZE_T length);
|
||||
-extern const convert_XXx32s_C1R convert_XXu32s_C1R_LUT[9]; /* up to 8bpp */
|
||||
-typedef void (* convert_32sXXx_C1R)(const OPJ_INT32* pSrc, OPJ_BYTE* pDst,
|
||||
- OPJ_SIZE_T length);
|
||||
-extern const convert_32sXXx_C1R convert_32sXXu_C1R_LUT[9]; /* up to 8bpp */
|
||||
-
|
||||
-
|
||||
-/* TGA conversion */
|
||||
-opj_image_t* tgatoimage(const char *filename, opj_cparameters_t *parameters);
|
||||
-int imagetotga(opj_image_t * image, const char *outfile);
|
||||
-
|
||||
-/* BMP conversion */
|
||||
-opj_image_t* bmptoimage(const char *filename, opj_cparameters_t *parameters);
|
||||
-int imagetobmp(opj_image_t *image, const char *outfile);
|
||||
-
|
||||
-/* TIFF conversion*/
|
||||
-opj_image_t* tiftoimage(const char *filename, opj_cparameters_t *parameters);
|
||||
-int imagetotif(opj_image_t *image, const char *outfile);
|
||||
-/**
|
||||
-Load a single image component encoded in PGX file format
|
||||
-@param filename Name of the PGX file to load
|
||||
-@param parameters *List ?*
|
||||
-@return Returns a greyscale image if successful, returns NULL otherwise
|
||||
-*/
|
||||
-opj_image_t* pgxtoimage(const char *filename, opj_cparameters_t *parameters);
|
||||
-int imagetopgx(opj_image_t *image, const char *outfile);
|
||||
-
|
||||
-opj_image_t* pnmtoimage(const char *filename, opj_cparameters_t *parameters);
|
||||
-int imagetopnm(opj_image_t *image, const char *outfile, int force_split);
|
||||
-
|
||||
-/* RAW conversion */
|
||||
-int imagetoraw(opj_image_t * image, const char *outfile);
|
||||
-int imagetorawl(opj_image_t * image, const char *outfile);
|
||||
-opj_image_t* rawtoimage(const char *filename, opj_cparameters_t *parameters,
|
||||
- raw_cparameters_t *raw_cp);
|
||||
-opj_image_t* rawltoimage(const char *filename, opj_cparameters_t *parameters,
|
||||
- raw_cparameters_t *raw_cp);
|
||||
-
|
||||
-/* PNG conversion*/
|
||||
-extern int imagetopng(opj_image_t *image, const char *write_idf);
|
||||
-extern opj_image_t* pngtoimage(const char *filename,
|
||||
- opj_cparameters_t *parameters);
|
||||
-
|
||||
-#endif /* __J2K_CONVERT_H */
|
||||
+#include "openjp2_sapi.sapi.h"
|
||||
|
||||
+const char* opj_version(void);
|
||||
+static int are_comps_similar(opj_image_t* image);
|
||||
+int imagetopnm(opj_image_t* image, const char* outfile, int force_split);
|
|
@ -0,0 +1,157 @@
|
|||
// 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.
|
||||
|
||||
// Perform decompression from *.jp2 to *.pnm format
|
||||
|
||||
#include <libgen.h>
|
||||
#include <syscall.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "gen_files/convert.h" // NOLINT(build/include)
|
||||
#include "openjp2_sapi.sapi.h" // NOLINT(build/include)
|
||||
|
||||
class Openjp2SapiSandbox : public Openjp2Sandbox {
|
||||
public:
|
||||
explicit Openjp2SapiSandbox(std::string in_file)
|
||||
: in_file_(std::move(in_file)) {}
|
||||
|
||||
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
||||
sandbox2::PolicyBuilder*) override {
|
||||
return sandbox2::PolicyBuilder()
|
||||
.AllowStaticStartup()
|
||||
.AllowOpen()
|
||||
.AllowRead()
|
||||
.AllowWrite()
|
||||
.AllowStat()
|
||||
.AllowSystemMalloc()
|
||||
.AllowExit()
|
||||
.AllowSyscalls({
|
||||
__NR_futex,
|
||||
__NR_close,
|
||||
__NR_lseek,
|
||||
})
|
||||
.AddFile(in_file_)
|
||||
.BuildOrDie();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string in_file_;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||
google::InitGoogleLogging(argv[0]);
|
||||
|
||||
if (argc != 3) {
|
||||
std::cerr << "Usage: " << basename(argv[0]) << " absolute/path/to/INPUT.jp2"
|
||||
<< " absolute/path/to/OUTPUT.pnm\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
std::string in_file(argv[1]);
|
||||
|
||||
// Initialize sandbox.
|
||||
Openjp2SapiSandbox sandbox(in_file);
|
||||
absl::Status status = sandbox.Init();
|
||||
CHECK(status.ok()) << "Sandbox initialization failed " << status;
|
||||
|
||||
Openjp2Api api(&sandbox);
|
||||
sapi::v::ConstCStr in_file_v(in_file.c_str());
|
||||
|
||||
// Initialize library's main data-holders.
|
||||
sapi::StatusOr<opj_stream_t*> stream =
|
||||
api.opj_stream_create_default_file_stream(in_file_v.PtrBefore(), 1);
|
||||
CHECK(stream.ok()) << "Stream initialization failed: " << stream.status();
|
||||
sapi::v::RemotePtr stream_pointer(stream.value());
|
||||
|
||||
sapi::StatusOr<opj_codec_t*> codec = api.opj_create_decompress(OPJ_CODEC_JP2);
|
||||
CHECK(codec.ok()) << "Codec initialization failed: " << stream.status();
|
||||
sapi::v::RemotePtr codec_pointer(codec.value());
|
||||
|
||||
sapi::v::Struct<opj_dparameters_t> parameters;
|
||||
status = api.opj_set_default_decoder_parameters(parameters.PtrBoth());
|
||||
CHECK(status.ok()) << "Parameters initialization failed " << status;
|
||||
|
||||
sapi::StatusOr<OPJ_BOOL> bool_status =
|
||||
api.opj_setup_decoder(&codec_pointer, parameters.PtrBefore());
|
||||
CHECK(bool_status.ok() && bool_status.value()) << "Decoder setup failed";
|
||||
|
||||
// Start reading image from the input file.
|
||||
sapi::v::GenericPtr image_pointer;
|
||||
bool_status = api.opj_read_header(&stream_pointer, &codec_pointer,
|
||||
image_pointer.PtrAfter());
|
||||
CHECK(bool_status.ok() && bool_status.value())
|
||||
<< "Reading image header failed";
|
||||
|
||||
sapi::v::Struct<opj_image_t> image;
|
||||
image.SetRemote(reinterpret_cast<void*>(image_pointer.GetValue()));
|
||||
CHECK(sandbox.TransferFromSandboxee(&image).ok())
|
||||
<< "Transfer from sandboxee failed";
|
||||
|
||||
bool_status =
|
||||
api.opj_decode(&codec_pointer, &stream_pointer, image.PtrAfter());
|
||||
CHECK(bool_status.ok() && bool_status.value()) << "Decoding failed";
|
||||
|
||||
bool_status = api.opj_end_decompress(&codec_pointer, &stream_pointer);
|
||||
CHECK(bool_status.ok() && bool_status.value()) << "Ending decompress failed";
|
||||
|
||||
int components = image.data().numcomps;
|
||||
|
||||
// Transfer the read data to the main process.
|
||||
sapi::v::Array<opj_image_comp_t> image_components(components);
|
||||
image_components.SetRemote(image.data().comps);
|
||||
CHECK(sandbox.TransferFromSandboxee(&image_components).ok())
|
||||
<< "Transfer from sandboxee failed";
|
||||
|
||||
image.mutable_data()->comps =
|
||||
static_cast<opj_image_comp_t*>(image_components.GetLocal());
|
||||
|
||||
unsigned int width = static_cast<unsigned int>(image.data().comps[0].w);
|
||||
unsigned int height = static_cast<unsigned int>(image.data().comps[0].h);
|
||||
|
||||
std::vector<std::vector<OPJ_INT32>> data(components);
|
||||
sapi::v::Array<OPJ_INT32> image_components_data(width * height);
|
||||
|
||||
for (int i = 0; i < components; ++i) {
|
||||
image_components_data.SetRemote(image.data().comps[i].data);
|
||||
CHECK(sandbox.TransferFromSandboxee(&image_components_data).ok())
|
||||
<< "Transfer from sandboxee failed";
|
||||
|
||||
std::vector<OPJ_INT32> component_data(
|
||||
image_components_data.GetData(),
|
||||
image_components_data.GetData() + (width * height));
|
||||
data[i] = std::move(component_data);
|
||||
image_components[i].data = &data[i][0];
|
||||
}
|
||||
|
||||
// Convert the image to the desired format and save it to the file.
|
||||
int error =
|
||||
imagetopnm(static_cast<opj_image_t*>(image.GetLocal()), argv[2], 0);
|
||||
CHECK(!error) << "Image convert failed";
|
||||
|
||||
// Clean up.
|
||||
status = api.opj_image_destroy(image.PtrNone());
|
||||
CHECK(status.ok()) << "Image destroy failed " << status;
|
||||
|
||||
status = api.opj_stream_destroy(&stream_pointer);
|
||||
CHECK(status.ok()) << "Stream destroy failed " << status;
|
||||
|
||||
status = api.opj_destroy_codec(&codec_pointer);
|
||||
CHECK(status.ok()) << "Codec destroy failed " << status;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
*.o
|
||||
*.a
|
||||
pffft_main
|
|
@ -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
|
||||
)
|
|
@ -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
|
||||
library’s 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/*`
|
|
@ -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;
|
||||
}
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -254,9 +254,8 @@ def sapi_library(
|
|||
native.genrule(
|
||||
name = name + ".isystem",
|
||||
outs = [name + ".isystem.list"],
|
||||
cmd = """echo |
|
||||
$(CC) -E -x c++ - -v 2>&1 |
|
||||
awk '/> search starts here:/{flag=1;next}/End of search/{flag=0}flag' > $@
|
||||
cmd = """$(CC) -E -x c++ -v /dev/null 2>&1 |
|
||||
awk '/> search starts here:/{f=1;next}/^End of search/{f=0}f{print $$1}' > $@
|
||||
""",
|
||||
toolchains = ["@bazel_tools//tools/cpp:current_cc_toolchain"],
|
||||
)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))) {
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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_; }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
@ -265,17 +265,16 @@ bool Comms::SendTLV(uint32_t tag, uint64_t length, const uint8_t* bytes) {
|
|||
}
|
||||
|
||||
bool Comms::RecvString(std::string* v) {
|
||||
TLV tlv;
|
||||
if (!RecvTLV(&tlv)) {
|
||||
uint32_t tag;
|
||||
if (!RecvTLV(&tag, v)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tlv.tag != kTagString) {
|
||||
if (tag != kTagString) {
|
||||
SAPI_RAW_LOG(ERROR, "Expected (kTagString == 0x%x), got: 0x%x", kTagString,
|
||||
tlv.tag);
|
||||
tag);
|
||||
return false;
|
||||
}
|
||||
v->assign(reinterpret_cast<const char*>(tlv.value.data()), tlv.value.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -285,16 +284,16 @@ bool Comms::SendString(const std::string& v) {
|
|||
}
|
||||
|
||||
bool Comms::RecvBytes(std::vector<uint8_t>* buffer) {
|
||||
TLV tlv;
|
||||
if (!RecvTLV(&tlv)) {
|
||||
uint32_t tag;
|
||||
if (!RecvTLV(&tag, buffer)) {
|
||||
return false;
|
||||
}
|
||||
if (tlv.tag != kTagBytes) {
|
||||
if (tag != kTagBytes) {
|
||||
buffer->clear();
|
||||
SAPI_RAW_LOG(ERROR, "Expected (kTagBytes == 0x%x), got: 0x%u", kTagBytes,
|
||||
tlv.tag);
|
||||
tag);
|
||||
return false;
|
||||
}
|
||||
buffer->swap(tlv.value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -347,7 +346,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));
|
||||
};
|
||||
|
@ -462,8 +461,9 @@ bool Comms::SendFD(int fd) {
|
|||
}
|
||||
|
||||
bool Comms::RecvProtoBuf(google::protobuf::Message* message) {
|
||||
TLV tlv;
|
||||
if (!RecvTLV(&tlv)) {
|
||||
uint32_t tag;
|
||||
std::vector<uint8_t> bytes;
|
||||
if (!RecvTLV(&tag, &bytes)) {
|
||||
if (IsConnected()) {
|
||||
SAPI_RAW_PLOG(ERROR, "RecvProtoBuf failed for (%s)", socket_name_);
|
||||
} else {
|
||||
|
@ -473,11 +473,11 @@ bool Comms::RecvProtoBuf(google::protobuf::Message* message) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (tlv.tag != kTagProto2) {
|
||||
SAPI_RAW_LOG(ERROR, "Expected tag: 0x%x, got: 0x%u", kTagProto2, tlv.tag);
|
||||
if (tag != kTagProto2) {
|
||||
SAPI_RAW_LOG(ERROR, "Expected tag: 0x%x, got: 0x%u", kTagProto2, tag);
|
||||
return false;
|
||||
}
|
||||
return message->ParseFromArray(tlv.value.data(), tlv.value.size());
|
||||
return message->ParseFromArray(bytes.data(), bytes.size());
|
||||
}
|
||||
|
||||
bool Comms::SendProtoBuf(const google::protobuf::Message& message) {
|
||||
|
@ -599,18 +599,16 @@ bool Comms::RecvTL(uint32_t* tag, uint64_t* length) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Comms::RecvTLV(TLV* tlv) {
|
||||
absl::MutexLock lock(&tlv_recv_transmission_mutex_);
|
||||
uint64_t length;
|
||||
if (!RecvTL(&tlv->tag, &length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
tlv->value.resize(length);
|
||||
return length == 0 || Recv(tlv->value.data(), length);
|
||||
bool Comms::RecvTLV(uint32_t* tag, std::vector<uint8_t>* value) {
|
||||
return RecvTLVGeneric(tag, value);
|
||||
}
|
||||
|
||||
bool Comms::RecvTLV(uint32_t* tag, std::vector<uint8_t>* value) {
|
||||
bool Comms::RecvTLV(uint32_t* tag, std::string* value) {
|
||||
return RecvTLVGeneric(tag, value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool Comms::RecvTLVGeneric(uint32_t* tag, T* value) {
|
||||
absl::MutexLock lock(&tlv_recv_transmission_mutex_);
|
||||
uint64_t length;
|
||||
if (!RecvTL(tag, &length)) {
|
||||
|
@ -618,7 +616,7 @@ bool Comms::RecvTLV(uint32_t* tag, std::vector<uint8_t>* value) {
|
|||
}
|
||||
|
||||
value->resize(length);
|
||||
return length == 0 || Recv(value->data(), length);
|
||||
return length == 0 || Recv(reinterpret_cast<uint8_t*>(value->data()), length);
|
||||
}
|
||||
|
||||
bool Comms::RecvTLV(uint32_t* tag, uint64_t* length, void* buffer,
|
||||
|
|
|
@ -109,6 +109,9 @@ class Comms {
|
|||
// Receive a TLV structure, the memory for the value will be allocated
|
||||
// by std::vector.
|
||||
bool RecvTLV(uint32_t* tag, std::vector<uint8_t>* value);
|
||||
// Receive a TLV structure, the memory for the value will be allocated
|
||||
// by std::string.
|
||||
bool RecvTLV(uint32_t* tag, std::string* value);
|
||||
// Receives a TLV value into a specified buffer without allocating memory.
|
||||
bool RecvTLV(uint32_t* tag, uint64_t* length, void* buffer, uint64_t buffer_size);
|
||||
|
||||
|
@ -174,12 +177,6 @@ class Comms {
|
|||
// State of the channel (enum), socket will have to be connected later on.
|
||||
State state_ = State::kUnconnected;
|
||||
|
||||
// TLV structure used to pass messages around.
|
||||
struct TLV {
|
||||
uint32_t tag;
|
||||
std::vector<uint8_t> value;
|
||||
};
|
||||
|
||||
// Special struct for passing credentials or FDs. Different from the one above
|
||||
// as it inlines the value. This is important as the data is transmitted using
|
||||
// sendmsg/recvmsg instead of send/recv.
|
||||
|
@ -201,8 +198,9 @@ class Comms {
|
|||
bool RecvTL(uint32_t* tag, uint64_t* length)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(tlv_recv_transmission_mutex_);
|
||||
|
||||
// Receives whole TLV structure, allocates memory for the data.
|
||||
bool RecvTLV(TLV* tlv);
|
||||
// T has to be a ContiguousContainer
|
||||
template <typename T>
|
||||
bool RecvTLVGeneric(uint32_t* tag, T* value);
|
||||
|
||||
// Receives arbitrary integers.
|
||||
bool RecvInt(void* buffer, uint64_t len, uint32_t tag);
|
||||
|
|
|
@ -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_
|
|
@ -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",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))];
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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",
|
||||
],
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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)),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_; }
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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]"};
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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(); }
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -159,6 +159,7 @@ set_target_properties(policy PROPERTIES
|
|||
)
|
||||
target_link_libraries(policy PRIVATE
|
||||
sapi::base
|
||||
sandbox2::config
|
||||
${_sandbox2_fully_static_linkopts}
|
||||
)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue