1 // Copyright 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 // Implementation of the sandbox2::IPC class
16
17 #include "sandboxed_api/sandbox2/ipc.h"
18
19 #include <sys/socket.h>
20 #include <unistd.h>
21
22 #include <memory>
23 #include <string>
24 #include <tuple>
25 #include <vector>
26
27 #include "absl/log/log.h"
28 #include "absl/strings/string_view.h"
29 #include "sandboxed_api/sandbox2/comms.h"
30 #include "sandboxed_api/sandbox2/logserver.h"
31 #include "sandboxed_api/sandbox2/logsink.h"
32 #include "sandboxed_api/util/thread.h"
33
34 namespace sandbox2 {
35
SetUpServerSideComms(int fd)36 void IPC::SetUpServerSideComms(int fd) { comms_ = std::make_unique<Comms>(fd); }
37
MapFd(int local_fd,int remote_fd)38 void IPC::MapFd(int local_fd, int remote_fd) {
39 VLOG(3) << "Will send: " << local_fd << ", to overwrite: " << remote_fd;
40 fd_map_.push_back(std::make_tuple(local_fd, remote_fd, ""));
41 }
42
MapDupedFd(int local_fd,int remote_fd)43 void IPC::MapDupedFd(int local_fd, int remote_fd) {
44 const int dup_local_fd = dup(local_fd);
45 if (dup_local_fd == -1) {
46 PLOG(FATAL) << "dup(" << local_fd << ")";
47 }
48 VLOG(3) << "Will send: " << dup_local_fd << " (dup of " << local_fd
49 << "), to overwrite: " << remote_fd;
50 fd_map_.push_back(std::make_tuple(dup_local_fd, remote_fd, ""));
51 }
52
ReceiveFd(int remote_fd)53 int IPC::ReceiveFd(int remote_fd) { return ReceiveFd(remote_fd, ""); }
54
ReceiveFd(absl::string_view name)55 int IPC::ReceiveFd(absl::string_view name) { return ReceiveFd(-1, name); }
56
ReceiveFd(int remote_fd,absl::string_view name)57 int IPC::ReceiveFd(int remote_fd, absl::string_view name) {
58 int sv[2];
59 if (socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) == -1) {
60 PLOG(FATAL) << "socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)";
61 }
62 VLOG(3) << "Created a socketpair (" << sv[0] << "/" << sv[1] << "), "
63 << "which will overwrite remote_fd: " << remote_fd;
64 fd_map_.push_back(std::make_tuple(sv[1], remote_fd, std::string(name)));
65 return sv[0];
66 }
67
SendFdsOverComms()68 bool IPC::SendFdsOverComms() {
69 if (!(comms_->SendUint32(fd_map_.size()))) {
70 LOG(ERROR) << "Couldn't send IPC fd size";
71 return false;
72 }
73
74 for (const auto& fd_tuple : fd_map_) {
75 if (!(comms_->SendInt32(std::get<1>(fd_tuple)))) {
76 LOG(ERROR) << "SendInt32: Couldn't send " << std::get<1>(fd_tuple);
77 return false;
78 }
79 if (!(comms_->SendFD(std::get<0>(fd_tuple)))) {
80 LOG(ERROR) << "SendFd: Couldn't send " << std::get<0>(fd_tuple);
81 return false;
82 }
83
84 if (!(comms_->SendString(std::get<2>(fd_tuple)))) {
85 LOG(ERROR) << "SendString: Couldn't send " << std::get<2>(fd_tuple);
86 return false;
87 }
88 VLOG(3) << "IPC: local_fd: " << std::get<0>(fd_tuple)
89 << ", remote_fd: " << std::get<1>(fd_tuple) << " sent";
90 }
91
92 return true;
93 }
94
InternalCleanupFdMap()95 void IPC::InternalCleanupFdMap() {
96 for (const auto& fd_tuple : fd_map_) {
97 close(std::get<0>(fd_tuple));
98 }
99 fd_map_.clear();
100 }
101
EnableLogServer()102 void IPC::EnableLogServer() {
103 int fd = ReceiveFd(LogSink::kLogFDName);
104 auto logger = [fd] {
105 LogServer log_server(fd);
106 log_server.Run();
107 };
108 sapi::Thread::StartDetachedThread(logger, "LogServer");
109 }
110
111 } // namespace sandbox2
112