mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
Refactor Comms to split out listening/connecting part
Deprecated APIs slated for removal after migration of internal clients. PiperOrigin-RevId: 566598245 Change-Id: I5d7b920f3a788d4eccc6e78f239b660ba903adcc
This commit is contained in:
parent
d26262d82e
commit
1cf45be7df
|
@ -835,6 +835,7 @@ cc_library(
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
":util",
|
":util",
|
||||||
|
"//sandboxed_api/util:fileops",
|
||||||
"//sandboxed_api/util:raw_logging",
|
"//sandboxed_api/util:raw_logging",
|
||||||
"//sandboxed_api/util:status",
|
"//sandboxed_api/util:status",
|
||||||
"//sandboxed_api/util:status_cc_proto",
|
"//sandboxed_api/util:status_cc_proto",
|
||||||
|
|
|
@ -763,6 +763,7 @@ target_link_libraries(sandbox2_comms
|
||||||
PUBLIC absl::core_headers
|
PUBLIC absl::core_headers
|
||||||
absl::status
|
absl::status
|
||||||
protobuf::libprotobuf
|
protobuf::libprotobuf
|
||||||
|
sapi::fileops
|
||||||
sapi::status
|
sapi::status
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -43,11 +43,14 @@
|
||||||
#include "absl/status/statusor.h"
|
#include "absl/status/statusor.h"
|
||||||
#include "absl/strings/numbers.h"
|
#include "absl/strings/numbers.h"
|
||||||
#include "absl/strings/str_format.h"
|
#include "absl/strings/str_format.h"
|
||||||
|
#include "absl/strings/string_view.h"
|
||||||
#include "google/protobuf/message_lite.h"
|
#include "google/protobuf/message_lite.h"
|
||||||
#include "sandboxed_api/sandbox2/util.h"
|
#include "sandboxed_api/sandbox2/util.h"
|
||||||
|
#include "sandboxed_api/util/fileops.h"
|
||||||
#include "sandboxed_api/util/raw_logging.h"
|
#include "sandboxed_api/util/raw_logging.h"
|
||||||
#include "sandboxed_api/util/status.h"
|
#include "sandboxed_api/util/status.h"
|
||||||
#include "sandboxed_api/util/status.pb.h"
|
#include "sandboxed_api/util/status.pb.h"
|
||||||
|
#include "sandboxed_api/util/status_macros.h"
|
||||||
|
|
||||||
namespace sandbox2 {
|
namespace sandbox2 {
|
||||||
|
|
||||||
|
@ -59,6 +62,9 @@ class PotentiallyBlockingRegion {
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
using sapi::file_util::fileops::FDCloser;
|
||||||
|
|
||||||
bool IsFatalError(int saved_errno) {
|
bool IsFatalError(int saved_errno) {
|
||||||
return saved_errno != EAGAIN && saved_errno != EWOULDBLOCK &&
|
return saved_errno != EAGAIN && saved_errno != EWOULDBLOCK &&
|
||||||
saved_errno != EFAULT && saved_errno != EINTR &&
|
saved_errno != EFAULT && saved_errno != EINTR &&
|
||||||
|
@ -74,16 +80,47 @@ int GetDefaultCommsFd() {
|
||||||
}
|
}
|
||||||
return Comms::kSandbox2ClientCommsFD;
|
return Comms::kSandbox2ClientCommsFD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
socklen_t CreateSockaddrUn(const std::string& socket_name, bool abstract_uds,
|
||||||
|
sockaddr_un* sun) {
|
||||||
|
sun->sun_family = AF_UNIX;
|
||||||
|
bzero(sun->sun_path, sizeof(sun->sun_path));
|
||||||
|
socklen_t slen = sizeof(sun->sun_family) + strlen(socket_name.c_str());
|
||||||
|
if (abstract_uds) {
|
||||||
|
// Create an 'abstract socket address' by specifying a leading null byte.
|
||||||
|
// The remainder of the path is used as a unique name, but no file is
|
||||||
|
// created on the filesystem. No need to NUL-terminate the string. See `man
|
||||||
|
// 7 unix` for further explanation.
|
||||||
|
strncpy(&sun->sun_path[1], socket_name.c_str(), sizeof(sun->sun_path) - 1);
|
||||||
|
// Len is complicated - it's essentially size of the path, plus initial
|
||||||
|
// NUL-byte, minus size of the sun.sun_family.
|
||||||
|
slen++;
|
||||||
|
} else {
|
||||||
|
// Create the socket address as it was passed from the constructor.
|
||||||
|
strncpy(&sun->sun_path[0], socket_name.c_str(), sizeof(sun->sun_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
// This takes care of the socket address overflow.
|
||||||
|
if (slen > sizeof(sockaddr_un)) {
|
||||||
|
SAPI_RAW_LOG(ERROR, "Socket address is too long, will be truncated");
|
||||||
|
slen = sizeof(sockaddr_un);
|
||||||
|
}
|
||||||
|
return slen;
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Comms::Comms(const std::string& socket_name, bool abstract_uds)
|
Comms::Comms(const std::string& socket_name, bool abstract_uds)
|
||||||
: socket_name_(socket_name), abstract_uds_(abstract_uds) {}
|
: name_(socket_name), abstract_uds_(abstract_uds) {}
|
||||||
|
|
||||||
Comms::Comms(int fd) : connection_fd_(fd) {
|
Comms::Comms(int fd, absl::string_view name) : connection_fd_(fd) {
|
||||||
// Generate a unique and meaningful socket name for this FD.
|
// Generate a unique and meaningful socket name for this FD.
|
||||||
// Note: getpid()/gettid() are non-blocking syscalls.
|
// Note: getpid()/gettid() are non-blocking syscalls.
|
||||||
socket_name_ = absl::StrFormat("sandbox2::Comms:FD=%d/PID=%d/TID=%ld", fd,
|
if (name.empty()) {
|
||||||
getpid(), syscall(__NR_gettid));
|
name_ = absl::StrFormat("sandbox2::Comms:FD=%d/PID=%d/TID=%ld", fd,
|
||||||
|
getpid(), syscall(__NR_gettid));
|
||||||
|
} else {
|
||||||
|
name_ = std::string(name);
|
||||||
|
}
|
||||||
|
|
||||||
// File descriptor is already connected.
|
// File descriptor is already connected.
|
||||||
state_ = State::kConnected;
|
state_ = State::kConnected;
|
||||||
|
@ -94,7 +131,36 @@ Comms::Comms(Comms::DefaultConnectionTag) : Comms(GetDefaultCommsFd()) {}
|
||||||
Comms::~Comms() { Terminate(); }
|
Comms::~Comms() { Terminate(); }
|
||||||
|
|
||||||
int Comms::GetConnectionFD() const {
|
int Comms::GetConnectionFD() const {
|
||||||
return connection_fd_;
|
return connection_fd_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::StatusOr<ListeningComms> ListeningComms::Create(
|
||||||
|
absl::string_view socket_name, bool abstract_uds) {
|
||||||
|
ListeningComms comms(std::string(socket_name), abstract_uds);
|
||||||
|
SAPI_RETURN_IF_ERROR(comms.Listen());
|
||||||
|
return comms;
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::Status ListeningComms::Listen() {
|
||||||
|
bind_fd_ = FDCloser(socket(AF_UNIX, SOCK_STREAM, 0)); // Non-blocking
|
||||||
|
if (bind_fd_.get() == -1) {
|
||||||
|
return absl::ErrnoToStatus(errno, "socket(AF_UNIX) failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
sockaddr_un sus;
|
||||||
|
socklen_t slen = CreateSockaddrUn(socket_name_, abstract_uds_, &sus);
|
||||||
|
// bind() is non-blocking.
|
||||||
|
if (bind(bind_fd_.get(), reinterpret_cast<sockaddr*>(&sus), slen) == -1) {
|
||||||
|
return absl::ErrnoToStatus(errno, "bind failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// listen() non-blocking.
|
||||||
|
if (listen(bind_fd_.get(), 0) == -1) {
|
||||||
|
return absl::ErrnoToStatus(errno, "listen failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
SAPI_RAW_VLOG(1, "Listening at: %s", socket_name_.c_str());
|
||||||
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Comms::Listen() {
|
bool Comms::Listen() {
|
||||||
|
@ -102,123 +168,98 @@ bool Comms::Listen() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bind_fd_ = socket(AF_UNIX, SOCK_STREAM, 0); // Non-blocking
|
absl::StatusOr<ListeningComms> listening_comms =
|
||||||
if (bind_fd_ == -1) {
|
ListeningComms::Create(name_, abstract_uds_);
|
||||||
SAPI_RAW_PLOG(ERROR, "socket(AF_UNIX)");
|
if (!listening_comms.ok()) {
|
||||||
|
SAPI_RAW_LOG(ERROR, "Listening failed: %s",
|
||||||
|
std::string(listening_comms.status().message()).c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
listening_comms_ =
|
||||||
sockaddr_un sus;
|
std::make_unique<ListeningComms>(*std::move(listening_comms));
|
||||||
socklen_t slen = CreateSockaddrUn(&sus);
|
|
||||||
// bind() is non-blocking.
|
|
||||||
if (bind(bind_fd_, reinterpret_cast<sockaddr*>(&sus), slen) == -1) {
|
|
||||||
SAPI_RAW_PLOG(ERROR, "bind(bind_fd)");
|
|
||||||
|
|
||||||
// Note: checking for EINTR on close() syscall is useless and possibly
|
|
||||||
// harmful, see https://lwn.net/Articles/576478/.
|
|
||||||
{
|
|
||||||
PotentiallyBlockingRegion region;
|
|
||||||
close(bind_fd_);
|
|
||||||
}
|
|
||||||
bind_fd_ = -1;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// listen() non-blocking.
|
|
||||||
if (listen(bind_fd_, 0) == -1) {
|
|
||||||
SAPI_RAW_PLOG(ERROR, "listen(bind_fd)");
|
|
||||||
{
|
|
||||||
PotentiallyBlockingRegion region;
|
|
||||||
close(bind_fd_);
|
|
||||||
}
|
|
||||||
bind_fd_ = -1;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
SAPI_RAW_VLOG(1, "Listening at: %s", socket_name_.c_str());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
absl::StatusOr<Comms> ListeningComms::Accept() {
|
||||||
|
sockaddr_un suc;
|
||||||
|
socklen_t len = sizeof(suc);
|
||||||
|
int connection_fd;
|
||||||
|
{
|
||||||
|
PotentiallyBlockingRegion region;
|
||||||
|
connection_fd = TEMP_FAILURE_RETRY(
|
||||||
|
accept(bind_fd_.get(), reinterpret_cast<sockaddr*>(&suc), &len));
|
||||||
|
}
|
||||||
|
if (connection_fd == -1) {
|
||||||
|
return absl::ErrnoToStatus(errno, "accept failed");
|
||||||
|
}
|
||||||
|
SAPI_RAW_VLOG(1, "Accepted connection at: %s, fd: %d", socket_name_.c_str(),
|
||||||
|
connection_fd);
|
||||||
|
return Comms(connection_fd, socket_name_);
|
||||||
|
}
|
||||||
|
|
||||||
bool Comms::Accept() {
|
bool Comms::Accept() {
|
||||||
if (IsConnected()) {
|
if (IsConnected()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
sockaddr_un suc;
|
if (listening_comms_ == nullptr) {
|
||||||
socklen_t len = sizeof(suc);
|
SAPI_RAW_LOG(ERROR, "Comms::Listen needs to be called first");
|
||||||
{
|
|
||||||
PotentiallyBlockingRegion region;
|
|
||||||
connection_fd_ = TEMP_FAILURE_RETRY(
|
|
||||||
accept(bind_fd_, reinterpret_cast<sockaddr*>(&suc), &len));
|
|
||||||
}
|
|
||||||
if (connection_fd_ == -1) {
|
|
||||||
SAPI_RAW_PLOG(ERROR, "accept(bind_fd)");
|
|
||||||
{
|
|
||||||
PotentiallyBlockingRegion region;
|
|
||||||
close(bind_fd_);
|
|
||||||
}
|
|
||||||
bind_fd_ = -1;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
state_ = State::kConnected;
|
absl::StatusOr<Comms> comms = listening_comms_->Accept();
|
||||||
|
if (!comms.ok()) {
|
||||||
SAPI_RAW_VLOG(1, "Accepted connection at: %s, fd: %d", socket_name_.c_str(),
|
SAPI_RAW_LOG(ERROR, "%s", std::string(comms.status().message()).c_str());
|
||||||
connection_fd_);
|
return false;
|
||||||
|
}
|
||||||
|
*this = *std::move(comms);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
absl::StatusOr<Comms> Comms::Connect(const std::string& socket_name,
|
||||||
|
bool abstract_uds) {
|
||||||
|
FDCloser connection_fd(socket(AF_UNIX, SOCK_STREAM, 0)); // Non-blocking
|
||||||
|
if (connection_fd.get() == -1) {
|
||||||
|
return absl::ErrnoToStatus(errno, "socket(AF_UNIX)");
|
||||||
|
}
|
||||||
|
|
||||||
|
sockaddr_un suc;
|
||||||
|
socklen_t slen = CreateSockaddrUn(socket_name, abstract_uds, &suc);
|
||||||
|
int ret;
|
||||||
|
{
|
||||||
|
PotentiallyBlockingRegion region;
|
||||||
|
ret = TEMP_FAILURE_RETRY(
|
||||||
|
connect(connection_fd.get(), reinterpret_cast<sockaddr*>(&suc), slen));
|
||||||
|
}
|
||||||
|
if (ret == -1) {
|
||||||
|
return absl::ErrnoToStatus(errno, "connect(connection_fd)");
|
||||||
|
}
|
||||||
|
|
||||||
|
SAPI_RAW_VLOG(1, "Connected to: %s, fd: %d", socket_name.c_str(),
|
||||||
|
connection_fd.get());
|
||||||
|
return Comms(connection_fd.Release(), socket_name);
|
||||||
|
}
|
||||||
|
|
||||||
bool Comms::Connect() {
|
bool Comms::Connect() {
|
||||||
if (IsConnected()) {
|
if (IsConnected()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
connection_fd_ = socket(AF_UNIX, SOCK_STREAM, 0); // Non-blocking
|
absl::StatusOr<Comms> connected = Connect(name_, abstract_uds_);
|
||||||
if (connection_fd_ == -1) {
|
if (!connected.ok()) {
|
||||||
SAPI_RAW_PLOG(ERROR, "socket(AF_UNIX)");
|
SAPI_RAW_LOG(ERROR, "%s",
|
||||||
|
std::string(connected.status().message()).c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
*this = *std::move(connected);
|
||||||
sockaddr_un suc;
|
|
||||||
socklen_t slen = CreateSockaddrUn(&suc);
|
|
||||||
int ret;
|
|
||||||
{
|
|
||||||
PotentiallyBlockingRegion region;
|
|
||||||
ret = TEMP_FAILURE_RETRY(
|
|
||||||
connect(connection_fd_, reinterpret_cast<sockaddr*>(&suc), slen));
|
|
||||||
}
|
|
||||||
if (ret == -1) {
|
|
||||||
SAPI_RAW_PLOG(ERROR, "connect(connection_fd)");
|
|
||||||
{
|
|
||||||
PotentiallyBlockingRegion region;
|
|
||||||
close(connection_fd_);
|
|
||||||
}
|
|
||||||
connection_fd_ = -1;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
state_ = State::kConnected;
|
|
||||||
|
|
||||||
SAPI_RAW_VLOG(1, "Connected to: %s, fd: %d", socket_name_.c_str(),
|
|
||||||
connection_fd_);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Comms::Terminate() {
|
void Comms::Terminate() {
|
||||||
{
|
state_ = State::kTerminated;
|
||||||
PotentiallyBlockingRegion region;
|
|
||||||
|
|
||||||
state_ = State::kTerminated;
|
connection_fd_.Close();
|
||||||
|
listening_comms_.reset();
|
||||||
if (bind_fd_ != -1) {
|
|
||||||
close(bind_fd_);
|
|
||||||
bind_fd_ = -1;
|
|
||||||
}
|
|
||||||
if (connection_fd_ != -1) {
|
|
||||||
close(connection_fd_);
|
|
||||||
connection_fd_ = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Comms::SendTLV(uint32_t tag, size_t length, const void* value) {
|
bool Comms::SendTLV(uint32_t tag, size_t length, const void* value) {
|
||||||
|
@ -349,7 +390,7 @@ bool Comms::RecvFD(int* fd) {
|
||||||
util::Syscall(__NR_recvmsg, fd, reinterpret_cast<uintptr_t>(&msg), 0));
|
util::Syscall(__NR_recvmsg, fd, reinterpret_cast<uintptr_t>(&msg), 0));
|
||||||
};
|
};
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
len = op(connection_fd_);
|
len = op(connection_fd_.get());
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
if (IsFatalError(errno)) {
|
if (IsFatalError(errno)) {
|
||||||
Terminate();
|
Terminate();
|
||||||
|
@ -432,7 +473,7 @@ bool Comms::SendFD(int fd) {
|
||||||
util::Syscall(__NR_sendmsg, fd, reinterpret_cast<uintptr_t>(&msg), 0));
|
util::Syscall(__NR_sendmsg, fd, reinterpret_cast<uintptr_t>(&msg), 0));
|
||||||
};
|
};
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
len = op(connection_fd_);
|
len = op(connection_fd_.get());
|
||||||
if (len == -1 && errno == EPIPE) {
|
if (len == -1 && errno == EPIPE) {
|
||||||
Terminate();
|
Terminate();
|
||||||
SAPI_RAW_LOG(ERROR, "sendmsg(SCM_RIGHTS): Peer disconnected");
|
SAPI_RAW_LOG(ERROR, "sendmsg(SCM_RIGHTS): Peer disconnected");
|
||||||
|
@ -458,10 +499,10 @@ bool Comms::RecvProtoBuf(google::protobuf::MessageLite* message) {
|
||||||
std::vector<uint8_t> bytes;
|
std::vector<uint8_t> bytes;
|
||||||
if (!RecvTLV(&tag, &bytes)) {
|
if (!RecvTLV(&tag, &bytes)) {
|
||||||
if (IsConnected()) {
|
if (IsConnected()) {
|
||||||
SAPI_RAW_PLOG(ERROR, "RecvProtoBuf failed for (%s)", socket_name_);
|
SAPI_RAW_PLOG(ERROR, "RecvProtoBuf failed for (%s)", name_);
|
||||||
} else {
|
} else {
|
||||||
Terminate();
|
Terminate();
|
||||||
SAPI_RAW_VLOG(2, "Connection terminated (%s)", socket_name_.c_str());
|
SAPI_RAW_VLOG(2, "Connection terminated (%s)", name_.c_str());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -488,32 +529,6 @@ bool Comms::SendProtoBuf(const google::protobuf::MessageLite& message) {
|
||||||
// All methods below are private, for internal use only.
|
// All methods below are private, for internal use only.
|
||||||
// *****************************************************************************
|
// *****************************************************************************
|
||||||
|
|
||||||
socklen_t Comms::CreateSockaddrUn(sockaddr_un* sun) {
|
|
||||||
sun->sun_family = AF_UNIX;
|
|
||||||
bzero(sun->sun_path, sizeof(sun->sun_path));
|
|
||||||
socklen_t slen = sizeof(sun->sun_family) + strlen(socket_name_.c_str());
|
|
||||||
if (abstract_uds_) {
|
|
||||||
// Create an 'abstract socket address' by specifying a leading null byte.
|
|
||||||
// The remainder of the path is used as a unique name, but no file is
|
|
||||||
// created on the filesystem. No need to NUL-terminate the string. See `man
|
|
||||||
// 7 unix` for further explanation.
|
|
||||||
strncpy(&sun->sun_path[1], socket_name_.c_str(), sizeof(sun->sun_path) - 1);
|
|
||||||
// Len is complicated - it's essentially size of the path, plus initial
|
|
||||||
// NUL-byte, minus size of the sun.sun_family.
|
|
||||||
slen++;
|
|
||||||
} else {
|
|
||||||
// Create the socket address as it was passed from the constructor.
|
|
||||||
strncpy(&sun->sun_path[0], socket_name_.c_str(), sizeof(sun->sun_path));
|
|
||||||
}
|
|
||||||
|
|
||||||
// This takes care of the socket address overflow.
|
|
||||||
if (slen > sizeof(sockaddr_un)) {
|
|
||||||
SAPI_RAW_LOG(ERROR, "Socket address is too long, will be truncated");
|
|
||||||
slen = sizeof(sockaddr_un);
|
|
||||||
}
|
|
||||||
return slen;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Comms::Send(const void* data, size_t len) {
|
bool Comms::Send(const void* data, size_t len) {
|
||||||
size_t total_sent = 0;
|
size_t total_sent = 0;
|
||||||
const char* bytes = reinterpret_cast<const char*>(data);
|
const char* bytes = reinterpret_cast<const char*>(data);
|
||||||
|
@ -523,7 +538,7 @@ bool Comms::Send(const void* data, size_t len) {
|
||||||
};
|
};
|
||||||
while (total_sent < len) {
|
while (total_sent < len) {
|
||||||
ssize_t s;
|
ssize_t s;
|
||||||
s = op(connection_fd_);
|
s = op(connection_fd_.get());
|
||||||
if (s == -1 && errno == EPIPE) {
|
if (s == -1 && errno == EPIPE) {
|
||||||
Terminate();
|
Terminate();
|
||||||
// We do not expect the other end to disappear.
|
// We do not expect the other end to disappear.
|
||||||
|
@ -557,7 +572,7 @@ bool Comms::Recv(void* data, size_t len) {
|
||||||
};
|
};
|
||||||
while (total_recv < len) {
|
while (total_recv < len) {
|
||||||
ssize_t s;
|
ssize_t s;
|
||||||
s = op(connection_fd_);
|
s = op(connection_fd_.get());
|
||||||
if (s == -1) {
|
if (s == -1) {
|
||||||
SAPI_RAW_PLOG(ERROR, "read");
|
SAPI_RAW_PLOG(ERROR, "read");
|
||||||
if (IsFatalError(errno)) {
|
if (IsFatalError(errno)) {
|
||||||
|
@ -675,12 +690,11 @@ bool Comms::SendStatus(const absl::Status& status) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Comms::MoveToAnotherFd() {
|
void Comms::MoveToAnotherFd() {
|
||||||
SAPI_RAW_CHECK(connection_fd_ != -1,
|
SAPI_RAW_CHECK(connection_fd_.get() != -1,
|
||||||
"Cannot move comms fd as it's not connected");
|
"Cannot move comms fd as it's not connected");
|
||||||
int new_fd = dup(connection_fd_);
|
FDCloser new_fd(dup(connection_fd_.get()));
|
||||||
SAPI_RAW_CHECK(new_fd != -1, "Failed to move comms to another fd");
|
SAPI_RAW_CHECK(new_fd.get() != -1, "Failed to move comms to another fd");
|
||||||
close(connection_fd_);
|
connection_fd_.Swap(new_fd);
|
||||||
connection_fd_ = new_fd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sandbox2
|
} // namespace sandbox2
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "absl/status/statusor.h"
|
#include "absl/status/statusor.h"
|
||||||
#include "absl/strings/string_view.h"
|
#include "absl/strings/string_view.h"
|
||||||
#include "google/protobuf/message_lite.h"
|
#include "google/protobuf/message_lite.h"
|
||||||
|
#include "sandboxed_api/util/fileops.h"
|
||||||
|
|
||||||
namespace proto2 {
|
namespace proto2 {
|
||||||
class Message;
|
class Message;
|
||||||
|
@ -49,6 +50,7 @@ class Message;
|
||||||
namespace sandbox2 {
|
namespace sandbox2 {
|
||||||
|
|
||||||
class Client;
|
class Client;
|
||||||
|
class ListeningComms;
|
||||||
|
|
||||||
class Comms {
|
class Comms {
|
||||||
public:
|
public:
|
||||||
|
@ -93,8 +95,13 @@ class Comms {
|
||||||
|
|
||||||
static constexpr const char* kSandbox2CommsFDEnvVar = "SANDBOX2_COMMS_FD";
|
static constexpr const char* kSandbox2CommsFDEnvVar = "SANDBOX2_COMMS_FD";
|
||||||
|
|
||||||
|
static absl::StatusOr<Comms> Connect(const std::string& socket_name,
|
||||||
|
bool abstract_uds = true);
|
||||||
|
|
||||||
// This object will have to be connected later on.
|
// This object will have to be connected later on.
|
||||||
// When not specified the constructor uses abstract unix domain sockets.
|
// When not specified the constructor uses abstract unix domain sockets.
|
||||||
|
ABSL_DEPRECATED(
|
||||||
|
"Use ListeningComms or absl::StatusOr<Comms> Connect() instead")
|
||||||
explicit Comms(const std::string& socket_name, bool abstract_uds = true);
|
explicit Comms(const std::string& socket_name, bool abstract_uds = true);
|
||||||
|
|
||||||
Comms(Comms&& other) { *this = std::move(other); }
|
Comms(Comms&& other) { *this = std::move(other); }
|
||||||
|
@ -112,7 +119,7 @@ class Comms {
|
||||||
|
|
||||||
// Instantiates a pre-connected object.
|
// Instantiates a pre-connected object.
|
||||||
// Takes ownership over fd, which will be closed on object's destruction.
|
// Takes ownership over fd, which will be closed on object's destruction.
|
||||||
explicit Comms(int fd);
|
explicit Comms(int fd, absl::string_view name = "");
|
||||||
|
|
||||||
// Instantiates a pre-connected object using the default connection params.
|
// Instantiates a pre-connected object using the default connection params.
|
||||||
explicit Comms(DefaultConnectionTag);
|
explicit Comms(DefaultConnectionTag);
|
||||||
|
@ -120,12 +127,17 @@ class Comms {
|
||||||
~Comms();
|
~Comms();
|
||||||
|
|
||||||
// Binds to an address and make it listen to connections.
|
// Binds to an address and make it listen to connections.
|
||||||
|
ABSL_DEPRECATED("Use ListeningComms::Create() instead")
|
||||||
bool Listen();
|
bool Listen();
|
||||||
|
|
||||||
// Accepts the connection.
|
// Accepts the connection.
|
||||||
|
ABSL_DEPRECATED("Use ListeningComms::Accept() instead")
|
||||||
bool Accept();
|
bool Accept();
|
||||||
|
|
||||||
// Connects to a remote socket.
|
// Connects to a remote socket.
|
||||||
|
ABSL_DEPRECATED(
|
||||||
|
"Use absl::StatusOr<Comms> Comms::Connect(std::string& socket_name, bool "
|
||||||
|
"abstract_uds) instead")
|
||||||
bool Connect();
|
bool Connect();
|
||||||
|
|
||||||
// Terminates all underlying file descriptors, and sets the status of the
|
// Terminates all underlying file descriptors, and sets the status of the
|
||||||
|
@ -201,11 +213,11 @@ class Comms {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(socket_name_, other.socket_name_);
|
swap(name_, other.name_);
|
||||||
swap(abstract_uds_, other.abstract_uds_);
|
swap(abstract_uds_, other.abstract_uds_);
|
||||||
swap(connection_fd_, other.connection_fd_);
|
swap(connection_fd_, other.connection_fd_);
|
||||||
swap(bind_fd_, other.bind_fd_);
|
|
||||||
swap(state_, other.state_);
|
swap(state_, other.state_);
|
||||||
|
swap(listening_comms_, other.listening_comms_);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend void swap(Comms& x, Comms& y) { return x.Swap(y); }
|
friend void swap(Comms& x, Comms& y) { return x.Swap(y); }
|
||||||
|
@ -221,10 +233,11 @@ class Comms {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Connection parameters.
|
// Connection parameters.
|
||||||
std::string socket_name_;
|
std::string name_;
|
||||||
bool abstract_uds_ = true;
|
bool abstract_uds_ = true;
|
||||||
int connection_fd_ = -1;
|
sapi::file_util::fileops::FDCloser connection_fd_;
|
||||||
int bind_fd_ = -1;
|
|
||||||
|
std::unique_ptr<ListeningComms> listening_comms_;
|
||||||
|
|
||||||
// State of the channel (enum), socket will have to be connected later on.
|
// State of the channel (enum), socket will have to be connected later on.
|
||||||
State state_ = State::kUnconnected;
|
State state_ = State::kUnconnected;
|
||||||
|
@ -239,9 +252,6 @@ class Comms {
|
||||||
size_t len;
|
size_t len;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fills sockaddr_un struct with proper values.
|
|
||||||
socklen_t CreateSockaddrUn(sockaddr_un* sun);
|
|
||||||
|
|
||||||
// Moves the comms fd to an other free file descriptor.
|
// Moves the comms fd to an other free file descriptor.
|
||||||
void MoveToAnotherFd();
|
void MoveToAnotherFd();
|
||||||
|
|
||||||
|
@ -270,6 +280,26 @@ class Comms {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ListeningComms {
|
||||||
|
public:
|
||||||
|
static absl::StatusOr<ListeningComms> Create(absl::string_view socket_name,
|
||||||
|
bool abstract_uds = true);
|
||||||
|
|
||||||
|
ListeningComms(ListeningComms&& other) = default;
|
||||||
|
ListeningComms& operator=(ListeningComms&& other) = default;
|
||||||
|
~ListeningComms() = default;
|
||||||
|
absl::StatusOr<Comms> Accept();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ListeningComms(absl::string_view socket_name, bool abstract_uds)
|
||||||
|
: socket_name_(socket_name), abstract_uds_(abstract_uds), bind_fd_(-1) {}
|
||||||
|
absl::Status Listen();
|
||||||
|
|
||||||
|
std::string socket_name_;
|
||||||
|
bool abstract_uds_;
|
||||||
|
sapi::file_util::fileops::FDCloser bind_fd_;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace sandbox2
|
} // namespace sandbox2
|
||||||
|
|
||||||
#endif // SANDBOXED_API_SANDBOX2_COMMS_H_
|
#endif // SANDBOXED_API_SANDBOX2_COMMS_H_
|
||||||
|
|
Loading…
Reference in New Issue
Block a user