Chromium Code Reviews| Index: sandbox/mac/seatbelt_exec.cc |
| diff --git a/sandbox/mac/seatbelt_exec.cc b/sandbox/mac/seatbelt_exec.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..731766b46795fe213fc1cc3a4a2cbe0be77bb676 |
| --- /dev/null |
| +++ b/sandbox/mac/seatbelt_exec.cc |
| @@ -0,0 +1,139 @@ |
| +// Copyright 2017 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "sandbox/mac/seatbelt_exec.h" |
| + |
| +#include <sys/socket.h> |
| +#include <sys/uio.h> |
| +#include <unistd.h> |
| + |
| +#include <vector> |
| + |
| +#include "base/logging.h" |
| +#include "base/macros.h" |
| +#include "base/posix/eintr_wrapper.h" |
| +#include "base/strings/stringprintf.h" |
| +#include "sandbox/mac/seatbelt.h" |
| + |
| +namespace sandbox { |
| + |
| +SeatbeltExecClient::SeatbeltExecClient() { |
| + PCHECK(pipe(pipe_) == 0) << "pipe"; |
| +} |
| + |
| +SeatbeltExecClient::~SeatbeltExecClient() { |
| + if (pipe_[1] != -1) |
| + IGNORE_EINTR(close(pipe_[1])); |
| + // If pipe() fails, PCHECK() will be hit in the constructor, so this file |
| + // descriptor should always be closed if the proess is alive at this point. |
| + IGNORE_EINTR(close(pipe_[0])); |
| +} |
| + |
| +bool SeatbeltExecClient::SetBooleanParameter(const std::string& key, |
| + bool value) { |
| + google::protobuf::MapPair<std::string, std::string> pair( |
| + key, value ? "TRUE" : "FALSE"); |
| + return policy_.mutable_params()->insert(pair).second; |
| +} |
| + |
| +bool SeatbeltExecClient::SetParameter(const std::string& key, |
| + const std::string& value) { |
| + google::protobuf::MapPair<std::string, std::string> pair(key, value); |
| + return policy_.mutable_params()->insert(pair).second; |
| +} |
| + |
| +void SeatbeltExecClient::SetProfile(const char* policy) { |
| + policy_.set_profile(policy); |
| +} |
| + |
| +int SeatbeltExecClient::SendProfileAndGetFD() { |
| + std::string serialized_protobuf; |
| + if (!policy_.SerializeToString(&serialized_protobuf)) |
| + return -1; |
| + |
| + if (!WriteString(serialized_protobuf)) |
| + return -1; |
| + |
| + close(pipe_[1]); |
|
Robert Sesek
2017/05/15 21:05:24
IGNORE_EINTR
Greg K
2017/05/17 17:57:24
Done.
|
| + pipe_[1] = -1; |
| + |
| + return pipe_[0]; |
| +} |
| + |
| +bool SeatbeltExecClient::WriteString(const std::string& str) { |
| + // iov takes a non-const pointer. |
|
Robert Sesek
2017/05/15 21:05:24
&str[0] is probably const because the arg is. If y
Greg K
2017/05/17 17:57:24
Done.
|
| + char buffer[str.size() + 1]; |
| + memcpy(buffer, str.c_str(), sizeof(buffer)); |
| + |
| + struct iovec iov[1]; |
| + iov[0].iov_base = buffer; |
| + iov[0].iov_len = sizeof(buffer); |
| + |
| + ssize_t written = HANDLE_EINTR(writev(pipe_[1], iov, arraysize(iov))); |
| + if (written < 0) { |
| + PLOG(ERROR) << "writev"; |
| + return false; |
| + } |
| + return static_cast<uint64_t>(written) == str.size(); |
| +} |
| + |
| +SeatbeltExecServer::SeatbeltExecServer(int fd) : fd_(fd) {} |
| + |
| +SeatbeltExecServer::~SeatbeltExecServer() { |
| + close(fd_); |
|
Robert Sesek
2017/05/15 21:05:24
IGNORE_EINTR
Greg K
2017/05/17 17:57:24
This no longer exists because it uses a ScopedFD.
|
| +} |
| + |
| +int SeatbeltExecServer::InitializeSandbox() { |
| + std::string policy_string; |
| + if (!ReadString(&policy_string)) |
| + return -1; |
| + |
| + mac::SandboxPolicy policy; |
| + if (!policy.ParseFromString(policy_string)) { |
| + LOG(ERROR) << "ParseFromString failed"; |
| + return -1; |
| + } |
| + |
| + return ApplySandboxProfile(policy); |
| +} |
| + |
| +int SeatbeltExecServer::ApplySandboxProfile(const mac::SandboxPolicy& policy) { |
| + std::vector<const char*> weak_params; |
| + for (const auto& pair : policy.params()) { |
| + weak_params.push_back(pair.first.c_str()); |
| + weak_params.push_back(pair.second.c_str()); |
| + } |
| + weak_params.push_back(nullptr); |
| + |
| + char* error = nullptr; |
| + int rv = Seatbelt::InitWithParams(policy.profile().c_str(), 0, |
| + weak_params.data(), &error); |
| + if (error) { |
| + LOG(ERROR) << "Failed to initialize sandbox: " << rv << " " << error; |
| + Seatbelt::FreeError(error); |
| + return rv; |
| + } |
| + |
| + return rv; |
| +} |
| + |
| +bool SeatbeltExecServer::ReadString(std::string* str) { |
| + // 4 pages of memory is enough to hold the sandbox profiles. |
| + std::vector<char> buffer(4096 * 4); |
| + memset(buffer.data(), '\0', buffer.size()); |
|
Robert Sesek
2017/05/15 21:05:24
Drop the memset in favor of constructor #2
http:/
Greg K
2017/05/17 17:57:24
Done.
|
| + |
| + struct iovec iov[1]; |
| + iov[0].iov_base = buffer.data(); |
| + iov[0].iov_len = buffer.size(); |
| + |
| + ssize_t read_length = HANDLE_EINTR(readv(fd_, iov, arraysize(iov))); |
| + if (read_length < 0) { |
| + PLOG(ERROR) << "readv"; |
| + return false; |
| + } |
| + str->assign(buffer.data()); |
| + return true; |
| +} |
| + |
| +} // namespace sandbox |