blob: 00f6df1bb04b4293cf3e3144b23b05186d317faa [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>
10
11#include <utility>
12
13#include <base/bind.h>
14#include <base/logging.h>
15#include <base/strings/stringprintf.h>
16#include <brillo/minijail/minijail.h>
17
18namespace arc_networkd {
19namespace {
20constexpr uint16_t kTcpPort = 5555;
21constexpr uint32_t kTcpAddr = 0x64735C02; // 100.115.92.2
jasongustaman14076282019-05-20 15:38:41 +090022constexpr uint32_t kVsockPort = 5555;
23// Reference: (./src/private-overlays/project-cheets-private/
24// chromeos-base/android-vm-pi/files/run-arcvm)
25constexpr uint32_t kVsockCid = 5;
Garrick Evans3cbac7c2019-04-18 15:31:31 +090026constexpr uint64_t kCapMask = CAP_TO_MASK(CAP_NET_RAW);
27constexpr char kUnprivilegedUser[] = "arc-networkd";
28constexpr int kMaxConn = 16;
29
30} // namespace
31
32AdbProxy::AdbProxy() : src_watcher_(FROM_HERE) {}
33
34AdbProxy::~AdbProxy() {
35 src_watcher_.StopWatchingFileDescriptor();
36}
37
38int AdbProxy::OnInit() {
39 // Prevent the main process from sending us any signals.
40 if (setsid() < 0) {
41 PLOG(ERROR) << "Failed to created a new session with setsid; exiting";
42 return -1;
43 }
44
45 // Run with minimal privileges.
46 brillo::Minijail* m = brillo::Minijail::GetInstance();
47 struct minijail* jail = m->New();
48
49 // Most of these return void, but DropRoot() can fail if the user/group
50 // does not exist.
51 CHECK(m->DropRoot(jail, kUnprivilegedUser, kUnprivilegedUser))
52 << "Could not drop root privileges";
53 m->UseCapabilities(jail, kCapMask);
54 m->Enter(jail);
55 m->Destroy(jail);
56
57 src_ = std::make_unique<Socket>(AF_INET, SOCK_STREAM | SOCK_NONBLOCK);
58 struct sockaddr_in addr = {0};
59 addr.sin_family = AF_INET;
60 addr.sin_port = htons(kTcpPort);
61 addr.sin_addr.s_addr = htonl(INADDR_ANY);
Garrick Evansfa872f62019-05-28 16:49:25 +090062 if (!src_->Bind((const struct sockaddr*)&addr, sizeof(addr))) {
Garrick Evans3cbac7c2019-04-18 15:31:31 +090063 LOG(ERROR) << "Cannot bind source socket; exiting";
64 return -1;
65 }
66
67 if (!src_->Listen(kMaxConn)) {
68 LOG(ERROR) << "Cannot listen on source socket; exiting";
69 return -1;
70 }
71
72 RegisterHandler(SIGUSR1,
73 base::Bind(&AdbProxy::OnSignal, base::Unretained(this)));
74 RegisterHandler(SIGUSR2,
75 base::Bind(&AdbProxy::OnSignal, base::Unretained(this)));
76
77 base::MessageLoopForIO::current()->WatchFileDescriptor(
78 src_->fd(), true, base::MessageLoopForIO::WATCH_READ, &src_watcher_,
79 this);
80
81 return Daemon::OnInit();
82}
83
84void AdbProxy::OnFileCanReadWithoutBlocking(int fd) {
85 if (auto conn = src_->Accept()) {
86 if (auto dst = Connect()) {
87 LOG(INFO) << "Connection established: " << *conn << " <-> " << *dst;
88 auto fwd = std::make_unique<SocketForwarder>(
89 base::StringPrintf("adbp%d-%d", conn->fd(), dst->fd()),
90 std::move(conn), std::move(dst));
91 fwd->Start();
92 fwd_.emplace_back(std::move(fwd));
93 }
94 }
95
96 // Cleanup any defunct forwarders.
97 for (auto it = fwd_.begin(); it != fwd_.end();) {
Garrick Evans4e96fad2019-05-17 10:19:38 +090098 if (!(*it)->IsValid() && (*it)->HasBeenStarted())
Garrick Evans3cbac7c2019-04-18 15:31:31 +090099 it = fwd_.erase(it);
Garrick Evans4e96fad2019-05-17 10:19:38 +0900100 else
101 ++it;
Garrick Evans3cbac7c2019-04-18 15:31:31 +0900102 }
103}
104
105std::unique_ptr<Socket> AdbProxy::Connect() const {
jasongustaman14076282019-05-20 15:38:41 +0900106 // Try to connect with VSOCK.
jasongustaman8587cc02019-05-27 15:01:29 +0900107 struct sockaddr_vm addr_vm = {0};
jasongustaman14076282019-05-20 15:38:41 +0900108 addr_vm.svm_family = AF_VSOCK;
109 addr_vm.svm_port = kVsockPort;
110 addr_vm.svm_cid = kVsockCid;
111
112 auto dst = std::make_unique<Socket>(AF_VSOCK, SOCK_STREAM);
Garrick Evansfa872f62019-05-28 16:49:25 +0900113 if (dst->Connect((const struct sockaddr*)&addr_vm, sizeof(addr_vm)))
jasongustaman14076282019-05-20 15:38:41 +0900114 return dst;
115
116 // Try to connect with TCP IPv4.
jasongustaman8587cc02019-05-27 15:01:29 +0900117 struct sockaddr_in addr_in = {0};
Garrick Evans3cbac7c2019-04-18 15:31:31 +0900118 addr_in.sin_family = AF_INET;
119 addr_in.sin_port = htons(kTcpPort);
120 addr_in.sin_addr.s_addr = htonl(kTcpAddr);
121
jasongustaman14076282019-05-20 15:38:41 +0900122 dst = std::make_unique<Socket>(AF_INET, SOCK_STREAM);
Garrick Evansfa872f62019-05-28 16:49:25 +0900123 if (dst->Connect((const struct sockaddr*)&addr_in, sizeof(addr_in)))
jasongustaman14076282019-05-20 15:38:41 +0900124 return dst;
125
126 return nullptr;
Garrick Evans3cbac7c2019-04-18 15:31:31 +0900127}
128
129bool AdbProxy::OnSignal(const struct signalfd_siginfo& info) {
130 // On guest down just ensure any existing connections are culled.
131 if (info.ssi_signo == SIGUSR2)
132 fwd_.clear();
133
134 // Stay registered.
135 return false;
136}
137
138} // namespace arc_networkd