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