service_instance.cc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. // Copyright 2019 The Chromium 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. #include "services/service_manager/service_instance.h"
  5. #include <set>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/containers/contains.h"
  9. #include "base/logging.h"
  10. #include "base/strings/strcat.h"
  11. #include "base/strings/utf_string_conversions.h"
  12. #include "build/build_config.h"
  13. #include "mojo/public/cpp/bindings/callback_helpers.h"
  14. #include "services/service_manager/public/cpp/constants.h"
  15. #include "services/service_manager/public/mojom/constants.mojom.h"
  16. #include "services/service_manager/service_manager.h"
  17. #include "services/service_manager/service_process_host.h"
  18. #include "ui/base/l10n/l10n_util.h"
  19. #if !BUILDFLAG(IS_IOS)
  20. #include "sandbox/policy/mojom/sandbox.mojom.h"
  21. #include "services/service_manager/service_process_launcher.h"
  22. #endif // !BUILDFLAG(IS_IOS)
  23. namespace service_manager {
  24. namespace {
  25. // Returns the set of capabilities required from the target by the source.
  26. std::set<std::string> GetRequiredCapabilities(
  27. const Manifest::RequiredCapabilityMap& source_requirements,
  28. const std::string& target_service) {
  29. std::set<std::string> capabilities;
  30. // Start by looking for requirements specific to the target identity.
  31. auto it = source_requirements.find(target_service);
  32. if (it != source_requirements.end()) {
  33. std::copy(it->second.begin(), it->second.end(),
  34. std::inserter(capabilities, capabilities.begin()));
  35. }
  36. // Apply wild card rules too.
  37. it = source_requirements.find("*");
  38. if (it != source_requirements.end()) {
  39. std::copy(it->second.begin(), it->second.end(),
  40. std::inserter(capabilities, capabilities.begin()));
  41. }
  42. return capabilities;
  43. }
  44. void ReportBlockedInterface(const Manifest::ServiceName& source_service_name,
  45. const Manifest::ServiceName& target_service_name,
  46. const std::string& target_interface_name) {
  47. #if DCHECK_IS_ON()
  48. // While it would not be correct to assert that this never happens (e.g. a
  49. // compromised process may request invalid interfaces), we do want to
  50. // effectively treat all occurrences of this branch in production code as
  51. // bugs that must be fixed. This crash allows such bugs to be caught in
  52. // testing rather than relying on easily overlooked log messages.
  53. NOTREACHED()
  54. #else
  55. LOG(ERROR)
  56. #endif
  57. << "The Service Manager prevented service \"" << source_service_name
  58. << "\" from binding interface \"" << target_interface_name << "\""
  59. << " in target service \"" << target_service_name << "\". You probably "
  60. << "need to update one or more service manifests to ensure that \""
  61. << target_service_name << "\" exposes \"" << target_interface_name
  62. << "\" through a capability and that \"" << source_service_name
  63. << "\" requires that capability from the \"" << target_service_name
  64. << "\" service.";
  65. }
  66. void ReportBlockedStartService(const std::string& source_service_name,
  67. const std::string& target_service_name) {
  68. #if DCHECK_IS_ON()
  69. // See the note in ReportBlockedInterface above.
  70. NOTREACHED()
  71. #else
  72. LOG(ERROR)
  73. #endif
  74. << "Service \"" << source_service_name << "\" has attempted to manually "
  75. << "start service \"" << target_service_name << "\", but it is not "
  76. << "sufficiently privileged to do so. You probably need to update one or "
  77. << "services' manifests in order to remedy this situation.";
  78. }
  79. bool AllowsInterface(const Manifest::RequiredCapabilityMap& source_requirements,
  80. const std::string& target_name,
  81. const Manifest::ExposedCapabilityMap& target_capabilities,
  82. const std::string& interface_name) {
  83. std::set<std::string> allowed_interfaces;
  84. std::set<std::string> required_capabilities =
  85. GetRequiredCapabilities(source_requirements, target_name);
  86. for (const auto& capability : required_capabilities) {
  87. auto it = target_capabilities.find(capability);
  88. if (it != target_capabilities.end()) {
  89. for (const auto& interface : it->second)
  90. allowed_interfaces.insert(interface);
  91. }
  92. }
  93. bool allowed =
  94. allowed_interfaces.count("*") || allowed_interfaces.count(interface_name);
  95. return allowed;
  96. }
  97. } // namespace
  98. ServiceInstance::ServiceInstance(
  99. service_manager::ServiceManager* service_manager,
  100. const Identity& identity,
  101. const Manifest& manifest)
  102. : service_manager_(service_manager),
  103. identity_(identity),
  104. manifest_(manifest),
  105. can_contact_all_services_(manifest_.required_capabilities.count("*") ==
  106. 1) {
  107. DCHECK(identity_.IsValid());
  108. }
  109. ServiceInstance::~ServiceInstance() {
  110. // The instance may have already been stopped prior to destruction if the
  111. // ServiceManager itself is being torn down.
  112. if (!stopped_)
  113. Stop();
  114. }
  115. void ServiceInstance::SetPID(base::ProcessId pid) {
  116. #if !BUILDFLAG(IS_IOS)
  117. // iOS does not support base::Process and simply passes 0 here, so elide
  118. // this check on that platform.
  119. if (pid == base::kNullProcessId) {
  120. // Destroys |this|.
  121. service_manager_->DestroyInstance(this);
  122. return;
  123. }
  124. #endif
  125. pid_ = pid;
  126. MaybeNotifyPidAvailable();
  127. }
  128. void ServiceInstance::StartWithRemote(
  129. mojo::PendingRemote<mojom::Service> remote) {
  130. DCHECK(!service_remote_);
  131. service_remote_.Bind(std::move(remote));
  132. service_remote_.set_disconnect_handler(base::BindOnce(
  133. &ServiceInstance::OnServiceDisconnected, base::Unretained(this)));
  134. service_remote_->OnStart(identity_,
  135. base::BindOnce(&ServiceInstance::OnStartCompleted,
  136. base::Unretained(this)));
  137. service_manager_->NotifyServiceCreated(*this);
  138. }
  139. #if !BUILDFLAG(IS_IOS)
  140. bool ServiceInstance::StartWithProcessHost(
  141. std::unique_ptr<ServiceProcessHost> host,
  142. sandbox::mojom::Sandbox sandbox_type) {
  143. DCHECK(!service_remote_);
  144. DCHECK(!process_host_);
  145. std::u16string display_name;
  146. switch (manifest_.display_name.type) {
  147. case Manifest::DisplayName::Type::kDefault:
  148. display_name =
  149. base::ASCIIToUTF16(base::StrCat({identity_.name(), "service"}));
  150. break;
  151. case Manifest::DisplayName::Type::kRawString:
  152. display_name = base::ASCIIToUTF16(manifest_.display_name.raw_string);
  153. break;
  154. case Manifest::DisplayName::Type::kResourceId:
  155. display_name =
  156. l10n_util::GetStringUTF16(manifest_.display_name.resource_id);
  157. break;
  158. }
  159. auto remote = host->Launch(
  160. identity_, sandbox_type, display_name,
  161. base::BindOnce(&ServiceInstance::SetPID, weak_ptr_factory_.GetWeakPtr()));
  162. if (!remote)
  163. return false;
  164. process_host_ = std::move(host);
  165. StartWithRemote(std::move(remote));
  166. return true;
  167. }
  168. #endif // !BUILDFLAG(IS_IOS)
  169. void ServiceInstance::BindProcessMetadataReceiver(
  170. mojo::PendingReceiver<mojom::ProcessMetadata> receiver) {
  171. process_metadata_receiver_.Bind(std::move(receiver));
  172. }
  173. bool ServiceInstance::MaybeAcceptConnectionRequest(
  174. const ServiceInstance& source_instance,
  175. const std::string& interface_name,
  176. mojo::ScopedMessagePipeHandle receiving_pipe,
  177. mojom::BindInterfacePriority priority) {
  178. if (state_ == mojom::InstanceState::kUnreachable)
  179. return false;
  180. const Manifest& source_manifest = source_instance.manifest();
  181. const bool bindable_on_any_service = base::Contains(
  182. source_manifest.interfaces_bindable_on_any_service, interface_name);
  183. const bool allowed_by_capabilities =
  184. AllowsInterface(source_manifest.required_capabilities, identity_.name(),
  185. manifest_.exposed_capabilities, interface_name);
  186. if (!bindable_on_any_service && !allowed_by_capabilities) {
  187. ReportBlockedInterface(source_instance.identity().name(), identity_.name(),
  188. interface_name);
  189. return false;
  190. }
  191. base::OnceClosure on_bind_interface_complete;
  192. if (priority == mojom::BindInterfacePriority::kImportant) {
  193. pending_service_connections_++;
  194. on_bind_interface_complete = base::BindOnce(
  195. &ServiceInstance::OnConnectRequestAcknowledged, base::Unretained(this));
  196. }
  197. service_remote_->OnBindInterface(
  198. BindSourceInfo(
  199. source_instance.identity(),
  200. GetRequiredCapabilities(source_manifest.required_capabilities,
  201. identity_.name())),
  202. interface_name, std::move(receiving_pipe),
  203. std::move(on_bind_interface_complete));
  204. return true;
  205. }
  206. bool ServiceInstance::CreatePackagedServiceInstance(
  207. const Identity& packaged_instance_identity,
  208. mojo::PendingReceiver<mojom::Service> receiver,
  209. mojo::PendingRemote<mojom::ProcessMetadata> metadata) {
  210. if (!service_remote_)
  211. return false;
  212. service_remote_->CreatePackagedServiceInstance(
  213. packaged_instance_identity, std::move(receiver), std::move(metadata));
  214. return true;
  215. }
  216. void ServiceInstance::Stop() {
  217. DCHECK(!stopped_);
  218. // Shut down all receivers as well as the Service remote. The service should
  219. // observe disconnection of its corresponding Service receiver and react by
  220. // self-terminating ASAP.
  221. service_remote_.reset();
  222. process_metadata_receiver_.reset();
  223. connector_receivers_.Clear();
  224. service_manager_receivers_.Clear();
  225. MarkUnreachable();
  226. if (state_ == mojom::InstanceState::kCreated)
  227. service_manager_->NotifyServiceFailedToStart(identity_);
  228. else
  229. service_manager_->OnInstanceStopped(identity_);
  230. stopped_ = true;
  231. }
  232. mojom::RunningServiceInfoPtr ServiceInstance::CreateRunningServiceInfo() const {
  233. return mojom::RunningServiceInfo::New(identity_, pid_, state_);
  234. }
  235. void ServiceInstance::BindServiceManagerReceiver(
  236. mojo::PendingReceiver<mojom::ServiceManager> receiver) {
  237. service_manager_receivers_.Add(this, std::move(receiver));
  238. }
  239. void ServiceInstance::OnStartCompleted(
  240. mojo::PendingReceiver<mojom::Connector> connector_receiver,
  241. mojo::PendingAssociatedReceiver<mojom::ServiceControl> control_receiver) {
  242. state_ = mojom::InstanceState::kStarted;
  243. if (connector_receiver.is_valid()) {
  244. connector_receivers_.Add(this, std::move(connector_receiver));
  245. connector_receivers_.set_disconnect_handler(base::BindRepeating(
  246. &ServiceInstance::OnConnectorDisconnected, base::Unretained(this)));
  247. }
  248. if (control_receiver.is_valid())
  249. control_receiver_.Bind(std::move(control_receiver));
  250. service_manager_->NotifyServiceStarted(identity_, pid_);
  251. MaybeNotifyPidAvailable();
  252. }
  253. void ServiceInstance::OnConnectRequestAcknowledged() {
  254. DCHECK_GT(pending_service_connections_, 0);
  255. pending_service_connections_--;
  256. }
  257. void ServiceInstance::MarkUnreachable() {
  258. state_ = mojom::InstanceState::kUnreachable;
  259. service_manager_->MakeInstanceUnreachable(this);
  260. }
  261. void ServiceInstance::MaybeNotifyPidAvailable() {
  262. // Ensure that we only notify listeners of the PID after notifying them of
  263. // instance start to ensure consistent ordering of ServiceManagerListener
  264. // messages pertaining to this instance.
  265. if (state_ == mojom::InstanceState::kStarted &&
  266. pid_ != base::kNullProcessId) {
  267. service_manager_->NotifyServicePIDReceived(identity_, pid_);
  268. }
  269. }
  270. void ServiceInstance::OnServiceDisconnected() {
  271. service_remote_.reset();
  272. HandleServiceOrConnectorDisconnection();
  273. }
  274. void ServiceInstance::OnConnectorDisconnected() {
  275. HandleServiceOrConnectorDisconnection();
  276. }
  277. void ServiceInstance::HandleServiceOrConnectorDisconnection() {
  278. // As long as the Service remote is still connected, the instance remains
  279. // alive and reachable.
  280. if (service_remote_)
  281. return;
  282. if (connector_receivers_.empty()) {
  283. // No more connections of any kind. Destroys |this|.
  284. service_manager_->DestroyInstance(this);
  285. } else {
  286. // The instance is no longer reachable since it has no Service remote, but
  287. // we still have active Connectors which may send requests to the Service
  288. // Manager.
  289. MarkUnreachable();
  290. }
  291. }
  292. bool ServiceInstance::CanConnectToOtherInstance(
  293. const ServiceFilter& target_filter,
  294. const absl::optional<std::string>& target_interface_name) {
  295. if (target_filter.service_name().empty()) {
  296. DLOG(ERROR) << "ServiceFilter has no service name.";
  297. return false;
  298. }
  299. bool skip_instance_group_check =
  300. manifest_.options.instance_sharing_policy ==
  301. Manifest::InstanceSharingPolicy::kSingleton ||
  302. manifest_.options.instance_sharing_policy ==
  303. Manifest::InstanceSharingPolicy::kSharedAcrossGroups ||
  304. manifest_.options.can_connect_to_instances_in_any_group;
  305. if (!skip_instance_group_check && target_filter.instance_group() &&
  306. target_filter.instance_group() != identity_.instance_group() &&
  307. target_filter.instance_group() != kSystemInstanceGroup) {
  308. LOG(ERROR) << "Instance " << identity_.ToString() << " attempting to "
  309. << "connect to " << target_filter.service_name() << " in "
  310. << "group " << target_filter.instance_group()->ToString()
  311. << " without |can_connect_to_instances_in_any_group| set to "
  312. << "|true|.";
  313. return false;
  314. }
  315. if (target_filter.instance_id() && !target_filter.instance_id()->is_zero() &&
  316. !manifest_.options.can_connect_to_instances_with_any_id) {
  317. LOG(ERROR) << "Instance " << identity_.ToString()
  318. << " attempting to connect to " << target_filter.service_name()
  319. << " with instance ID "
  320. << target_filter.instance_id()->ToString() << " without "
  321. << "|can_connect_to_instances_with_any_id| set to |true|.";
  322. return false;
  323. }
  324. if (can_contact_all_services_ ||
  325. !manifest_.interfaces_bindable_on_any_service.empty() ||
  326. manifest_.required_capabilities.find(target_filter.service_name()) !=
  327. manifest_.required_capabilities.end()) {
  328. return true;
  329. }
  330. if (target_interface_name) {
  331. ReportBlockedInterface(identity_.name(), target_filter.service_name(),
  332. *target_interface_name);
  333. } else {
  334. ReportBlockedStartService(identity_.name(), target_filter.service_name());
  335. }
  336. return false;
  337. }
  338. void ServiceInstance::BindInterface(
  339. const ServiceFilter& target_filter,
  340. const std::string& interface_name,
  341. mojo::ScopedMessagePipeHandle receiving_pipe,
  342. mojom::BindInterfacePriority priority,
  343. BindInterfaceCallback callback) {
  344. if (!CanConnectToOtherInstance(target_filter, interface_name)) {
  345. std::move(callback).Run(mojom::ConnectResult::ACCESS_DENIED, absl::nullopt);
  346. return;
  347. }
  348. ServiceInstance* target_instance =
  349. service_manager_->FindOrCreateMatchingTargetInstance(*this,
  350. target_filter);
  351. bool allowed =
  352. target_instance &&
  353. target_instance->MaybeAcceptConnectionRequest(
  354. *this, interface_name, std::move(receiving_pipe), priority);
  355. if (!allowed) {
  356. std::move(callback).Run(mojom::ConnectResult::ACCESS_DENIED, absl::nullopt);
  357. return;
  358. }
  359. std::move(callback).Run(mojom::ConnectResult::SUCCEEDED,
  360. target_instance->identity());
  361. }
  362. void ServiceInstance::QueryService(const std::string& service_name,
  363. QueryServiceCallback callback) {
  364. std::string sandbox_type;
  365. const bool success = service_manager_->QueryCatalog(
  366. service_name, identity_.instance_group(), &sandbox_type);
  367. if (success)
  368. std::move(callback).Run(mojom::ServiceInfo::New(sandbox_type));
  369. else
  370. std::move(callback).Run(nullptr);
  371. }
  372. void ServiceInstance::WarmService(const ServiceFilter& target_filter,
  373. WarmServiceCallback callback) {
  374. if (!CanConnectToOtherInstance(target_filter,
  375. absl::nullopt /* interface_name */)) {
  376. std::move(callback).Run(mojom::ConnectResult::ACCESS_DENIED, absl::nullopt);
  377. return;
  378. }
  379. ServiceInstance* target_instance =
  380. service_manager_->FindOrCreateMatchingTargetInstance(*this,
  381. target_filter);
  382. if (!target_instance) {
  383. std::move(callback).Run(mojom::ConnectResult::ACCESS_DENIED, absl::nullopt);
  384. return;
  385. }
  386. std::move(callback).Run(mojom::ConnectResult::SUCCEEDED,
  387. target_instance->identity());
  388. }
  389. void ServiceInstance::RegisterServiceInstance(
  390. const Identity& identity,
  391. mojo::ScopedMessagePipeHandle service_remote_handle,
  392. mojo::PendingReceiver<mojom::ProcessMetadata> metadata_receiver,
  393. RegisterServiceInstanceCallback callback) {
  394. auto target_filter = ServiceFilter::ForExactIdentity(identity);
  395. if (!CanConnectToOtherInstance(target_filter,
  396. absl::nullopt /* interface_name */)) {
  397. std::move(callback).Run(mojom::ConnectResult::ACCESS_DENIED);
  398. return;
  399. }
  400. mojo::PendingRemote<mojom::Service> service_remote(
  401. std::move(service_remote_handle), 0);
  402. if (!manifest_.options.can_register_other_service_instances) {
  403. LOG(ERROR) << "Instance: " << identity_.name() << " attempting "
  404. << "to register an instance for a process it created for "
  405. << "target: " << identity.name() << " without "
  406. << "the 'can_create_other_service_instances' option.";
  407. std::move(callback).Run(mojom::ConnectResult::ACCESS_DENIED);
  408. return;
  409. }
  410. if (service_manager_->GetExistingInstance(identity)) {
  411. LOG(ERROR) << "Instance already exists: " << identity.ToString();
  412. std::move(callback).Run(mojom::ConnectResult::INVALID_ARGUMENT);
  413. return;
  414. }
  415. if (!service_manager_->RegisterService(identity, std::move(service_remote),
  416. std::move(metadata_receiver))) {
  417. std::move(callback).Run(mojom::ConnectResult::ACCESS_DENIED);
  418. return;
  419. }
  420. std::move(callback).Run(mojom::ConnectResult::SUCCEEDED);
  421. }
  422. void ServiceInstance::Clone(mojo::PendingReceiver<mojom::Connector> receiver) {
  423. connector_receivers_.Add(this, std::move(receiver));
  424. }
  425. void ServiceInstance::RequestQuit() {
  426. // Ignore quit requests when there are in-flight connection requests that the
  427. // instance hasn't acknowledged yet.
  428. if (pending_service_connections_)
  429. return;
  430. // Otherwise behave as if the instance was disconnected.
  431. OnServiceDisconnected();
  432. }
  433. void ServiceInstance::AddListener(
  434. mojo::PendingRemote<mojom::ServiceManagerListener> listener) {
  435. service_manager_->AddListener(std::move(listener));
  436. }
  437. } // namespace service_manager