moved code in examples directory, modified README

This commit is contained in:
Andrei Medar 2020-08-14 15:56:57 +00:00
parent 18f58da954
commit eb2a2c023b
7 changed files with 159 additions and 128 deletions

View File

@ -19,69 +19,51 @@ project(lodepng_sapi CXX)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED 17) set(CMAKE_CXX_STANDARD_REQUIRED 17)
add_library(lodepng STATIC lodepng/lodepng.cpp lodepng/lodepng.h) # Build static library
add_library(lodepng STATIC
lodepng/lodepng.cpp
lodepng/lodepng.h
)
# Build SAPI library
# unsandboxed main
add_executable(lodepng_normal main.cc)
target_link_libraries(lodepng_normal PRIVATE lodepng)
# sandboxed main
set(SAPI_ROOT "/usr/local/google/home/amedar/internship/sandboxed-api" CACHE PATH "Path to the Sandboxed API source tree") set(SAPI_ROOT "/usr/local/google/home/amedar/internship/sandboxed-api" CACHE PATH "Path to the Sandboxed API source tree")
add_subdirectory("${SAPI_ROOT}" add_subdirectory("${SAPI_ROOT}"
"${CMAKE_BINARY_DIR}/sandboxed-api-build" "${CMAKE_BINARY_DIR}/sandboxed-api-build"
# Omit this to have the full Sandboxed API in IDE EXCLUDE_FROM_ALL
EXCLUDE_FROM_ALL)
add_sapi_library(
lodepng_sapi
FUNCTIONS lodepng_decode32_file
lodepng_encode32_file
lodepng_encode32
lodepng_save_file
lodepng_load_file
lodepng_decode32
INPUTS lodepng/lodepng.h
LIBRARY lodepng
LIBRARY_NAME Lodepng
NAMESPACE ""
) )
add_sapi_library(
lodepng_sapi
FUNCTIONS
lodepng_decode_memory
lodepng_decode32
lodepng_decode24
lodepng_decode_file
lodepng_decode32_file
lodepng_decode24_file
lodepng_encode_memory
lodepng_encode32
lodepng_encode24
lodepng_encode_file
lodepng_encode32_file
lodepng_encode24_file
lodepng_save_file
lodepng_load_file
INPUTS lodepng/lodepng.h
LIBRARY lodepng
LIBRARY_NAME Lodepng
NAMESPACE ""
)
target_include_directories(lodepng_sapi INTERFACE target_include_directories(lodepng_sapi INTERFACE
"${PROJECT_BINARY_DIR}" # To find the generated SAPI header "${PROJECT_BINARY_DIR}" # To find the generated SAPI header
) )
add_executable(lodepng_sandboxed main_sandboxed.cc sandbox.h) add_subdirectory(examples)
target_link_libraries(lodepng_sandboxed PRIVATE
lodepng_sapi
sapi::sapi
sapi::vars
sapi::status
glog::glog
)
# gtest
include(GoogleTest)
enable_testing()
add_executable(main_unit_test
main_unit_test.cc
)
target_link_libraries(main_unit_test PRIVATE
lodepng_sapi
absl::memory
absl::strings
absl::time
glog::glog
sapi::flags
sapi::sapi
sapi::status
sapi::test_main
sapi::vars
)
gtest_discover_tests(main_unit_test)

View File

@ -1,15 +1,40 @@
# LodePng Sandboxed
Sandboxed version of the [lodepng](https://github.com/lvandeve/lodepng) library, using [Sandboxed API](https://github.com/google/sandboxed-api)
## Details
With Sandboxed API, many of the library's functions can be sandboxed. However, they need the `extern "C"` keyword defined so that name mangling does not happen, which is why a fork of the **lodepng** library is used. The only differences are found in the header file. An alternative to this is to define another library that wraps every needed function, specifying the required keyword.
Even if many of the functions from the library can be sandboxed, there are some that are not supported (those which have `std::vector` parameters, overloaded functions etc.). If you really need these functions, a solution is to implement a custom library that wraps around these functions in order to make them compatible.
## Examples
The code found in the **examples** folder features a basic use case of the library. An image is generated, encoded into a file and then decoded to check that the values are the same. The encoding part was based on [this example](https://github.com/lvandeve/lodepng/blob/master/examples/example_encode.c) while decoding was based on [this](https://github.com/lvandeve/lodepng/blob/master/examples/example_decode.c).
This folder is structured as:
- `main.cc` - unsandboxed example
- `sandbox.h` - custom sandbox policy
- `main_sandboxed.cc` - sandboxed version of the example
- `main_unit_test.cc` - testing file using [Google Test](https://github.com/google/googletest).
The executables generated from these files will create the png files in the current directory. However, for the
`main_sandboxed.cc` file there is also the `images_path` flag which can be used to specify a different directory.
<!--
TODO TODO
- ~~check return value of functions~~ - ~~check return value of functions~~
- ~~integrate unit testing~~ - ~~integrate unit testing~~
- add more functions - add more functions
- this readme - this readme
- remove path from CMakeLists.txt
- include abseil flags for unit testing - include abseil flags for unit testing
- ~~improve tests (images, generating images etc.)~~ - ~~improve tests (images, generating images etc.)~~
- clear redundant includes - clear redundant includes
- check if security policy can be stricter - ~~check if security policy can be stricter~~
- ~~use addDirectoryAt instead of addDirectory~~ - ~~use addDirectoryAt instead of addDirectory~~
- ~~modify tests assertions~~ - ~~modify tests assertions~~
- ``add useful prints to unit tests`` - ~~add useful prints to unit tests~~
- ~~move examples to examples folder~~
-->

View File

@ -0,0 +1,58 @@
# 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.
# Build the unsandboxed main
add_executable(lodepng_normal
main.cc
)
target_link_libraries(lodepng_normal PRIVATE
lodepng
)
# Build the sandboxed main
add_executable(lodepng_sandboxed
main_sandboxed.cc
sandbox.h
)
target_link_libraries(lodepng_sandboxed PRIVATE
lodepng_sapi
sapi::sapi
sapi::vars
sapi::status
glog::glog
)
# Build the unit tests
include(GoogleTest)
enable_testing()
add_executable(main_unit_test
main_unit_test.cc
)
target_link_libraries(main_unit_test PRIVATE
lodepng_sapi
absl::memory
absl::strings
absl::time
glog::glog
sapi::flags
sapi::sapi
sapi::status
sapi::test_main
sapi::vars
)
gtest_discover_tests(main_unit_test)

View File

@ -12,22 +12,16 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include <stdio.h>
#include <stdlib.h>
#include <cassert> #include <cassert>
#include <filesystem> #include <filesystem>
#include <iostream> #include <iostream>
#include "lodepng/lodepng.h" #include "../lodepng/lodepng.h"
constexpr unsigned int img_len(unsigned int width, unsigned int height) {
return width * height * 4;
}
void generate_one_step(const std::string &images_path) { void generate_one_step(const std::string &images_path) {
unsigned int width = 512, height = 512; constexpr unsigned int width = 512, height = 512,
std::vector<unsigned char> image(img_len(width, height)); img_len = width * height * 4;
std::vector<unsigned char> image(img_len);
for (int y = 0; y < height; ++y) { for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) { for (int x = 0; x < width; ++x) {
@ -59,15 +53,16 @@ void generate_one_step(const std::string &images_path) {
assert(height2 == height); assert(height2 == height);
// now, we can compare the values // now, we can compare the values
for (size_t i = 0; i < img_len(width, height); ++i) { for (size_t i = 0; i < img_len; ++i) {
assert(image2[i] == image[i]); assert(image2[i] == image[i]);
} }
} }
void generate_two_steps(const std::string &images_path) { void generate_two_steps(const std::string &images_path) {
// generate the values // generate the values
unsigned int width = 512, height = 512; constexpr unsigned int width = 512, height = 512,
std::vector<unsigned char> image(img_len(width, height)); img_len = width * height * 4;
std::vector<unsigned char> image(img_len);
for (int y = 0; y < height; ++y) { for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) { for (int x = 0; x < width; ++x) {
@ -112,7 +107,7 @@ void generate_two_steps(const std::string &images_path) {
assert(height2 == height); assert(height2 == height);
// compare values // compare values
for (size_t i = 0; i < img_len(width, height); ++i) { for (size_t i = 0; i < img_len; ++i) {
assert(image2[i] == image[i]); assert(image2[i] == image[i]);
} }
} }

View File

@ -12,15 +12,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include <stdio.h>
#include <stdlib.h>
#include <cassert> #include <cassert>
#include <cstdlib>
#include <filesystem> #include <filesystem>
#include <iostream> #include <iostream>
#include "lodepng_sapi.sapi.h"
#include "sandbox.h" #include "sandbox.h"
#include "sandboxed_api/util/flag.h" #include "sandboxed_api/util/flag.h"
@ -29,13 +24,10 @@ ABSL_DECLARE_FLAG(string, sandbox2_danger_danger_permit_all_and_log);
ABSL_FLAG(string, images_path, std::filesystem::current_path().string(), ABSL_FLAG(string, images_path, std::filesystem::current_path().string(),
"path to the folder containing test images"); "path to the folder containing test images");
constexpr unsigned int img_len(unsigned int width, unsigned int height) {
return width * height * 4;
}
void generate_one_step(SapiLodepngSandbox &sandbox, LodepngApi &api) { void generate_one_step(SapiLodepngSandbox &sandbox, LodepngApi &api) {
unsigned int width = 512, height = 512; constexpr unsigned int width = 512, height = 512,
std::vector<unsigned char> image(img_len(width, height)); img_len = width * height * 4;
std::vector<unsigned char> image(img_len);
for (int y = 0; y < height; ++y) { for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) { for (int x = 0; x < width; ++x) {
@ -47,8 +39,7 @@ void generate_one_step(SapiLodepngSandbox &sandbox, LodepngApi &api) {
} }
// encode the image // encode the image
sapi::v::Array<unsigned char> sapi_image(image.data(), sapi::v::Array<unsigned char> sapi_image(image.data(), img_len);
img_len(width, height));
sapi::v::UInt sapi_width(width), sapi_height(height); sapi::v::UInt sapi_width(width), sapi_height(height);
std::string filename = "/output/out_generated1.png"; std::string filename = "/output/out_generated1.png";
sapi::v::ConstCStr sapi_filename(filename.c_str()); sapi::v::ConstCStr sapi_filename(filename.c_str());
@ -86,8 +77,7 @@ void generate_one_step(SapiLodepngSandbox &sandbox, LodepngApi &api) {
// 4) transfer the memory to this process (this step is why we need // 4) transfer the memory to this process (this step is why we need
// the pointer and the length) // the pointer and the length)
sapi::v::RemotePtr sapi_remote_out_ptr(sapi_image_ptr.GetValue()); sapi::v::RemotePtr sapi_remote_out_ptr(sapi_image_ptr.GetValue());
sapi::v::Array<unsigned char> sapi_pixels( sapi::v::Array<unsigned char> sapi_pixels(img_len);
img_len(sapi_width2.GetValue(), sapi_height2.GetValue()));
sapi_pixels.SetRemote(sapi_remote_out_ptr.GetValue()); sapi_pixels.SetRemote(sapi_remote_out_ptr.GetValue());
assert(sandbox.TransferFromSandboxee(&sapi_pixels).ok()); assert(sandbox.TransferFromSandboxee(&sapi_pixels).ok());
@ -97,15 +87,16 @@ void generate_one_step(SapiLodepngSandbox &sandbox, LodepngApi &api) {
unsigned char *pixels_ptr = sapi_pixels.GetData(); unsigned char *pixels_ptr = sapi_pixels.GetData();
// now, we can compare the values // now, we can compare the values
for (size_t i = 0; i < img_len(width, height); ++i) { for (size_t i = 0; i < img_len; ++i) {
assert(pixels_ptr[i] == image[i]); assert(pixels_ptr[i] == image[i]);
} }
} }
void generate_two_steps(SapiLodepngSandbox &sandbox, LodepngApi &api) { void generate_two_steps(SapiLodepngSandbox &sandbox, LodepngApi &api) {
// generate the values // generate the values
unsigned int width = 512, height = 512; constexpr unsigned int width = 512, height = 512,
std::vector<unsigned char> image(img_len(width, height)); img_len = width * height * 4;
std::vector<unsigned char> image(img_len);
for (int y = 0; y < height; ++y) { for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) { for (int x = 0; x < width; ++x) {
@ -117,8 +108,7 @@ void generate_two_steps(SapiLodepngSandbox &sandbox, LodepngApi &api) {
} }
// encode the image into memory first // encode the image into memory first
sapi::v::Array<unsigned char> sapi_image(image.data(), sapi::v::Array<unsigned char> sapi_image(image.data(), img_len);
img_len(width, height));
sapi::v::UInt sapi_width(width), sapi_height(height); sapi::v::UInt sapi_width(width), sapi_height(height);
std::string filename = "/output/out_generated2.png"; std::string filename = "/output/out_generated2.png";
sapi::v::ConstCStr sapi_filename(filename.c_str()); sapi::v::ConstCStr sapi_filename(filename.c_str());
@ -190,8 +180,7 @@ void generate_two_steps(SapiLodepngSandbox &sandbox, LodepngApi &api) {
// transfer the pixels so they can be used // transfer the pixels so they can be used
sapi::v::RemotePtr sapi_remote_out_ptr3(sapi_png_ptr3.GetValue()); sapi::v::RemotePtr sapi_remote_out_ptr3(sapi_png_ptr3.GetValue());
sapi::v::Array<unsigned char> sapi_pixels( sapi::v::Array<unsigned char> sapi_pixels(img_len);
img_len(sapi_width2.GetValue(), sapi_height2.GetValue()));
sapi_pixels.SetRemote(sapi_remote_out_ptr3.GetValue()); sapi_pixels.SetRemote(sapi_remote_out_ptr3.GetValue());
@ -200,24 +189,18 @@ void generate_two_steps(SapiLodepngSandbox &sandbox, LodepngApi &api) {
unsigned char *pixels_ptr = sapi_pixels.GetData(); unsigned char *pixels_ptr = sapi_pixels.GetData();
// compare values // compare values
for (size_t i = 0; i < img_len(width, height); ++i) { for (size_t i = 0; i < img_len; ++i) {
assert(pixels_ptr[i] == image[i]); assert(pixels_ptr[i] == image[i]);
} }
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true); gflags::ParseCommandLineFlags(&argc, &argv, true);
absl::Status ret;
std::string images_path(absl::GetFlag(FLAGS_images_path)); std::string images_path(absl::GetFlag(FLAGS_images_path));
SapiLodepngSandbox sandbox(images_path); SapiLodepngSandbox sandbox(images_path);
ret = sandbox.Init(); assert(sandbox.Init().ok());
if (!ret.ok()) {
std::cerr << "error code: " << ret.code() << std::endl
<< "message: " << ret.message() << std::endl;
exit(1);
}
LodepngApi api(&sandbox); LodepngApi api(&sandbox);

View File

@ -12,15 +12,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include <stdlib.h>
#include <filesystem> #include <filesystem>
#include "gmock/gmock.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "lodepng_sapi.sapi.h"
#include "sandbox.h" #include "sandbox.h"
#include "sandboxed_api/util/flag.h"
#include "sandboxed_api/util/status_matchers.h" #include "sandboxed_api/util/status_matchers.h"
using sapi::IsOk; using sapi::IsOk;
@ -29,10 +24,6 @@ using testing::NotNull;
namespace { namespace {
constexpr unsigned int img_len(unsigned int width, unsigned int height) {
return width * height * 4;
}
// use the current path // use the current path
std::string images_path = std::filesystem::current_path().string(); std::string images_path = std::filesystem::current_path().string();
@ -49,8 +40,9 @@ TEST(generate_image, encode_decode_compare_one_step) {
LodepngApi api(&sandbox); LodepngApi api(&sandbox);
// generate the values // generate the values
unsigned int width = 512, height = 512; constexpr unsigned int width = 512, height = 512,
std::vector<unsigned char> image(img_len(width, height)); img_len = width * height * 4;
std::vector<unsigned char> image(img_len);
for (int y = 0; y < height; ++y) { for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) { for (int x = 0; x < width; ++x) {
@ -62,8 +54,7 @@ TEST(generate_image, encode_decode_compare_one_step) {
} }
// encode the image // encode the image
sapi::v::Array<unsigned char> sapi_image(image.data(), sapi::v::Array<unsigned char> sapi_image(image.data(), img_len);
img_len(width, height));
sapi::v::UInt sapi_width(width), sapi_height(height); sapi::v::UInt sapi_width(width), sapi_height(height);
std::string filename = "/output/out_generated1.png"; std::string filename = "/output/out_generated1.png";
sapi::v::ConstCStr sapi_filename(filename.c_str()); sapi::v::ConstCStr sapi_filename(filename.c_str());
@ -102,8 +93,7 @@ TEST(generate_image, encode_decode_compare_one_step) {
// 4) transfer the memory to this process (this step is why we need // 4) transfer the memory to this process (this step is why we need
// the pointer and the length) // the pointer and the length)
sapi::v::RemotePtr sapi_remote_out_ptr(sapi_image_ptr.GetValue()); sapi::v::RemotePtr sapi_remote_out_ptr(sapi_image_ptr.GetValue());
sapi::v::Array<unsigned char> sapi_pixels( sapi::v::Array<unsigned char> sapi_pixels(img_len);
img_len(sapi_width2.GetValue(), sapi_height2.GetValue()));
sapi_pixels.SetRemote(sapi_remote_out_ptr.GetValue()); sapi_pixels.SetRemote(sapi_remote_out_ptr.GetValue());
ASSERT_THAT(sandbox.TransferFromSandboxee(&sapi_pixels), IsOk()) ASSERT_THAT(sandbox.TransferFromSandboxee(&sapi_pixels), IsOk())
@ -114,7 +104,7 @@ TEST(generate_image, encode_decode_compare_one_step) {
unsigned char *pixels_ptr = sapi_pixels.GetData(); unsigned char *pixels_ptr = sapi_pixels.GetData();
// now, we can compare the values // now, we can compare the values
for (size_t i = 0; i < img_len(width, height); ++i) { for (size_t i = 0; i < img_len; ++i) {
EXPECT_THAT(pixels_ptr[i], Eq(image[i])) << "Pixels values differ"; EXPECT_THAT(pixels_ptr[i], Eq(image[i])) << "Pixels values differ";
} }
} }
@ -128,8 +118,9 @@ TEST(generate_image, encode_decode_compare_two_steps) {
LodepngApi api(&sandbox); LodepngApi api(&sandbox);
// generate the values // generate the values
unsigned int width = 512, height = 512; constexpr unsigned int width = 512, height = 512,
std::vector<unsigned char> image(img_len(width, height)); img_len = width * height * 4;
std::vector<unsigned char> image(img_len);
for (int y = 0; y < height; ++y) { for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) { for (int x = 0; x < width; ++x) {
@ -141,8 +132,7 @@ TEST(generate_image, encode_decode_compare_two_steps) {
} }
// encode the image into memory first // encode the image into memory first
sapi::v::Array<unsigned char> sapi_image(image.data(), sapi::v::Array<unsigned char> sapi_image(image.data(), img_len);
img_len(width, height));
sapi::v::UInt sapi_width(width), sapi_height(height); sapi::v::UInt sapi_width(width), sapi_height(height);
std::string filename = "/output/out_generated2.png"; std::string filename = "/output/out_generated2.png";
sapi::v::ConstCStr sapi_filename(filename.c_str()); sapi::v::ConstCStr sapi_filename(filename.c_str());
@ -219,8 +209,7 @@ TEST(generate_image, encode_decode_compare_two_steps) {
// transfer the pixels so they can be used // transfer the pixels so they can be used
sapi::v::RemotePtr sapi_remote_out_ptr3(sapi_png_ptr3.GetValue()); sapi::v::RemotePtr sapi_remote_out_ptr3(sapi_png_ptr3.GetValue());
sapi::v::Array<unsigned char> sapi_pixels( sapi::v::Array<unsigned char> sapi_pixels(img_len);
img_len(sapi_width2.GetValue(), sapi_height2.GetValue()));
sapi_pixels.SetRemote(sapi_remote_out_ptr3.GetValue()); sapi_pixels.SetRemote(sapi_remote_out_ptr3.GetValue());
@ -230,7 +219,7 @@ TEST(generate_image, encode_decode_compare_two_steps) {
unsigned char *pixels_ptr = sapi_pixels.GetData(); unsigned char *pixels_ptr = sapi_pixels.GetData();
// compare values // compare values
for (size_t i = 0; i < img_len(width, height); ++i) { for (size_t i = 0; i < img_len; ++i) {
EXPECT_THAT(pixels_ptr[i], Eq(image[i])) << "Pixel values differ"; EXPECT_THAT(pixels_ptr[i], Eq(image[i])) << "Pixel values differ";
} }
} }

View File

@ -16,7 +16,6 @@
#define SAPI_LODEPNG_SANDBOX_H_ #define SAPI_LODEPNG_SANDBOX_H_
#include <syscall.h> #include <syscall.h>
#include <unistd.h>
#include "lodepng_sapi.sapi.h" #include "lodepng_sapi.sapi.h"