mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
Add external embedding example
This change contains a "hello world"-style example library to be sandboxed. It consists of a stand-alone CMake and Bazel project that uses Sandboxed API as its dependency. To use Sandboxed API in an external project, it should be enough to copy the files in the `sandboxed_api/examples/hello_sapi` directory as a starting point.
This commit is contained in:
parent
ba47adc21d
commit
2c8c9a489a
2
sandboxed_api/examples/hello_sapi/.bazelrc
Normal file
2
sandboxed_api/examples/hello_sapi/.bazelrc
Normal file
|
@ -0,0 +1,2 @@
|
|||
# Build in C++17 mode without a custom CROSSTOOL
|
||||
build --cxxopt=-std=c++17
|
60
sandboxed_api/examples/hello_sapi/BUILD.bazel
Normal file
60
sandboxed_api/examples/hello_sapi/BUILD.bazel
Normal file
|
@ -0,0 +1,60 @@
|
|||
# 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",
|
||||
)
|
||||
|
||||
# Library with code that should be sandboxed
|
||||
cc_library(
|
||||
name = "hello_lib",
|
||||
srcs = ["hello_lib.cc"],
|
||||
alwayslink = 1,
|
||||
)
|
||||
|
||||
# Sandboxed API for the library above
|
||||
sapi_library(
|
||||
name = "hello_sapi",
|
||||
functions = [
|
||||
"AddTwoIntegers",
|
||||
],
|
||||
input_files = ["hello_lib.cc"],
|
||||
lib = ":hello_lib",
|
||||
lib_name = "Hello",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
# Main executable demonstrating how the sandboxed library is used
|
||||
cc_binary(
|
||||
name = "hello",
|
||||
srcs = ["hello_main.cc"],
|
||||
copts = ["-I."], # To find the generated header
|
||||
deps = [":hello_sapi"],
|
||||
)
|
||||
|
||||
# Another example using the same library, but using the Transaction API that
|
||||
# automatically retries sandbox operations. Also demonstates error handling
|
||||
# and a custom security policy.
|
||||
cc_binary(
|
||||
name = "hello_transacted",
|
||||
srcs = ["hello_transacted.cc"],
|
||||
copts = ["-I."], # To find the generated header
|
||||
deps = [
|
||||
":hello_sapi",
|
||||
"@com_google_absl//absl/memory",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_sandboxed_api//sandboxed_api/util:status",
|
||||
],
|
||||
)
|
82
sandboxed_api/examples/hello_sapi/CMakeLists.txt
Normal file
82
sandboxed_api/examples/hello_sapi/CMakeLists.txt
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.
|
||||
|
||||
# Example that demonstrates how to embed Sandboxed API into a project using
|
||||
# CMake.
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
project(hello_sapi_project CXX)
|
||||
|
||||
# Path to the Sandboxed API source tree. Unlike Bazel, CMake does not download
|
||||
# downstream dependencies by default. So the option below needs to be adjusted
|
||||
# to point to a local checkout or a Git submodule.
|
||||
# The default value is chosen so that this example can be easily tried out for
|
||||
# a regular checkout of Sandboxed API.
|
||||
set(SAPI_ROOT "${PROJECT_SOURCE_DIR}/../../.."
|
||||
CACHE PATH "Path to the Sandboxed API source tree")
|
||||
|
||||
# Configure options and include Sandboxed API as a sub-directory.
|
||||
set(SAPI_ENABLE_EXAMPLES OFF CACHE BOOL "")
|
||||
set(SAPI_ENABLE_TESTS OFF CACHE BOOL "")
|
||||
add_subdirectory("${SAPI_ROOT}"
|
||||
"${CMAKE_BINARY_DIR}/sandboxed-api-build" EXCLUDE_FROM_ALL)
|
||||
|
||||
# Interface library with common settings for this projects
|
||||
add_library(hello_base INTERFACE)
|
||||
add_library(hello::base ALIAS hello_base)
|
||||
target_compile_features(hello_base INTERFACE cxx_std_17)
|
||||
target_include_directories(hello_base INTERFACE
|
||||
"${PROJECT_BINARY_DIR}" # To find the generated SAPI header
|
||||
)
|
||||
|
||||
# Library with code that should be sandboxed
|
||||
add_library(hello_lib STATIC
|
||||
hello_lib.cc
|
||||
)
|
||||
target_link_libraries(hello_lib PRIVATE
|
||||
hello::base
|
||||
)
|
||||
|
||||
# Sandboxed API for the library above
|
||||
add_sapi_library(hello_sapi
|
||||
FUNCTIONS AddTwoIntegers
|
||||
INPUTS hello_lib.cc
|
||||
LIBRARY hello_lib
|
||||
LIBRARY_NAME Hello
|
||||
NAMESPACE ""
|
||||
)
|
||||
add_library(hello::sapi ALIAS hello_sapi)
|
||||
|
||||
# Main executable demonstrating how the sandboxed library is used
|
||||
add_executable(hello
|
||||
hello_main.cc
|
||||
)
|
||||
target_link_libraries(hello PRIVATE
|
||||
hello::base
|
||||
hello::sapi
|
||||
sapi::sapi
|
||||
)
|
||||
|
||||
# Another example using the same library, but using the Transaction API that
|
||||
# automatically retries sandbox operations. Also demonstates error handling
|
||||
# and a custom security policy.
|
||||
add_executable(hello_transacted
|
||||
hello_transacted.cc
|
||||
)
|
||||
target_link_libraries(hello_transacted PRIVATE
|
||||
hello::base
|
||||
hello::sapi
|
||||
sapi::sapi
|
||||
)
|
49
sandboxed_api/examples/hello_sapi/WORKSPACE.bazel
Normal file
49
sandboxed_api/examples/hello_sapi/WORKSPACE.bazel
Normal file
|
@ -0,0 +1,49 @@
|
|||
# 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.
|
||||
|
||||
# Example workspace demonstrating how to embed Sandboxed API into a project
|
||||
# using Bazel.
|
||||
|
||||
workspace(name = "com_google_sandboxed_api_hello")
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
|
||||
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 version.
|
||||
# commit = "ba47adc21d4c9bc316f3c7c32b0faaef952c111e", # 2020-05-15
|
||||
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()
|
19
sandboxed_api/examples/hello_sapi/hello_lib.cc
Normal file
19
sandboxed_api/examples/hello_sapi/hello_lib.cc
Normal file
|
@ -0,0 +1,19 @@
|
|||
// 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.
|
||||
|
||||
// Adds two integer values and returns the result, serving as an example
|
||||
// function that will be sandboxed.
|
||||
extern "C" int AddTwoIntegers(int a, int b) {
|
||||
return a + b;
|
||||
}
|
38
sandboxed_api/examples/hello_sapi/hello_main.cc
Normal file
38
sandboxed_api/examples/hello_sapi/hello_main.cc
Normal file
|
@ -0,0 +1,38 @@
|
|||
// 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.
|
||||
|
||||
// A minimal "hello world" style example of how to use Sandboxed API. This
|
||||
// example does not include any error handling and will simply abort if
|
||||
// something goes wrong.
|
||||
// As the library function that is being called into is pure computation (i.e.
|
||||
// does not issue any syscalls), the restricted default sandbox policy is being
|
||||
// used.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include "hello_sapi.sapi.h" // Generated header
|
||||
|
||||
int main() {
|
||||
std::cout << "Calling into a sandboxee to add two numbers...\n";
|
||||
|
||||
HelloSandbox sandbox;
|
||||
sandbox.Init().IgnoreError();
|
||||
|
||||
HelloApi api(&sandbox);
|
||||
std::cout << " 1000 + 337 = " << api.AddTwoIntegers(1000, 337).value()
|
||||
<< "\n";
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
79
sandboxed_api/examples/hello_sapi/hello_transacted.cc
Normal file
79
sandboxed_api/examples/hello_sapi/hello_transacted.cc
Normal file
|
@ -0,0 +1,79 @@
|
|||
// 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.
|
||||
|
||||
// These are needed for the __NR_xxx syscall numbers
|
||||
#include <linux/audit.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#include "absl/memory/memory.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "hello_sapi.sapi.h" // Generated header
|
||||
#include "sandboxed_api/sandbox2/policy.h"
|
||||
#include "sandboxed_api/sandbox2/policybuilder.h"
|
||||
#include "sandboxed_api/transaction.h"
|
||||
#include "sandboxed_api/util/status_macros.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class CustomHelloSandbox : public HelloSandbox {
|
||||
public:
|
||||
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
||||
sandbox2::PolicyBuilder*) override {
|
||||
// Return a new policy.
|
||||
return sandbox2::PolicyBuilder()
|
||||
.AllowRead()
|
||||
.AllowWrite()
|
||||
.AllowOpen()
|
||||
.AllowSystemMalloc()
|
||||
.AllowHandleSignals()
|
||||
.AllowExit()
|
||||
.AllowStat()
|
||||
.AllowTime()
|
||||
.AllowGetIDs()
|
||||
.AllowGetPIDs()
|
||||
.AllowSyscalls({
|
||||
__NR_tgkill,
|
||||
__NR_recvmsg,
|
||||
__NR_sendmsg,
|
||||
__NR_lseek,
|
||||
__NR_nanosleep,
|
||||
__NR_futex,
|
||||
__NR_close,
|
||||
})
|
||||
.AddFile("/etc/localtime")
|
||||
.BuildOrDie();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int main() {
|
||||
std::cout << "Calling into a sandboxee to add two numbers...\n";
|
||||
|
||||
sapi::BasicTransaction transaction(absl::make_unique<CustomHelloSandbox>());
|
||||
|
||||
absl::Status status =
|
||||
transaction.Run([](sapi::Sandbox* sandbox) -> absl::Status {
|
||||
HelloApi api(sandbox);
|
||||
SAPI_ASSIGN_OR_RETURN(int result, api.AddTwoIntegers(1000, 337));
|
||||
std::cout << " 1000 + 337 = " << result << "\n";
|
||||
return absl::OkStatus();
|
||||
});
|
||||
if (!status.ok()) {
|
||||
std::cerr << "Error during sandbox call: " << status.message() << "\n";
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user