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 #include <thread>
27
28 #include "absl/log/log.h"
29 #include "absl/strings/string_view.h"
30 #include "sandboxed_api/sandbox2/comms.h"
31 #include "sandboxed_api/sandbox2/logserver.h"
32 #include "sandboxed_api/sandbox2/logsink.h"
33 #include "sandboxed_api/util/raw_logging.h"
34
35 namespace sandbox2 {
36
SetUpServerSideComms(int fd)37 void IPC::SetUpServerSideComms(int fd) { comms_ = std::make_unique<Comms>(fd); }
38
MapFd(int local_fd,int remote_fd)39 void IPC::MapFd(int local_fd, int remote_fd) {
40 VLOG(3) << "Will send: " << local_fd << ", to overwrite: " << remote_fd;
41 fd_map_.push_back(std::make_tuple(local_fd, remote_fd, ""));
42 }
43
MapDupedFd(int local_fd,int remote_fd)44 void IPC::MapDupedFd(int local_fd, int remote_fd) {
45 const int dup_local_fd = dup(local_fd);
46 if (dup_local_fd == -1) {
47 PLOG(FATAL) << "dup(" << local_fd << ")";
48 }
49 VLOG(3) << "Will send: " << dup_local_fd << " (dup of " << local_fd
50 << "), to overwrite: " << remote_fd;
51 fd_map_.push_back(std::make_tuple(dup_local_fd, remote_fd, ""));
52 }
53
ReceiveFd(int remote_fd)54 int IPC::ReceiveFd(int remote_fd) { return ReceiveFd(remote_fd, ""); }
55
ReceiveFd(absl::string_view name)56 int IPC::ReceiveFd(absl::string_view name) { return ReceiveFd(-1, name); }
57
ReceiveFd(int remote_fd,absl::string_view name)58 int IPC::ReceiveFd(int remote_fd, absl::string_view name) {
59 int sv[2];
60 if (socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) == -1) {
61 PLOG(FATAL) << "socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)";
62 }
63 VLOG(3) << "Created a socketpair (" << sv[0] << "/" << sv[1] << "), "
64 << "which will overwrite remote_fd: " << remote_fd;
65 fd_map_.push_back(std::make_tuple(sv[1], remote_fd, std::string(name)));
66 return sv[0];
67 }
68
SendFdsOverComms()69 bool IPC::SendFdsOverComms() {
70 if (!(comms_->SendUint32(fd_map_.size()))) {
71 LOG(ERROR) << "Couldn't send IPC fd size";
72 return false;
73 }
74
75 for (const auto& fd_tuple : fd_map_) {
76 if (!(comms_->SendInt32(std::get<1>(fd_tuple)))) {
77 LOG(ERROR) << "SendInt32: Couldn't send " << std::get<1>(fd_tuple);
78 return false;
79 }
80 if (!(comms_->SendFD(std::get<0>(fd_tuple)))) {
81 LOG(ERROR) << "SendFd: Couldn't send " << std::get<0>(fd_tuple);
82 return false;
83 }
84
85 if (!(comms_->SendString(std::get<2>(fd_tuple)))) {
86 LOG(ERROR) << "SendString: Couldn't send " << std::get<2>(fd_tuple);
87 return false;
88 }
89 VLOG(3) << "IPC: local_fd: " << std::get<0>(fd_tuple)
90 << ", remote_fd: " << std::get<1>(fd_tuple) << " sent";
91 }
92
93 return true;
94 }
95
InternalCleanupFdMap()96 void IPC::InternalCleanupFdMap() {
97 for (const auto& fd_tuple : fd_map_) {
98 close(std::get<0>(fd_tuple));
99 }
100 fd_map_.clear();
101 }
102
EnableLogServer()103 void IPC::EnableLogServer() {
104 int fd = ReceiveFd(LogSink::kLogFDName);
105 auto logger = [fd] {
106 LogServer log_server(fd);
107 log_server.Run();
108 };
109 std::thread log_thread{logger};
110 log_thread.detach();
111 }
112
113 } // namespace sandbox2
114