blob: 0f94ec32f19457b81ae81ec172c57a3d685f8c11 [file] [log] [blame]
Garrick Evans3cbac7c2019-04-18 15:31:31 +09001// Copyright 2019 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Garrick Evans3388a032020-03-24 11:25:55 +09005#include "patchpanel/adb_proxy.h"
Garrick Evans3cbac7c2019-04-18 15:31:31 +09006
jasongustaman14076282019-05-20 15:38:41 +09007#include <linux/vm_sockets.h>
Garrick Evans3cbac7c2019-04-18 15:31:31 +09008#include <sys/socket.h>
9#include <sys/types.h>
Jason Jeremy Imanf4156cb2019-11-14 15:36:22 +090010#include <sys/un.h>
Garrick Evansaa4f1ce2019-11-29 13:25:39 +090011#include <sysexits.h>
Garrick Evans3cbac7c2019-04-18 15:31:31 +090012
Jason Jeremy Iman510bd3d2019-12-16 13:05:30 +090013#include <set>
Jason Jeremy Imanf4156cb2019-11-14 15:36:22 +090014#include <string>
Garrick Evans3cbac7c2019-04-18 15:31:31 +090015#include <utility>
Jason Jeremy Imanf4156cb2019-11-14 15:36:22 +090016#include <vector>
Garrick Evans3cbac7c2019-04-18 15:31:31 +090017
18#include <base/bind.h>
19#include <base/logging.h>
Jason Jeremy Imanf4156cb2019-11-14 15:36:22 +090020#include <base/strings/string_number_conversions.h>
Garrick Evans3cbac7c2019-04-18 15:31:31 +090021#include <base/strings/stringprintf.h>
Jason Jeremy Imanf4156cb2019-11-14 15:36:22 +090022#include <brillo/key_value_store.h>
Garrick Evans3cbac7c2019-04-18 15:31:31 +090023
Garrick Evans3388a032020-03-24 11:25:55 +090024#include "patchpanel/manager.h"
25#include "patchpanel/minijailed_process_runner.h"
26#include "patchpanel/net_util.h"
Hugo Benichi2ac4d072019-05-28 14:51:23 +090027
Garrick Evans3388a032020-03-24 11:25:55 +090028namespace patchpanel {
Garrick Evans3cbac7c2019-04-18 15:31:31 +090029namespace {
Jason Jeremy Imanfa8b6d22020-02-20 03:44:21 +000030// adb-proxy will connect to adbd on its standard TCP port.
Garrick Evansa7556db2019-05-07 11:22:40 +090031constexpr uint16_t kTcpConnectPort = 5555;
Hugo Benichi2ac4d072019-05-28 14:51:23 +090032constexpr uint32_t kTcpAddr = Ipv4Addr(100, 115, 92, 2);
jasongustaman14076282019-05-20 15:38:41 +090033constexpr uint32_t kVsockPort = 5555;
Garrick Evans3cbac7c2019-04-18 15:31:31 +090034constexpr int kMaxConn = 16;
Jason Jeremy Imanf4156cb2019-11-14 15:36:22 +090035// Reference: "device/google/cheets2/init.usb.rc".
36constexpr char kUnixConnectAddr[] = "/run/arc/adb/adb.sock";
37
Garrick Evansb05a7ff2020-02-18 12:59:55 +090038const std::set<GuestMessage::GuestType> kArcGuestTypes{GuestMessage::ARC,
39 GuestMessage::ARC_VM};
Garrick Evans3cbac7c2019-04-18 15:31:31 +090040} // namespace
41
Garrick Evans96e03042019-05-28 14:30:52 +090042AdbProxy::AdbProxy(base::ScopedFD control_fd)
Garrick Evansbdf1f982019-06-07 09:46:49 +090043 : msg_dispatcher_(std::move(control_fd)),
Garrick Evans1cce71a2019-06-21 10:43:14 +090044 arc_type_(GuestMessage::UNKNOWN_GUEST),
45 arcvm_vsock_cid_(-1) {
Garrick Evans96e03042019-05-28 14:30:52 +090046 msg_dispatcher_.RegisterFailureHandler(
47 base::Bind(&AdbProxy::OnParentProcessExit, weak_factory_.GetWeakPtr()));
48
49 msg_dispatcher_.RegisterGuestMessageHandler(
50 base::Bind(&AdbProxy::OnGuestMessage, weak_factory_.GetWeakPtr()));
51}
Garrick Evans3cbac7c2019-04-18 15:31:31 +090052
Hidehiko Abede129222019-08-16 00:55:04 +090053AdbProxy::~AdbProxy() = default;
Garrick Evans3cbac7c2019-04-18 15:31:31 +090054
55int AdbProxy::OnInit() {
56 // Prevent the main process from sending us any signals.
57 if (setsid() < 0) {
58 PLOG(ERROR) << "Failed to created a new session with setsid; exiting";
Garrick Evansaa4f1ce2019-11-29 13:25:39 +090059 return EX_OSERR;
Garrick Evans3cbac7c2019-04-18 15:31:31 +090060 }
Jason Jeremy Imand89b5f52019-10-24 10:39:17 +090061 EnterChildProcessJail();
Garrick Evans3cbac7c2019-04-18 15:31:31 +090062 return Daemon::OnInit();
63}
64
Garrick Evansbdf1f982019-06-07 09:46:49 +090065void AdbProxy::Reset() {
Hidehiko Abede129222019-08-16 00:55:04 +090066 src_watcher_.reset();
Garrick Evansbdf1f982019-06-07 09:46:49 +090067 src_.reset();
68 fwd_.clear();
Garrick Evans1cce71a2019-06-21 10:43:14 +090069 arcvm_vsock_cid_ = -1;
70 arc_type_ = GuestMessage::UNKNOWN_GUEST;
Garrick Evansbdf1f982019-06-07 09:46:49 +090071}
72
Garrick Evans96e03042019-05-28 14:30:52 +090073void AdbProxy::OnParentProcessExit() {
74 LOG(ERROR) << "Quitting because the parent process died";
Garrick Evansbdf1f982019-06-07 09:46:49 +090075 Reset();
Garrick Evans96e03042019-05-28 14:30:52 +090076 Quit();
77}
78
Hidehiko Abede129222019-08-16 00:55:04 +090079void AdbProxy::OnFileCanReadWithoutBlocking() {
Hugo Benichidcc32392020-02-27 09:14:40 +090080 struct sockaddr_storage client_src = {};
81 socklen_t sockaddr_len = sizeof(client_src);
82 if (auto client_conn =
83 src_->Accept((struct sockaddr*)&client_src, &sockaddr_len)) {
84 LOG(INFO) << "new adb connection from " << client_src;
85 if (auto adbd_conn = Connect()) {
Garrick Evans3cbac7c2019-04-18 15:31:31 +090086 auto fwd = std::make_unique<SocketForwarder>(
Hugo Benichidcc32392020-02-27 09:14:40 +090087 base::StringPrintf("adbp%d-%d", client_conn->fd(), adbd_conn->fd()),
88 std::move(client_conn), std::move(adbd_conn));
Garrick Evans3cbac7c2019-04-18 15:31:31 +090089 fwd->Start();
90 fwd_.emplace_back(std::move(fwd));
91 }
92 }
93
94 // Cleanup any defunct forwarders.
95 for (auto it = fwd_.begin(); it != fwd_.end();) {
Garrick Evans088cd0e2019-06-04 15:20:43 +090096 if (!(*it)->IsRunning() && (*it)->HasBeenStarted())
Garrick Evans3cbac7c2019-04-18 15:31:31 +090097 it = fwd_.erase(it);
Garrick Evans4e96fad2019-05-17 10:19:38 +090098 else
99 ++it;
Garrick Evans3cbac7c2019-04-18 15:31:31 +0900100 }
101}
102
103std::unique_ptr<Socket> AdbProxy::Connect() const {
Garrick Evansbdf1f982019-06-07 09:46:49 +0900104 switch (arc_type_) {
Jason Jeremy Imanf4156cb2019-11-14 15:36:22 +0900105 case GuestMessage::ARC: {
Jason Jeremy Imane50426d2020-02-19 15:28:57 +0900106 struct sockaddr_un addr_un = {0};
107 addr_un.sun_family = AF_UNIX;
108 snprintf(addr_un.sun_path, sizeof(addr_un.sun_path), "%s",
109 kUnixConnectAddr);
110 auto dst = std::make_unique<Socket>(AF_UNIX, SOCK_STREAM);
Hugo Benichidcc32392020-02-27 09:14:40 +0900111 if (dst->Connect((const struct sockaddr*)&addr_un, sizeof(addr_un))) {
112 LOG(INFO) << "Established adbd connection to " << addr_un;
Jason Jeremy Imane50426d2020-02-19 15:28:57 +0900113 return dst;
Hugo Benichidcc32392020-02-27 09:14:40 +0900114 }
Garrick Evansb05a7ff2020-02-18 12:59:55 +0900115
116 LOG(WARNING) << "Failed to connect to UNIX domain socket: "
117 << kUnixConnectAddr << " - falling back to TCP";
118
Garrick Evansbdf1f982019-06-07 09:46:49 +0900119 struct sockaddr_in addr_in = {0};
120 addr_in.sin_family = AF_INET;
121 addr_in.sin_port = htons(kTcpConnectPort);
122 addr_in.sin_addr.s_addr = kTcpAddr;
Garrick Evansb05a7ff2020-02-18 12:59:55 +0900123 dst = std::make_unique<Socket>(AF_INET, SOCK_STREAM);
Hugo Benichidcc32392020-02-27 09:14:40 +0900124 if (!dst->Connect((const struct sockaddr*)&addr_in, sizeof(addr_in)))
125 return nullptr;
126 LOG(INFO) << "Established adbd connection to " << addr_in;
127 return dst;
Garrick Evansbdf1f982019-06-07 09:46:49 +0900128 }
129 case GuestMessage::ARC_VM: {
130 struct sockaddr_vm addr_vm = {0};
131 addr_vm.svm_family = AF_VSOCK;
132 addr_vm.svm_port = kVsockPort;
Garrick Evans1cce71a2019-06-21 10:43:14 +0900133 addr_vm.svm_cid = arcvm_vsock_cid_;
Garrick Evansbdf1f982019-06-07 09:46:49 +0900134 auto dst = std::make_unique<Socket>(AF_VSOCK, SOCK_STREAM);
Hugo Benichidcc32392020-02-27 09:14:40 +0900135 if (!dst->Connect((const struct sockaddr*)&addr_vm, sizeof(addr_vm)))
136 return nullptr;
137 LOG(INFO) << "Established adbd connection to " << addr_vm;
138 return dst;
Garrick Evansbdf1f982019-06-07 09:46:49 +0900139 }
140 default:
141 LOG(DFATAL) << "Unexpected connect - no ARC guest";
142 return nullptr;
143 }
Garrick Evans3cbac7c2019-04-18 15:31:31 +0900144}
145
Garrick Evans96e03042019-05-28 14:30:52 +0900146void AdbProxy::OnGuestMessage(const GuestMessage& msg) {
Garrick Evans1cce71a2019-06-21 10:43:14 +0900147 if (msg.type() == GuestMessage::UNKNOWN_GUEST) {
148 LOG(DFATAL) << "Unexpected message from unknown guest";
Garrick Evans96e03042019-05-28 14:30:52 +0900149 return;
Garrick Evans1cce71a2019-06-21 10:43:14 +0900150 }
Garrick Evans96e03042019-05-28 14:30:52 +0900151
Jason Jeremy Iman510bd3d2019-12-16 13:05:30 +0900152 if (kArcGuestTypes.find(msg.type()) == kArcGuestTypes.end()) {
153 return;
154 }
155
Garrick Evansbdf1f982019-06-07 09:46:49 +0900156 arc_type_ = msg.type();
Garrick Evans1cce71a2019-06-21 10:43:14 +0900157 arcvm_vsock_cid_ = msg.arcvm_vsock_cid();
Garrick Evansbdf1f982019-06-07 09:46:49 +0900158
Garrick Evans96e03042019-05-28 14:30:52 +0900159 // On ARC up, start accepting connections.
160 if (msg.event() == GuestMessage::START) {
Garrick Evans584210b2019-05-27 14:25:43 +0900161 src_ = std::make_unique<Socket>(AF_INET, SOCK_STREAM | SOCK_NONBLOCK);
Garrick Evans20cc37c2019-05-29 17:25:59 +0900162 // Need to set this to reuse the port on localhost.
Garrick Evans20cc37c2019-05-29 17:25:59 +0900163 int on = 1;
164 if (setsockopt(src_->fd(), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) <
165 0) {
166 PLOG(ERROR) << "setsockopt(SO_REUSEADDR) failed";
Garrick Evans96e03042019-05-28 14:30:52 +0900167 return;
Garrick Evans20cc37c2019-05-29 17:25:59 +0900168 }
Garrick Evans584210b2019-05-27 14:25:43 +0900169 struct sockaddr_in addr = {0};
170 addr.sin_family = AF_INET;
Jason Jeremy Imanfa8b6d22020-02-20 03:44:21 +0000171 addr.sin_port = htons(kAdbProxyTcpListenPort);
Garrick Evans584210b2019-05-27 14:25:43 +0900172 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
173 if (!src_->Bind((const struct sockaddr*)&addr, sizeof(addr))) {
Hugo Benichidcc32392020-02-27 09:14:40 +0900174 LOG(ERROR) << "Cannot bind source socket to " << addr;
Garrick Evans96e03042019-05-28 14:30:52 +0900175 return;
Garrick Evans584210b2019-05-27 14:25:43 +0900176 }
177
178 if (!src_->Listen(kMaxConn)) {
Hugo Benichidcc32392020-02-27 09:14:40 +0900179 LOG(ERROR) << "Cannot listen on " << addr;
Garrick Evans96e03042019-05-28 14:30:52 +0900180 return;
Garrick Evans584210b2019-05-27 14:25:43 +0900181 }
182
183 // Run the accept loop.
Hugo Benichidcc32392020-02-27 09:14:40 +0900184 LOG(INFO) << "Accepting connections on " << addr;
Hidehiko Abede129222019-08-16 00:55:04 +0900185 src_watcher_ = base::FileDescriptorWatcher::WatchReadable(
186 src_->fd(), base::BindRepeating(&AdbProxy::OnFileCanReadWithoutBlocking,
187 base::Unretained(this)));
Garrick Evans96e03042019-05-28 14:30:52 +0900188 return;
Garrick Evans584210b2019-05-27 14:25:43 +0900189 }
190
Garrick Evans96e03042019-05-28 14:30:52 +0900191 // On ARC down, cull any open connections and stop listening.
192 if (msg.event() == GuestMessage::STOP) {
Garrick Evansbdf1f982019-06-07 09:46:49 +0900193 Reset();
Garrick Evans584210b2019-05-27 14:25:43 +0900194 }
Garrick Evans3cbac7c2019-04-18 15:31:31 +0900195}
196
Garrick Evans3388a032020-03-24 11:25:55 +0900197} // namespace patchpanel