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_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
)
# unsandboxed main
add_executable(lodepng_normal main.cc)
target_link_libraries(lodepng_normal PRIVATE lodepng)
# sandboxed main
# Build SAPI library
set(SAPI_ROOT "/usr/local/google/home/amedar/internship/sandboxed-api" CACHE PATH "Path to the Sandboxed API source tree")
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(
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 ""
"${CMAKE_BINARY_DIR}/sandboxed-api-build"
EXCLUDE_FROM_ALL
)
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
"${PROJECT_BINARY_DIR}" # To find the generated SAPI header
)
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
)
# 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)
add_subdirectory(examples)

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
- ~~check return value of functions~~
- ~~integrate unit testing~~
- add more functions
- this readme
- remove path from CMakeLists.txt
- include abseil flags for unit testing
- ~~improve tests (images, generating images etc.)~~
- clear redundant includes
- check if security policy can be stricter
- ~~check if security policy can be stricter~~
- ~~use addDirectoryAt instead of addDirectory~~
- ~~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
// limitations under the License.
#include <stdio.h>
#include <stdlib.h>
#include <cassert>
#include <filesystem>
#include <iostream>
#include "lodepng/lodepng.h"
constexpr unsigned int img_len(unsigned int width, unsigned int height) {
return width * height * 4;
}
#include "../lodepng/lodepng.h"
void generate_one_step(const std::string &images_path) {
unsigned int width = 512, height = 512;
std::vector<unsigned char> image(img_len(width, height));
constexpr unsigned int width = 512, height = 512,
img_len = width * height * 4;
std::vector<unsigned char> image(img_len);
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
@ -59,15 +53,16 @@ void generate_one_step(const std::string &images_path) {
assert(height2 == height);
// 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]);
}
}
void generate_two_steps(const std::string &images_path) {
// generate the values
unsigned int width = 512, height = 512;
std::vector<unsigned char> image(img_len(width, height));
constexpr unsigned int width = 512, height = 512,
img_len = width * height * 4;
std::vector<unsigned char> image(img_len);
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
@ -112,7 +107,7 @@ void generate_two_steps(const std::string &images_path) {
assert(height2 == height);
// 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]);
}
}

View File

@ -12,15 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <stdlib.h>
#include <cassert>
#include <cstdlib>
#include <filesystem>
#include <iostream>
#include "lodepng_sapi.sapi.h"
#include "sandbox.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(),
"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) {
unsigned int width = 512, height = 512;
std::vector<unsigned char> image(img_len(width, height));
constexpr unsigned int width = 512, height = 512,
img_len = width * height * 4;
std::vector<unsigned char> image(img_len);
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
@ -47,8 +39,7 @@ void generate_one_step(SapiLodepngSandbox &sandbox, LodepngApi &api) {
}
// encode the image
sapi::v::Array<unsigned char> sapi_image(image.data(),
img_len(width, height));
sapi::v::Array<unsigned char> sapi_image(image.data(), img_len);
sapi::v::UInt sapi_width(width), sapi_height(height);
std::string filename = "/output/out_generated1.png";
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
// the pointer and the length)
sapi::v::RemotePtr sapi_remote_out_ptr(sapi_image_ptr.GetValue());
sapi::v::Array<unsigned char> sapi_pixels(
img_len(sapi_width2.GetValue(), sapi_height2.GetValue()));
sapi::v::Array<unsigned char> sapi_pixels(img_len);
sapi_pixels.SetRemote(sapi_remote_out_ptr.GetValue());
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();
// 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]);
}
}
void generate_two_steps(SapiLodepngSandbox &sandbox, LodepngApi &api) {
// generate the values
unsigned int width = 512, height = 512;
std::vector<unsigned char> image(img_len(width, height));
constexpr unsigned int width = 512, height = 512,
img_len = width * height * 4;
std::vector<unsigned char> image(img_len);
for (int y = 0; y < height; ++y) {
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
sapi::v::Array<unsigned char> sapi_image(image.data(),
img_len(width, height));
sapi::v::Array<unsigned char> sapi_image(image.data(), img_len);
sapi::v::UInt sapi_width(width), sapi_height(height);
std::string filename = "/output/out_generated2.png";
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
sapi::v::RemotePtr sapi_remote_out_ptr3(sapi_png_ptr3.GetValue());
sapi::v::Array<unsigned char> sapi_pixels(
img_len(sapi_width2.GetValue(), sapi_height2.GetValue()));
sapi::v::Array<unsigned char> sapi_pixels(img_len);
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();
// 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]);
}
}
int main(int argc, char *argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
absl::Status ret;
std::string images_path(absl::GetFlag(FLAGS_images_path));
SapiLodepngSandbox sandbox(images_path);
ret = sandbox.Init();
if (!ret.ok()) {
std::cerr << "error code: " << ret.code() << std::endl
<< "message: " << ret.message() << std::endl;
exit(1);
}
assert(sandbox.Init().ok());
LodepngApi api(&sandbox);
@ -225,4 +208,4 @@ int main(int argc, char *argv[]) {
generate_two_steps(sandbox, api);
return EXIT_SUCCESS;
}
}

View File

@ -12,15 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdlib.h>
#include <filesystem>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "lodepng_sapi.sapi.h"
#include "sandbox.h"
#include "sandboxed_api/util/flag.h"
#include "sandboxed_api/util/status_matchers.h"
using sapi::IsOk;
@ -29,10 +24,6 @@ using testing::NotNull;
namespace {
constexpr unsigned int img_len(unsigned int width, unsigned int height) {
return width * height * 4;
}
// use the current path
std::string images_path = std::filesystem::current_path().string();
@ -49,8 +40,9 @@ TEST(generate_image, encode_decode_compare_one_step) {
LodepngApi api(&sandbox);
// generate the values
unsigned int width = 512, height = 512;
std::vector<unsigned char> image(img_len(width, height));
constexpr unsigned int width = 512, height = 512,
img_len = width * height * 4;
std::vector<unsigned char> image(img_len);
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
@ -62,8 +54,7 @@ TEST(generate_image, encode_decode_compare_one_step) {
}
// encode the image
sapi::v::Array<unsigned char> sapi_image(image.data(),
img_len(width, height));
sapi::v::Array<unsigned char> sapi_image(image.data(), img_len);
sapi::v::UInt sapi_width(width), sapi_height(height);
std::string filename = "/output/out_generated1.png";
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
// the pointer and the length)
sapi::v::RemotePtr sapi_remote_out_ptr(sapi_image_ptr.GetValue());
sapi::v::Array<unsigned char> sapi_pixels(
img_len(sapi_width2.GetValue(), sapi_height2.GetValue()));
sapi::v::Array<unsigned char> sapi_pixels(img_len);
sapi_pixels.SetRemote(sapi_remote_out_ptr.GetValue());
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();
// 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";
}
}
@ -128,8 +118,9 @@ TEST(generate_image, encode_decode_compare_two_steps) {
LodepngApi api(&sandbox);
// generate the values
unsigned int width = 512, height = 512;
std::vector<unsigned char> image(img_len(width, height));
constexpr unsigned int width = 512, height = 512,
img_len = width * height * 4;
std::vector<unsigned char> image(img_len);
for (int y = 0; y < height; ++y) {
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
sapi::v::Array<unsigned char> sapi_image(image.data(),
img_len(width, height));
sapi::v::Array<unsigned char> sapi_image(image.data(), img_len);
sapi::v::UInt sapi_width(width), sapi_height(height);
std::string filename = "/output/out_generated2.png";
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
sapi::v::RemotePtr sapi_remote_out_ptr3(sapi_png_ptr3.GetValue());
sapi::v::Array<unsigned char> sapi_pixels(
img_len(sapi_width2.GetValue(), sapi_height2.GetValue()));
sapi::v::Array<unsigned char> sapi_pixels(img_len);
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();
// 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";
}
}

View File

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