mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
sync with upstream sapi repo
This commit is contained in:
commit
99d8df5400
|
@ -1,4 +1,6 @@
|
|||
---
|
||||
Language: Cpp
|
||||
BasedOnStyle: Google
|
||||
Language: Cpp
|
||||
BasedOnStyle: Google
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Left
|
||||
...
|
||||
|
|
9
.gitmodules
vendored
9
.gitmodules
vendored
|
@ -1,3 +1,12 @@
|
|||
[submodule "oss-internship-2020/sapi_lodepng/lodepng"]
|
||||
path = oss-internship-2020/sapi_lodepng/lodepng
|
||||
url = https://github.com/lvandeve/lodepng
|
||||
[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/
|
||||
[submodule "oss-internship-2020/curl/curl_wrapper/curl"]
|
||||
path = oss-internship-2020/curl/curl_wrapper/curl
|
||||
url = https://github.com/curl/curl
|
||||
|
|
|
@ -14,6 +14,16 @@
|
|||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
# Fix Ninja generator output to not rebuild entire sub-trees needlessly.
|
||||
if(CMAKE_GENERATOR MATCHES "Ninja")
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/UserMakeRulesOverride.cmake"
|
||||
"string(REPLACE \"-MD\" \"-MMD\" CMAKE_DEPFILE_FLAGS_C \"\${CMAKE_DEPFILE_FLAGS_C}\")\n"
|
||||
"string(REPLACE \"-MD\" \"-MMD\" CMAKE_DEPFILE_FLAGS_CXX \"\${CMAKE_DEPFILE_FLAGS_CXX}\")\n"
|
||||
)
|
||||
set(CMAKE_USER_MAKE_RULES_OVERRIDE
|
||||
"${CMAKE_BINARY_DIR}/UserMakeRulesOverride.cmake" CACHE INTERNAL "")
|
||||
endif()
|
||||
|
||||
project(SandboxedAPI C CXX ASM)
|
||||
|
||||
# SAPI-wide setting for the language level
|
||||
|
@ -31,15 +41,8 @@ include(SapiDeps)
|
|||
include(SapiUtil)
|
||||
include(SapiBuildDefs)
|
||||
|
||||
# Fix Ninja generator output to not rebuild entire sub-trees needlessly.
|
||||
if(CMAKE_GENERATOR MATCHES "Ninja")
|
||||
file(WRITE "${SAPI_BINARY_DIR}/UserMakeRulesOverride.cmake"
|
||||
"STRING(REPLACE \"-MD\" \"-MMD\" CMAKE_DEPFILE_FLAGS_C \"\${CMAKE_DEPFILE_FLAGS_C}\")\n"
|
||||
"STRING(REPLACE \"-MD\" \"-MMD\" CMAKE_DEPFILE_FLAGS_CXX \"\${CMAKE_DEPFILE_FLAGS_CXX}\")\n"
|
||||
)
|
||||
set(CMAKE_USER_MAKE_RULES_OVERRIDE
|
||||
"${SAPI_BINARY_DIR}/UserMakeRulesOverride.cmake" CACHE INTERNAL "")
|
||||
endif()
|
||||
# Allow the header generator to auto-configure include paths
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
if (SAPI_FORCE_COLOR_OUTPUT)
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # GCC
|
||||
|
|
|
@ -123,7 +123,7 @@ function(add_sapi_library)
|
|||
endif()
|
||||
|
||||
# Interface
|
||||
list_join(_sapi_FUNCTIONS "," _sapi_funcs)
|
||||
list(JOIN _sapi_FUNCTIONS "," _sapi_funcs)
|
||||
foreach(src IN LISTS _sapi_INPUTS)
|
||||
get_filename_component(src "${src}" ABSOLUTE)
|
||||
list(APPEND _sapi_full_inputs "${src}")
|
||||
|
@ -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()
|
||||
list_join(_sapi_full_inputs "," _sapi_full_inputs)
|
||||
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()
|
||||
|
||||
|
|
|
@ -35,16 +35,6 @@ function(create_directory_symlink SOURCE DESTINATION)
|
|||
endif()
|
||||
endfunction()
|
||||
|
||||
# Implements list(JOIN ...) for CMake < 3.12.
|
||||
function(list_join LIST SEP OUTPUT)
|
||||
foreach(item IN LISTS ${LIST})
|
||||
set(_concat "${_concat}${SEP}${item}")
|
||||
endforeach()
|
||||
string(LENGTH "${SEP}" _len)
|
||||
string(SUBSTRING "${_concat}" ${_len} -1 _concat)
|
||||
set(${OUTPUT} "${_concat}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Helper function that behaves just like Protobuf's protobuf_generate_cpp(),
|
||||
# except that it strips import paths. This is necessary, because CMake's
|
||||
# protobuf rules don't work well with imports across different directories.
|
||||
|
|
|
@ -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 ""
|
||||
|
|
1
oss-internship-2020/curl/.gitignore
vendored
Normal file
1
oss-internship-2020/curl/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
build/
|
144
oss-internship-2020/curl/CMakeLists.txt
Normal file
144
oss-internship-2020/curl/CMakeLists.txt
Normal file
|
@ -0,0 +1,144 @@
|
|||
# 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.16)
|
||||
|
||||
project(libcurl_sandbox)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
option(CURL_SAPI_ENABLE_EXAMPLES "" ON)
|
||||
option(CURL_SAPI_ENABLE_TESTS "" ON)
|
||||
|
||||
# Add callbacks used by examples and tests
|
||||
if (CURL_SAPI_ENABLE_EXAMPLES OR CURL_SAPI_ENABLE_TESTS)
|
||||
list(APPEND CURL_SAPI_CALLBACKS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/callbacks/callbacks.h"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/callbacks/callbacks.cc"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Add folder containing the non-sandboxed custom curl library
|
||||
add_subdirectory(curl_wrapper)
|
||||
|
||||
# Setup Sandboxed API
|
||||
set(SAPI_ROOT "" CACHE PATH "Path to the Sandboxed API source tree")
|
||||
set(SAPI_ENABLE_EXAMPLES ${CURL_SAPI_ENABLE_EXAMPLES} CACHE BOOL "" FORCE)
|
||||
set(SAPI_ENABLE_TESTS ${CURL_SAPI_ENABLE_TESTS} CACHE BOOL "" FORCE)
|
||||
add_subdirectory(
|
||||
"${SAPI_ROOT}"
|
||||
"${CMAKE_BINARY_DIR}/sandboxed-api-build"
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
|
||||
# Generate SAPI header
|
||||
add_sapi_library(curl_sapi
|
||||
|
||||
# List of all the methods in https://curl.haxx.se/libcurl/c/allfuncs.html
|
||||
# Some are added or modified because the original ones are not supported
|
||||
# by Sandboxed API (details can be found in curl_wrapper.h)
|
||||
FUNCTIONS curl_easy_cleanup
|
||||
curl_easy_duphandle
|
||||
curl_easy_escape
|
||||
curl_easy_getinfo
|
||||
curl_easy_getinfo_ptr
|
||||
curl_easy_init
|
||||
curl_easy_pause
|
||||
curl_easy_perform
|
||||
curl_easy_recv
|
||||
curl_easy_reset
|
||||
curl_easy_send
|
||||
curl_easy_setopt
|
||||
curl_easy_setopt_ptr
|
||||
curl_easy_setopt_long
|
||||
curl_easy_setopt_curl_off_t
|
||||
curl_easy_strerror
|
||||
curl_easy_unescape
|
||||
curl_easy_upkeep
|
||||
curl_free
|
||||
curl_getdate_sapi
|
||||
curl_global_cleanup
|
||||
curl_global_init
|
||||
curl_global_init_mem
|
||||
curl_global_sslset
|
||||
curl_mime_addpart
|
||||
curl_mime_data
|
||||
curl_mime_data_cb
|
||||
curl_mime_encoder
|
||||
curl_mime_filedata
|
||||
curl_mime_filename
|
||||
curl_mime_free
|
||||
curl_mime_headers
|
||||
curl_mime_init
|
||||
curl_mime_name
|
||||
curl_mime_subparts
|
||||
curl_mime_type
|
||||
curl_multi_add_handle
|
||||
curl_multi_assign
|
||||
curl_multi_cleanup
|
||||
curl_multi_fdset_sapi
|
||||
curl_multi_info_read
|
||||
curl_multi_init
|
||||
curl_multi_perform
|
||||
curl_multi_remove_handle
|
||||
curl_multi_setopt
|
||||
curl_multi_setopt_ptr
|
||||
curl_multi_setopt_long
|
||||
curl_multi_setopt_curl_off_t
|
||||
curl_multi_socket_action
|
||||
curl_multi_strerror
|
||||
curl_multi_timeout
|
||||
curl_multi_poll_sapi
|
||||
curl_multi_wait_sapi
|
||||
curl_multi_wakeup
|
||||
curl_share_init
|
||||
curl_share_setopt
|
||||
curl_share_setopt_ptr
|
||||
curl_share_setopt_long
|
||||
curl_share_strerror
|
||||
curl_slist_append
|
||||
curl_slist_free_all
|
||||
curl_url
|
||||
curl_url_cleanup
|
||||
curl_url_dup
|
||||
curl_url_get
|
||||
curl_url_set
|
||||
curl_version
|
||||
curl_version_info
|
||||
|
||||
INPUTS curl_wrapper/curl/include/curl/curl.h
|
||||
curl_wrapper/curl_wrapper.h
|
||||
|
||||
LIBRARY curl_wrapper_and_callbacks
|
||||
|
||||
LIBRARY_NAME Curl
|
||||
|
||||
NAMESPACE ""
|
||||
)
|
||||
|
||||
# Include generated SAPI header
|
||||
target_include_directories(curl_sapi INTERFACE
|
||||
"${PROJECT_BINARY_DIR}"
|
||||
)
|
||||
|
||||
# Add examples
|
||||
if (CURL_SAPI_ENABLE_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
|
||||
# Add tests
|
||||
if (CURL_SAPI_ENABLE_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
112
oss-internship-2020/curl/README.md
Normal file
112
oss-internship-2020/curl/README.md
Normal file
|
@ -0,0 +1,112 @@
|
|||
# LibCurl Sandbox
|
||||
|
||||
This library is a sandboxed version of curl's C API,
|
||||
[libcurl](https://curl.haxx.se/libcurl/c/), implemented using Sandboxed API.
|
||||
|
||||
## Setup
|
||||
|
||||
The repository can be cloned using: `git clone --recursive [URL to this repo]`
|
||||
The `--recursive` flag ensures that submodules are also cloned.
|
||||
|
||||
Alternatively, if the repository has already been cloned but the submodules have
|
||||
not, these can be cloned using: `git submodule update --init --recursive`
|
||||
|
||||
The full list of Sandboxed API dependencies can be found on
|
||||
[Sandboxed API Getting Started page](https://developers.google.com/sandboxed-api/docs/getting-started).
|
||||
|
||||
The following commands, used from the current `curl/` directory, build the
|
||||
library: `mkdir -p build cd build cmake .. -G Ninja -D SAPI_ROOT=[path to
|
||||
sandboxed-api] cmake --build .`
|
||||
|
||||
## Implementation details
|
||||
|
||||
All of libcurl's methods are supported by the library. However, a few of these
|
||||
have different signatures defined in the sandboxed header `custom_curl.h`, which
|
||||
wraps and extends libcurl.
|
||||
|
||||
This is necessary because Sandboxed API sandboxes most of libcurl correctly, but
|
||||
encounters some issues when sandboxing a few methods. The simplest solution is
|
||||
wrapping these methods into wrapper methods that accomplish the same tasks but
|
||||
can also be sandboxed.
|
||||
|
||||
The next sections describe the issues encountered and contain some information
|
||||
on the signatures of the wrapper methods solving these issues.
|
||||
|
||||
#### Variadic methods
|
||||
|
||||
Variadic methods are currently not supported by Sandboxed API. To solve this,
|
||||
these methods are defined with an additional explicit parameter in
|
||||
`custom_curl.h`.
|
||||
|
||||
The methods are: - `curl_easy_setopt`. Use `curl_easy_setopt_ptr`,
|
||||
`curl_easy_setopt_long` or `curl_easy_setopt_curl_off_t` instead. -
|
||||
`curl_easy_getinfo`. Use `curl_easy_getinfo_ptr` instead. - `curl_multi_setopt`.
|
||||
Use `curl_multi_setopt_ptr`, `curl_multi_setopt_long` or
|
||||
`curl_multi_setopt_curl_off_t` instead. - `curl_share_setopt`. Use
|
||||
`curl_share_setopt_ptr` or `curl_share_setopt_long` instead
|
||||
|
||||
#### Methods with incomplete array arguments
|
||||
|
||||
Incomplete array arguments are currently not supported by Sandboxed API. To
|
||||
solve this, methods taking an incomplete array argument have a wrapper in
|
||||
`custom_curl.h`, and take a pointer as the argument.
|
||||
|
||||
The methods are: - `curl_multi_poll`. Use `curl_multi_poll_sapi` instead. -
|
||||
`curl_multi_wait`. Use `curl_multi_wait_sapi` instead.
|
||||
|
||||
#### Methods with conflicts on the generated header
|
||||
|
||||
Some methods create conflicts on the generated header because of redefined
|
||||
`#define` directives from files included by the header. To solve this, the
|
||||
conflicting types and methods are redefined in `custom_curl.h`.
|
||||
|
||||
The types are: - `time_t`. Use `time_t_sapi` instead. - `fd_set`. Use
|
||||
`fd_set_sapi` instead.
|
||||
|
||||
The methods are: - `curl_getdate`. Use `curl_getdate_sapi` instead. -
|
||||
`curl_multi_fdset`. Use `curl_multi_fdset_sapi` instead.
|
||||
|
||||
#### Function pointers
|
||||
|
||||
The functions whose pointers will be passed to the library's methods
|
||||
(*callbacks*) can't be implemented in the files making use of the library, but
|
||||
must be in other files. These files must be compiled together with the library,
|
||||
and this is done by adding their absolute path to the cmake variable
|
||||
`CURL_SAPI_CALLBACKS`.
|
||||
|
||||
The pointers can then be obtained using an `RPCChannel` object, as shown in
|
||||
`example2.cc`.
|
||||
|
||||
## Examples
|
||||
|
||||
The `examples` directory contains the sandboxed versions of example source codes
|
||||
taken from [this page](https://curl.haxx.se/libcurl/c/example.html) on curl's
|
||||
website. More information about each example can be found in the examples'
|
||||
[README](examples/README.md).
|
||||
|
||||
To build these examples when building the library, the cmake variable
|
||||
`CURL_SAPI_ENABLE_EXAMPLES` must be set to `ON`. This enables Sandboxed API
|
||||
examples as well.
|
||||
|
||||
## Policy
|
||||
|
||||
The `sandbox.h` file contains a policy allowing all is necessary for libcurl to
|
||||
perform simple requests. It is used by all the examples, except by example3.
|
||||
This example needs some additional policies and files in its namespace (since it
|
||||
uses HTTPS), and the file `example3.cc` shows how to easily extend an existing
|
||||
policy.
|
||||
|
||||
## Testing
|
||||
|
||||
The `tests` folder contains some test cases created using Google Test. The class
|
||||
`CurlTestUtils` is used to facilitate some tasks that all test cases need,
|
||||
including the setup of a mock local server on which test requests are performed.
|
||||
|
||||
To build these tests when building the library, the cmake variable
|
||||
`CURL_SAPI_ENABLE_TESTS` must be set to `ON`. This enables Sandboxed API tests
|
||||
as well.
|
||||
|
||||
## Callbacks
|
||||
|
||||
The `callbacks.h` and `callbacks.cc` files implement all the callbacks used by
|
||||
examples and tests.
|
37
oss-internship-2020/curl/callbacks/callbacks.cc
Normal file
37
oss-internship-2020/curl/callbacks/callbacks.cc
Normal file
|
@ -0,0 +1,37 @@
|
|||
// 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 "callbacks.h" // NOLINT(build/include)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "sandboxed_api/vars.h"
|
||||
|
||||
size_t WriteToMemory(char* contents, size_t size, size_t num_bytes,
|
||||
void* userp) {
|
||||
size_t real_size = size * num_bytes;
|
||||
auto* mem = static_cast<sapi::LenValStruct*>(userp);
|
||||
|
||||
char* ptr = static_cast<char*>(realloc(mem->data, mem->size + real_size + 1));
|
||||
if (ptr == nullptr) return 0;
|
||||
|
||||
mem->data = ptr;
|
||||
auto data = static_cast<char*>(mem->data);
|
||||
memcpy(&(data[mem->size]), contents, real_size);
|
||||
mem->size += real_size;
|
||||
data[mem->size] = 0;
|
||||
|
||||
return real_size;
|
||||
}
|
24
oss-internship-2020/curl/callbacks/callbacks.h
Normal file
24
oss-internship-2020/curl/callbacks/callbacks.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
// 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 TESTS_CALLBACKS_H
|
||||
#define TESTS_CALLBACKS_H
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
// Append contents to the string stored by userp, which is a sapi::LenValStruct*
|
||||
extern "C" size_t WriteToMemory(char* contents, size_t size, size_t num_bytes,
|
||||
void* userp);
|
||||
|
||||
#endif // TESTS_CALLBACKS_H
|
37
oss-internship-2020/curl/curl_wrapper/CMakeLists.txt
Normal file
37
oss-internship-2020/curl/curl_wrapper/CMakeLists.txt
Normal file
|
@ -0,0 +1,37 @@
|
|||
# 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.
|
||||
|
||||
# Wrapper library including curl, wrappers for some methods and callbacks
|
||||
# The CURL_SAPI_CALLBACKS variable should contain the absolute paths of
|
||||
# all the files implementing the callbacks
|
||||
add_library(curl_wrapper_and_callbacks OBJECT
|
||||
curl_wrapper.h
|
||||
curl_wrapper.cc
|
||||
"${CURL_SAPI_CALLBACKS}"
|
||||
)
|
||||
set_target_properties(curl_wrapper_and_callbacks
|
||||
PROPERTIES LINKER_LANGUAGE C
|
||||
)
|
||||
|
||||
# Flags needed to build curl statically
|
||||
set(CURL_HIDDEN_SYMBOLS OFF)
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
|
||||
# Link the wrapper to the original curl library (testing is disabled in curl)
|
||||
set(BUILD_TESTING OFF)
|
||||
add_subdirectory(curl)
|
||||
target_link_libraries(curl_wrapper_and_callbacks
|
||||
CURL::libcurl
|
||||
sapi::sapi
|
||||
)
|
86
oss-internship-2020/curl/curl_wrapper/curl_wrapper.cc
Normal file
86
oss-internship-2020/curl/curl_wrapper/curl_wrapper.cc
Normal file
|
@ -0,0 +1,86 @@
|
|||
// 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 "curl_wrapper.h" // NOLINT(build/include)
|
||||
|
||||
CURLcode curl_easy_setopt_ptr(CURL* handle, CURLoption option,
|
||||
void* parameter) {
|
||||
return curl_easy_setopt(handle, option, parameter);
|
||||
}
|
||||
|
||||
CURLcode curl_easy_setopt_long(CURL* handle, CURLoption option,
|
||||
long parameter) {
|
||||
return curl_easy_setopt(handle, option, parameter);
|
||||
}
|
||||
|
||||
CURLcode curl_easy_setopt_curl_off_t(CURL* handle, CURLoption option,
|
||||
curl_off_t parameter) {
|
||||
return curl_easy_setopt(handle, option, parameter);
|
||||
}
|
||||
|
||||
CURLcode curl_easy_getinfo_ptr(CURL* handle, CURLINFO option, void* parameter) {
|
||||
return curl_easy_getinfo(handle, option, parameter);
|
||||
}
|
||||
|
||||
time_t_sapi curl_getdate_sapi(char* datestring, time_t_sapi* now) {
|
||||
return curl_getdate(datestring, now);
|
||||
}
|
||||
|
||||
CURLMcode curl_multi_fdset_sapi(CURLM* multi_handle, fd_set_sapi* read_fd_set,
|
||||
fd_set_sapi* write_fd_set,
|
||||
fd_set_sapi* exc_fd_set, int* max_fd) {
|
||||
return curl_multi_fdset(multi_handle, read_fd_set, write_fd_set, exc_fd_set,
|
||||
max_fd);
|
||||
}
|
||||
|
||||
CURLMcode curl_multi_setopt_ptr(CURLM* handle, CURLMoption option,
|
||||
void* parameter) {
|
||||
return curl_multi_setopt(handle, option, parameter);
|
||||
}
|
||||
|
||||
CURLMcode curl_multi_setopt_long(CURLM* handle, CURLMoption option,
|
||||
long parameter) {
|
||||
return curl_multi_setopt(handle, option, parameter);
|
||||
}
|
||||
|
||||
CURLMcode curl_multi_setopt_curl_off_t(CURLM* handle, CURLMoption option,
|
||||
curl_off_t parameter) {
|
||||
return curl_multi_setopt(handle, option, parameter);
|
||||
}
|
||||
|
||||
CURLMcode curl_multi_poll_sapi(CURLM* multi_handle,
|
||||
struct curl_waitfd* extra_fds,
|
||||
unsigned int extra_nfds, int timeout_ms,
|
||||
int* numfds) {
|
||||
return curl_multi_poll(multi_handle, extra_fds, extra_nfds, timeout_ms,
|
||||
numfds);
|
||||
}
|
||||
|
||||
CURLMcode curl_multi_wait_sapi(CURLM* multi_handle,
|
||||
struct curl_waitfd* extra_fds,
|
||||
unsigned int extra_nfds, int timeout_ms,
|
||||
int* numfds) {
|
||||
return curl_multi_wait(multi_handle, extra_fds, extra_nfds, timeout_ms,
|
||||
numfds);
|
||||
}
|
||||
|
||||
CURLSHcode curl_share_setopt_ptr(CURLSH* handle, CURLSHoption option,
|
||||
void* parameter) {
|
||||
return curl_share_setopt(handle, option, parameter);
|
||||
}
|
||||
|
||||
CURLSHcode curl_share_setopt_long(CURLSH* handle, CURLSHoption option,
|
||||
long parameter) {
|
||||
return curl_share_setopt(handle, option, parameter);
|
||||
}
|
82
oss-internship-2020/curl/curl_wrapper/curl_wrapper.h
Normal file
82
oss-internship-2020/curl/curl_wrapper/curl_wrapper.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
// 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.
|
||||
|
||||
// Wrapper for curl library
|
||||
|
||||
#ifndef CURL_WRAPPER_H
|
||||
#define CURL_WRAPPER_H
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
// The wrapper method is needed to make the variadic argument explicit
|
||||
CURLcode curl_easy_setopt_ptr(CURL* handle, CURLoption option, void* parameter);
|
||||
|
||||
// The wrapper method is needed to make the variadic argument explicit
|
||||
CURLcode curl_easy_setopt_long(CURL* handle, CURLoption option, long parameter);
|
||||
|
||||
// The wrapper method is needed to make the variadic argument explicit
|
||||
CURLcode curl_easy_setopt_curl_off_t(CURL* handle, CURLoption option,
|
||||
curl_off_t parameter);
|
||||
|
||||
// The wrapper method is needed to make the variadic argument explicit
|
||||
CURLcode curl_easy_getinfo_ptr(CURL* handle, CURLINFO option, void* parameter);
|
||||
|
||||
// The typedef and wrapper method are needed because the original method has
|
||||
// some conflicts in curl_sapi.sapi.h
|
||||
typedef time_t time_t_sapi;
|
||||
time_t_sapi curl_getdate_sapi(char* datestring, time_t_sapi* now);
|
||||
|
||||
// The typedef and wrapper method are needed because the original method has
|
||||
// some conflicts in curl_sapi.sapi.h
|
||||
typedef fd_set fd_set_sapi;
|
||||
CURLMcode curl_multi_fdset_sapi(CURLM* multi_handle, fd_set_sapi* read_fd_set,
|
||||
fd_set_sapi* write_fd_set,
|
||||
fd_set_sapi* exc_fd_set, int* max_fd);
|
||||
|
||||
// The wrapper method is needed to make the variadic argument explicit
|
||||
CURLMcode curl_multi_setopt_ptr(CURLM* handle, CURLMoption option,
|
||||
void* parameter);
|
||||
|
||||
// The wrapper method is needed to make the variadic argument explicit
|
||||
CURLMcode curl_multi_setopt_long(CURLM* handle, CURLMoption option,
|
||||
long parameter);
|
||||
|
||||
// The wrapper method is needed to make the variadic argument explicit
|
||||
CURLMcode curl_multi_setopt_curl_off_t(CURLM* handle, CURLMoption option,
|
||||
curl_off_t parameter);
|
||||
|
||||
// The wrapper method is needed because incomplete array type is not supported
|
||||
CURLMcode curl_multi_poll_sapi(CURLM* multi_handle,
|
||||
struct curl_waitfd* extra_fds,
|
||||
unsigned int extra_nfds, int timeout_ms,
|
||||
int* numfds);
|
||||
|
||||
// The wrapper method is needed because incomplete array type is not supported
|
||||
CURLMcode curl_multi_wait_sapi(CURLM* multi_handle,
|
||||
struct curl_waitfd* extra_fds,
|
||||
unsigned int extra_nfds, int timeout_ms,
|
||||
int* numfds);
|
||||
|
||||
// The wrapper method is needed to make the variadic argument explicit
|
||||
CURLSHcode curl_share_setopt_ptr(CURLSH* handle, CURLSHoption option,
|
||||
void* parameter);
|
||||
|
||||
// The wrapper method is needed to make the variadic argument explicit
|
||||
CURLSHcode curl_share_setopt_long(CURLSH* handle, CURLSHoption option,
|
||||
long parameter);
|
||||
}
|
||||
|
||||
#endif // CURL_WRAPPER_H
|
76
oss-internship-2020/curl/examples/CMakeLists.txt
Normal file
76
oss-internship-2020/curl/examples/CMakeLists.txt
Normal file
|
@ -0,0 +1,76 @@
|
|||
# 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.
|
||||
|
||||
# All the examples are sandboxed versions of curl's examples
|
||||
# (https://curl.haxx.se/libcurl/c/example.html)
|
||||
|
||||
# Example 1: simple.c
|
||||
add_executable(example1
|
||||
example1.cc
|
||||
../sandbox.h
|
||||
)
|
||||
target_link_libraries(example1 PRIVATE
|
||||
curl_sapi
|
||||
sapi::sapi
|
||||
)
|
||||
|
||||
# Example 2: getinmemory.c
|
||||
add_executable(example2
|
||||
example2.cc
|
||||
../sandbox.h
|
||||
)
|
||||
target_link_libraries(example2 PRIVATE
|
||||
curl_sapi
|
||||
sapi::sapi
|
||||
)
|
||||
|
||||
# Example 3: simplessl.c
|
||||
add_executable(example3
|
||||
example3.cc
|
||||
../sandbox.h
|
||||
)
|
||||
target_link_libraries(example3 PRIVATE
|
||||
curl_sapi
|
||||
sapi::sapi
|
||||
)
|
||||
|
||||
# Example 4: multi-poll.c
|
||||
add_executable(example4
|
||||
example4.cc
|
||||
../sandbox.h
|
||||
)
|
||||
target_link_libraries(example4 PRIVATE
|
||||
curl_sapi
|
||||
sapi::sapi
|
||||
)
|
||||
|
||||
# Example 5: multithread.c
|
||||
add_executable(example5
|
||||
example5.cc
|
||||
../sandbox.h
|
||||
)
|
||||
target_link_libraries(example5 PRIVATE
|
||||
curl_sapi
|
||||
sapi::sapi
|
||||
)
|
||||
|
||||
# Example 6: simple.c (using transactions)
|
||||
add_executable(example6
|
||||
example6.cc
|
||||
../sandbox.h
|
||||
)
|
||||
target_link_libraries(example6 PRIVATE
|
||||
curl_sapi
|
||||
sapi::sapi
|
||||
)
|
38
oss-internship-2020/curl/examples/README.md
Normal file
38
oss-internship-2020/curl/examples/README.md
Normal file
|
@ -0,0 +1,38 @@
|
|||
# LibCurl Sandbox Examples
|
||||
|
||||
Each example in this folder is the sandboxed version of a code snippet from
|
||||
[this page](https://curl.haxx.se/libcurl/c/example.html) on curl's website.
|
||||
These examples perform some basic tasks using libcurl, and can be useful both to
|
||||
understand how to use LibCurl Sandbox, but also to get an idea of how regular
|
||||
and sandboxed code compare to each other.
|
||||
|
||||
This is the list of the examples:
|
||||
|
||||
- **example1**: sandboxed version of
|
||||
[simple.c](https://curl.haxx.se/libcurl/c/simple.html). Really simple HTTP
|
||||
request, downloads and prints out the page at
|
||||
[example.com](http://example.com).
|
||||
- **example2**: sandboxed version of
|
||||
[getinmemory.c](https://curl.haxx.se/libcurl/c/getinmemory.html). Same HTTP
|
||||
request as example1. The difference is that this example uses a callback to
|
||||
save the page directly in memory. Only the page size is printed out.
|
||||
- **example3**: sandboxed version of
|
||||
[simplessl.c](https://curl.haxx.se/libcurl/c/simplessl.html). HTTPS request
|
||||
of the [example.com](https://example.com) page, using SSL authentication.
|
||||
This script takes 4 arguments (SSL certificates file, SSL keys file, SSL
|
||||
keys password and CA certificates files), and prints out the page.
|
||||
- **example4**: sandboxed version of
|
||||
[multi-poll.c](https://curl.haxx.se/libcurl/c/multi-poll.html). Same HTTP
|
||||
request as example1, with the addition of a polling method that can be used
|
||||
to track the status of the request. The page is printed out after it is
|
||||
downloaded.
|
||||
- **example5**: sandboxed version of
|
||||
[multithread.c](https://curl.haxx.se/libcurl/c/multithread.html). Four HTTP
|
||||
request of the pages [example.com](http://example.com),
|
||||
[example.edu](http://example.edu), [example.net](http://example.net) and
|
||||
[example.org](http://example.org), performed at the same time using
|
||||
libcurl's multithreading methods. The pages are printed out.
|
||||
- **example6**: sandboxed version of
|
||||
[simple.c](https://curl.haxx.se/libcurl/c/simple.html). Performs the same
|
||||
tasks as example1, but Sandbox API Transactions are used to show how they
|
||||
can be used to perform a simple request.
|
78
oss-internship-2020/curl/examples/example1.cc
Normal file
78
oss-internship-2020/curl/examples/example1.cc
Normal file
|
@ -0,0 +1,78 @@
|
|||
// 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.
|
||||
|
||||
// Sandboxed version of simple.c
|
||||
// Simple HTTP GET request
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "../sandbox.h" // NOLINT(build/include)
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||
google::InitGoogleLogging(argv[0]);
|
||||
|
||||
absl::Status status;
|
||||
|
||||
// Initialize sandbox2 and sapi
|
||||
CurlSapiSandbox sandbox;
|
||||
status = sandbox.Init();
|
||||
if (!status.ok()) {
|
||||
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
|
||||
}
|
||||
CurlApi api(&sandbox);
|
||||
|
||||
// Initialize the curl session
|
||||
absl::StatusOr<CURL*> curl_handle = api.curl_easy_init();
|
||||
if (!curl_handle.ok()) {
|
||||
LOG(FATAL) << "curl_easy_init failed: " << curl_handle.status();
|
||||
}
|
||||
sapi::v::RemotePtr curl(curl_handle.value());
|
||||
if (!curl.GetValue()) LOG(FATAL) << "curl_easy_init failed: curl is NULL";
|
||||
|
||||
absl::StatusOr<int> curl_code;
|
||||
|
||||
// Specify URL to get
|
||||
sapi::v::ConstCStr url("http://example.com");
|
||||
curl_code = api.curl_easy_setopt_ptr(&curl, CURLOPT_URL, url.PtrBefore());
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Set the library to follow a redirection
|
||||
curl_code = api.curl_easy_setopt_long(&curl, CURLOPT_FOLLOWLOCATION, 1l);
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_easy_setopt_long failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Disable authentication of peer certificate
|
||||
curl_code = api.curl_easy_setopt_long(&curl, CURLOPT_SSL_VERIFYPEER, 0l);
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_easy_setopt_long failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Perform the request
|
||||
curl_code = api.curl_easy_perform(&curl);
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_easy_perform failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Cleanup curl
|
||||
status = api.curl_easy_cleanup(&curl);
|
||||
if (!status.ok()) {
|
||||
LOG(FATAL) << "curl_easy_cleanup failed: " << status;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
107
oss-internship-2020/curl/examples/example2.cc
Normal file
107
oss-internship-2020/curl/examples/example2.cc
Normal file
|
@ -0,0 +1,107 @@
|
|||
// 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.
|
||||
|
||||
// Sandboxed version of getinmemory.c
|
||||
// HTTP GET request using callbacks
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include "../sandbox.h" // NOLINT(build/include)
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||
google::InitGoogleLogging(argv[0]);
|
||||
|
||||
absl::Status status;
|
||||
|
||||
// Initialize sandbox2 and sapi
|
||||
CurlSapiSandbox sandbox;
|
||||
status = sandbox.Init();
|
||||
if (!status.ok()) {
|
||||
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
|
||||
}
|
||||
CurlApi api(&sandbox);
|
||||
|
||||
// Generate pointer to WriteMemoryCallback function
|
||||
void* function_ptr;
|
||||
status = sandbox.rpc_channel()->Symbol("WriteToMemory", &function_ptr);
|
||||
if (!status.ok()) {
|
||||
LOG(FATAL) << "sapi::Sandbox::rpc_channel().Symbol failed: " << status;
|
||||
}
|
||||
sapi::v::RemotePtr remote_function_ptr(function_ptr);
|
||||
|
||||
// Initialize the curl session
|
||||
absl::StatusOr<CURL*> curl_handle = api.curl_easy_init();
|
||||
if (!curl_handle.ok()) {
|
||||
LOG(FATAL) << "curl_easy_init failed: " << curl_handle.status();
|
||||
}
|
||||
sapi::v::RemotePtr curl(curl_handle.value());
|
||||
if (!curl.GetValue()) {
|
||||
LOG(FATAL) << "curl_easy_init failed: curl is NULL";
|
||||
}
|
||||
|
||||
absl::StatusOr<int> curl_code;
|
||||
|
||||
// Specify URL to get
|
||||
sapi::v::ConstCStr url("http://example.com");
|
||||
curl_code = api.curl_easy_setopt_ptr(&curl, CURLOPT_URL, url.PtrBefore());
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Set WriteMemoryCallback as the write function
|
||||
curl_code = api.curl_easy_setopt_ptr(&curl, CURLOPT_WRITEFUNCTION,
|
||||
&remote_function_ptr);
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Pass 'chunk' struct to the callback function
|
||||
sapi::v::LenVal chunk(0);
|
||||
curl_code =
|
||||
api.curl_easy_setopt_ptr(&curl, CURLOPT_WRITEDATA, chunk.PtrBoth());
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Set a user agent
|
||||
sapi::v::ConstCStr user_agent("libcurl-agent/1.0");
|
||||
curl_code = api.curl_easy_setopt_ptr(&curl, CURLOPT_USERAGENT,
|
||||
user_agent.PtrBefore());
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Perform the request
|
||||
curl_code = api.curl_easy_perform(&curl);
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_easy_perform failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Retrieve memory size
|
||||
status = sandbox.TransferFromSandboxee(&chunk);
|
||||
if (!status.ok()) {
|
||||
LOG(FATAL) << "sandbox.TransferFromSandboxee failed: " << status;
|
||||
}
|
||||
std::cout << "memory size: " << chunk.GetDataSize() << " bytes" << std::endl;
|
||||
|
||||
// Cleanup curl
|
||||
status = api.curl_easy_cleanup(&curl);
|
||||
if (!status.ok()) {
|
||||
LOG(FATAL) << "curl_easy_cleanup failed: " << status;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
166
oss-internship-2020/curl/examples/example3.cc
Normal file
166
oss-internship-2020/curl/examples/example3.cc
Normal file
|
@ -0,0 +1,166 @@
|
|||
// 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.
|
||||
|
||||
// Sandboxed version of simplessl.c
|
||||
// HTTPS GET request
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "../sandbox.h" // NOLINT(build/include)
|
||||
|
||||
class CurlSapiSandboxEx3 : public CurlSapiSandbox {
|
||||
public:
|
||||
CurlSapiSandboxEx3(std::string ssl_certificate, std::string ssl_key,
|
||||
std::string ca_certificates)
|
||||
: ssl_certificate(ssl_certificate),
|
||||
ssl_key(ssl_key),
|
||||
ca_certificates(ca_certificates) {}
|
||||
|
||||
private:
|
||||
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
||||
sandbox2::PolicyBuilder*) override {
|
||||
// Add the syscalls and files missing in CurlSandbox to a new PolicyBuilder
|
||||
auto policy_builder = std::make_unique<sandbox2::PolicyBuilder>();
|
||||
(*policy_builder)
|
||||
.AllowFutexOp(FUTEX_WAIT_PRIVATE)
|
||||
.AllowGetPIDs()
|
||||
.AllowGetRandom()
|
||||
.AllowHandleSignals()
|
||||
.AllowSyscall(__NR_sysinfo)
|
||||
.AddFile(ssl_certificate)
|
||||
.AddFile(ssl_key)
|
||||
.AddFile(ca_certificates);
|
||||
// Provide the new PolicyBuilder to ModifyPolicy in CurlSandbox
|
||||
return CurlSapiSandbox::ModifyPolicy(policy_builder.get());
|
||||
}
|
||||
|
||||
std::string ssl_certificate;
|
||||
std::string ssl_key;
|
||||
std::string ca_certificates;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||
google::InitGoogleLogging(argv[0]);
|
||||
|
||||
absl::Status status;
|
||||
|
||||
// Get input parameters (should be absolute paths)
|
||||
if (argc != 5) {
|
||||
LOG(FATAL) << "wrong number of arguments (4 expected)";
|
||||
}
|
||||
std::string ssl_certificate = argv[1];
|
||||
std::string ssl_key = argv[2];
|
||||
std::string ssl_key_password = argv[3];
|
||||
std::string ca_certificates = argv[4];
|
||||
|
||||
// Initialize sandbox2 and sapi
|
||||
CurlSapiSandboxEx3 sandbox(ssl_certificate, ssl_key, ca_certificates);
|
||||
status = sandbox.Init();
|
||||
if (!status.ok()) {
|
||||
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
|
||||
}
|
||||
CurlApi api(&sandbox);
|
||||
|
||||
absl::StatusOr<int> curl_code;
|
||||
|
||||
// Initialize curl (CURL_GLOBAL_DEFAULT = 3)
|
||||
curl_code = api.curl_global_init(3l);
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_global_init failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Initialize curl easy handle
|
||||
absl::StatusOr<CURL*> curl_handle = api.curl_easy_init();
|
||||
if (!curl_handle.ok()) {
|
||||
LOG(FATAL) << "curl_easy_init failed: " << curl_handle.status();
|
||||
}
|
||||
sapi::v::RemotePtr curl(curl_handle.value());
|
||||
if (!curl.GetValue()) {
|
||||
LOG(FATAL) << "curl_easy_init failed: curl is NULL";
|
||||
}
|
||||
|
||||
// Specify URL to get (using HTTPS)
|
||||
sapi::v::ConstCStr url("https://example.com");
|
||||
curl_code = api.curl_easy_setopt_ptr(&curl, CURLOPT_URL, url.PtrBefore());
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Set the SSL certificate type to "PEM"
|
||||
sapi::v::ConstCStr ssl_cert_type("PEM");
|
||||
curl_code = api.curl_easy_setopt_ptr(&curl, CURLOPT_SSLCERTTYPE,
|
||||
ssl_cert_type.PtrBefore());
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Set the certificate for client authentication
|
||||
sapi::v::ConstCStr sapi_ssl_certificate(ssl_certificate.c_str());
|
||||
curl_code = api.curl_easy_setopt_ptr(&curl, CURLOPT_SSLCERT,
|
||||
sapi_ssl_certificate.PtrBefore());
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Set the private key for client authentication
|
||||
sapi::v::ConstCStr sapi_ssl_key(ssl_key.c_str());
|
||||
curl_code =
|
||||
api.curl_easy_setopt_ptr(&curl, CURLOPT_SSLKEY, sapi_ssl_key.PtrBefore());
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Set the password used to protect the private key
|
||||
sapi::v::ConstCStr sapi_ssl_key_password(ssl_key_password.c_str());
|
||||
curl_code = api.curl_easy_setopt_ptr(&curl, CURLOPT_KEYPASSWD,
|
||||
sapi_ssl_key_password.PtrBefore());
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Set the file with the certificates vaildating the server
|
||||
sapi::v::ConstCStr sapi_ca_certificates(ca_certificates.c_str());
|
||||
curl_code = api.curl_easy_setopt_ptr(&curl, CURLOPT_CAINFO,
|
||||
sapi_ca_certificates.PtrBefore());
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Verify the authenticity of the server
|
||||
curl_code = api.curl_easy_setopt_long(&curl, CURLOPT_SSL_VERIFYPEER, 1L);
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_easy_setopt_long failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Perform the request
|
||||
curl_code = api.curl_easy_perform(&curl);
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_easy_perform failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Cleanup curl easy handle
|
||||
status = api.curl_easy_cleanup(&curl);
|
||||
if (!status.ok()) {
|
||||
LOG(FATAL) << "curl_easy_cleanup failed: " << status;
|
||||
}
|
||||
|
||||
// Cleanup curl
|
||||
status = api.curl_global_cleanup();
|
||||
if (!status.ok()) {
|
||||
LOG(FATAL) << "curl_global_cleanup failed: " << status;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
128
oss-internship-2020/curl/examples/example4.cc
Normal file
128
oss-internship-2020/curl/examples/example4.cc
Normal file
|
@ -0,0 +1,128 @@
|
|||
// 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.
|
||||
|
||||
// Sandboxed version of multi-poll.c
|
||||
// HTTP GET request with polling
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "../sandbox.h" // NOLINT(build/include)
|
||||
#include "curl_sapi.sapi.h" // NOLINT(build/include)
|
||||
#include "sandboxed_api/util/flag.h"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||
google::InitGoogleLogging(argv[0]);
|
||||
|
||||
absl::Status status;
|
||||
|
||||
// Initialize sandbox2 and sapi
|
||||
CurlSapiSandbox sandbox;
|
||||
status = sandbox.Init();
|
||||
if (!status.ok()) {
|
||||
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
|
||||
}
|
||||
CurlApi api(&sandbox);
|
||||
|
||||
// Number of running handles
|
||||
sapi::v::Int still_running(1);
|
||||
|
||||
absl::StatusOr<int> curl_code;
|
||||
|
||||
// Initialize curl (CURL_GLOBAL_DEFAULT = 3)
|
||||
curl_code = api.curl_global_init(3l);
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_global_init failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Initialize http_handle
|
||||
absl::StatusOr<CURL*> curl_handle = api.curl_easy_init();
|
||||
if (!curl_handle.ok()) {
|
||||
LOG(FATAL) << "curl_easy_init failed: " << curl_handle.status();
|
||||
}
|
||||
sapi::v::RemotePtr http_handle(curl_handle.value());
|
||||
if (!http_handle.GetValue()) {
|
||||
LOG(FATAL) << "curl_easy_init failed: http_handle is NULL";
|
||||
}
|
||||
|
||||
// Specify URL to get
|
||||
sapi::v::ConstCStr url("http://example.com");
|
||||
curl_code =
|
||||
api.curl_easy_setopt_ptr(&http_handle, CURLOPT_URL, url.PtrBefore());
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Initialize multi_handle
|
||||
absl::StatusOr<CURLM*> curlm_handle = api.curl_multi_init();
|
||||
if (!curlm_handle.ok()) {
|
||||
LOG(FATAL) << "curl_multi_init failed: " << curlm_handle.status();
|
||||
}
|
||||
sapi::v::RemotePtr multi_handle(curlm_handle.value());
|
||||
if (!multi_handle.GetValue()) {
|
||||
LOG(FATAL) << "curl_multi_init failed: multi_handle is NULL";
|
||||
}
|
||||
|
||||
// Add http_handle to the multi stack
|
||||
curl_code = api.curl_multi_add_handle(&multi_handle, &http_handle);
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_multi_add_handle failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
while (still_running.GetValue()) {
|
||||
sapi::v::Int numfds(0);
|
||||
|
||||
// Perform the request
|
||||
curl_code = api.curl_multi_perform(&multi_handle, still_running.PtrBoth());
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_mutli_perform failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
if (still_running.GetValue()) {
|
||||
// Wait for an event or timeout
|
||||
sapi::v::NullPtr null_ptr;
|
||||
curl_code = api.curl_multi_poll_sapi(&multi_handle, &null_ptr, 0, 1000,
|
||||
numfds.PtrBoth());
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_multi_poll_sapi failed: " << curl_code.status();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove http_handle from the multi stack
|
||||
curl_code = api.curl_multi_remove_handle(&multi_handle, &http_handle);
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_multi_remove_handle failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Cleanup http_handle
|
||||
status = api.curl_easy_cleanup(&http_handle);
|
||||
if (!status.ok()) {
|
||||
LOG(FATAL) << "curl_easy_cleanup failed: " << status;
|
||||
}
|
||||
|
||||
// Cleanup multi_handle
|
||||
curl_code = api.curl_multi_cleanup(&multi_handle);
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_multi_cleanup failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Cleanup curl
|
||||
status = api.curl_global_cleanup();
|
||||
if (!status.ok()) {
|
||||
LOG(FATAL) << "curl_global_cleanup failed: " << status;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
102
oss-internship-2020/curl/examples/example5.cc
Normal file
102
oss-internship-2020/curl/examples/example5.cc
Normal file
|
@ -0,0 +1,102 @@
|
|||
// 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.
|
||||
|
||||
// Sandboxed version of multithread.c
|
||||
// Multithreaded HTTP GET requests
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "../sandbox.h" // NOLINT(build/include)
|
||||
|
||||
void pull_one_url(const std::string& url, CurlApi& api) {
|
||||
// Initialize the curl session
|
||||
absl::StatusOr<CURL*> curl_handle = api.curl_easy_init();
|
||||
if (!curl_handle.ok()) {
|
||||
LOG(FATAL) << "curl_easy_init failed: " << curl_handle.status();
|
||||
}
|
||||
sapi::v::RemotePtr curl(curl_handle.value());
|
||||
if (!curl.GetValue()) {
|
||||
LOG(FATAL) << "curl_easy_init failed: curl is NULL";
|
||||
}
|
||||
|
||||
absl::StatusOr<int> curl_code;
|
||||
|
||||
// Specify URL to get
|
||||
sapi::v::ConstCStr sapi_url(url.c_str());
|
||||
curl_code =
|
||||
api.curl_easy_setopt_ptr(&curl, CURLOPT_URL, sapi_url.PtrBefore());
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Perform the request
|
||||
curl_code = api.curl_easy_perform(&curl);
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_easy_perform failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Cleanup curl
|
||||
absl::Status status = api.curl_easy_cleanup(&curl);
|
||||
if (!status.ok()) {
|
||||
LOG(FATAL) << "curl_easy_cleanup failed: " << status;
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<std::string> urls = {
|
||||
"http://example.com", "http://example.edu", "http://example.net",
|
||||
"http://example.org"};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||
google::InitGoogleLogging(argv[0]);
|
||||
|
||||
absl::Status status;
|
||||
|
||||
// Initialize sandbox2 and sapi
|
||||
CurlSapiSandbox sandbox;
|
||||
status = sandbox.Init();
|
||||
if (!status.ok()) {
|
||||
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
|
||||
}
|
||||
CurlApi api(&sandbox);
|
||||
|
||||
absl::StatusOr<int> curl_code;
|
||||
|
||||
// Initialize curl (CURL_GLOBAL_DEFAULT = 3)
|
||||
curl_code = api.curl_global_init(3l);
|
||||
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
|
||||
LOG(FATAL) << "curl_global_init failed: " << curl_code.status();
|
||||
}
|
||||
|
||||
// Create the threads
|
||||
std::vector<std::thread> threads;
|
||||
for (auto& url : urls) {
|
||||
threads.emplace_back(pull_one_url, std::ref(url), std::ref(api));
|
||||
}
|
||||
|
||||
// Join the threads
|
||||
for (auto& thread : threads) {
|
||||
thread.join();
|
||||
}
|
||||
|
||||
// Cleanup curl
|
||||
status = api.curl_global_cleanup();
|
||||
if (!status.ok()) {
|
||||
LOG(FATAL) << "curl_global_cleanup failed: " << status;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
72
oss-internship-2020/curl/examples/example6.cc
Normal file
72
oss-internship-2020/curl/examples/example6.cc
Normal file
|
@ -0,0 +1,72 @@
|
|||
// 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.
|
||||
|
||||
// Sandboxed version of simple.c using transactions
|
||||
// Simple HTTP GET request
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "../sandbox.h" // NOLINT(build/include)
|
||||
#include "sandboxed_api/transaction.h"
|
||||
|
||||
class CurlTransaction : public sapi::Transaction {
|
||||
public:
|
||||
explicit CurlTransaction(std::unique_ptr<sapi::Sandbox> sandbox)
|
||||
: sapi::Transaction(std::move(sandbox)) {
|
||||
sapi::Transaction::SetTimeLimit(kTimeOutVal);
|
||||
}
|
||||
|
||||
private:
|
||||
// Default timeout value for each transaction run.
|
||||
static constexpr time_t kTimeOutVal = 2;
|
||||
|
||||
// The main processing function.
|
||||
absl::Status Main() override;
|
||||
};
|
||||
|
||||
absl::Status CurlTransaction::Main() {
|
||||
CurlApi api(sandbox());
|
||||
|
||||
// Initialize the curl session
|
||||
SAPI_ASSIGN_OR_RETURN(void* curl_remote, api.curl_easy_init());
|
||||
sapi::v::RemotePtr curl(curl_remote);
|
||||
TRANSACTION_FAIL_IF_NOT(curl.GetValue(), "curl_easy_init failed");
|
||||
|
||||
// Specify URL to get
|
||||
sapi::v::ConstCStr url("http://example.com");
|
||||
SAPI_ASSIGN_OR_RETURN(
|
||||
int setopt_url_code,
|
||||
api.curl_easy_setopt_ptr(&curl, CURLOPT_URL, url.PtrBefore()));
|
||||
TRANSACTION_FAIL_IF_NOT(setopt_url_code == CURLE_OK,
|
||||
"curl_easy_setopt_ptr failed");
|
||||
|
||||
// Perform the request
|
||||
SAPI_ASSIGN_OR_RETURN(int perform_code, api.curl_easy_perform(&curl));
|
||||
TRANSACTION_FAIL_IF_NOT(setopt_url_code == CURLE_OK,
|
||||
"curl_easy_perform failed");
|
||||
|
||||
// Cleanup curl
|
||||
TRANSACTION_FAIL_IF_NOT(api.curl_easy_cleanup(&curl).ok(),
|
||||
"curl_easy_cleanup failed");
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
CurlTransaction curl{std::make_unique<CurlSapiSandbox>()};
|
||||
absl::Status status = curl.Run();
|
||||
CHECK(status.ok()) << "CurlTransaction failed";
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
67
oss-internship-2020/curl/sandbox.h
Normal file
67
oss-internship-2020/curl/sandbox.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
// 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 SANDBOX_H_
|
||||
#define SANDBOX_H_
|
||||
|
||||
#include <linux/futex.h>
|
||||
#include <sys/mman.h> // For mmap arguments
|
||||
#include <syscall.h>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "curl_sapi.sapi.h" // NOLINT(build/include)
|
||||
#include "sandboxed_api/sandbox2/util/bpf_helper.h"
|
||||
|
||||
class CurlSapiSandbox : public CurlSandbox {
|
||||
protected:
|
||||
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
||||
sandbox2::PolicyBuilder* policy_builder) override {
|
||||
// Return a new policy
|
||||
return (*policy_builder)
|
||||
.AllowDynamicStartup()
|
||||
.AllowExit()
|
||||
.AllowFork()
|
||||
.AllowFutexOp(FUTEX_WAKE_PRIVATE)
|
||||
.AllowMmap()
|
||||
.AllowOpen()
|
||||
.AllowRead()
|
||||
.AllowSafeFcntl()
|
||||
.AllowWrite()
|
||||
.AllowSyscalls({
|
||||
__NR_accept,
|
||||
__NR_access,
|
||||
__NR_bind,
|
||||
__NR_connect,
|
||||
__NR_getpeername,
|
||||
__NR_getsockname,
|
||||
__NR_getsockopt,
|
||||
__NR_ioctl,
|
||||
__NR_listen,
|
||||
__NR_madvise,
|
||||
__NR_poll,
|
||||
__NR_recvfrom,
|
||||
__NR_recvmsg,
|
||||
__NR_sendmmsg,
|
||||
__NR_sendto,
|
||||
__NR_setsockopt,
|
||||
__NR_socket,
|
||||
})
|
||||
.AllowUnrestrictedNetworking()
|
||||
.AddDirectory("/lib")
|
||||
.BuildOrDie();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SANDBOX_H_
|
28
oss-internship-2020/curl/tests/CMakeLists.txt
Normal file
28
oss-internship-2020/curl/tests/CMakeLists.txt
Normal file
|
@ -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.
|
||||
|
||||
include(GoogleTest)
|
||||
|
||||
add_executable(tests
|
||||
test_utils.h
|
||||
test_utils.cc
|
||||
tests.cc
|
||||
)
|
||||
|
||||
target_link_libraries(tests
|
||||
curl_sapi sapi::sapi
|
||||
gtest gmock gtest_main
|
||||
)
|
||||
|
||||
gtest_discover_tests(tests)
|
301
oss-internship-2020/curl/tests/test_utils.cc
Normal file
301
oss-internship-2020/curl/tests/test_utils.cc
Normal file
|
@ -0,0 +1,301 @@
|
|||
// 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 "test_utils.h" // NOLINT(build/include)
|
||||
|
||||
#include <absl/strings/match.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <memory>
|
||||
#include <thread> // NOLINT(build/c++11)
|
||||
|
||||
int CurlTestUtils::port_;
|
||||
std::thread CurlTestUtils::server_thread_;
|
||||
|
||||
absl::Status CurlTestUtils::CurlTestSetUp() {
|
||||
// Initialize sandbox2 and sapi
|
||||
sandbox_ = std::make_unique<CurlSapiSandbox>();
|
||||
absl::Status init = sandbox_->Init();
|
||||
if (!init.ok()) {
|
||||
return init;
|
||||
}
|
||||
api_ = std::make_unique<CurlApi>(sandbox_.get());
|
||||
|
||||
// Initialize curl
|
||||
absl::StatusOr<CURL*> curl_handle = api_->curl_easy_init();
|
||||
if (!curl_handle.ok()) {
|
||||
return curl_handle.status();
|
||||
}
|
||||
if (!curl_handle.value()) {
|
||||
return absl::UnavailableError("curl_easy_init returned NULL ");
|
||||
}
|
||||
curl_ = std::make_unique<sapi::v::RemotePtr>(curl_handle.value());
|
||||
|
||||
absl::StatusOr<int> curl_code;
|
||||
|
||||
// Specify request URL
|
||||
sapi::v::ConstCStr sapi_url(kUrl.data());
|
||||
curl_code = api_->curl_easy_setopt_ptr(curl_.get(), CURLOPT_URL,
|
||||
sapi_url.PtrBefore());
|
||||
if (!curl_code.ok()) {
|
||||
return curl_code.status();
|
||||
}
|
||||
if (curl_code.value() != CURLE_OK) {
|
||||
return absl::UnavailableError(
|
||||
"curl_easy_setopt_ptr returned with the error code " +
|
||||
curl_code.value());
|
||||
}
|
||||
|
||||
// Set port
|
||||
curl_code = api_->curl_easy_setopt_long(curl_.get(), CURLOPT_PORT, port_);
|
||||
if (!curl_code.ok()) {
|
||||
return curl_code.status();
|
||||
}
|
||||
if (curl_code.value() != CURLE_OK) {
|
||||
return absl::UnavailableError(
|
||||
"curl_easy_setopt_long returned with the error code " +
|
||||
curl_code.value());
|
||||
}
|
||||
|
||||
// Generate pointer to the WriteToMemory callback
|
||||
void* function_ptr;
|
||||
absl::Status symbol =
|
||||
sandbox_->rpc_channel()->Symbol("WriteToMemory", &function_ptr);
|
||||
if (!symbol.ok()) {
|
||||
return symbol;
|
||||
}
|
||||
sapi::v::RemotePtr remote_function_ptr(function_ptr);
|
||||
|
||||
// Set WriteToMemory as the write function
|
||||
curl_code = api_->curl_easy_setopt_ptr(curl_.get(), CURLOPT_WRITEFUNCTION,
|
||||
&remote_function_ptr);
|
||||
if (!curl_code.ok()) {
|
||||
return curl_code.status();
|
||||
}
|
||||
if (curl_code.value() != CURLE_OK) {
|
||||
return absl::UnavailableError(
|
||||
"curl_easy_setopt_ptr returned with the error code " +
|
||||
curl_code.value());
|
||||
}
|
||||
|
||||
// Pass memory chunk object to the callback
|
||||
chunk_ = std::make_unique<sapi::v::LenVal>(0);
|
||||
curl_code = api_->curl_easy_setopt_ptr(curl_.get(), CURLOPT_WRITEDATA,
|
||||
chunk_->PtrBoth());
|
||||
if (!curl_code.ok()) {
|
||||
return curl_code.status();
|
||||
}
|
||||
if (curl_code.value() != CURLE_OK) {
|
||||
return absl::UnavailableError(
|
||||
"curl_easy_setopt_ptr returned with the error code " +
|
||||
curl_code.value());
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status CurlTestUtils::CurlTestTearDown() {
|
||||
// Cleanup curl
|
||||
return api_->curl_easy_cleanup(curl_.get());
|
||||
}
|
||||
|
||||
absl::StatusOr<std::string> CurlTestUtils::PerformRequest() {
|
||||
// Perform the request
|
||||
absl::StatusOr<int> curl_code = api_->curl_easy_perform(curl_.get());
|
||||
if (!curl_code.ok()) {
|
||||
return curl_code.status();
|
||||
}
|
||||
if (curl_code.value() != CURLE_OK) {
|
||||
return absl::UnavailableError(
|
||||
"curl_easy_perform returned with the error code " + curl_code.value());
|
||||
}
|
||||
|
||||
// Get pointer to the memory chunk
|
||||
absl::Status status = sandbox_->TransferFromSandboxee(chunk_.get());
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return std::string{reinterpret_cast<char*>(chunk_->GetData())};
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Read the socket until str is completely read
|
||||
std::string ReadUntil(const int socket, const std::string& str,
|
||||
const size_t max_request_size) {
|
||||
std::string str_read;
|
||||
str_read.reserve(max_request_size);
|
||||
|
||||
// Read one char at a time until str is suffix of buf
|
||||
while (!absl::EndsWith(str_read, str)) {
|
||||
char next_char;
|
||||
if (str_read.size() >= max_request_size ||
|
||||
read(socket, &next_char, 1) < 1) {
|
||||
return "";
|
||||
}
|
||||
str_read += next_char;
|
||||
}
|
||||
|
||||
return str_read;
|
||||
}
|
||||
|
||||
// Parse HTTP headers to return the Content-Length
|
||||
ssize_t GetContentLength(const std::string& headers) {
|
||||
// Find the Content-Length header
|
||||
std::string::size_type length_header_start = headers.find("Content-Length: ");
|
||||
|
||||
// There is no Content-Length field
|
||||
if (length_header_start == std::string::npos) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Find Content-Length string
|
||||
std::string::size_type length_start =
|
||||
length_header_start + std::string{"Content-Length: "}.size();
|
||||
std::string::size_type length_bytes =
|
||||
headers.find("\r\n", length_start) - length_start;
|
||||
|
||||
// length_bytes exceeds maximum
|
||||
if (length_bytes >= 64) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Convert string to int and return
|
||||
return std::stoi(headers.substr(length_start, length_bytes));
|
||||
}
|
||||
|
||||
// Read exactly content_bytes from the socket
|
||||
std::string ReadExact(int socket, size_t content_bytes) {
|
||||
std::string str_read;
|
||||
str_read.reserve(content_bytes);
|
||||
|
||||
// Read one char at a time until all chars are read
|
||||
while (str_read.size() < content_bytes) {
|
||||
char next_char;
|
||||
if (read(socket, &next_char, 1) < 1) {
|
||||
return "";
|
||||
}
|
||||
str_read += next_char;
|
||||
}
|
||||
|
||||
return str_read;
|
||||
}
|
||||
|
||||
// Listen on the socket and answer back to requests
|
||||
void ServerLoop(int listening_socket, sockaddr_in socket_address) {
|
||||
socklen_t socket_address_size = sizeof(socket_address);
|
||||
|
||||
// Listen on the socket (maximum 1 connection)
|
||||
if (listen(listening_socket, 1) == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep accepting connections until the thread is terminated
|
||||
// (i.e. server_thread_ is assigned to a new thread or destroyed)
|
||||
for (;;) {
|
||||
// File descriptor to the connection socket
|
||||
// This blocks the thread until a connection is established
|
||||
int accepted_socket =
|
||||
accept(listening_socket, reinterpret_cast<sockaddr*>(&socket_address),
|
||||
reinterpret_cast<socklen_t*>(&socket_address_size));
|
||||
if (accepted_socket == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
constexpr int kMaxRequestSize = 4096;
|
||||
|
||||
// Read until the end of the headers
|
||||
std::string headers =
|
||||
ReadUntil(accepted_socket, "\r\n\r\n", kMaxRequestSize);
|
||||
|
||||
if (headers == "") {
|
||||
close(accepted_socket);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the length of the request content
|
||||
ssize_t content_length = GetContentLength(headers);
|
||||
if (content_length > kMaxRequestSize - headers.size() ||
|
||||
content_length < 0) {
|
||||
close(accepted_socket);
|
||||
return;
|
||||
}
|
||||
|
||||
// Read the request content
|
||||
std::string content = ReadExact(accepted_socket, content_length);
|
||||
|
||||
// Prepare a response for the request
|
||||
std::string http_response =
|
||||
"HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: ";
|
||||
|
||||
if (headers.substr(0, 3) == "GET") {
|
||||
http_response += "2\r\n\r\nOK";
|
||||
|
||||
} else if (headers.substr(0, 4) == "POST") {
|
||||
http_response +=
|
||||
std::to_string(content.size()) + "\r\n\r\n" + std::string{content};
|
||||
|
||||
} else {
|
||||
close(accepted_socket);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore any errors, the connection will be closed anyway
|
||||
write(accepted_socket, http_response.c_str(), http_response.size());
|
||||
|
||||
// Close the socket
|
||||
close(accepted_socket);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void CurlTestUtils::StartMockServer() {
|
||||
// Get the socket file descriptor
|
||||
int listening_socket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
// Create the socket address object
|
||||
// The port is set to 0, meaning that it will be auto assigned
|
||||
// Only local connections can access this socket
|
||||
sockaddr_in socket_address{AF_INET, 0, htonl(INADDR_LOOPBACK)};
|
||||
socklen_t socket_address_size = sizeof(socket_address);
|
||||
if (listening_socket == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Bind the file descriptor to the socket address object
|
||||
if (bind(listening_socket, reinterpret_cast<sockaddr*>(&socket_address),
|
||||
socket_address_size) == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Assign an available port to the socket address object
|
||||
if (getsockname(listening_socket,
|
||||
reinterpret_cast<sockaddr*>(&socket_address),
|
||||
&socket_address_size) == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the port number
|
||||
port_ = ntohs(socket_address.sin_port);
|
||||
|
||||
// Set server_thread_ operation to socket listening
|
||||
server_thread_ = std::thread(ServerLoop, listening_socket, socket_address);
|
||||
}
|
55
oss-internship-2020/curl/tests/test_utils.h
Normal file
55
oss-internship-2020/curl/tests/test_utils.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
// 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 TESTS_H_
|
||||
#define TESTS_H_
|
||||
|
||||
#include "../sandbox.h" // NOLINT(build/include)
|
||||
#include "curl_sapi.sapi.h" // NOLINT(build/include)
|
||||
#include "gtest/gtest.h"
|
||||
#include "sandboxed_api/util/flag.h"
|
||||
#include "sandboxed_api/util/status_matchers.h"
|
||||
|
||||
// Helper class that can be used to test Curl Sandboxed
|
||||
class CurlTestUtils {
|
||||
protected:
|
||||
// Initialize and set up the curl handle
|
||||
absl::Status CurlTestSetUp();
|
||||
// Clean up the curl handle
|
||||
absl::Status CurlTestTearDown();
|
||||
|
||||
// Perform a request to the mock server, return the response
|
||||
absl::StatusOr<std::string> PerformRequest();
|
||||
|
||||
// Start a mock server (only once) that will manage connections for the tests
|
||||
// The server listens on a port asynchronously by creating a thread
|
||||
// The port number is stored in port_
|
||||
// Responds with "OK" to a GET request
|
||||
// Responds with the POST request fields to a POST request
|
||||
static void StartMockServer();
|
||||
|
||||
std::unique_ptr<CurlSapiSandbox> sandbox_;
|
||||
std::unique_ptr<CurlApi> api_;
|
||||
std::unique_ptr<sapi::v::RemotePtr> curl_;
|
||||
|
||||
static std::thread server_thread_;
|
||||
|
||||
static constexpr absl::string_view kUrl = "http://127.0.0.1/";
|
||||
static int port_;
|
||||
|
||||
private:
|
||||
std::unique_ptr<sapi::v::LenVal> chunk_;
|
||||
};
|
||||
|
||||
#endif // TESTS_H_
|
138
oss-internship-2020/curl/tests/tests.cc
Normal file
138
oss-internship-2020/curl/tests/tests.cc
Normal file
|
@ -0,0 +1,138 @@
|
|||
// 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 "test_utils.h" // NOLINT(build/include)
|
||||
|
||||
class CurlTest : public CurlTestUtils, public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
// Start mock server, get port number and check for any error
|
||||
StartMockServer();
|
||||
ASSERT_TRUE(server_thread_.joinable());
|
||||
ASSERT_TRUE(CurlTestSetUp().ok());
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
ASSERT_TRUE(CurlTestTearDown().ok());
|
||||
// Detach the server thread
|
||||
server_thread_.detach();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(CurlTest, EffectiveUrl) {
|
||||
sapi::v::RemotePtr effective_url_ptr(nullptr);
|
||||
|
||||
ASSERT_TRUE(PerformRequest().ok());
|
||||
|
||||
// Get effective URL
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int getinfo_code,
|
||||
api_->curl_easy_getinfo_ptr(curl_.get(), CURLINFO_EFFECTIVE_URL,
|
||||
effective_url_ptr.PtrBoth()));
|
||||
ASSERT_EQ(getinfo_code, CURLE_OK);
|
||||
|
||||
// Store effective URL in a string
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string effective_url,
|
||||
sandbox_->GetCString(sapi::v::RemotePtr(
|
||||
effective_url_ptr.GetPointedVar())));
|
||||
|
||||
// Compare effective URL with original URL
|
||||
ASSERT_EQ(effective_url, kUrl);
|
||||
}
|
||||
|
||||
TEST_F(CurlTest, EffectivePort) {
|
||||
sapi::v::Int effective_port;
|
||||
|
||||
ASSERT_TRUE(PerformRequest().ok());
|
||||
|
||||
// Get effective port
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(int getinfo_code, api_->curl_easy_getinfo_ptr(
|
||||
curl_.get(), CURLINFO_PRIMARY_PORT,
|
||||
effective_port.PtrBoth()));
|
||||
ASSERT_EQ(getinfo_code, CURLE_OK);
|
||||
|
||||
// Compare effective port with port set by the mock server
|
||||
ASSERT_EQ(effective_port.GetValue(), port_);
|
||||
}
|
||||
|
||||
TEST_F(CurlTest, ResponseCode) {
|
||||
sapi::v::Int response_code;
|
||||
|
||||
ASSERT_TRUE(PerformRequest().ok());
|
||||
|
||||
// Get response code
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int getinfo_code,
|
||||
api_->curl_easy_getinfo_ptr(curl_.get(), CURLINFO_RESPONSE_CODE,
|
||||
response_code.PtrBoth()));
|
||||
ASSERT_EQ(getinfo_code, CURLE_OK);
|
||||
|
||||
// Check response code
|
||||
ASSERT_EQ(response_code.GetValue(), 200);
|
||||
}
|
||||
|
||||
TEST_F(CurlTest, ContentType) {
|
||||
sapi::v::RemotePtr content_type_ptr(nullptr);
|
||||
|
||||
ASSERT_TRUE(PerformRequest().ok());
|
||||
|
||||
// Get effective URL
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(int getinfo_code, api_->curl_easy_getinfo_ptr(
|
||||
curl_.get(), CURLINFO_CONTENT_TYPE,
|
||||
content_type_ptr.PtrBoth()));
|
||||
ASSERT_EQ(getinfo_code, CURLE_OK);
|
||||
|
||||
// Store content type in a string
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string content_type,
|
||||
sandbox_->GetCString(sapi::v::RemotePtr(
|
||||
content_type_ptr.GetPointedVar())));
|
||||
|
||||
// Compare content type with "text/plain"
|
||||
ASSERT_EQ(content_type, "text/plain");
|
||||
}
|
||||
|
||||
TEST_F(CurlTest, GETResponse) {
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string response, PerformRequest());
|
||||
|
||||
// Compare response with expected response
|
||||
ASSERT_EQ(response, "OK");
|
||||
}
|
||||
|
||||
TEST_F(CurlTest, POSTResponse) {
|
||||
sapi::v::ConstCStr post_fields("postfields");
|
||||
|
||||
// Set request method to POST
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(int setopt_post, api_->curl_easy_setopt_long(
|
||||
curl_.get(), CURLOPT_POST, 1l));
|
||||
ASSERT_EQ(setopt_post, CURLE_OK);
|
||||
|
||||
// Set the size of the POST fields
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int setopt_post_fields_size,
|
||||
api_->curl_easy_setopt_long(curl_.get(), CURLOPT_POSTFIELDSIZE,
|
||||
post_fields.GetSize()));
|
||||
ASSERT_EQ(setopt_post_fields_size, CURLE_OK);
|
||||
|
||||
// Set the POST fields
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
int setopt_post_fields,
|
||||
api_->curl_easy_setopt_ptr(curl_.get(), CURLOPT_POSTFIELDS,
|
||||
post_fields.PtrBefore()));
|
||||
ASSERT_EQ(setopt_post_fields, CURLE_OK);
|
||||
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string response, PerformRequest());
|
||||
|
||||
// Compare response with expected response
|
||||
ASSERT_EQ(std::string(post_fields.GetData()), response);
|
||||
}
|
2
oss-internship-2020/guetzli/.bazelrc
Normal file
2
oss-internship-2020/guetzli/.bazelrc
Normal file
|
@ -0,0 +1,2 @@
|
|||
# Build in C++17 mode without a custom CROSSTOOL
|
||||
build --cxxopt=-std=c++17
|
83
oss-internship-2020/guetzli/BUILD.bazel
Normal file
83
oss-internship-2020/guetzli/BUILD.bazel
Normal file
|
@ -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",
|
||||
],
|
||||
)
|
32
oss-internship-2020/guetzli/README.md
Normal file
32
oss-internship-2020/guetzli/README.md
Normal file
|
@ -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`
|
100
oss-internship-2020/guetzli/WORKSPACE
Normal file
100
oss-internship-2020/guetzli/WORKSPACE
Normal file
|
@ -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"],
|
||||
)
|
28
oss-internship-2020/guetzli/external/butteraugli.BUILD
vendored
Normal file
28
oss-internship-2020/guetzli/external/butteraugli.BUILD
vendored
Normal file
|
@ -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"],
|
||||
)
|
32
oss-internship-2020/guetzli/external/guetzli.BUILD
vendored
Normal file
32
oss-internship-2020/guetzli/external/guetzli.BUILD
vendored
Normal file
|
@ -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",
|
||||
],
|
||||
)
|
89
oss-internship-2020/guetzli/external/jpeg.BUILD
vendored
Normal file
89
oss-internship-2020/guetzli/external/jpeg.BUILD
vendored
Normal file
|
@ -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",
|
||||
)
|
33
oss-internship-2020/guetzli/external/png.BUILD
vendored
Normal file
33
oss-internship-2020/guetzli/external/png.BUILD
vendored
Normal file
|
@ -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"],
|
||||
)
|
56
oss-internship-2020/guetzli/external/zlib.BUILD
vendored
Normal file
56
oss-internship-2020/guetzli/external/zlib.BUILD
vendored
Normal file
|
@ -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"],
|
||||
)
|
293
oss-internship-2020/guetzli/guetzli_entry_points.cc
Normal file
293
oss-internship-2020/guetzli/guetzli_entry_points.cc
Normal file
|
@ -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);
|
||||
}
|
35
oss-internship-2020/guetzli/guetzli_entry_points.h
Normal file
35
oss-internship-2020/guetzli/guetzli_entry_points.h
Normal file
|
@ -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_
|
45
oss-internship-2020/guetzli/guetzli_sandbox.h
Normal file
45
oss-internship-2020/guetzli/guetzli_sandbox.h
Normal file
|
@ -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_
|
96
oss-internship-2020/guetzli/guetzli_sandboxed.cc
Normal file
96
oss-internship-2020/guetzli/guetzli_sandboxed.cc
Normal file
|
@ -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;
|
||||
}
|
124
oss-internship-2020/guetzli/guetzli_sapi_test.cc
Normal file
124
oss-internship-2020/guetzli/guetzli_sapi_test.cc
Normal file
|
@ -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
|
123
oss-internship-2020/guetzli/guetzli_transaction.cc
Normal file
123
oss-internship-2020/guetzli/guetzli_transaction.cc
Normal file
|
@ -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
|
59
oss-internship-2020/guetzli/guetzli_transaction.h
Normal file
59
oss-internship-2020/guetzli/guetzli_transaction.h
Normal file
|
@ -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_
|
145
oss-internship-2020/guetzli/guetzli_transaction_test.cc
Normal file
145
oss-internship-2020/guetzli/guetzli_transaction_test.cc
Normal file
|
@ -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
|
BIN
oss-internship-2020/guetzli/testdata/bees.png
vendored
Normal file
BIN
oss-internship-2020/guetzli/testdata/bees.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 173 KiB |
BIN
oss-internship-2020/guetzli/testdata/bees_reference.jpg
vendored
Normal file
BIN
oss-internship-2020/guetzli/testdata/bees_reference.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
BIN
oss-internship-2020/guetzli/testdata/nature.jpg
vendored
Normal file
BIN
oss-internship-2020/guetzli/testdata/nature.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
oss-internship-2020/guetzli/testdata/nature_reference.jpg
vendored
Normal file
BIN
oss-internship-2020/guetzli/testdata/nature_reference.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
1
oss-internship-2020/openjpeg/.gitignore
vendored
Normal file
1
oss-internship-2020/openjpeg/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
build/
|
56
oss-internship-2020/openjpeg/CMakeLists.txt
Normal file
56
oss-internship-2020/openjpeg/CMakeLists.txt
Normal file
|
@ -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)
|
29
oss-internship-2020/openjpeg/README.md
Normal file
29
oss-internship-2020/openjpeg/README.md
Normal file
|
@ -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
|
||||
```
|
48
oss-internship-2020/openjpeg/examples/CMakeLists.txt
Normal file
48
oss-internship-2020/openjpeg/examples/CMakeLists.txt
Normal file
|
@ -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
|
||||
)
|
2871
oss-internship-2020/openjpeg/examples/convert.patch
Normal file
2871
oss-internship-2020/openjpeg/examples/convert.patch
Normal file
File diff suppressed because it is too large
Load Diff
135
oss-internship-2020/openjpeg/examples/convert_h.patch
Normal file
135
oss-internship-2020/openjpeg/examples/convert_h.patch
Normal file
|
@ -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);
|
157
oss-internship-2020/openjpeg/examples/decompress_example.cc
Normal file
157
oss-internship-2020/openjpeg/examples/decompress_example.cc
Normal file
|
@ -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;
|
||||
}
|
3
oss-internship-2020/pffft/.gitignore
vendored
Normal file
3
oss-internship-2020/pffft/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
*.o
|
||||
*.a
|
||||
pffft_main
|
104
oss-internship-2020/pffft/CMakeLists.txt
Normal file
104
oss-internship-2020/pffft/CMakeLists.txt
Normal file
|
@ -0,0 +1,104 @@
|
|||
# Copyright 2020 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(pffft CXX C)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
add_library(pffft STATIC
|
||||
master/pffft.c
|
||||
master/pffft.h
|
||||
master/fftpack.c
|
||||
master/fftpack.h
|
||||
)
|
||||
|
||||
add_executable(pffft_main
|
||||
master/test_pffft.c
|
||||
)
|
||||
|
||||
target_link_libraries(pffft_main PRIVATE
|
||||
pffft
|
||||
)
|
||||
|
||||
set(MATH_LIBS "")
|
||||
include(CheckLibraryExists)
|
||||
check_library_exists(m sin "" LIBM)
|
||||
if(LIBM)
|
||||
list(APPEND MATH_LIBS "m")
|
||||
endif()
|
||||
|
||||
target_link_libraries(pffft PUBLIC ${MATH_LIBS})
|
||||
|
||||
# Adding dependencies
|
||||
set(SAPI_ROOT "../.." CACHE PATH "Path to the Sandboxed API source tree")
|
||||
# Then configure:
|
||||
# mkdir -p build && cd build
|
||||
# cmake .. -G Ninja -DSAPI_ROOT=$HOME/sapi_root
|
||||
|
||||
set(SAPI_ENABLE_EXAMPLES OFF CACHE BOOL "")
|
||||
set(SAPI_ENABLE_TESTS OFF CACHE BOOL "")
|
||||
add_subdirectory("${SAPI_ROOT}"
|
||||
"${CMAKE_BINARY_DIR}/sandboxed-api-build"
|
||||
# Omit this to have the full Sandboxed API in IDE
|
||||
EXCLUDE_FROM_ALL)
|
||||
|
||||
add_sapi_library(pffft_sapi
|
||||
FUNCTIONS pffft_new_setup
|
||||
pffft_destroy_setup
|
||||
pffft_transform
|
||||
pffft_transform_ordered
|
||||
pffft_zreorder
|
||||
pffft_zconvolve_accumulate
|
||||
pffft_aligned_malloc
|
||||
pffft_aligned_free
|
||||
pffft_simd_size
|
||||
cffti
|
||||
cfftf
|
||||
cfftb
|
||||
rffti
|
||||
rfftf
|
||||
rfftb
|
||||
cosqi
|
||||
cosqf
|
||||
cosqb
|
||||
costi
|
||||
cost
|
||||
sinqi
|
||||
sinqb
|
||||
sinqf
|
||||
sinti
|
||||
sint
|
||||
|
||||
INPUTS master/pffft.h master/fftpack.h
|
||||
LIBRARY pffft
|
||||
LIBRARY_NAME Pffft
|
||||
|
||||
NAMESPACE ""
|
||||
)
|
||||
|
||||
target_include_directories(pffft_sapi INTERFACE
|
||||
"${PROJECT_BINARY_DIR}"
|
||||
)
|
||||
|
||||
add_executable(pffft_sandboxed
|
||||
main_pffft_sandboxed.cc
|
||||
)
|
||||
|
||||
target_link_libraries(pffft_sandboxed PRIVATE
|
||||
pffft_sapi
|
||||
sapi::sapi
|
||||
)
|
87
oss-internship-2020/pffft/README.md
Normal file
87
oss-internship-2020/pffft/README.md
Normal file
|
@ -0,0 +1,87 @@
|
|||
# Sandboxing PFFFT library
|
||||
|
||||
Build System: CMake
|
||||
OS: Linux
|
||||
|
||||
### Check out the PFFFT library & CMake set up
|
||||
```
|
||||
git submodule update --init --recursive
|
||||
|
||||
mkdir -p build && cd build
|
||||
cmake .. -G Ninja -DPFFFT_ROOT_DIR=$PWD
|
||||
ninjas
|
||||
```
|
||||
### For testing:
|
||||
`cd build`, then `./pffft_sandboxed`
|
||||
|
||||
### For debug:
|
||||
display custom info with
|
||||
`./pffft_sandboxed --logtostderr`
|
||||
|
||||
## ***About the project***
|
||||
*PFFFT library is concerned with 1D Fast-Fourier Transformations finding a
|
||||
compromise between accuracy and speed. It deals with real and complex
|
||||
vectors, both cases being illustrated in the testing part (`test_pffft.c`
|
||||
for initially and original version, `main_pffft_sandboxed.cc` for our
|
||||
currently implemented sandboxed version).
|
||||
The original files can be found at: https://bitbucket.org/jpommier/pffft/src.*
|
||||
|
||||
*The purpose of sandboxing is to limit the permissions and capabilities of
|
||||
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/*`
|
207
oss-internship-2020/pffft/main_pffft_sandboxed.cc
Normal file
207
oss-internship-2020/pffft/main_pffft_sandboxed.cc
Normal file
|
@ -0,0 +1,207 @@
|
|||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include "pffft_sapi.sapi.h" // NOLINT(build/include)
|
||||
#include "sandboxed_api/util/flag.h"
|
||||
#include "sandboxed_api/vars.h"
|
||||
|
||||
ABSL_DECLARE_FLAG(string, sandbox2_danger_danger_permit_all);
|
||||
ABSL_DECLARE_FLAG(string, sandbox2_danger_danger_permit_all_and_log);
|
||||
|
||||
class PffftSapiSandbox : public PffftSandbox {
|
||||
public:
|
||||
std::unique_ptr<sandbox2::Policy> ModifyPolicy(sandbox2::PolicyBuilder*) {
|
||||
return sandbox2::PolicyBuilder()
|
||||
.AllowStaticStartup()
|
||||
.AllowOpen()
|
||||
.AllowRead()
|
||||
.AllowWrite()
|
||||
.AllowSystemMalloc()
|
||||
.AllowExit()
|
||||
.AllowSyscalls({
|
||||
__NR_futex,
|
||||
__NR_close,
|
||||
__NR_getrusage,
|
||||
})
|
||||
.BuildOrDie();
|
||||
}
|
||||
};
|
||||
|
||||
// output_format flag determines whether the output shows information in detail
|
||||
// or not. By default, the flag is set as 0, meaning an elaborate display
|
||||
// (see ShowOutput method).
|
||||
static bool ValidateFlag(const char* flagname, int32_t value) {
|
||||
if (value >= 0 && value < 32768) {
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG(ERROR) << "Invalid value for --" << flagname << ".";
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFINE_int32(output_format, 0, "Value to specific the output format.");
|
||||
DEFINE_validator(output_format, &ValidateFlag);
|
||||
|
||||
double UclockSec() { return static_cast<double>(clock()) / CLOCKS_PER_SEC; }
|
||||
|
||||
void ShowOutput(const char* name, int n, int complex, float flops, float t0,
|
||||
float t1, int max_iter) {
|
||||
float mflops = flops / 1e6 / (t1 - t0 + 1e-16);
|
||||
if (FLAGS_output_format) {
|
||||
if (flops != -1) {
|
||||
printf("|%9.0f ", mflops);
|
||||
} else {
|
||||
printf("| n/a ");
|
||||
}
|
||||
} else if (flops != -1) {
|
||||
printf("n=%5d, %s %16s : %6.0f MFlops [t=%6.0f ns, %d runs]\n", n,
|
||||
(complex ? "CPLX" : "REAL"), name, mflops,
|
||||
(t1 - t0) / 2 / max_iter * 1e9, max_iter);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
absl::Status PffftMain() {
|
||||
LOG(INFO) << "Initializing sandbox...\n";
|
||||
|
||||
PffftSapiSandbox sandbox;
|
||||
SAPI_RETURN_IF_ERROR(sandbox.Init());
|
||||
|
||||
PffftApi api(&sandbox);
|
||||
|
||||
// kTransformSizes is a vector keeping the values by which iterates n, its
|
||||
// value representing the input length. More concrete, n is the number of data
|
||||
// points the caclulus is up to (determinating its accuracy). To show the
|
||||
// performance of Fast-Fourier Transformations the program is testing for
|
||||
// various values of n.
|
||||
constexpr int kTransformSizes[] = {
|
||||
64, 96, 128, 160, 192, 256, 384, 5 * 96, 512, 5 * 128,
|
||||
3 * 256, 800, 1024, 2048, 2400, 4096, 8192, 9 * 1024, 16384, 32768};
|
||||
|
||||
for (int complex : {0, 1}) {
|
||||
for (int n : kTransformSizes) {
|
||||
const int n_float = n * (complex ? 2 : 1);
|
||||
int n_bytes = n_float * sizeof(float);
|
||||
|
||||
std::vector<float> work(2 * n_float + 15, 0.0);
|
||||
sapi::v::Array<float> work_array(&work[0], work.size());
|
||||
|
||||
std::vector<float> x(n_bytes, 0.0);
|
||||
sapi::v::Array<float> x_array(&x[0], x.size());
|
||||
|
||||
std::vector<float> y(n_bytes, 0.0);
|
||||
sapi::v::Array<float> y_array(&y[0], y.size());
|
||||
|
||||
std::vector<float> z(n_bytes, 0.0);
|
||||
sapi::v::Array<float> z_array(&z[0], z.size());
|
||||
|
||||
double t0;
|
||||
double t1;
|
||||
double flops;
|
||||
|
||||
int max_iter = 5120000 / n * 4;
|
||||
|
||||
for (int k = 0; k < n_float; ++k) {
|
||||
x[k] = 0;
|
||||
}
|
||||
|
||||
// FFTPack benchmark
|
||||
{
|
||||
// SIMD_SZ == 4 (returning value of pffft_simd_size())
|
||||
int simd_size_iter = max_iter / 4;
|
||||
|
||||
if (simd_size_iter == 0) simd_size_iter = 1;
|
||||
if (complex) {
|
||||
SAPI_RETURN_IF_ERROR(api.cffti(n, work_array.PtrBoth()))
|
||||
} else {
|
||||
SAPI_RETURN_IF_ERROR(api.rffti(n, work_array.PtrBoth()));
|
||||
}
|
||||
t0 = UclockSec();
|
||||
|
||||
for (int iter = 0; iter < simd_size_iter; ++iter) {
|
||||
if (complex) {
|
||||
SAPI_RETURN_IF_ERROR(
|
||||
api.cfftf(n, x_array.PtrBoth(), work_array.PtrBoth()));
|
||||
SAPI_RETURN_IF_ERROR(
|
||||
api.cfftb(n, x_array.PtrBoth(), work_array.PtrBoth()));
|
||||
} else {
|
||||
SAPI_RETURN_IF_ERROR(
|
||||
api.rfftf(n, x_array.PtrBoth(), work_array.PtrBoth()));
|
||||
SAPI_RETURN_IF_ERROR(
|
||||
api.rfftb(n, x_array.PtrBoth(), work_array.PtrBoth()));
|
||||
}
|
||||
}
|
||||
t1 = UclockSec();
|
||||
|
||||
flops = (simd_size_iter * 2) *
|
||||
((complex ? 5 : 2.5) * static_cast<double>(n) *
|
||||
log(static_cast<double>(n)) / M_LN2);
|
||||
ShowOutput("FFTPack", n, complex, flops, t0, t1, simd_size_iter);
|
||||
}
|
||||
|
||||
// PFFFT benchmark
|
||||
{
|
||||
SAPI_ASSIGN_OR_RETURN(
|
||||
PFFFT_Setup * s,
|
||||
api.pffft_new_setup(n, complex ? PFFFT_COMPLEX : PFFFT_REAL));
|
||||
|
||||
sapi::v::RemotePtr s_reg(s);
|
||||
|
||||
t0 = UclockSec();
|
||||
for (int iter = 0; iter < max_iter; ++iter) {
|
||||
SAPI_RETURN_IF_ERROR(
|
||||
api.pffft_transform(&s_reg, x_array.PtrBoth(), z_array.PtrBoth(),
|
||||
y_array.PtrBoth(), PFFFT_FORWARD));
|
||||
SAPI_RETURN_IF_ERROR(
|
||||
api.pffft_transform(&s_reg, x_array.PtrBoth(), z_array.PtrBoth(),
|
||||
y_array.PtrBoth(), PFFFT_FORWARD));
|
||||
}
|
||||
|
||||
t1 = UclockSec();
|
||||
SAPI_RETURN_IF_ERROR(api.pffft_destroy_setup(&s_reg));
|
||||
|
||||
flops = (max_iter * 2) * ((complex ? 5 : 2.5) * static_cast<double>(n) *
|
||||
log(static_cast<double>(n)) / M_LN2);
|
||||
ShowOutput("PFFFT", n, complex, flops, t0, t1, max_iter);
|
||||
|
||||
LOG(INFO) << "n = " << n << " SUCCESSFULLY";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// Initialize Google's logging library.
|
||||
google::InitGoogleLogging(argv[0]);
|
||||
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||
|
||||
if (absl::Status status = PffftMain(); !status.ok()) {
|
||||
LOG(ERROR) << "Initialization failed: " << status.ToString();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
exports_files([
|
||||
|
@ -19,3 +21,33 @@ exports_files([
|
|||
"embed_data.bzl",
|
||||
"sapi.bzl",
|
||||
])
|
||||
|
||||
bzl_library(
|
||||
name = "build_defs_bzl",
|
||||
srcs = ["build_defs.bzl"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "embed_data_bzl",
|
||||
srcs = ["embed_data.bzl"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "proto_bzl",
|
||||
srcs = ["proto.bzl"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "repositories_bzl",
|
||||
srcs = ["repositories.bzl"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "sapi_deps_bzl",
|
||||
srcs = ["sapi_deps.bzl"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
|
||||
_FILEWRAPPER = "//sandboxed_api/tools/filewrapper"
|
||||
|
||||
# TODO(cblichmann): Convert this is to use a "_cc_toolchain" once Bazel #4370
|
||||
# is fixed.
|
||||
# TODO(cblichmann): Convert this to use a "_cc_toolchain" once Bazel #4370 is
|
||||
# fixed.
|
||||
def _sapi_cc_embed_data_impl(ctx):
|
||||
cc_file_artifact = None
|
||||
h_file_artifact = None
|
||||
|
|
|
@ -56,7 +56,7 @@ def sapi_proto_library(
|
|||
deps = [],
|
||||
alwayslink = False,
|
||||
**kwargs):
|
||||
"""Generates proto targets in various languages.
|
||||
"""Generates proto library and C++ targets.
|
||||
|
||||
Args:
|
||||
name: Name for proto_library and base for the cc_proto_library name, name +
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -23,8 +23,8 @@ namespace sapi {
|
|||
namespace comms {
|
||||
|
||||
struct ReallocRequest {
|
||||
uint64_t old_addr;
|
||||
uint64_t size;
|
||||
uintptr_t old_addr;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
// Types of TAGs used with Comms channel.
|
||||
|
|
|
@ -229,7 +229,7 @@ void HandleCallMsg(const FuncCall& call, FuncRet* ret) {
|
|||
}
|
||||
|
||||
// Handles requests to allocate memory inside the sandboxee.
|
||||
void HandleAllocMsg(const uintptr_t size, FuncRet* ret) {
|
||||
void HandleAllocMsg(const size_t size, FuncRet* ret) {
|
||||
VLOG(1) << "HandleAllocMsg: size=" << size;
|
||||
|
||||
ret->ret_type = v::Type::kPointer;
|
||||
|
@ -237,16 +237,15 @@ void HandleAllocMsg(const uintptr_t size, FuncRet* ret) {
|
|||
// Memory is copied to the pointer using an API that the memory sanitizer
|
||||
// is blind to (process_vm_writev). Initialize the memory here so that
|
||||
// the sandboxed code can still be tested with the memory sanitizer.
|
||||
ret->int_val =
|
||||
reinterpret_cast<uintptr_t>(calloc(1, static_cast<size_t>(size)));
|
||||
ret->int_val = reinterpret_cast<uintptr_t>(calloc(1, size));
|
||||
#else
|
||||
ret->int_val = reinterpret_cast<uintptr_t>(malloc(static_cast<size_t>(size)));
|
||||
ret->int_val = reinterpret_cast<uintptr_t>(malloc(size));
|
||||
#endif
|
||||
ret->success = true;
|
||||
}
|
||||
|
||||
// Like HandleAllocMsg(), but handles requests to reallocate memory.
|
||||
void HandleReallocMsg(uintptr_t ptr, uintptr_t size, FuncRet* ret) {
|
||||
void HandleReallocMsg(uintptr_t ptr, size_t size, FuncRet* ret) {
|
||||
VLOG(1) << "HandleReallocMsg(" << absl::StrCat(absl::Hex(ptr)) << ", " << size
|
||||
<< ")";
|
||||
#ifdef MEMORY_SANITIZER
|
||||
|
@ -254,8 +253,8 @@ void HandleReallocMsg(uintptr_t ptr, uintptr_t size, FuncRet* ret) {
|
|||
__sanitizer_get_allocated_size(reinterpret_cast<const void*>(ptr));
|
||||
#endif
|
||||
ret->ret_type = v::Type::kPointer;
|
||||
ret->int_val = reinterpret_cast<uintptr_t>(
|
||||
realloc(const_cast<void*>(reinterpret_cast<const void*>(ptr)), size));
|
||||
ret->int_val =
|
||||
reinterpret_cast<uintptr_t>(realloc(reinterpret_cast<void*>(ptr), size));
|
||||
ret->success = true;
|
||||
#ifdef MEMORY_SANITIZER
|
||||
// Memory is copied to the pointer using an API that the memory sanitizer
|
||||
|
@ -273,7 +272,7 @@ void HandleReallocMsg(uintptr_t ptr, uintptr_t size, FuncRet* ret) {
|
|||
void HandleFreeMsg(uintptr_t ptr, FuncRet* ret) {
|
||||
VLOG(1) << "HandleFreeMsg: free(0x" << absl::StrCat(absl::Hex(ptr)) << ")";
|
||||
|
||||
free(const_cast<void*>(reinterpret_cast<const void*>(ptr)));
|
||||
free(reinterpret_cast<void*>(ptr));
|
||||
ret->ret_type = v::Type::kVoid;
|
||||
ret->success = true;
|
||||
ret->int_val = 0ULL;
|
||||
|
@ -363,14 +362,13 @@ void ServeRequest(sandbox2::Comms* comms) {
|
|||
break;
|
||||
case comms::kMsgAllocate:
|
||||
VLOG(1) << "Client::kMsgAllocate";
|
||||
HandleAllocMsg(BytesAs<uintptr_t>(bytes), &ret);
|
||||
HandleAllocMsg(BytesAs<size_t>(bytes), &ret);
|
||||
break;
|
||||
case comms::kMsgReallocate:
|
||||
VLOG(1) << "Client::kMsgReallocate";
|
||||
{
|
||||
auto req = BytesAs<comms::ReallocRequest>(bytes);
|
||||
HandleReallocMsg(static_cast<uintptr_t>(req.old_addr),
|
||||
static_cast<uintptr_t>(req.size), &ret);
|
||||
HandleReallocMsg(req.old_addr, req.size, &ret);
|
||||
}
|
||||
break;
|
||||
case comms::kMsgFree:
|
||||
|
|
|
@ -113,7 +113,7 @@ TEST(StringopTest, RawStringReversal) {
|
|||
{
|
||||
// Let's call it again with different data as argument, reusing the
|
||||
// existing LenVal object.
|
||||
EXPECT_THAT(param.ResizeData(sandbox.GetRpcChannel(), 16), IsOk());
|
||||
EXPECT_THAT(param.ResizeData(sandbox.rpc_channel(), 16), IsOk());
|
||||
memcpy(param.GetData() + 10, "ABCDEF", 6);
|
||||
absl::string_view data(reinterpret_cast<const char*>(param.GetData()),
|
||||
param.GetDataSize());
|
||||
|
@ -134,8 +134,8 @@ TEST(StringopTest, RawStringLength) {
|
|||
ASSERT_THAT(sandbox.Init(), IsOk());
|
||||
StringopApi api(&sandbox);
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(void* target_mem_ptr, api.get_raw_c_string());
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(uint64_t len,
|
||||
sandbox.GetRpcChannel()->Strlen(target_mem_ptr));
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(size_t len,
|
||||
sandbox.rpc_channel()->Strlen(target_mem_ptr));
|
||||
EXPECT_THAT(len, Eq(10));
|
||||
}
|
||||
|
||||
|
@ -144,8 +144,8 @@ TEST(StringopTest, RawStringReading) {
|
|||
ASSERT_THAT(sandbox.Init(), IsOk());
|
||||
StringopApi api(&sandbox);
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(void* target_mem_ptr, api.get_raw_c_string());
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(uint64_t len,
|
||||
sandbox.GetRpcChannel()->Strlen(target_mem_ptr));
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(size_t len,
|
||||
sandbox.rpc_channel()->Strlen(target_mem_ptr));
|
||||
EXPECT_THAT(len, Eq(10));
|
||||
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string data,
|
||||
|
|
|
@ -161,7 +161,7 @@ absl::Status SumTransaction::Main() {
|
|||
LOG(INFO) << "Read from /proc/self/comm = [" << buffer << "]";
|
||||
|
||||
// Close test.
|
||||
SAPI_RETURN_IF_ERROR(fd2.CloseRemoteFd(sandbox()->GetRpcChannel()));
|
||||
SAPI_RETURN_IF_ERROR(fd2.CloseRemoteFd(sandbox()->rpc_channel()));
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
SAPI_RETURN_IF_ERROR(sandbox()->Call("read", &ret, &fd2, buf.PtrBoth(), &size));
|
||||
LOG(INFO) << "Read from closed /proc/self/comm = [" << buffer << "]";
|
||||
|
|
|
@ -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"
|
||||
|
@ -26,8 +27,7 @@ namespace sapi {
|
|||
absl::Status RPCChannel::Call(const FuncCall& call, uint32_t tag, FuncRet* ret,
|
||||
v::Type exp_type) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
if (!comms_->SendTLV(tag, sizeof(call),
|
||||
reinterpret_cast<const uint8_t*>(&call))) {
|
||||
if (!comms_->SendTLV(tag, sizeof(call), &call)) {
|
||||
return absl::UnavailableError("Sending TLV value failed");
|
||||
}
|
||||
SAPI_ASSIGN_OR_RETURN(auto fret, Return(exp_type));
|
||||
|
@ -35,9 +35,9 @@ 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;
|
||||
size_t len;
|
||||
FuncRet ret;
|
||||
if (!comms_->RecvTLV(&tag, &len, &ret, sizeof(ret))) {
|
||||
return absl::UnavailableError("Receiving TLV value failed");
|
||||
|
@ -66,9 +66,7 @@ sapi::StatusOr<FuncRet> RPCChannel::Return(v::Type exp_type) {
|
|||
|
||||
absl::Status RPCChannel::Allocate(size_t size, void** addr) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
uint64_t sz = size;
|
||||
if (!comms_->SendTLV(comms::kMsgAllocate, sizeof(sz),
|
||||
reinterpret_cast<uint8_t*>(&sz))) {
|
||||
if (!comms_->SendTLV(comms::kMsgAllocate, sizeof(size), &size)) {
|
||||
return absl::UnavailableError("Sending TLV value failed");
|
||||
}
|
||||
|
||||
|
@ -80,12 +78,13 @@ absl::Status RPCChannel::Allocate(size_t size, void** addr) {
|
|||
absl::Status RPCChannel::Reallocate(void* old_addr, size_t size,
|
||||
void** new_addr) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
comms::ReallocRequest req;
|
||||
req.old_addr = reinterpret_cast<uint64_t>(old_addr);
|
||||
req.size = size;
|
||||
comms::ReallocRequest req = {
|
||||
.old_addr = reinterpret_cast<uintptr_t>(old_addr),
|
||||
.size = size,
|
||||
};
|
||||
|
||||
if (!comms_->SendTLV(comms::kMsgReallocate, sizeof(comms::ReallocRequest),
|
||||
reinterpret_cast<uint8_t*>(&req))) {
|
||||
&req)) {
|
||||
return absl::UnavailableError("Sending TLV value failed");
|
||||
}
|
||||
|
||||
|
@ -102,9 +101,8 @@ absl::Status RPCChannel::Reallocate(void* old_addr, size_t size,
|
|||
|
||||
absl::Status RPCChannel::Free(void* addr) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
uint64_t remote = reinterpret_cast<uint64_t>(addr);
|
||||
if (!comms_->SendTLV(comms::kMsgFree, sizeof(remote),
|
||||
reinterpret_cast<uint8_t*>(&remote))) {
|
||||
uintptr_t remote = reinterpret_cast<uintptr_t>(addr);
|
||||
if (!comms_->SendTLV(comms::kMsgFree, sizeof(remote), &remote)) {
|
||||
return absl::UnavailableError("Sending TLV value failed");
|
||||
}
|
||||
|
||||
|
@ -117,8 +115,7 @@ absl::Status RPCChannel::Free(void* addr) {
|
|||
|
||||
absl::Status RPCChannel::Symbol(const char* symname, void** addr) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
if (!comms_->SendTLV(comms::kMsgSymbol, strlen(symname) + 1,
|
||||
reinterpret_cast<const uint8_t*>(symname))) {
|
||||
if (!comms_->SendTLV(comms::kMsgSymbol, strlen(symname) + 1, symname)) {
|
||||
return absl::UnavailableError("Sending TLV value failed");
|
||||
}
|
||||
|
||||
|
@ -136,9 +133,8 @@ absl::Status RPCChannel::Exit() {
|
|||
|
||||
// Try the RPC exit sequence. But, the only thing that matters as a success
|
||||
// indicator is whether the Comms channel had been closed
|
||||
bool unused = true;
|
||||
comms_->SendTLV(comms::kMsgExit, sizeof(unused),
|
||||
reinterpret_cast<uint8_t*>(&unused));
|
||||
comms_->SendTLV(comms::kMsgExit, 0, nullptr);
|
||||
bool unused;
|
||||
comms_->RecvBool(&unused);
|
||||
|
||||
if (!comms_->IsTerminated()) {
|
||||
|
@ -153,9 +149,7 @@ absl::Status RPCChannel::Exit() {
|
|||
|
||||
absl::Status RPCChannel::SendFD(int local_fd, int* remote_fd) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
bool unused = true;
|
||||
if (!comms_->SendTLV(comms::kMsgSendFd, sizeof(unused),
|
||||
reinterpret_cast<uint8_t*>(&unused))) {
|
||||
if (!comms_->SendTLV(comms::kMsgSendFd, 0, nullptr)) {
|
||||
return absl::UnavailableError("Sending TLV value failed");
|
||||
}
|
||||
if (!comms_->SendFD(local_fd)) {
|
||||
|
@ -172,8 +166,7 @@ absl::Status RPCChannel::SendFD(int local_fd, int* remote_fd) {
|
|||
|
||||
absl::Status RPCChannel::RecvFD(int remote_fd, int* local_fd) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
if (!comms_->SendTLV(comms::kMsgRecvFd, sizeof(remote_fd),
|
||||
reinterpret_cast<uint8_t*>(&remote_fd))) {
|
||||
if (!comms_->SendTLV(comms::kMsgRecvFd, sizeof(remote_fd), &remote_fd)) {
|
||||
return absl::UnavailableError("Sending TLV value failed");
|
||||
}
|
||||
|
||||
|
@ -190,8 +183,7 @@ absl::Status RPCChannel::RecvFD(int remote_fd, int* local_fd) {
|
|||
|
||||
absl::Status RPCChannel::Close(int remote_fd) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
if (!comms_->SendTLV(comms::kMsgClose, sizeof(remote_fd),
|
||||
reinterpret_cast<uint8_t*>(&remote_fd))) {
|
||||
if (!comms_->SendTLV(comms::kMsgClose, sizeof(remote_fd), &remote_fd)) {
|
||||
return absl::UnavailableError("Sending TLV value failed");
|
||||
}
|
||||
|
||||
|
@ -202,10 +194,9 @@ absl::Status RPCChannel::Close(int remote_fd) {
|
|||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
sapi::StatusOr<uint64_t> RPCChannel::Strlen(void* str) {
|
||||
absl::StatusOr<size_t> RPCChannel::Strlen(void* str) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
if (!comms_->SendTLV(comms::kMsgStrlen, sizeof(str),
|
||||
reinterpret_cast<uint8_t*>(&str))) {
|
||||
if (!comms_->SendTLV(comms::kMsgStrlen, sizeof(str), &str)) {
|
||||
return absl::UnavailableError("Sending TLV value failed");
|
||||
}
|
||||
|
||||
|
|
|
@ -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<size_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
|
||||
|
@ -100,7 +102,7 @@ void InitDefaultPolicyBuilder(sandbox2::PolicyBuilder* builder) {
|
|||
}
|
||||
|
||||
void Sandbox::Terminate(bool attempt_graceful_exit) {
|
||||
if (!IsActive()) {
|
||||
if (!is_active()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -129,7 +131,7 @@ static std::string PathToSAPILib(const std::string& lib_path) {
|
|||
|
||||
absl::Status Sandbox::Init() {
|
||||
// It's already initialized
|
||||
if (IsActive()) {
|
||||
if (is_active()) {
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
|
@ -156,7 +158,7 @@ absl::Status Sandbox::Init() {
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> args{lib_path};
|
||||
std::vector<std::string> args = {lib_path};
|
||||
// Additional arguments, if needed.
|
||||
GetArgs(&args);
|
||||
std::vector<std::string> envs{};
|
||||
|
@ -214,24 +216,24 @@ absl::Status Sandbox::Init() {
|
|||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
bool Sandbox::IsActive() const { return s2_ && !s2_->IsTerminated(); }
|
||||
bool Sandbox::is_active() const { return s2_ && !s2_->IsTerminated(); }
|
||||
|
||||
absl::Status Sandbox::Allocate(v::Var* var, bool automatic_free) {
|
||||
if (!IsActive()) {
|
||||
if (!is_active()) {
|
||||
return absl::UnavailableError("Sandbox not active");
|
||||
}
|
||||
return var->Allocate(GetRpcChannel(), automatic_free);
|
||||
}
|
||||
|
||||
absl::Status Sandbox::Free(v::Var* var) {
|
||||
if (!IsActive()) {
|
||||
if (!is_active()) {
|
||||
return absl::UnavailableError("Sandbox not active");
|
||||
}
|
||||
return var->Free(GetRpcChannel());
|
||||
}
|
||||
|
||||
absl::Status Sandbox::SynchronizePtrBefore(v::Callable* ptr) {
|
||||
if (!IsActive()) {
|
||||
if (!is_active()) {
|
||||
return absl::UnavailableError("Sandbox not active");
|
||||
}
|
||||
if (ptr->GetType() != v::Type::kPointer) {
|
||||
|
@ -259,11 +261,11 @@ absl::Status Sandbox::SynchronizePtrBefore(v::Callable* ptr) {
|
|||
VLOG(3) << "Synchronization (TO), ptr " << p << ", Type: " << p->GetSyncType()
|
||||
<< " for var: " << p->GetPointedVar()->ToString();
|
||||
|
||||
return p->GetPointedVar()->TransferToSandboxee(GetRpcChannel(), GetPid());
|
||||
return p->GetPointedVar()->TransferToSandboxee(GetRpcChannel(), pid());
|
||||
}
|
||||
|
||||
absl::Status Sandbox::SynchronizePtrAfter(v::Callable* ptr) const {
|
||||
if (!IsActive()) {
|
||||
if (!is_active()) {
|
||||
return absl::UnavailableError("Sandbox not active");
|
||||
}
|
||||
if (ptr->GetType() != v::Type::kPointer) {
|
||||
|
@ -287,12 +289,12 @@ absl::Status Sandbox::SynchronizePtrAfter(v::Callable* ptr) const {
|
|||
p->ToString()));
|
||||
}
|
||||
|
||||
return p->GetPointedVar()->TransferFromSandboxee(GetRpcChannel(), GetPid());
|
||||
return p->GetPointedVar()->TransferFromSandboxee(GetRpcChannel(), pid());
|
||||
}
|
||||
|
||||
absl::Status Sandbox::Call(const std::string& func, v::Callable* ret,
|
||||
std::initializer_list<v::Callable*> args) {
|
||||
if (!IsActive()) {
|
||||
if (!is_active()) {
|
||||
return absl::UnavailableError("Sandbox not active");
|
||||
}
|
||||
// Send data.
|
||||
|
@ -371,29 +373,29 @@ absl::Status Sandbox::Call(const std::string& func, v::Callable* ret,
|
|||
}
|
||||
|
||||
absl::Status Sandbox::Symbol(const char* symname, void** addr) {
|
||||
if (!IsActive()) {
|
||||
if (!is_active()) {
|
||||
return absl::UnavailableError("Sandbox not active");
|
||||
}
|
||||
return rpc_channel_->Symbol(symname, addr);
|
||||
}
|
||||
|
||||
absl::Status Sandbox::TransferToSandboxee(v::Var* var) {
|
||||
if (!IsActive()) {
|
||||
if (!is_active()) {
|
||||
return absl::UnavailableError("Sandbox not active");
|
||||
}
|
||||
return var->TransferToSandboxee(GetRpcChannel(), GetPid());
|
||||
return var->TransferToSandboxee(GetRpcChannel(), pid());
|
||||
}
|
||||
|
||||
absl::Status Sandbox::TransferFromSandboxee(v::Var* var) {
|
||||
if (!IsActive()) {
|
||||
if (!is_active()) {
|
||||
return absl::UnavailableError("Sandbox not active");
|
||||
}
|
||||
return var->TransferFromSandboxee(GetRpcChannel(), GetPid());
|
||||
return var->TransferFromSandboxee(GetRpcChannel(), pid());
|
||||
}
|
||||
|
||||
sapi::StatusOr<std::string> Sandbox::GetCString(const v::RemotePtr& str,
|
||||
uint64_t max_length) {
|
||||
if (!IsActive()) {
|
||||
absl::StatusOr<std::string> Sandbox::GetCString(const v::RemotePtr& str,
|
||||
size_t max_length) {
|
||||
if (!is_active()) {
|
||||
return absl::UnavailableError("Sandbox not active");
|
||||
}
|
||||
|
||||
|
@ -436,22 +438,25 @@ const sandbox2::Result& Sandbox::AwaitResult() {
|
|||
return result_;
|
||||
}
|
||||
|
||||
absl::Status Sandbox::SetWallTimeLimit(time_t limit) const {
|
||||
if (!IsActive()) {
|
||||
absl::Status Sandbox::SetWallTimeLimit(absl::Duration limit) const {
|
||||
if (!is_active()) {
|
||||
return absl::UnavailableError("Sandbox not active");
|
||||
}
|
||||
s2_->SetWallTimeLimit(limit);
|
||||
s2_->set_walltime_limit(limit);
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status Sandbox::SetWallTimeLimit(time_t limit) const {
|
||||
return SetWallTimeLimit(absl::Seconds(limit));
|
||||
}
|
||||
|
||||
void Sandbox::Exit() const {
|
||||
if (!IsActive()) {
|
||||
if (!is_active()) {
|
||||
return;
|
||||
}
|
||||
// Give it 1 second
|
||||
s2_->SetWallTimeLimit(1);
|
||||
s2_->set_walltime_limit(absl::Seconds(1));
|
||||
if (!rpc_channel_->Exit().ok()) {
|
||||
LOG(WARNING) << "rpc_channel->Exit() failed, killing PID: " << GetPid();
|
||||
LOG(WARNING) << "rpc_channel->Exit() failed, killing PID: " << pid();
|
||||
s2_->Kill();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,18 +35,21 @@ namespace sapi {
|
|||
// means to communicate with it (make function calls, transfer memory).
|
||||
class Sandbox {
|
||||
public:
|
||||
explicit Sandbox(const FileToc* embed_lib_toc)
|
||||
: embed_lib_toc_(embed_lib_toc) {}
|
||||
|
||||
Sandbox(const Sandbox&) = delete;
|
||||
Sandbox& operator=(const Sandbox&) = delete;
|
||||
|
||||
explicit Sandbox(const FileToc* embed_lib_toc)
|
||||
: comms_(nullptr), pid_(0), embed_lib_toc_(embed_lib_toc) {}
|
||||
virtual ~Sandbox();
|
||||
|
||||
// Initializes a new sandboxing session.
|
||||
absl::Status Init();
|
||||
|
||||
// Is the current sandboxing session alive?
|
||||
bool IsActive() const;
|
||||
ABSL_DEPRECATED("Use sapi::Sandbox::is_active() instead")
|
||||
bool IsActive() const { return is_active(); }
|
||||
// Returns whether the current sandboxing session is active.
|
||||
bool is_active() const;
|
||||
|
||||
// Terminates the current sandboxing session (if it exists).
|
||||
void Terminate(bool attempt_graceful_exit = true);
|
||||
|
@ -60,9 +63,13 @@ class Sandbox {
|
|||
// Getters for common fields.
|
||||
sandbox2::Comms* comms() const { return comms_; }
|
||||
|
||||
ABSL_DEPRECATED("Use sapi::Sandbox::rpc_channel() instead")
|
||||
RPCChannel* GetRpcChannel() const { return rpc_channel_.get(); }
|
||||
RPCChannel* rpc_channel() const { return rpc_channel_.get(); }
|
||||
|
||||
ABSL_DEPRECATED("Use sapi::Sandbox::pid() instead")
|
||||
int GetPid() const { return pid_; }
|
||||
int pid() const { return pid_; }
|
||||
|
||||
// Synchronizes the underlying memory for the pointer before the call.
|
||||
absl::Status SynchronizePtrBefore(v::Callable* ptr);
|
||||
|
@ -87,7 +94,7 @@ class Sandbox {
|
|||
// Frees memory in the sandboxee.
|
||||
absl::Status Free(v::Var* var);
|
||||
|
||||
// Finds address of a symbol in the sandboxee.
|
||||
// Finds the address of a symbol in the sandboxee.
|
||||
absl::Status Symbol(const char* symname, void** addr);
|
||||
|
||||
// Transfers memory (both directions). Status is returned (memory transfer
|
||||
|
@ -95,14 +102,18 @@ 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 = 10 * 1024 *
|
||||
1024);
|
||||
absl::StatusOr<std::string> GetCString(const v::RemotePtr& str,
|
||||
size_t max_length = 10ULL
|
||||
<< 20 /* 10 MiB*/
|
||||
);
|
||||
|
||||
// Waits until the sandbox terminated and returns the result.
|
||||
const sandbox2::Result& AwaitResult();
|
||||
const sandbox2::Result& result() const { return result_; }
|
||||
|
||||
absl::Status SetWallTimeLimit(absl::Duration limit) const;
|
||||
ABSL_DEPRECATED(
|
||||
"Use sapi::Sandbox::SetWallTimeLimit(absl::Duration) overload instead")
|
||||
absl::Status SetWallTimeLimit(time_t limit) const;
|
||||
|
||||
protected:
|
||||
|
@ -144,11 +155,11 @@ class Sandbox {
|
|||
sandbox2::Result result_;
|
||||
|
||||
// Comms with the sandboxee.
|
||||
sandbox2::Comms* comms_;
|
||||
sandbox2::Comms* comms_ = nullptr;
|
||||
// RPCChannel object.
|
||||
std::unique_ptr<RPCChannel> rpc_channel_;
|
||||
// The main pid of the sandboxee.
|
||||
pid_t pid_;
|
||||
pid_t pid_ = 0;
|
||||
|
||||
// FileTOC with the embedded library, takes precedence over GetLibPath if
|
||||
// present (not nullptr).
|
||||
|
|
|
@ -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"
|
||||
|
@ -228,7 +228,7 @@ void Comms::Terminate() {
|
|||
}
|
||||
}
|
||||
|
||||
bool Comms::SendTLV(uint32_t tag, uint64_t length, const uint8_t* bytes) {
|
||||
bool Comms::SendTLV(uint32_t tag, size_t length, const void* value) {
|
||||
if (length > GetMaxMsgSize()) {
|
||||
SAPI_RAW_LOG(ERROR, "Maximum TLV message size exceeded: (%u > %u)", length,
|
||||
GetMaxMsgSize());
|
||||
|
@ -249,14 +249,14 @@ bool Comms::SendTLV(uint32_t tag, uint64_t length, const uint8_t* bytes) {
|
|||
length);
|
||||
{
|
||||
absl::MutexLock lock(&tlv_send_transmission_mutex_);
|
||||
if (!Send(reinterpret_cast<uint8_t*>(&tag), sizeof(tag))) {
|
||||
if (!Send(&tag, sizeof(tag))) {
|
||||
return false;
|
||||
}
|
||||
if (!Send(reinterpret_cast<uint8_t*>(&length), sizeof(length))) {
|
||||
if (!Send(&length, sizeof(length))) {
|
||||
return false;
|
||||
}
|
||||
if (length > 0) {
|
||||
if (!Send(bytes, length)) {
|
||||
if (!Send(value, length)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -265,40 +265,38 @@ 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;
|
||||
}
|
||||
|
||||
bool Comms::SendString(const std::string& v) {
|
||||
return SendTLV(kTagString, v.length(),
|
||||
reinterpret_cast<const uint8_t*>(v.c_str()));
|
||||
return SendTLV(kTagString, v.length(), v.c_str());
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool Comms::SendBytes(const uint8_t* v, uint64_t len) {
|
||||
bool Comms::SendBytes(const uint8_t* v, size_t len) {
|
||||
return SendTLV(kTagBytes, len, v);
|
||||
}
|
||||
|
||||
|
@ -347,7 +345,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));
|
||||
};
|
||||
|
@ -419,7 +417,7 @@ bool Comms::SendFD(int fd) {
|
|||
int* fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
|
||||
fds[0] = fd;
|
||||
|
||||
InternalTLV tlv = {kTagFd, sizeof(tlv.val), 0};
|
||||
InternalTLV tlv = {kTagFd, 0};
|
||||
|
||||
iovec iov;
|
||||
iov.iov_base = &tlv;
|
||||
|
@ -462,8 +460,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 +472,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) {
|
||||
|
@ -513,8 +512,9 @@ socklen_t Comms::CreateSockaddrUn(sockaddr_un* sun) {
|
|||
return slen;
|
||||
}
|
||||
|
||||
bool Comms::Send(const uint8_t* bytes, uint64_t len) {
|
||||
uint64_t total_sent = 0;
|
||||
bool Comms::Send(const void* data, size_t len) {
|
||||
size_t total_sent = 0;
|
||||
const char* bytes = reinterpret_cast<const char*>(data);
|
||||
const auto op = [bytes, len, &total_sent](int fd) -> ssize_t {
|
||||
PotentiallyBlockingRegion region;
|
||||
return TEMP_FAILURE_RETRY(write(fd, &bytes[total_sent], len - total_sent));
|
||||
|
@ -545,8 +545,9 @@ bool Comms::Send(const uint8_t* bytes, uint64_t len) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Comms::Recv(uint8_t* bytes, uint64_t len) {
|
||||
uint64_t total_recv = 0;
|
||||
bool Comms::Recv(void* data, size_t len) {
|
||||
size_t total_recv = 0;
|
||||
char* bytes = reinterpret_cast<char*>(data);
|
||||
const auto op = [bytes, len, &total_recv](int fd) -> ssize_t {
|
||||
PotentiallyBlockingRegion region;
|
||||
return TEMP_FAILURE_RETRY(read(fd, &bytes[total_recv], len - total_recv));
|
||||
|
@ -573,7 +574,7 @@ bool Comms::Recv(uint8_t* bytes, uint64_t len) {
|
|||
}
|
||||
|
||||
// Internal helper method (low level).
|
||||
bool Comms::RecvTL(uint32_t* tag, uint64_t* length) {
|
||||
bool Comms::RecvTL(uint32_t* tag, size_t* length) {
|
||||
if (!Recv(reinterpret_cast<uint8_t*>(tag), sizeof(*tag))) {
|
||||
return false;
|
||||
}
|
||||
|
@ -599,50 +600,49 @@ 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;
|
||||
size_t length;
|
||||
if (!RecvTL(tag, &length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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,
|
||||
uint64_t buffer_size) {
|
||||
bool Comms::RecvTLV(uint32_t* tag, size_t* length, void* buffer,
|
||||
size_t buffer_size) {
|
||||
absl::MutexLock lock(&tlv_recv_transmission_mutex_);
|
||||
if (!RecvTL(tag, length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*length == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (*length > buffer_size) {
|
||||
SAPI_RAW_LOG(ERROR, "Buffer size too small (0x%x > 0x%x)", *length,
|
||||
buffer_size);
|
||||
return false;
|
||||
} else if (*length > 0) {
|
||||
if (!Recv(reinterpret_cast<uint8_t*>(buffer), *length)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
return Recv(reinterpret_cast<uint8_t*>(buffer), *length);
|
||||
}
|
||||
|
||||
bool Comms::RecvInt(void* buffer, uint64_t len, uint32_t tag) {
|
||||
bool Comms::RecvInt(void* buffer, size_t len, uint32_t tag) {
|
||||
uint32_t received_tag;
|
||||
uint64_t received_length;
|
||||
size_t received_length;
|
||||
if (!RecvTLV(&received_tag, &received_length, buffer, len)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ class Comms {
|
|||
static constexpr uint32_t kTagFd = 0X80000201;
|
||||
|
||||
// Any payload size above this limit will LOG(WARNING).
|
||||
static constexpr uint64_t kWarnMsgSize = (256ULL << 20);
|
||||
static constexpr size_t kWarnMsgSize = (256ULL << 20);
|
||||
|
||||
// Sandbox2-specific convention where FD=1023 is always passed to the
|
||||
// sandboxed process as a communication channel (encapsulated in the
|
||||
|
@ -103,14 +103,17 @@ class Comms {
|
|||
// Note: The actual size is "unlimited", although the Buffer API is more
|
||||
// efficient for large transfers. There is an arbitrary limit to ~2GiB to
|
||||
// avoid protobuf serialization issues.
|
||||
uint64_t GetMaxMsgSize() const { return std::numeric_limits<int32_t>::max(); }
|
||||
size_t GetMaxMsgSize() const { return std::numeric_limits<int32_t>::max(); }
|
||||
|
||||
bool SendTLV(uint32_t tag, uint64_t length, const uint8_t* bytes);
|
||||
bool SendTLV(uint32_t tag, size_t length, const void* value);
|
||||
// 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);
|
||||
bool RecvTLV(uint32_t* tag, size_t* length, void* buffer, size_t buffer_size);
|
||||
|
||||
// Sends/receives various types of data.
|
||||
bool RecvUint8(uint8_t* v) { return RecvIntGeneric(v, kTagUint8); }
|
||||
|
@ -135,7 +138,7 @@ class Comms {
|
|||
bool SendString(const std::string& v);
|
||||
|
||||
bool RecvBytes(std::vector<uint8_t>* buffer);
|
||||
bool SendBytes(const uint8_t* v, uint64_t len);
|
||||
bool SendBytes(const uint8_t* v, size_t len);
|
||||
bool SendBytes(const std::vector<uint8_t>& buffer);
|
||||
|
||||
// Receives remote process credentials.
|
||||
|
@ -174,38 +177,32 @@ 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.
|
||||
struct ABSL_ATTRIBUTE_PACKED InternalTLV {
|
||||
uint32_t tag;
|
||||
uint32_t len;
|
||||
uint64_t val;
|
||||
};
|
||||
|
||||
// Fills sockaddr_un struct with proper values.
|
||||
socklen_t CreateSockaddrUn(sockaddr_un* sun);
|
||||
|
||||
// Support for EINTR and size completion.
|
||||
bool Send(const uint8_t* bytes, uint64_t len);
|
||||
bool Recv(uint8_t* bytes, uint64_t len);
|
||||
bool Send(const void* data, size_t len);
|
||||
bool Recv(void* data, size_t len);
|
||||
|
||||
// Receives tag and length. Assumes that the `tlv_transmission_mutex_` mutex
|
||||
// is locked.
|
||||
bool RecvTL(uint32_t* tag, uint64_t* length)
|
||||
bool RecvTL(uint32_t* tag, size_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);
|
||||
bool RecvInt(void* buffer, size_t len, uint32_t tag);
|
||||
|
||||
template <typename T>
|
||||
bool RecvIntGeneric(T* output, uint32_t tag) {
|
||||
|
@ -214,7 +211,7 @@ class Comms {
|
|||
|
||||
template <typename T>
|
||||
bool SendGeneric(T value, uint32_t tag) {
|
||||
return SendTLV(tag, sizeof(T), reinterpret_cast<const uint8_t*>(&value));
|
||||
return SendTLV(tag, sizeof(T), &value);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
85
sandboxed_api/sandbox2/config.h
Normal file
85
sandboxed_api/sandbox2/config.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SANDBOXED_API_SANDBOX2_CONFIG_H_
|
||||
#define SANDBOXED_API_SANDBOX2_CONFIG_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
|
||||
// GCC/Clang define __x86_64__, Visual Studio uses _M_X64
|
||||
#if defined(__x86_64__) || defined(_M_X64)
|
||||
#define SAPI_X86_64 1
|
||||
|
||||
// Check various spellings for 64-bit POWER. Not checking for Visual Studio, as
|
||||
// it does not support 64-bit POWER.
|
||||
#elif (defined(__PPC64__) || defined(__powerpc64__) || defined(__ppc64__)) && \
|
||||
defined(ABSL_IS_LITTLE_ENDIAN)
|
||||
#define SAPI_PPC64_LE 1
|
||||
|
||||
// Spellings for AArch64
|
||||
#elif defined(__aarch64__) || defined(_M_ARM64)
|
||||
#define SAPI_ARM64 1
|
||||
#endif
|
||||
|
||||
namespace sandbox2 {
|
||||
|
||||
namespace cpu {
|
||||
|
||||
// CPU architectures known to Sandbox2
|
||||
enum Architecture : uint16_t {
|
||||
// Linux: Use a magic value, so it can be easily spotted in the seccomp-bpf
|
||||
// bytecode decompilation stream. Must be < (1<<15), as/ that's the size of
|
||||
// data which can be returned by BPF.
|
||||
kUnknown = 0xCAF0,
|
||||
kX8664,
|
||||
kX86,
|
||||
kPPC64LE,
|
||||
kArm64,
|
||||
};
|
||||
|
||||
} // namespace cpu
|
||||
|
||||
namespace host_cpu {
|
||||
|
||||
// Returns the current host CPU architecture if supported. If not supported,
|
||||
// returns cpu::kUnknown.
|
||||
constexpr cpu::Architecture Architecture() {
|
||||
#if defined(SAPI_X86_64)
|
||||
return cpu::kX8664;
|
||||
#elif defined(SAPI_PPC64_LE)
|
||||
return cpu::kPPC64LE;
|
||||
#elif defined(SAPI_ARM64)
|
||||
return cpu::kArm64;
|
||||
#else
|
||||
return cpu::kUnknown;
|
||||
#endif
|
||||
}
|
||||
|
||||
constexpr bool IsX8664() { return Architecture() == cpu::kX8664; }
|
||||
|
||||
constexpr bool IsPPC64LE() { return Architecture() == cpu::kPPC64LE; }
|
||||
|
||||
constexpr bool IsArm64() { return Architecture() == cpu::kArm64; }
|
||||
|
||||
} // namespace host_cpu
|
||||
|
||||
static_assert(host_cpu::Architecture() != cpu::kUnknown,
|
||||
"Host CPU architecture is not supported: One of x86-64, POWER64 "
|
||||
"(little endian) or AArch64 is required.");
|
||||
|
||||
} // namespace sandbox2
|
||||
|
||||
#endif // SANDBOXED_API_SANDBOX2_CONFIG_H_
|
|
@ -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 {
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user