sandboxed_api: Expose strlen in the rpc channel

PiperOrigin-RevId: 281958333
Change-Id: If15d7d5b915fec3c5521ef53ee44c58d7482d1bc
This commit is contained in:
Kevin Hamacher 2019-11-22 06:44:03 -08:00 committed by Copybara-Service
parent d9d45bcfe5
commit a193cb4ed7
8 changed files with 46 additions and 3 deletions

View File

@ -38,6 +38,7 @@ constexpr uint32_t kMsgSendFd = 0x106;
constexpr uint32_t kMsgRecvFd = 0x107; constexpr uint32_t kMsgRecvFd = 0x107;
constexpr uint32_t kMsgClose = 0x108; constexpr uint32_t kMsgClose = 0x108;
constexpr uint32_t kMsgReallocate = 0x109; constexpr uint32_t kMsgReallocate = 0x109;
constexpr uint32_t kMsgStrlen = 0x10A;
// Return: // Return:
constexpr uint32_t kMsgReturn = 0x201; constexpr uint32_t kMsgReturn = 0x201;

View File

@ -329,6 +329,12 @@ void HandleCloseFd(sandbox2::Comms* comms, int fd_to_close, FuncRet* ret) {
ret->success = true; ret->success = true;
} }
void HandleStrlen(sandbox2::Comms* comms, const char* ptr, FuncRet* ret) {
ret->ret_type = v::Type::kInt;
ret->int_val = strlen(ptr);
ret->success = true;
}
template <typename T> template <typename T>
static T BytesAs(const std::vector<uint8_t>& bytes) { static T BytesAs(const std::vector<uint8_t>& bytes) {
static_assert(std::is_trivial<T>(), static_assert(std::is_trivial<T>(),
@ -394,6 +400,11 @@ void ServeRequest(sandbox2::Comms* comms) {
VLOG(1) << "Received Client::kMsgClose message"; VLOG(1) << "Received Client::kMsgClose message";
HandleCloseFd(comms, BytesAs<int>(bytes), &ret); HandleCloseFd(comms, BytesAs<int>(bytes), &ret);
break; break;
case comms::kMsgStrlen:
VLOG(1) << "Received Client::kMsgStrlen message";
HandleStrlen(comms, BytesAs<const char*>(bytes), &ret);
break;
break;
default: default:
LOG(FATAL) << "Received unknown tag: " << tag; LOG(FATAL) << "Received unknown tag: " << tag;
break; // Not reached break; // Not reached

View File

@ -12,12 +12,12 @@
# 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.
licenses(["notice"])
load("//sandboxed_api/bazel:build_defs.bzl", "sapi_platform_copts") load("//sandboxed_api/bazel:build_defs.bzl", "sapi_platform_copts")
load("//sandboxed_api/bazel:proto.bzl", "sapi_proto_library") load("//sandboxed_api/bazel:proto.bzl", "sapi_proto_library")
load("//sandboxed_api/bazel:sapi.bzl", "sapi_library") load("//sandboxed_api/bazel:sapi.bzl", "sapi_library")
licenses(["notice"])
sapi_proto_library( sapi_proto_library(
name = "stringop_params_proto", name = "stringop_params_proto",
srcs = ["stringop_params.proto"], srcs = ["stringop_params.proto"],
@ -47,6 +47,7 @@ sapi_library(
"pb_reverse_string", "pb_reverse_string",
"nop", "nop",
"violate", "violate",
"get_raw_c_string",
], ],
input_files = [ input_files = [
"stringop.cc", "stringop.cc",

View File

@ -51,6 +51,7 @@ add_sapi_library(stringop-sapi
pb_reverse_string pb_reverse_string
nop nop
violate violate
get_raw_c_string
INPUTS stringop.cc INPUTS stringop.cc
LIBRARY sapi_stringop LIBRARY sapi_stringop
LIBRARY_NAME Stringop LIBRARY_NAME Stringop

View File

@ -48,7 +48,6 @@ extern "C" int reverse_string(sapi::LenValStruct* input) {
for (size_t i = 0; i < input->size; i++) { for (size_t i = 0; i < input->size; i++) {
new_buf[i] = src_buf[input->size - i - 1]; new_buf[i] = src_buf[input->size - i - 1];
} }
// Free old value. // Free old value.
free(input->data); free(input->data);
// Replace pointer to our new string. // Replace pointer to our new string.
@ -74,6 +73,8 @@ extern "C" int duplicate_string(sapi::LenValStruct* input) {
return 1; return 1;
} }
extern "C" const void* get_raw_c_string() { return "Ten chars."; }
extern "C" void nop() {} extern "C" void nop() {}
extern "C" void violate() { ptrace((__ptrace_request)990, 991, 992, 993); } extern "C" void violate() { ptrace((__ptrace_request)990, 991, 992, 993); }

View File

@ -130,4 +130,14 @@ TEST(StringopTest, RawStringReversal) {
} }
} }
TEST(StringopTest, RawStringLength) {
StringopSapiSandbox sandbox;
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));
EXPECT_THAT(len, Eq(10));
}
} // namespace } // namespace

View File

@ -17,6 +17,7 @@
#include <glog/logging.h> #include <glog/logging.h>
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "absl/synchronization/mutex.h" #include "absl/synchronization/mutex.h"
#include "sandboxed_api/call.h"
#include "sandboxed_api/sandbox2/comms.h" #include "sandboxed_api/sandbox2/comms.h"
#include "sandboxed_api/util/canonical_errors.h" #include "sandboxed_api/util/canonical_errors.h"
#include "sandboxed_api/util/status_macros.h" #include "sandboxed_api/util/status_macros.h"
@ -204,4 +205,18 @@ sapi::Status RPCChannel::Close(int remote_fd) {
return sapi::OkStatus(); return sapi::OkStatus();
} }
sapi::StatusOr<uint64_t> RPCChannel::Strlen(void* str) {
absl::MutexLock lock(&mutex_);
if (!comms_->SendTLV(comms::kMsgStrlen, sizeof(str),
reinterpret_cast<uint8_t*>(&str))) {
return sapi::UnavailableError("Sending TLV value failed");
}
SAPI_ASSIGN_OR_RETURN(auto fret, Return(v::Type::kInt));
if (!fret.success) {
return sapi::UnavailableError("Close() failed on the remote side");
}
return fret.int_val;
}
} // namespace sapi } // namespace sapi

View File

@ -60,6 +60,9 @@ class RPCChannel {
// Closes fd in sandboxee. // Closes fd in sandboxee.
sapi::Status Close(int remote_fd); sapi::Status Close(int remote_fd);
// Returns length of a null-terminated c-style string (invokes strlen).
sapi::StatusOr<uint64_t> Strlen(void* str);
sandbox2::Comms* comms() const { return comms_; } sandbox2::Comms* comms() const { return comms_; }
private: private: