Allow sandboxee c-strings to be read as std::string

PiperOrigin-RevId: 281960106
Change-Id: I54256dda2b6b0374d0f2ce3f762370478b912683
This commit is contained in:
Kevin Hamacher 2019-11-22 06:59:37 -08:00 committed by Copybara-Service
parent a193cb4ed7
commit 3cbd871454
3 changed files with 55 additions and 0 deletions

View File

@ -140,4 +140,18 @@ TEST(StringopTest, RawStringLength) {
EXPECT_THAT(len, Eq(10));
}
TEST(StringopTest, RawStringReading) {
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));
SAPI_ASSERT_OK_AND_ASSIGN(std::string data,
sandbox.GetCString(sapi::v::RemotePtr(target_mem_ptr)));
EXPECT_THAT(data, StrEq("Ten chars."));
}
} // namespace

View File

@ -391,6 +391,43 @@ sapi::Status Sandbox::TransferFromSandboxee(v::Var* var) {
return var->TransferFromSandboxee(GetRpcChannel(), GetPid());
}
sapi::StatusOr<std::string> Sandbox::GetCString(const v::RemotePtr& str,
uint64_t max_length) {
if (!IsActive()) {
return sapi::UnavailableError("Sandbox not active");
}
SAPI_ASSIGN_OR_RETURN(auto len, GetRpcChannel()->Strlen(str.GetValue()));
if (len > max_length) {
return sapi::InvalidArgumentError(
absl::StrCat("Target string too large: ", len, " > ", max_length));
}
std::string buffer(len, '\0');
struct iovec local = {
.iov_base = &buffer[0],
.iov_len = len,
};
struct iovec remote = {
.iov_base = str.GetValue(),
.iov_len = len,
};
ssize_t ret = process_vm_readv(pid_, &local, 1, &remote, 1, 0);
if (ret == -1) {
PLOG(WARNING) << "reading c-string failed: process_vm_readv(pid: " << pid_
<< " raddr: " << str.GetValue() << " size: " << len << ")";
return sapi::UnavailableError("process_vm_readv failed");
}
if (ret != len) {
LOG(WARNING) << "partial read when reading c-string: process_vm_readv(pid: "
<< pid_ << " raddr: " << str.GetValue() << " size: " << len
<< ") transferred " << ret << " bytes";
return sapi::UnavailableError("process_vm_readv succeeded partially");
}
return buffer;
}
const sandbox2::Result& Sandbox::AwaitResult() {
if (s2_) {
result_ = s2_->AwaitResult();

View File

@ -95,6 +95,10 @@ class Sandbox {
sapi::Status TransferToSandboxee(v::Var* var);
sapi::Status TransferFromSandboxee(v::Var* var);
sapi::StatusOr<std::string> GetCString(const v::RemotePtr& str,
uint64_t max_length = 10 * 1024 *
1024);
// Waits until the sandbox terminated and returns the result.
const sandbox2::Result& AwaitResult();
const sandbox2::Result& result() const { return result_; }