Kevin Cernekee | 95d4ae9 | 2016-06-19 10:26:29 -0700 | [diff] [blame] | 1 | // 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 Abe | 3a7e513 | 2018-02-15 13:07:50 +0900 | [diff] [blame] | 5 | #include "arc/network/manager.h" |
Kevin Cernekee | 4e62cc1 | 2016-12-03 11:50:53 -0800 | [diff] [blame] | 6 | |
Kevin Cernekee | 95d4ae9 | 2016-06-19 10:26:29 -0700 | [diff] [blame] | 7 | #include <arpa/inet.h> |
Hugo Benichi | 935eca9 | 2018-07-03 13:47:24 +0900 | [diff] [blame] | 8 | #include <netinet/in.h> |
Kevin Cernekee | 95d4ae9 | 2016-06-19 10:26:29 -0700 | [diff] [blame] | 9 | #include <stdint.h> |
| 10 | |
Kevin Cernekee | 27bcaa6 | 2016-12-03 11:16:26 -0800 | [diff] [blame] | 11 | #include <utility> |
| 12 | |
Kevin Cernekee | 95d4ae9 | 2016-06-19 10:26:29 -0700 | [diff] [blame] | 13 | #include <base/bind.h> |
| 14 | #include <base/logging.h> |
| 15 | #include <base/message_loop/message_loop.h> |
Garrick Evans | 4987953 | 2018-12-03 13:15:36 +0900 | [diff] [blame] | 16 | #include <base/strings/stringprintf.h> |
Kevin Cernekee | 27bcaa6 | 2016-12-03 11:16:26 -0800 | [diff] [blame] | 17 | #include <brillo/minijail/minijail.h> |
| 18 | |
Garrick Evans | 428e476 | 2018-12-11 15:18:42 +0900 | [diff] [blame] | 19 | #include "arc/network/ipc.pb.h" |
| 20 | |
Kevin Cernekee | 95d4ae9 | 2016-06-19 10:26:29 -0700 | [diff] [blame] | 21 | namespace { |
| 22 | |
Kevin Cernekee | 27bcaa6 | 2016-12-03 11:16:26 -0800 | [diff] [blame] | 23 | const uint64_t kManagerCapMask = CAP_TO_MASK(CAP_NET_RAW); |
Garrick Evans | d2bb850 | 2019-02-20 15:59:35 +0900 | [diff] [blame] | 24 | const char kUnprivilegedUser[] = "arc-networkd"; |
Kevin Cernekee | 95d4ae9 | 2016-06-19 10:26:29 -0700 | [diff] [blame] | 25 | |
| 26 | } // namespace |
| 27 | |
| 28 | namespace arc_networkd { |
| 29 | |
Garrick Evans | d2bb850 | 2019-02-20 15:59:35 +0900 | [diff] [blame] | 30 | Manager::Manager(std::unique_ptr<HelperProcess> ip_helper, bool enable_multinet) |
Garrick Evans | f4a9329 | 2019-03-13 14:19:43 +0900 | [diff] [blame] | 31 | : addr_mgr_({ |
| 32 | AddressManager::Guest::ARC, |
| 33 | AddressManager::Guest::ARC_NET, |
| 34 | }), |
| 35 | enable_multinet_(enable_multinet) { |
Kevin Cernekee | 27bcaa6 | 2016-12-03 11:16:26 -0800 | [diff] [blame] | 36 | ip_helper_ = std::move(ip_helper); |
| 37 | } |
Kevin Cernekee | 95d4ae9 | 2016-06-19 10:26:29 -0700 | [diff] [blame] | 38 | |
| 39 | int Manager::OnInit() { |
Kevin Cernekee | 27bcaa6 | 2016-12-03 11:16:26 -0800 | [diff] [blame] | 40 | // Run with minimal privileges. |
| 41 | brillo::Minijail* m = brillo::Minijail::GetInstance(); |
| 42 | struct minijail* jail = m->New(); |
Kevin Cernekee | 95d4ae9 | 2016-06-19 10:26:29 -0700 | [diff] [blame] | 43 | |
Kevin Cernekee | 27bcaa6 | 2016-12-03 11:16:26 -0800 | [diff] [blame] | 44 | // Most of these return void, but DropRoot() can fail if the user/group |
| 45 | // does not exist. |
Hugo Benichi | 935eca9 | 2018-07-03 13:47:24 +0900 | [diff] [blame] | 46 | CHECK(m->DropRoot(jail, kUnprivilegedUser, kUnprivilegedUser)) |
| 47 | << "Could not drop root privileges"; |
Kevin Cernekee | 27bcaa6 | 2016-12-03 11:16:26 -0800 | [diff] [blame] | 48 | m->UseCapabilities(jail, kManagerCapMask); |
| 49 | m->Enter(jail); |
| 50 | m->Destroy(jail); |
| 51 | |
| 52 | // Handle subprocess lifecycle. |
Hugo Benichi | 935eca9 | 2018-07-03 13:47:24 +0900 | [diff] [blame] | 53 | |
Kevin Cernekee | 27bcaa6 | 2016-12-03 11:16:26 -0800 | [diff] [blame] | 54 | process_reaper_.Register(this); |
Hugo Benichi | 935eca9 | 2018-07-03 13:47:24 +0900 | [diff] [blame] | 55 | |
| 56 | CHECK(process_reaper_.WatchForChild( |
Hidehiko Abe | 3a7e513 | 2018-02-15 13:07:50 +0900 | [diff] [blame] | 57 | FROM_HERE, ip_helper_->pid(), |
| 58 | base::Bind(&Manager::OnSubprocessExited, weak_factory_.GetWeakPtr(), |
Hugo Benichi | 935eca9 | 2018-07-03 13:47:24 +0900 | [diff] [blame] | 59 | ip_helper_->pid()))) |
| 60 | << "Failed to watch child IpHelper process"; |
Kevin Cernekee | 27bcaa6 | 2016-12-03 11:16:26 -0800 | [diff] [blame] | 61 | |
Garrick Evans | 4987953 | 2018-12-03 13:15:36 +0900 | [diff] [blame] | 62 | // Handle container lifecycle. |
| 63 | RegisterHandler( |
| 64 | SIGUSR1, base::Bind(&Manager::OnContainerStart, base::Unretained(this))); |
| 65 | RegisterHandler( |
| 66 | SIGUSR2, base::Bind(&Manager::OnContainerStop, base::Unretained(this))); |
| 67 | |
| 68 | // Run after Daemon::OnInit(). |
Eric Caruso | 9ce5418 | 2018-01-04 11:19:47 -0800 | [diff] [blame] | 69 | base::MessageLoopForIO::current()->task_runner()->PostTask( |
Kevin Cernekee | 95d4ae9 | 2016-06-19 10:26:29 -0700 | [diff] [blame] | 70 | FROM_HERE, |
| 71 | base::Bind(&Manager::InitialSetup, weak_factory_.GetWeakPtr())); |
| 72 | |
| 73 | return DBusDaemon::OnInit(); |
| 74 | } |
| 75 | |
| 76 | void Manager::InitialSetup() { |
Garrick Evans | 428e476 | 2018-12-11 15:18:42 +0900 | [diff] [blame] | 77 | shill_client_ = std::make_unique<ShillClient>(std::move(bus_)); |
Garrick Evans | 428e476 | 2018-12-11 15:18:42 +0900 | [diff] [blame] | 78 | device_mgr_ = std::make_unique<DeviceManager>( |
Garrick Evans | f4a9329 | 2019-03-13 14:19:43 +0900 | [diff] [blame] | 79 | &addr_mgr_, base::Bind(&Manager::SendMessage, weak_factory_.GetWeakPtr()), |
Garrick Evans | d2bb850 | 2019-02-20 15:59:35 +0900 | [diff] [blame] | 80 | enable_multinet_ ? kAndroidDevice : kAndroidLegacyDevice); |
| 81 | |
| 82 | if (enable_multinet_) { |
| 83 | shill_client_->RegisterDevicesChangedHandler( |
| 84 | base::Bind(&Manager::OnDevicesChanged, weak_factory_.GetWeakPtr())); |
| 85 | shill_client_->ScanDevices( |
| 86 | base::Bind(&Manager::OnDevicesChanged, weak_factory_.GetWeakPtr())); |
| 87 | } |
Garrick Evans | 4987953 | 2018-12-03 13:15:36 +0900 | [diff] [blame] | 88 | } |
| 89 | |
Garrick Evans | 4987953 | 2018-12-03 13:15:36 +0900 | [diff] [blame] | 90 | bool Manager::OnContainerStart(const struct signalfd_siginfo& info) { |
| 91 | if (info.ssi_code == SI_USER) { |
| 92 | shill_client_->RegisterDefaultInterfaceChangedHandler(base::Bind( |
| 93 | &Manager::OnDefaultInterfaceChanged, weak_factory_.GetWeakPtr())); |
| 94 | } |
| 95 | |
Hugo Benichi | ee787ff | 2019-05-20 16:42:42 +0900 | [diff] [blame^] | 96 | if (enable_multinet_ && device_mgr_) { |
| 97 | device_mgr_->EnableAllDevices(); |
| 98 | } |
| 99 | |
Garrick Evans | 4987953 | 2018-12-03 13:15:36 +0900 | [diff] [blame] | 100 | // Stay registered. |
| 101 | return false; |
| 102 | } |
| 103 | |
| 104 | bool Manager::OnContainerStop(const struct signalfd_siginfo& info) { |
| 105 | if (info.ssi_code == SI_USER) { |
| 106 | shill_client_->UnregisterDefaultInterfaceChangedHandler(); |
Hugo Benichi | ee787ff | 2019-05-20 16:42:42 +0900 | [diff] [blame^] | 107 | if (device_mgr_) { |
| 108 | if (enable_multinet_) { |
| 109 | device_mgr_->DisableAllDevices(); |
| 110 | } else { |
| 111 | device_mgr_->DisableLegacyDevice(); |
| 112 | } |
| 113 | } |
Garrick Evans | 4987953 | 2018-12-03 13:15:36 +0900 | [diff] [blame] | 114 | } |
| 115 | |
| 116 | // Stay registered. |
| 117 | return false; |
Kevin Cernekee | 95d4ae9 | 2016-06-19 10:26:29 -0700 | [diff] [blame] | 118 | } |
| 119 | |
| 120 | void Manager::OnDefaultInterfaceChanged(const std::string& ifname) { |
Garrick Evans | 4987953 | 2018-12-03 13:15:36 +0900 | [diff] [blame] | 121 | LOG(INFO) << "Default interface changed to " << ifname; |
Hugo Benichi | ee787ff | 2019-05-20 16:42:42 +0900 | [diff] [blame^] | 122 | if (!enable_multinet_ && device_mgr_) |
| 123 | device_mgr_->EnableLegacyDevice(ifname); |
Kevin Cernekee | 95d4ae9 | 2016-06-19 10:26:29 -0700 | [diff] [blame] | 124 | } |
| 125 | |
Garrick Evans | 4987953 | 2018-12-03 13:15:36 +0900 | [diff] [blame] | 126 | void Manager::OnDevicesChanged(const std::set<std::string>& devices) { |
Garrick Evans | 428e476 | 2018-12-11 15:18:42 +0900 | [diff] [blame] | 127 | if (device_mgr_) |
| 128 | device_mgr_->Reset(devices); |
Kevin Cernekee | 31a3d90 | 2017-07-11 16:46:39 -0700 | [diff] [blame] | 129 | } |
| 130 | |
Kevin Cernekee | 27bcaa6 | 2016-12-03 11:16:26 -0800 | [diff] [blame] | 131 | void Manager::OnShutdown(int* exit_code) { |
Garrick Evans | 428e476 | 2018-12-11 15:18:42 +0900 | [diff] [blame] | 132 | device_mgr_.reset(); |
Kevin Cernekee | 27bcaa6 | 2016-12-03 11:16:26 -0800 | [diff] [blame] | 133 | } |
| 134 | |
| 135 | void Manager::OnSubprocessExited(pid_t pid, const siginfo_t& info) { |
Hugo Benichi | 10a2af4 | 2018-08-27 10:09:42 +0900 | [diff] [blame] | 136 | LOG(ERROR) << "Subprocess " << pid << " exited unexpectedly"; |
| 137 | Quit(); |
Kevin Cernekee | 27bcaa6 | 2016-12-03 11:16:26 -0800 | [diff] [blame] | 138 | } |
| 139 | |
Garrick Evans | 4987953 | 2018-12-03 13:15:36 +0900 | [diff] [blame] | 140 | void Manager::SendMessage(const IpHelperMessage& msg) { |
| 141 | ip_helper_->SendMessage(msg); |
Hugo Benichi | 935eca9 | 2018-07-03 13:47:24 +0900 | [diff] [blame] | 142 | } |
| 143 | |
Kevin Cernekee | 95d4ae9 | 2016-06-19 10:26:29 -0700 | [diff] [blame] | 144 | } // namespace arc_networkd |