blob: 64f37ad5902f982217056835071faa54d13862f5 [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>
10
Kevin Cernekee27bcaa62016-12-03 11:16:26 -080011#include <utility>
12
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070013#include <base/bind.h>
14#include <base/logging.h>
15#include <base/message_loop/message_loop.h>
Garrick Evans49879532018-12-03 13:15:36 +090016#include <base/strings/stringprintf.h>
Kevin Cernekee27bcaa62016-12-03 11:16:26 -080017#include <brillo/minijail/minijail.h>
18
Garrick Evans428e4762018-12-11 15:18:42 +090019#include "arc/network/ipc.pb.h"
20
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070021namespace {
22
Kevin Cernekee27bcaa62016-12-03 11:16:26 -080023const uint64_t kManagerCapMask = CAP_TO_MASK(CAP_NET_RAW);
Garrick Evansd2bb8502019-02-20 15:59:35 +090024const char kUnprivilegedUser[] = "arc-networkd";
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070025
26} // namespace
27
28namespace arc_networkd {
29
Garrick Evansd2bb8502019-02-20 15:59:35 +090030Manager::Manager(std::unique_ptr<HelperProcess> ip_helper, bool enable_multinet)
Garrick Evansf4a93292019-03-13 14:19:43 +090031 : addr_mgr_({
32 AddressManager::Guest::ARC,
33 AddressManager::Guest::ARC_NET,
34 }),
35 enable_multinet_(enable_multinet) {
Kevin Cernekee27bcaa62016-12-03 11:16:26 -080036 ip_helper_ = std::move(ip_helper);
37}
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070038
39int Manager::OnInit() {
Kevin Cernekee27bcaa62016-12-03 11:16:26 -080040 // Run with minimal privileges.
41 brillo::Minijail* m = brillo::Minijail::GetInstance();
42 struct minijail* jail = m->New();
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070043
Kevin Cernekee27bcaa62016-12-03 11:16:26 -080044 // Most of these return void, but DropRoot() can fail if the user/group
45 // does not exist.
Hugo Benichi935eca92018-07-03 13:47:24 +090046 CHECK(m->DropRoot(jail, kUnprivilegedUser, kUnprivilegedUser))
47 << "Could not drop root privileges";
Kevin Cernekee27bcaa62016-12-03 11:16:26 -080048 m->UseCapabilities(jail, kManagerCapMask);
49 m->Enter(jail);
50 m->Destroy(jail);
51
52 // Handle subprocess lifecycle.
53 process_reaper_.Register(this);
Hugo Benichi935eca92018-07-03 13:47:24 +090054
55 CHECK(process_reaper_.WatchForChild(
Hidehiko Abe3a7e5132018-02-15 13:07:50 +090056 FROM_HERE, ip_helper_->pid(),
57 base::Bind(&Manager::OnSubprocessExited, weak_factory_.GetWeakPtr(),
Hugo Benichi935eca92018-07-03 13:47:24 +090058 ip_helper_->pid())))
59 << "Failed to watch child IpHelper process";
Kevin Cernekee27bcaa62016-12-03 11:16:26 -080060
Garrick Evans49879532018-12-03 13:15:36 +090061 // Handle container lifecycle.
62 RegisterHandler(
63 SIGUSR1, base::Bind(&Manager::OnContainerStart, base::Unretained(this)));
64 RegisterHandler(
65 SIGUSR2, base::Bind(&Manager::OnContainerStop, base::Unretained(this)));
66
67 // Run after Daemon::OnInit().
Eric Caruso9ce54182018-01-04 11:19:47 -080068 base::MessageLoopForIO::current()->task_runner()->PostTask(
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070069 FROM_HERE,
70 base::Bind(&Manager::InitialSetup, weak_factory_.GetWeakPtr()));
71
72 return DBusDaemon::OnInit();
73}
74
75void Manager::InitialSetup() {
Garrick Evans428e4762018-12-11 15:18:42 +090076 device_mgr_ = std::make_unique<DeviceManager>(
Garrick Evansef6b20d2019-05-31 13:29:24 +090077 std::make_unique<ShillClient>(std::move(bus_)), &addr_mgr_,
78 base::Bind(&Manager::SendMessage, weak_factory_.GetWeakPtr()),
79 !enable_multinet_);
Garrick Evans49879532018-12-03 13:15:36 +090080}
81
Garrick Evans49879532018-12-03 13:15:36 +090082bool Manager::OnContainerStart(const struct signalfd_siginfo& info) {
83 if (info.ssi_code == SI_USER) {
Garrick Evansef6b20d2019-05-31 13:29:24 +090084 device_mgr_->OnGuestStart();
Hugo Benichiee787ff2019-05-20 16:42:42 +090085 }
86
Garrick Evans49879532018-12-03 13:15:36 +090087 // Stay registered.
88 return false;
89}
90
91bool Manager::OnContainerStop(const struct signalfd_siginfo& info) {
92 if (info.ssi_code == SI_USER) {
Garrick Evansef6b20d2019-05-31 13:29:24 +090093 device_mgr_->OnGuestStop();
Garrick Evans49879532018-12-03 13:15:36 +090094 }
95
96 // Stay registered.
97 return false;
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070098}
99
Kevin Cernekee27bcaa62016-12-03 11:16:26 -0800100void Manager::OnShutdown(int* exit_code) {
Garrick Evans428e4762018-12-11 15:18:42 +0900101 device_mgr_.reset();
Kevin Cernekee27bcaa62016-12-03 11:16:26 -0800102}
103
104void Manager::OnSubprocessExited(pid_t pid, const siginfo_t& info) {
Hugo Benichi10a2af42018-08-27 10:09:42 +0900105 LOG(ERROR) << "Subprocess " << pid << " exited unexpectedly";
106 Quit();
Kevin Cernekee27bcaa62016-12-03 11:16:26 -0800107}
108
Garrick Evans49879532018-12-03 13:15:36 +0900109void Manager::SendMessage(const IpHelperMessage& msg) {
110 ip_helper_->SendMessage(msg);
Hugo Benichi935eca92018-07-03 13:47:24 +0900111}
112
Kevin Cernekee95d4ae92016-06-19 10:26:29 -0700113} // namespace arc_networkd