blob: 2a112d2cb6d4294ef2a4fabf24a69e4a460b7e96 [file] [log] [blame]
Kevin Cernekee95d4ae92016-06-19 10:26:29 -07001// Copyright 2016 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
Hidehiko Abe3a7e5132018-02-15 13:07:50 +09005#include "arc/network/manager.h"
Kevin Cernekee4e62cc12016-12-03 11:50:53 -08006
Kevin Cernekee95d4ae92016-06-19 10:26:29 -07007#include <arpa/inet.h>
Hugo Benichi935eca92018-07-03 13:47:24 +09008#include <netinet/in.h>
Kevin Cernekee95d4ae92016-06-19 10:26:29 -07009#include <stdint.h>
Garrick Evans96e03042019-05-28 14:30:52 +090010#include <sys/socket.h>
11#include <sys/un.h>
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070012
Kevin Cernekee27bcaa62016-12-03 11:16:26 -080013#include <utility>
Garrick Evans96e03042019-05-28 14:30:52 +090014#include <vector>
Kevin Cernekee27bcaa62016-12-03 11:16:26 -080015
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070016#include <base/bind.h>
17#include <base/logging.h>
18#include <base/message_loop/message_loop.h>
Garrick Evans96e03042019-05-28 14:30:52 +090019#include <base/posix/unix_domain_socket_linux.h>
Garrick Evans49879532018-12-03 13:15:36 +090020#include <base/strings/stringprintf.h>
Garrick Evans96e03042019-05-28 14:30:52 +090021#include <base/strings/string_number_conversions.h>
22#include <base/strings/string_split.h>
Kevin Cernekee27bcaa62016-12-03 11:16:26 -080023#include <brillo/minijail/minijail.h>
24
Garrick Evans428e4762018-12-11 15:18:42 +090025#include "arc/network/ipc.pb.h"
26
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070027namespace {
28
Garrick Evans96e03042019-05-28 14:30:52 +090029constexpr uint64_t kManagerCapMask = CAP_TO_MASK(CAP_NET_RAW);
30constexpr char kUnprivilegedUser[] = "arc-networkd";
31constexpr char kGuestSocketPath[] = "/run/arc/network.gsock";
32// These values are used to make guest event messages:
33// Indicates the ARC guest (either ARC++ or ARCVM) is the source of the event.
34constexpr char kGuestArc[] = "ARC";
35// Indicates the guest is starting up.
36constexpr char kEventUp[] = "UP";
37// Indicates the guest is shutting down.
38constexpr char kEventDown[] = "DOWN";
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070039
40} // namespace
41
42namespace arc_networkd {
43
Garrick Evans96e03042019-05-28 14:30:52 +090044Manager::Manager(std::unique_ptr<HelperProcess> ip_helper,
45 std::unique_ptr<HelperProcess> adb_proxy,
46 bool enable_multinet)
47 : ip_helper_(std::move(ip_helper)),
48 adb_proxy_(std::move(adb_proxy)),
49 addr_mgr_({
Garrick Evansf4a93292019-03-13 14:19:43 +090050 AddressManager::Guest::ARC,
51 AddressManager::Guest::ARC_NET,
52 }),
Garrick Evans96e03042019-05-28 14:30:52 +090053 enable_multinet_(enable_multinet),
54 gsock_(AF_UNIX, SOCK_DGRAM),
55 gsock_watcher_(FROM_HERE) {}
56
57Manager::~Manager() {
58 gsock_watcher_.StopWatchingFileDescriptor();
Kevin Cernekee27bcaa62016-12-03 11:16:26 -080059}
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070060
61int Manager::OnInit() {
Kevin Cernekee27bcaa62016-12-03 11:16:26 -080062 // Run with minimal privileges.
63 brillo::Minijail* m = brillo::Minijail::GetInstance();
64 struct minijail* jail = m->New();
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070065
Kevin Cernekee27bcaa62016-12-03 11:16:26 -080066 // Most of these return void, but DropRoot() can fail if the user/group
67 // does not exist.
Hugo Benichi935eca92018-07-03 13:47:24 +090068 CHECK(m->DropRoot(jail, kUnprivilegedUser, kUnprivilegedUser))
69 << "Could not drop root privileges";
Kevin Cernekee27bcaa62016-12-03 11:16:26 -080070 m->UseCapabilities(jail, kManagerCapMask);
71 m->Enter(jail);
72 m->Destroy(jail);
73
74 // Handle subprocess lifecycle.
75 process_reaper_.Register(this);
Hugo Benichi935eca92018-07-03 13:47:24 +090076
77 CHECK(process_reaper_.WatchForChild(
Hidehiko Abe3a7e5132018-02-15 13:07:50 +090078 FROM_HERE, ip_helper_->pid(),
79 base::Bind(&Manager::OnSubprocessExited, weak_factory_.GetWeakPtr(),
Hugo Benichi935eca92018-07-03 13:47:24 +090080 ip_helper_->pid())))
Garrick Evans96e03042019-05-28 14:30:52 +090081 << "Failed to watch ip-helper child process";
Kevin Cernekee27bcaa62016-12-03 11:16:26 -080082
Garrick Evans96e03042019-05-28 14:30:52 +090083 CHECK(process_reaper_.WatchForChild(
84 FROM_HERE, adb_proxy_->pid(),
85 base::Bind(&Manager::OnSubprocessExited, weak_factory_.GetWeakPtr(),
86 adb_proxy_->pid())))
87 << "Failed to watch adb-proxy child process";
88
89 // Setup the socket for guests to connect and notify certain events.
90 struct sockaddr_un addr = {0};
91 addr.sun_family = AF_UNIX;
92 // Start at pos 1 to make this an abstract socket. Note that SUN_LEN does not
93 // work in this case since it uses strlen, so this is the correct way to
94 // compute the length of addr.
95 strncpy(&addr.sun_path[1], kGuestSocketPath, strlen(kGuestSocketPath));
96 socklen_t addrlen =
97 offsetof(struct sockaddr_un, sun_path) + strlen(kGuestSocketPath) + 1;
98 if (!gsock_.Bind((const struct sockaddr*)&addr, addrlen)) {
99 LOG(ERROR) << "Cannot bind guest socket @" << kGuestSocketPath
100 << "; exiting";
101 return -1;
102 }
103
104 base::MessageLoopForIO::current()->WatchFileDescriptor(
105 gsock_.fd(), true, base::MessageLoopForIO::WATCH_READ, &gsock_watcher_,
106 this);
Garrick Evans49879532018-12-03 13:15:36 +0900107
108 // Run after Daemon::OnInit().
Eric Caruso9ce54182018-01-04 11:19:47 -0800109 base::MessageLoopForIO::current()->task_runner()->PostTask(
Kevin Cernekee95d4ae92016-06-19 10:26:29 -0700110 FROM_HERE,
111 base::Bind(&Manager::InitialSetup, weak_factory_.GetWeakPtr()));
112
113 return DBusDaemon::OnInit();
114}
115
116void Manager::InitialSetup() {
Garrick Evans428e4762018-12-11 15:18:42 +0900117 device_mgr_ = std::make_unique<DeviceManager>(
Garrick Evansef6b20d2019-05-31 13:29:24 +0900118 std::make_unique<ShillClient>(std::move(bus_)), &addr_mgr_,
Garrick Evans96e03042019-05-28 14:30:52 +0900119 base::Bind(&Manager::SendDeviceMessage, weak_factory_.GetWeakPtr()),
Garrick Evansef6b20d2019-05-31 13:29:24 +0900120 !enable_multinet_);
Garrick Evans49879532018-12-03 13:15:36 +0900121}
122
Garrick Evans96e03042019-05-28 14:30:52 +0900123void Manager::OnFileCanReadWithoutBlocking(int fd) {
124 char buf[128] = {0};
125 std::vector<base::ScopedFD> fds{};
126 ssize_t len = base::UnixDomainSocket::RecvMsg(fd, buf, sizeof(buf), &fds);
127
128 if (len <= 0) {
129 PLOG(WARNING) << "Read failed";
130 return;
Hugo Benichiee787ff2019-05-20 16:42:42 +0900131 }
132
Garrick Evans96e03042019-05-28 14:30:52 +0900133 std::string msg(buf);
134 OnGuestNotification(msg);
Garrick Evans49879532018-12-03 13:15:36 +0900135}
136
Garrick Evans96e03042019-05-28 14:30:52 +0900137void Manager::OnGuestNotification(const std::string& notification) {
138 // Notification strings are in the form:
139 // guest_type event_type [container_pid]
140 // where the first two fields are required and the thrid is only for ARC++.
141 const auto args = base::SplitString(notification, " ", base::TRIM_WHITESPACE,
142 base::SPLIT_WANT_NONEMPTY);
143 if (args.size() < 2) {
144 LOG(WARNING) << "Unexpected notification: " << notification;
145 return;
Garrick Evans49879532018-12-03 13:15:36 +0900146 }
147
Garrick Evans96e03042019-05-28 14:30:52 +0900148 if (args[0] != kGuestArc) {
149 LOG(DFATAL) << "Unexpected guest: " << args[0];
150 return;
151 }
152
153 GuestMessage msg;
154 msg.set_type(GuestMessage::ARC);
155
156 if (args[1] == kEventUp) {
157 msg.set_event(GuestMessage::START);
158 } else if (args[1] == kEventDown) {
159 msg.set_event(GuestMessage::STOP);
160 } else {
161 LOG(DFATAL) << "Unexpected event: " << args[1];
162 return;
163 }
164
165 // ARC++
166 if (args.size() == 3) {
167 int pid = 0;
168 if (!base::StringToInt(args[2], &pid)) {
169 LOG(DFATAL) << "Invalid ARC++ pid: " << args[2];
170 return;
171 }
172 msg.set_arc_pid(pid);
173
174 if (msg.event() == GuestMessage::START) {
175 device_mgr_->OnGuestStart();
176 } else if (msg.event() == GuestMessage::STOP) {
177 device_mgr_->OnGuestStop();
178 }
179 }
180
181 SendGuestMessage(msg);
Kevin Cernekee95d4ae92016-06-19 10:26:29 -0700182}
183
Kevin Cernekee27bcaa62016-12-03 11:16:26 -0800184void Manager::OnShutdown(int* exit_code) {
Garrick Evans428e4762018-12-11 15:18:42 +0900185 device_mgr_.reset();
Kevin Cernekee27bcaa62016-12-03 11:16:26 -0800186}
187
188void Manager::OnSubprocessExited(pid_t pid, const siginfo_t& info) {
Hugo Benichi10a2af42018-08-27 10:09:42 +0900189 LOG(ERROR) << "Subprocess " << pid << " exited unexpectedly";
190 Quit();
Kevin Cernekee27bcaa62016-12-03 11:16:26 -0800191}
192
Garrick Evans96e03042019-05-28 14:30:52 +0900193void Manager::SendGuestMessage(const GuestMessage& msg) {
194 IpHelperMessage ipm;
195 *ipm.mutable_guest_message() = msg;
196 ip_helper_->SendMessage(ipm);
197 adb_proxy_->SendMessage(ipm);
198}
199
200void Manager::SendDeviceMessage(const DeviceMessage& msg) {
201 IpHelperMessage ipm;
202 *ipm.mutable_device_message() = msg;
203 ip_helper_->SendMessage(ipm);
Hugo Benichi935eca92018-07-03 13:47:24 +0900204}
205
Kevin Cernekee95d4ae92016-06-19 10:26:29 -0700206} // namespace arc_networkd