blob: 770d42d67a91b82fa6bb754a34590cebee9011fa [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
7#include <sys/socket.h>
8#include <sys/types.h>
9
10#include <utility>
11
12#include <base/bind.h>
13#include <base/logging.h>
14#include <base/strings/stringprintf.h>
15#include <brillo/minijail/minijail.h>
16
17namespace arc_networkd {
18namespace {
19constexpr uint16_t kTcpPort = 5555;
20constexpr uint32_t kTcpAddr = 0x64735C02; // 100.115.92.2
21constexpr uint64_t kCapMask = CAP_TO_MASK(CAP_NET_RAW);
22constexpr char kUnprivilegedUser[] = "arc-networkd";
23constexpr int kMaxConn = 16;
24
25} // namespace
26
27AdbProxy::AdbProxy() : src_watcher_(FROM_HERE) {}
28
29AdbProxy::~AdbProxy() {
30 src_watcher_.StopWatchingFileDescriptor();
31}
32
33int AdbProxy::OnInit() {
34 // Prevent the main process from sending us any signals.
35 if (setsid() < 0) {
36 PLOG(ERROR) << "Failed to created a new session with setsid; exiting";
37 return -1;
38 }
39
40 // Run with minimal privileges.
41 brillo::Minijail* m = brillo::Minijail::GetInstance();
42 struct minijail* jail = m->New();
43
44 // Most of these return void, but DropRoot() can fail if the user/group
45 // does not exist.
46 CHECK(m->DropRoot(jail, kUnprivilegedUser, kUnprivilegedUser))
47 << "Could not drop root privileges";
48 m->UseCapabilities(jail, kCapMask);
49 m->Enter(jail);
50 m->Destroy(jail);
51
52 src_ = std::make_unique<Socket>(AF_INET, SOCK_STREAM | SOCK_NONBLOCK);
53 struct sockaddr_in addr = {0};
54 addr.sin_family = AF_INET;
55 addr.sin_port = htons(kTcpPort);
56 addr.sin_addr.s_addr = htonl(INADDR_ANY);
57 if (!src_->Bind((const struct sockaddr*)&addr)) {
58 LOG(ERROR) << "Cannot bind source socket; exiting";
59 return -1;
60 }
61
62 if (!src_->Listen(kMaxConn)) {
63 LOG(ERROR) << "Cannot listen on source socket; exiting";
64 return -1;
65 }
66
67 RegisterHandler(SIGUSR1,
68 base::Bind(&AdbProxy::OnSignal, base::Unretained(this)));
69 RegisterHandler(SIGUSR2,
70 base::Bind(&AdbProxy::OnSignal, base::Unretained(this)));
71
72 base::MessageLoopForIO::current()->WatchFileDescriptor(
73 src_->fd(), true, base::MessageLoopForIO::WATCH_READ, &src_watcher_,
74 this);
75
76 return Daemon::OnInit();
77}
78
79void AdbProxy::OnFileCanReadWithoutBlocking(int fd) {
80 if (auto conn = src_->Accept()) {
81 if (auto dst = Connect()) {
82 LOG(INFO) << "Connection established: " << *conn << " <-> " << *dst;
83 auto fwd = std::make_unique<SocketForwarder>(
84 base::StringPrintf("adbp%d-%d", conn->fd(), dst->fd()),
85 std::move(conn), std::move(dst));
86 fwd->Start();
87 fwd_.emplace_back(std::move(fwd));
88 }
89 }
90
91 // Cleanup any defunct forwarders.
92 for (auto it = fwd_.begin(); it != fwd_.end();) {
93 if ((*it)->IsValid())
94 ++it;
95 else
96 it = fwd_.erase(it);
97 }
98}
99
100std::unique_ptr<Socket> AdbProxy::Connect() const {
101 // TODO(garrick): Add others.
102 struct sockaddr_in addr_in;
103 addr_in.sin_family = AF_INET;
104 addr_in.sin_port = htons(kTcpPort);
105 addr_in.sin_addr.s_addr = htonl(kTcpAddr);
106
107 auto dst = std::make_unique<Socket>(AF_INET, SOCK_STREAM);
108 return dst->Connect((const struct sockaddr*)&addr_in) ? std::move(dst)
109 : nullptr;
110}
111
112bool AdbProxy::OnSignal(const struct signalfd_siginfo& info) {
113 // On guest down just ensure any existing connections are culled.
114 if (info.ssi_signo == SIGUSR2)
115 fwd_.clear();
116
117 // Stay registered.
118 return false;
119}
120
121} // namespace arc_networkd