blob: d6510be192d3fa1dec883cd58c039f068166fe08 [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
5#include "arc/network/adb_proxy.h"
6
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
Jason Jeremy Imanf4156cb2019-11-14 15:36:22 +090024#include "arc/network/manager.h"
Jason Jeremy Imand89b5f52019-10-24 10:39:17 +090025#include "arc/network/minijailed_process_runner.h"
Hugo Benichi2ac4d072019-05-28 14:51:23 +090026#include "arc/network/net_util.h"
27
Garrick Evans3cbac7c2019-04-18 15:31:31 +090028namespace arc_networkd {
29namespace {
Jason Jeremy Imanf19e4e52020-02-19 07:15:18 +000030// adb gets confused if we listen on 5555 and thinks there is an emulator
31// running, which in turn ends up confusing our integration test libraries
32// because multiple devices show up.
33constexpr uint16_t kTcpListenPort = 5550;
34// But we still connect to adbd on its standard TCP port.
Garrick Evansa7556db2019-05-07 11:22:40 +090035constexpr uint16_t kTcpConnectPort = 5555;
Hugo Benichi2ac4d072019-05-28 14:51:23 +090036constexpr uint32_t kTcpAddr = Ipv4Addr(100, 115, 92, 2);
jasongustaman14076282019-05-20 15:38:41 +090037constexpr uint32_t kVsockPort = 5555;
Garrick Evans3cbac7c2019-04-18 15:31:31 +090038constexpr int kMaxConn = 16;
Jason Jeremy Imanf4156cb2019-11-14 15:36:22 +090039// Reference: "device/google/cheets2/init.usb.rc".
40constexpr char kUnixConnectAddr[] = "/run/arc/adb/adb.sock";
41
Garrick Evansb05a7ff2020-02-18 12:59:55 +090042const std::set<GuestMessage::GuestType> kArcGuestTypes{GuestMessage::ARC,
43 GuestMessage::ARC_VM};
Garrick Evans3cbac7c2019-04-18 15:31:31 +090044} // namespace
45
Garrick Evans96e03042019-05-28 14:30:52 +090046AdbProxy::AdbProxy(base::ScopedFD control_fd)
Garrick Evansbdf1f982019-06-07 09:46:49 +090047 : msg_dispatcher_(std::move(control_fd)),
Garrick Evans1cce71a2019-06-21 10:43:14 +090048 arc_type_(GuestMessage::UNKNOWN_GUEST),
49 arcvm_vsock_cid_(-1) {
Garrick Evans96e03042019-05-28 14:30:52 +090050 msg_dispatcher_.RegisterFailureHandler(
51 base::Bind(&AdbProxy::OnParentProcessExit, weak_factory_.GetWeakPtr()));
52
53 msg_dispatcher_.RegisterGuestMessageHandler(
54 base::Bind(&AdbProxy::OnGuestMessage, weak_factory_.GetWeakPtr()));
55}
Garrick Evans3cbac7c2019-04-18 15:31:31 +090056
Hidehiko Abede129222019-08-16 00:55:04 +090057AdbProxy::~AdbProxy() = default;
Garrick Evans3cbac7c2019-04-18 15:31:31 +090058
59int AdbProxy::OnInit() {
60 // Prevent the main process from sending us any signals.
61 if (setsid() < 0) {
62 PLOG(ERROR) << "Failed to created a new session with setsid; exiting";
Garrick Evansaa4f1ce2019-11-29 13:25:39 +090063 return EX_OSERR;
Garrick Evans3cbac7c2019-04-18 15:31:31 +090064 }
Jason Jeremy Imand89b5f52019-10-24 10:39:17 +090065 EnterChildProcessJail();
Garrick Evans3cbac7c2019-04-18 15:31:31 +090066 return Daemon::OnInit();
67}
68
Garrick Evansbdf1f982019-06-07 09:46:49 +090069void AdbProxy::Reset() {
Hidehiko Abede129222019-08-16 00:55:04 +090070 src_watcher_.reset();
Garrick Evansbdf1f982019-06-07 09:46:49 +090071 src_.reset();
72 fwd_.clear();
Garrick Evans1cce71a2019-06-21 10:43:14 +090073 arcvm_vsock_cid_ = -1;
74 arc_type_ = GuestMessage::UNKNOWN_GUEST;
Garrick Evansbdf1f982019-06-07 09:46:49 +090075}
76
Garrick Evans96e03042019-05-28 14:30:52 +090077void AdbProxy::OnParentProcessExit() {
78 LOG(ERROR) << "Quitting because the parent process died";
Garrick Evansbdf1f982019-06-07 09:46:49 +090079 Reset();
Garrick Evans96e03042019-05-28 14:30:52 +090080 Quit();
81}
82
Hidehiko Abede129222019-08-16 00:55:04 +090083void AdbProxy::OnFileCanReadWithoutBlocking() {
Hugo Benichidcc32392020-02-27 09:14:40 +090084 struct sockaddr_storage client_src = {};
85 socklen_t sockaddr_len = sizeof(client_src);
86 if (auto client_conn =
87 src_->Accept((struct sockaddr*)&client_src, &sockaddr_len)) {
88 LOG(INFO) << "new adb connection from " << client_src;
89 if (auto adbd_conn = Connect()) {
Garrick Evans3cbac7c2019-04-18 15:31:31 +090090 auto fwd = std::make_unique<SocketForwarder>(
Hugo Benichidcc32392020-02-27 09:14:40 +090091 base::StringPrintf("adbp%d-%d", client_conn->fd(), adbd_conn->fd()),
92 std::move(client_conn), std::move(adbd_conn));
Garrick Evans3cbac7c2019-04-18 15:31:31 +090093 fwd->Start();
94 fwd_.emplace_back(std::move(fwd));
95 }
96 }
97
98 // Cleanup any defunct forwarders.
99 for (auto it = fwd_.begin(); it != fwd_.end();) {
Garrick Evans088cd0e2019-06-04 15:20:43 +0900100 if (!(*it)->IsRunning() && (*it)->HasBeenStarted())
Garrick Evans3cbac7c2019-04-18 15:31:31 +0900101 it = fwd_.erase(it);
Garrick Evans4e96fad2019-05-17 10:19:38 +0900102 else
103 ++it;
Garrick Evans3cbac7c2019-04-18 15:31:31 +0900104 }
105}
106
107std::unique_ptr<Socket> AdbProxy::Connect() const {
Garrick Evansbdf1f982019-06-07 09:46:49 +0900108 switch (arc_type_) {
Jason Jeremy Imanf4156cb2019-11-14 15:36:22 +0900109 case GuestMessage::ARC: {
Jason Jeremy Imane50426d2020-02-19 15:28:57 +0900110 struct sockaddr_un addr_un = {0};
111 addr_un.sun_family = AF_UNIX;
112 snprintf(addr_un.sun_path, sizeof(addr_un.sun_path), "%s",
113 kUnixConnectAddr);
114 auto dst = std::make_unique<Socket>(AF_UNIX, SOCK_STREAM);
Hugo Benichidcc32392020-02-27 09:14:40 +0900115 if (dst->Connect((const struct sockaddr*)&addr_un, sizeof(addr_un))) {
116 LOG(INFO) << "Established adbd connection to " << addr_un;
Jason Jeremy Imane50426d2020-02-19 15:28:57 +0900117 return dst;
Hugo Benichidcc32392020-02-27 09:14:40 +0900118 }
Garrick Evansb05a7ff2020-02-18 12:59:55 +0900119
120 LOG(WARNING) << "Failed to connect to UNIX domain socket: "
121 << kUnixConnectAddr << " - falling back to TCP";
122
Garrick Evansbdf1f982019-06-07 09:46:49 +0900123 struct sockaddr_in addr_in = {0};
124 addr_in.sin_family = AF_INET;
125 addr_in.sin_port = htons(kTcpConnectPort);
126 addr_in.sin_addr.s_addr = kTcpAddr;
Garrick Evansb05a7ff2020-02-18 12:59:55 +0900127 dst = std::make_unique<Socket>(AF_INET, SOCK_STREAM);
Hugo Benichidcc32392020-02-27 09:14:40 +0900128 if (!dst->Connect((const struct sockaddr*)&addr_in, sizeof(addr_in)))
129 return nullptr;
130 LOG(INFO) << "Established adbd connection to " << addr_in;
131 return dst;
Garrick Evansbdf1f982019-06-07 09:46:49 +0900132 }
133 case GuestMessage::ARC_VM: {
134 struct sockaddr_vm addr_vm = {0};
135 addr_vm.svm_family = AF_VSOCK;
136 addr_vm.svm_port = kVsockPort;
Garrick Evans1cce71a2019-06-21 10:43:14 +0900137 addr_vm.svm_cid = arcvm_vsock_cid_;
Garrick Evansbdf1f982019-06-07 09:46:49 +0900138 auto dst = std::make_unique<Socket>(AF_VSOCK, SOCK_STREAM);
Hugo Benichidcc32392020-02-27 09:14:40 +0900139 if (!dst->Connect((const struct sockaddr*)&addr_vm, sizeof(addr_vm)))
140 return nullptr;
141 LOG(INFO) << "Established adbd connection to " << addr_vm;
142 return dst;
Garrick Evansbdf1f982019-06-07 09:46:49 +0900143 }
144 default:
145 LOG(DFATAL) << "Unexpected connect - no ARC guest";
146 return nullptr;
147 }
Garrick Evans3cbac7c2019-04-18 15:31:31 +0900148}
149
Garrick Evans96e03042019-05-28 14:30:52 +0900150void AdbProxy::OnGuestMessage(const GuestMessage& msg) {
Garrick Evans1cce71a2019-06-21 10:43:14 +0900151 if (msg.type() == GuestMessage::UNKNOWN_GUEST) {
152 LOG(DFATAL) << "Unexpected message from unknown guest";
Garrick Evans96e03042019-05-28 14:30:52 +0900153 return;
Garrick Evans1cce71a2019-06-21 10:43:14 +0900154 }
Garrick Evans96e03042019-05-28 14:30:52 +0900155
Jason Jeremy Iman510bd3d2019-12-16 13:05:30 +0900156 if (kArcGuestTypes.find(msg.type()) == kArcGuestTypes.end()) {
157 return;
158 }
159
Garrick Evansbdf1f982019-06-07 09:46:49 +0900160 arc_type_ = msg.type();
Garrick Evans1cce71a2019-06-21 10:43:14 +0900161 arcvm_vsock_cid_ = msg.arcvm_vsock_cid();
Garrick Evansbdf1f982019-06-07 09:46:49 +0900162
Garrick Evans96e03042019-05-28 14:30:52 +0900163 // On ARC up, start accepting connections.
164 if (msg.event() == GuestMessage::START) {
Garrick Evans584210b2019-05-27 14:25:43 +0900165 src_ = std::make_unique<Socket>(AF_INET, SOCK_STREAM | SOCK_NONBLOCK);
Garrick Evans20cc37c2019-05-29 17:25:59 +0900166 // Need to set this to reuse the port on localhost.
Garrick Evans20cc37c2019-05-29 17:25:59 +0900167 int on = 1;
168 if (setsockopt(src_->fd(), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) <
169 0) {
170 PLOG(ERROR) << "setsockopt(SO_REUSEADDR) failed";
Garrick Evans96e03042019-05-28 14:30:52 +0900171 return;
Garrick Evans20cc37c2019-05-29 17:25:59 +0900172 }
Garrick Evans584210b2019-05-27 14:25:43 +0900173 struct sockaddr_in addr = {0};
174 addr.sin_family = AF_INET;
Jason Jeremy Imanf19e4e52020-02-19 07:15:18 +0000175 addr.sin_port = htons(kTcpListenPort);
Garrick Evans584210b2019-05-27 14:25:43 +0900176 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
177 if (!src_->Bind((const struct sockaddr*)&addr, sizeof(addr))) {
Hugo Benichidcc32392020-02-27 09:14:40 +0900178 LOG(ERROR) << "Cannot bind source socket to " << addr;
Garrick Evans96e03042019-05-28 14:30:52 +0900179 return;
Garrick Evans584210b2019-05-27 14:25:43 +0900180 }
181
182 if (!src_->Listen(kMaxConn)) {
Hugo Benichidcc32392020-02-27 09:14:40 +0900183 LOG(ERROR) << "Cannot listen on " << addr;
Garrick Evans96e03042019-05-28 14:30:52 +0900184 return;
Garrick Evans584210b2019-05-27 14:25:43 +0900185 }
186
187 // Run the accept loop.
Hugo Benichidcc32392020-02-27 09:14:40 +0900188 LOG(INFO) << "Accepting connections on " << addr;
Hidehiko Abede129222019-08-16 00:55:04 +0900189 src_watcher_ = base::FileDescriptorWatcher::WatchReadable(
190 src_->fd(), base::BindRepeating(&AdbProxy::OnFileCanReadWithoutBlocking,
191 base::Unretained(this)));
Garrick Evans96e03042019-05-28 14:30:52 +0900192 return;
Garrick Evans584210b2019-05-27 14:25:43 +0900193 }
194
Garrick Evans96e03042019-05-28 14:30:52 +0900195 // On ARC down, cull any open connections and stop listening.
196 if (msg.event() == GuestMessage::STOP) {
Garrick Evansbdf1f982019-06-07 09:46:49 +0900197 Reset();
Garrick Evans584210b2019-05-27 14:25:43 +0900198 }
Garrick Evans3cbac7c2019-04-18 15:31:31 +0900199}
200
Garrick Evans3cbac7c2019-04-18 15:31:31 +0900201} // namespace arc_networkd