Compare commits

...

4 Commits

Author SHA1 Message Date
Oliver Kunz 86e356b7ee Add `Sandbox::AllocateAndTransferToSandboxee` utility function.
Create a utility function to copy a hostcode local buffer into the sandboxee. This combines the following steps into one API call:

1) Create a SAPI variable backed with the hostcode local buffer
2) Allocate the SAPI variable in the sandboxee's memory space
3) Transfer the SAPI variable into the sandboxee's memory space

The function returns a `std::unique_ptr` wrapped `sapi:✌️:RemotePtr` which points to the address of the buffer in the sandboxee's memory space.

PiperOrigin-RevId: 611151615
Change-Id: Ie5012bf17826614395d2056d560689fd9e429d75
2024-02-28 10:39:15 -08:00
Kevin Hamacher 180aa03603 Internal change
PiperOrigin-RevId: 611097384
Change-Id: Ib4189548bc08e12807e74143591c3ff341d105d4
2024-02-28 07:37:06 -08:00
Wiktor Garbacz e7c5de0db8 Fix `sapi:✌️:Proto<T>::FromMessage`
PiperOrigin-RevId: 611076146
Change-Id: I60edf17b83e0ded8ed62aeebba45b6401bac8e53
2024-02-28 06:01:30 -08:00
Wiktor Garbacz f7f4cdb458 More complete error handling in `SerializeProto`
PiperOrigin-RevId: 611073556
Change-Id: Id29c3dbe15bb55c7d4e68d9a3e1c82327af0ad23
2024-02-28 05:47:15 -08:00
8 changed files with 80 additions and 8 deletions

View File

@ -86,10 +86,8 @@ cc_library(
"//sandboxed_api/util:raw_logging",
"//sandboxed_api/util:runfiles",
"//sandboxed_api/util:status",
"@com_google_absl//absl/base",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/base:dynamic_annotations",
"@com_google_absl//absl/base:log_severity",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/log",
"@com_google_absl//absl/log:check",
@ -100,6 +98,7 @@ cc_library(
"@com_google_absl//absl/strings:str_format",
"@com_google_absl//absl/synchronization",
"@com_google_absl//absl/time",
"@com_google_absl//absl/types:span",
],
)
@ -208,13 +207,17 @@ cc_test(
deps = [
":sapi",
":testing",
":vars",
"//sandboxed_api/examples/stringop:stringop-sapi",
"//sandboxed_api/examples/stringop:stringop_params_cc_proto",
"//sandboxed_api/examples/sum:sum-sapi",
"//sandboxed_api/util:status_matchers",
"@com_google_absl//absl/log",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings:string_view",
"@com_google_absl//absl/time",
"@com_google_absl//absl/types:span",
"@com_google_benchmark//:benchmark",
"@com_google_googletest//:gtest_main",
],

View File

@ -76,6 +76,7 @@ target_link_libraries(sapi_sapi
absl::flat_hash_map
absl::log
absl::log_globals
absl::span
absl::status
absl::statusor
absl::str_format

View File

@ -17,6 +17,7 @@
#include <cstddef>
#include <cstdint>
#include <string>
#include <utility>
#include <vector>
#include "absl/status/status.h"
@ -47,7 +48,11 @@ absl::StatusOr<std::vector<uint8_t>> SerializeProto(
// Wrap protobuf in a envelope so that we know the name of the protobuf
// structure when deserializing in the sandboxee.
ProtoArg proto_arg;
proto_arg.set_protobuf_data(proto.SerializeAsString());
std::string proto_data;
if (!proto.SerializeToString(&proto_data)) {
return absl::InternalError("Unable to serialize proto data");
}
proto_arg.set_protobuf_data(std::move(proto_data));
proto_arg.set_full_name(proto.GetTypeName());
std::vector<uint8_t> serialized_proto(proto_arg.ByteSizeLong());
if (!proto_arg.SerializeToArray(serialized_proto.data(),

View File

@ -19,6 +19,7 @@
#include <sys/uio.h>
#include <syscall.h>
#include <cstdint>
#include <cstdio>
#include <initializer_list>
#include <memory>
@ -33,7 +34,9 @@
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "sandboxed_api/config.h"
#include "sandboxed_api/embed_file.h"
#include "sandboxed_api/rpcchannel.h"
@ -48,6 +51,8 @@
#include "sandboxed_api/util/raw_logging.h"
#include "sandboxed_api/util/runfiles.h"
#include "sandboxed_api/util/status_macros.h"
#include "sandboxed_api/var_array.h"
#include "sandboxed_api/var_ptr.h"
namespace sapi {
@ -422,6 +427,15 @@ absl::Status Sandbox::TransferFromSandboxee(v::Var* var) {
return var->TransferFromSandboxee(rpc_channel(), pid());
}
absl::StatusOr<std::unique_ptr<sapi::v::Array<const uint8_t>>>
Sandbox::AllocateAndTransferToSandboxee(absl::Span<const uint8_t> buffer) {
auto sapi_buffer = std::make_unique<sapi::v::Array<const uint8_t>>(
buffer.data(), buffer.size());
SAPI_RETURN_IF_ERROR(Allocate(sapi_buffer.get(), /*automatic_free=*/true));
SAPI_RETURN_IF_ERROR(TransferToSandboxee(sapi_buffer.get()));
return sapi_buffer;
}
absl::StatusOr<std::string> Sandbox::GetCString(const v::RemotePtr& str,
size_t max_length) {
if (!is_active()) {

View File

@ -15,6 +15,7 @@
#ifndef SANDBOXED_API_SANDBOX_H_
#define SANDBOXED_API_SANDBOX_H_
#include <cstdint>
#include <ctime>
#include <initializer_list>
#include <memory>
@ -28,6 +29,7 @@
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "sandboxed_api/config.h"
#include "sandboxed_api/rpcchannel.h"
#include "sandboxed_api/sandbox2/client.h"
@ -124,6 +126,12 @@ class Sandbox {
// SAPI_RETURN_IF_ERROR(sandbox.TransferFromSandboxee(&sapi_buffer));
absl::Status TransferFromSandboxee(v::Var* var);
// Allocates and transfers a buffer to the sandboxee's address space from the
// hostcode. Returns a status on failure, or a unique_ptr to
// sapi::v::Array<const uint8_t> on success.
absl::StatusOr<std::unique_ptr<sapi::v::Array<const uint8_t>>>
AllocateAndTransferToSandboxee(absl::Span<const uint8_t> buffer);
absl::StatusOr<std::string> GetCString(const v::RemotePtr& str,
size_t max_length = 10ULL
<< 20 /* 10 MiB*/

View File

@ -45,6 +45,7 @@ namespace sandbox2 {
class AllowAllSyscalls;
class TraceAllSyscalls;
class UnrestrictedNetworking;
class LoadUserBpfCodeFromFile;
// PolicyBuilder is a helper class to simplify creation of policies. The builder
// uses fluent interface for convenience and increased readability of policies.

View File

@ -13,18 +13,24 @@
// limitations under the License.
#include <fcntl.h>
#include <sys/types.h>
#include <cstdint>
#include <memory>
#include <string>
#include <thread> // NOLINT(build/c++11)
#include <vector>
#include "benchmark/benchmark.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "sandboxed_api/examples/stringop/stringop-sapi.sapi.h"
#include "sandboxed_api/examples/stringop/stringop_params.pb.h"
#include "sandboxed_api/examples/sum/sum-sapi.sapi.h"
@ -32,15 +38,18 @@
#include "sandboxed_api/testing.h"
#include "sandboxed_api/transaction.h"
#include "sandboxed_api/util/status_matchers.h"
#include "sandboxed_api/var_array.h"
namespace sapi {
namespace {
using ::sapi::IsOk;
using ::sapi::StatusIs;
using ::testing::ContainerEq;
using ::testing::Eq;
using ::testing::Gt;
using ::testing::HasSubstr;
using ::testing::NotNull;
// Functions that will be used during the benchmarks:
@ -303,5 +312,30 @@ TEST(SandboxTest, UseUnotifyMonitor) {
EXPECT_THAT(result, Eq(3));
}
TEST(SandboxTest, AllocateAndTransferTest) {
std::string test_string("This is a test");
std::vector<uint8_t> test_string_vector(test_string.begin(),
test_string.end());
absl::Span<uint8_t> buffer_input(
reinterpret_cast<uint8_t*>(test_string_vector.data()),
test_string_vector.size());
std::vector<uint8_t> buffer_output(test_string_vector.size());
SumSandbox sandbox;
ASSERT_THAT(sandbox.Init(), IsOk());
SumApi api(&sandbox);
SAPI_ASSERT_OK_AND_ASSIGN(
auto sapi_array, sandbox.AllocateAndTransferToSandboxee(buffer_input));
ASSERT_THAT(sapi_array, NotNull());
sapi::v::Array<const uint8_t> sapi_buffer_output(
reinterpret_cast<const uint8_t*>(buffer_output.data()),
buffer_output.size());
sapi_buffer_output.SetRemote(sapi_array->GetRemote());
ASSERT_THAT(sandbox.TransferFromSandboxee(&sapi_buffer_output), IsOk());
EXPECT_THAT(test_string_vector, ContainerEq(buffer_output));
}
} // namespace
} // namespace sapi

View File

@ -42,16 +42,26 @@ namespace sapi::v {
template <typename T>
class Proto : public Var {
public:
class PrivateToken {
private:
explicit PrivateToken() = default;
friend class Proto;
};
static_assert(std::is_base_of<google::protobuf::MessageLite, T>::value,
"Template argument must be a proto message");
Proto(PrivateToken, std::vector<uint8_t> data)
: wrapped_var_(std::move(data)) {}
ABSL_DEPRECATED("Use Proto<>::FromMessage() instead")
explicit Proto(const T& proto)
: wrapped_var_(SerializeProto(proto).value()) {}
static absl::StatusOr<Proto<T>> FromMessage(const T& proto) {
SAPI_ASSIGN_OR_RETURN(std::vector<uint8_t> len_val, SerializeProto(proto));
return absl::StatusOr<Proto<T>>(absl::in_place, proto);
return absl::StatusOr<Proto<T>>(absl::in_place, PrivateToken{},
std::move(len_val));
}
size_t GetSize() const final { return wrapped_var_.GetSize(); }
@ -105,10 +115,6 @@ class Proto : public Var {
}
private:
friend class absl::StatusOr<Proto<T>>;
explicit Proto(std::vector<uint8_t> data) : wrapped_var_(std::move(data)) {}
// The management of reading/writing the data to the sandboxee is handled by
// the LenVal class.
LenVal wrapped_var_;