| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/arc/arc_session.h" | 5 #include "components/arc/arc_session.h" |
| 6 | 6 |
| 7 #include <fcntl.h> | 7 #include <fcntl.h> |
| 8 #include <grp.h> | 8 #include <grp.h> |
| 9 #include <poll.h> | 9 #include <poll.h> |
| 10 #include <unistd.h> | 10 #include <unistd.h> |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 #include "base/task_runner_util.h" | 21 #include "base/task_runner_util.h" |
| 22 #include "base/threading/thread_checker.h" | 22 #include "base/threading/thread_checker.h" |
| 23 #include "base/threading/thread_task_runner_handle.h" | 23 #include "base/threading/thread_task_runner_handle.h" |
| 24 #include "chromeos/cryptohome/cryptohome_parameters.h" | 24 #include "chromeos/cryptohome/cryptohome_parameters.h" |
| 25 #include "chromeos/dbus/dbus_method_call_status.h" | 25 #include "chromeos/dbus/dbus_method_call_status.h" |
| 26 #include "chromeos/dbus/dbus_thread_manager.h" | 26 #include "chromeos/dbus/dbus_thread_manager.h" |
| 27 #include "chromeos/dbus/session_manager_client.h" | 27 #include "chromeos/dbus/session_manager_client.h" |
| 28 #include "components/arc/arc_bridge_host_impl.h" | 28 #include "components/arc/arc_bridge_host_impl.h" |
| 29 #include "components/arc/arc_features.h" | 29 #include "components/arc/arc_features.h" |
| 30 #include "components/user_manager/user_manager.h" | 30 #include "components/user_manager/user_manager.h" |
| 31 #include "ipc/unix_domain_socket_util.h" | |
| 32 #include "mojo/edk/embedder/embedder.h" | 31 #include "mojo/edk/embedder/embedder.h" |
| 32 #include "mojo/edk/embedder/named_platform_handle.h" |
| 33 #include "mojo/edk/embedder/named_platform_handle_utils.h" |
| 33 #include "mojo/edk/embedder/platform_channel_pair.h" | 34 #include "mojo/edk/embedder/platform_channel_pair.h" |
| 34 #include "mojo/edk/embedder/platform_channel_utils_posix.h" | 35 #include "mojo/edk/embedder/platform_channel_utils_posix.h" |
| 35 #include "mojo/edk/embedder/platform_handle_vector.h" | 36 #include "mojo/edk/embedder/platform_handle_vector.h" |
| 36 #include "mojo/edk/embedder/scoped_platform_handle.h" | 37 #include "mojo/edk/embedder/scoped_platform_handle.h" |
| 37 #include "mojo/public/cpp/bindings/binding.h" | 38 #include "mojo/public/cpp/bindings/binding.h" |
| 38 | 39 |
| 39 namespace arc { | 40 namespace arc { |
| 40 | 41 |
| 41 namespace { | 42 namespace { |
| 42 | 43 |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 ~ArcSessionImpl() override; | 204 ~ArcSessionImpl() override; |
| 204 | 205 |
| 205 // ArcSession overrides: | 206 // ArcSession overrides: |
| 206 void Start() override; | 207 void Start() override; |
| 207 void Stop() override; | 208 void Stop() override; |
| 208 void OnShutdown() override; | 209 void OnShutdown() override; |
| 209 | 210 |
| 210 private: | 211 private: |
| 211 // Creates the UNIX socket on a worker pool and then processes its file | 212 // Creates the UNIX socket on a worker pool and then processes its file |
| 212 // descriptor. | 213 // descriptor. |
| 213 static base::ScopedFD CreateSocket(); | 214 static mojo::edk::ScopedPlatformHandle CreateSocket(); |
| 214 void OnSocketCreated(base::ScopedFD fd); | 215 void OnSocketCreated(mojo::edk::ScopedPlatformHandle fd); |
| 215 | 216 |
| 216 // DBus callback for StartArcInstance(). | 217 // DBus callback for StartArcInstance(). |
| 217 void OnInstanceStarted(base::ScopedFD socket_fd, | 218 void OnInstanceStarted(mojo::edk::ScopedPlatformHandle socket_fd, |
| 218 StartArcInstanceResult result); | 219 StartArcInstanceResult result); |
| 219 | 220 |
| 220 // Synchronously accepts a connection on |socket_fd| and then processes the | 221 // Synchronously accepts a connection on |socket_fd| and then processes the |
| 221 // connected socket's file descriptor. | 222 // connected socket's file descriptor. |
| 222 static base::ScopedFD ConnectMojo(base::ScopedFD socket_fd, | 223 static mojo::edk::ScopedPlatformHandle ConnectMojo( |
| 223 base::ScopedFD cancel_fd); | 224 mojo::edk::ScopedPlatformHandle socket_fd, |
| 224 void OnMojoConnected(base::ScopedFD fd); | 225 base::ScopedFD cancel_fd); |
| 226 void OnMojoConnected(mojo::edk::ScopedPlatformHandle fd); |
| 225 | 227 |
| 226 // Request to stop ARC instance via DBus. | 228 // Request to stop ARC instance via DBus. |
| 227 void StopArcInstance(); | 229 void StopArcInstance(); |
| 228 | 230 |
| 229 // chromeos::SessionManagerClient::Observer: | 231 // chromeos::SessionManagerClient::Observer: |
| 230 void ArcInstanceStopped(bool clean) override; | 232 void ArcInstanceStopped(bool clean) override; |
| 231 | 233 |
| 232 // Completes the termination procedure. | 234 // Completes the termination procedure. |
| 233 void OnStopped(ArcBridgeService::StopReason reason); | 235 void OnStopped(ArcBridgeService::StopReason reason); |
| 234 | 236 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 VLOG(2) << "Creating socket..."; | 286 VLOG(2) << "Creating socket..."; |
| 285 | 287 |
| 286 state_ = State::CREATING_SOCKET; | 288 state_ = State::CREATING_SOCKET; |
| 287 base::PostTaskAndReplyWithResult( | 289 base::PostTaskAndReplyWithResult( |
| 288 blocking_task_runner_.get(), FROM_HERE, | 290 blocking_task_runner_.get(), FROM_HERE, |
| 289 base::Bind(&ArcSessionImpl::CreateSocket), | 291 base::Bind(&ArcSessionImpl::CreateSocket), |
| 290 base::Bind(&ArcSessionImpl::OnSocketCreated, weak_factory_.GetWeakPtr())); | 292 base::Bind(&ArcSessionImpl::OnSocketCreated, weak_factory_.GetWeakPtr())); |
| 291 } | 293 } |
| 292 | 294 |
| 293 // static | 295 // static |
| 294 base::ScopedFD ArcSessionImpl::CreateSocket() { | 296 mojo::edk::ScopedPlatformHandle ArcSessionImpl::CreateSocket() { |
| 295 base::FilePath socket_path(kArcBridgeSocketPath); | 297 base::FilePath socket_path(kArcBridgeSocketPath); |
| 296 | 298 |
| 297 int raw_fd = -1; | 299 mojo::edk::ScopedPlatformHandle socket_fd = mojo::edk::CreateServerHandle( |
| 298 if (!IPC::CreateServerUnixDomainSocket(socket_path, &raw_fd)) | 300 mojo::edk::NamedPlatformHandle(socket_path.value())); |
| 299 return base::ScopedFD(); | 301 if (!socket_fd.is_valid()) |
| 300 base::ScopedFD socket_fd(raw_fd); | 302 return socket_fd; |
| 301 | 303 |
| 302 // Change permissions on the socket. | 304 // Change permissions on the socket. |
| 303 struct group arc_bridge_group; | 305 struct group arc_bridge_group; |
| 304 struct group* arc_bridge_group_res = nullptr; | 306 struct group* arc_bridge_group_res = nullptr; |
| 305 char buf[10000]; | 307 char buf[10000]; |
| 306 if (HANDLE_EINTR(getgrnam_r(kArcBridgeSocketGroup, &arc_bridge_group, buf, | 308 if (HANDLE_EINTR(getgrnam_r(kArcBridgeSocketGroup, &arc_bridge_group, buf, |
| 307 sizeof(buf), &arc_bridge_group_res)) < 0) { | 309 sizeof(buf), &arc_bridge_group_res)) < 0) { |
| 308 PLOG(ERROR) << "getgrnam_r"; | 310 PLOG(ERROR) << "getgrnam_r"; |
| 309 return base::ScopedFD(); | 311 return mojo::edk::ScopedPlatformHandle(); |
| 310 } | 312 } |
| 311 | 313 |
| 312 if (!arc_bridge_group_res) { | 314 if (!arc_bridge_group_res) { |
| 313 LOG(ERROR) << "Group '" << kArcBridgeSocketGroup << "' not found"; | 315 LOG(ERROR) << "Group '" << kArcBridgeSocketGroup << "' not found"; |
| 314 return base::ScopedFD(); | 316 return mojo::edk::ScopedPlatformHandle(); |
| 315 } | 317 } |
| 316 | 318 |
| 317 if (HANDLE_EINTR(chown(kArcBridgeSocketPath, -1, arc_bridge_group.gr_gid)) < | 319 if (HANDLE_EINTR(chown(kArcBridgeSocketPath, -1, arc_bridge_group.gr_gid)) < |
| 318 0) { | 320 0) { |
| 319 PLOG(ERROR) << "chown"; | 321 PLOG(ERROR) << "chown"; |
| 320 return base::ScopedFD(); | 322 return mojo::edk::ScopedPlatformHandle(); |
| 321 } | 323 } |
| 322 | 324 |
| 323 if (!base::SetPosixFilePermissions(socket_path, 0660)) { | 325 if (!base::SetPosixFilePermissions(socket_path, 0660)) { |
| 324 PLOG(ERROR) << "Could not set permissions: " << socket_path.value(); | 326 PLOG(ERROR) << "Could not set permissions: " << socket_path.value(); |
| 325 return base::ScopedFD(); | 327 return mojo::edk::ScopedPlatformHandle(); |
| 326 } | 328 } |
| 327 | 329 |
| 328 return socket_fd; | 330 return socket_fd; |
| 329 } | 331 } |
| 330 | 332 |
| 331 void ArcSessionImpl::OnSocketCreated(base::ScopedFD socket_fd) { | 333 void ArcSessionImpl::OnSocketCreated( |
| 334 mojo::edk::ScopedPlatformHandle socket_fd) { |
| 332 DCHECK(thread_checker_.CalledOnValidThread()); | 335 DCHECK(thread_checker_.CalledOnValidThread()); |
| 333 DCHECK_EQ(state_, State::CREATING_SOCKET); | 336 DCHECK_EQ(state_, State::CREATING_SOCKET); |
| 334 | 337 |
| 335 if (stop_requested_) { | 338 if (stop_requested_) { |
| 336 VLOG(1) << "Stop() called while connecting"; | 339 VLOG(1) << "Stop() called while connecting"; |
| 337 OnStopped(ArcBridgeService::StopReason::SHUTDOWN); | 340 OnStopped(ArcBridgeService::StopReason::SHUTDOWN); |
| 338 return; | 341 return; |
| 339 } | 342 } |
| 340 | 343 |
| 341 if (!socket_fd.is_valid()) { | 344 if (!socket_fd.is_valid()) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 355 !base::FeatureList::IsEnabled(arc::kBootCompletedBroadcastFeature); | 358 !base::FeatureList::IsEnabled(arc::kBootCompletedBroadcastFeature); |
| 356 | 359 |
| 357 chromeos::SessionManagerClient* session_manager_client = | 360 chromeos::SessionManagerClient* session_manager_client = |
| 358 chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); | 361 chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); |
| 359 session_manager_client->StartArcInstance( | 362 session_manager_client->StartArcInstance( |
| 360 cryptohome_id, disable_boot_completed_broadcast, | 363 cryptohome_id, disable_boot_completed_broadcast, |
| 361 base::Bind(&ArcSessionImpl::OnInstanceStarted, weak_factory_.GetWeakPtr(), | 364 base::Bind(&ArcSessionImpl::OnInstanceStarted, weak_factory_.GetWeakPtr(), |
| 362 base::Passed(&socket_fd))); | 365 base::Passed(&socket_fd))); |
| 363 } | 366 } |
| 364 | 367 |
| 365 void ArcSessionImpl::OnInstanceStarted(base::ScopedFD socket_fd, | 368 void ArcSessionImpl::OnInstanceStarted( |
| 366 StartArcInstanceResult result) { | 369 mojo::edk::ScopedPlatformHandle socket_fd, |
| 370 StartArcInstanceResult result) { |
| 367 DCHECK(thread_checker_.CalledOnValidThread()); | 371 DCHECK(thread_checker_.CalledOnValidThread()); |
| 368 if (state_ == State::STOPPED) { | 372 if (state_ == State::STOPPED) { |
| 369 // This is the case that error is notified via DBus before the | 373 // This is the case that error is notified via DBus before the |
| 370 // OnInstanceStarted() callback is invoked. The stopping procedure has | 374 // OnInstanceStarted() callback is invoked. The stopping procedure has |
| 371 // been run, so do nothing. | 375 // been run, so do nothing. |
| 372 return; | 376 return; |
| 373 } | 377 } |
| 374 | 378 |
| 375 DCHECK_EQ(state_, State::STARTING_INSTANCE); | 379 DCHECK_EQ(state_, State::STARTING_INSTANCE); |
| 376 | 380 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 404 } | 408 } |
| 405 | 409 |
| 406 base::PostTaskAndReplyWithResult( | 410 base::PostTaskAndReplyWithResult( |
| 407 blocking_task_runner_.get(), FROM_HERE, | 411 blocking_task_runner_.get(), FROM_HERE, |
| 408 base::Bind(&ArcSessionImpl::ConnectMojo, base::Passed(&socket_fd), | 412 base::Bind(&ArcSessionImpl::ConnectMojo, base::Passed(&socket_fd), |
| 409 base::Passed(&cancel_fd)), | 413 base::Passed(&cancel_fd)), |
| 410 base::Bind(&ArcSessionImpl::OnMojoConnected, weak_factory_.GetWeakPtr())); | 414 base::Bind(&ArcSessionImpl::OnMojoConnected, weak_factory_.GetWeakPtr())); |
| 411 } | 415 } |
| 412 | 416 |
| 413 // static | 417 // static |
| 414 base::ScopedFD ArcSessionImpl::ConnectMojo(base::ScopedFD socket_fd, | 418 mojo::edk::ScopedPlatformHandle ArcSessionImpl::ConnectMojo( |
| 415 base::ScopedFD cancel_fd) { | 419 mojo::edk::ScopedPlatformHandle socket_fd, |
| 416 if (!WaitForSocketReadable(socket_fd.get(), cancel_fd.get())) { | 420 base::ScopedFD cancel_fd) { |
| 421 if (!WaitForSocketReadable(socket_fd.get().handle, cancel_fd.get())) { |
| 417 VLOG(1) << "Mojo connection was cancelled."; | 422 VLOG(1) << "Mojo connection was cancelled."; |
| 418 return base::ScopedFD(); | 423 return mojo::edk::ScopedPlatformHandle(); |
| 419 } | 424 } |
| 420 | 425 |
| 421 int raw_fd = -1; | 426 mojo::edk::ScopedPlatformHandle scoped_fd; |
| 422 if (!IPC::ServerOnConnect(socket_fd.get(), &raw_fd)) { | 427 if (!mojo::edk::ServerAcceptConnection(socket_fd.get(), &scoped_fd, |
| 423 return base::ScopedFD(); | 428 /* check_peer_user = */ false) || |
| 429 !scoped_fd.is_valid()) { |
| 430 return mojo::edk::ScopedPlatformHandle(); |
| 424 } | 431 } |
| 425 base::ScopedFD scoped_fd(raw_fd); | |
| 426 | 432 |
| 427 // Hardcode pid 0 since it is unused in mojo. | 433 // Hardcode pid 0 since it is unused in mojo. |
| 428 const base::ProcessHandle kUnusedChildProcessHandle = 0; | 434 const base::ProcessHandle kUnusedChildProcessHandle = 0; |
| 429 mojo::edk::PlatformChannelPair channel_pair; | 435 mojo::edk::PlatformChannelPair channel_pair; |
| 430 mojo::edk::ChildProcessLaunched(kUnusedChildProcessHandle, | 436 mojo::edk::ChildProcessLaunched(kUnusedChildProcessHandle, |
| 431 channel_pair.PassServerHandle(), | 437 channel_pair.PassServerHandle(), |
| 432 mojo::edk::GenerateRandomToken()); | 438 mojo::edk::GenerateRandomToken()); |
| 433 | 439 |
| 434 mojo::edk::ScopedPlatformHandleVectorPtr handles( | 440 mojo::edk::ScopedPlatformHandleVectorPtr handles( |
| 435 new mojo::edk::PlatformHandleVector{ | 441 new mojo::edk::PlatformHandleVector{ |
| 436 channel_pair.PassClientHandle().release()}); | 442 channel_pair.PassClientHandle().release()}); |
| 437 | 443 |
| 438 struct iovec iov = {const_cast<char*>(""), 1}; | 444 struct iovec iov = {const_cast<char*>(""), 1}; |
| 439 ssize_t result = mojo::edk::PlatformChannelSendmsgWithHandles( | 445 ssize_t result = mojo::edk::PlatformChannelSendmsgWithHandles( |
| 440 mojo::edk::PlatformHandle(scoped_fd.get()), &iov, 1, handles->data(), | 446 scoped_fd.get(), &iov, 1, handles->data(), handles->size()); |
| 441 handles->size()); | |
| 442 if (result == -1) { | 447 if (result == -1) { |
| 443 PLOG(ERROR) << "sendmsg"; | 448 PLOG(ERROR) << "sendmsg"; |
| 444 return base::ScopedFD(); | 449 return mojo::edk::ScopedPlatformHandle(); |
| 445 } | 450 } |
| 446 | 451 |
| 447 return scoped_fd; | 452 return scoped_fd; |
| 448 } | 453 } |
| 449 | 454 |
| 450 void ArcSessionImpl::OnMojoConnected(base::ScopedFD fd) { | 455 void ArcSessionImpl::OnMojoConnected(mojo::edk::ScopedPlatformHandle fd) { |
| 451 DCHECK(thread_checker_.CalledOnValidThread()); | 456 DCHECK(thread_checker_.CalledOnValidThread()); |
| 452 | 457 |
| 453 if (state_ == State::STOPPED) { | 458 if (state_ == State::STOPPED) { |
| 454 // This is the case that error is notified via DBus before the | 459 // This is the case that error is notified via DBus before the |
| 455 // OnMojoConnected() callback is invoked. The stopping procedure has | 460 // OnMojoConnected() callback is invoked. The stopping procedure has |
| 456 // been run, so do nothing. | 461 // been run, so do nothing. |
| 457 return; | 462 return; |
| 458 } | 463 } |
| 459 | 464 |
| 460 DCHECK_EQ(state_, State::CONNECTING_MOJO); | 465 DCHECK_EQ(state_, State::CONNECTING_MOJO); |
| 461 accept_cancel_pipe_.reset(); | 466 accept_cancel_pipe_.reset(); |
| 462 | 467 |
| 463 if (stop_requested_) { | 468 if (stop_requested_) { |
| 464 StopArcInstance(); | 469 StopArcInstance(); |
| 465 return; | 470 return; |
| 466 } | 471 } |
| 467 | 472 |
| 468 if (!fd.is_valid()) { | 473 if (!fd.is_valid()) { |
| 469 LOG(ERROR) << "Invalid handle"; | 474 LOG(ERROR) << "Invalid handle"; |
| 470 StopArcInstance(); | 475 StopArcInstance(); |
| 471 return; | 476 return; |
| 472 } | 477 } |
| 473 | 478 |
| 474 mojo::ScopedMessagePipeHandle server_pipe = mojo::edk::CreateMessagePipe( | 479 mojo::ScopedMessagePipeHandle server_pipe = |
| 475 mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle(fd.release()))); | 480 mojo::edk::CreateMessagePipe(std::move(fd)); |
| 476 if (!server_pipe.is_valid()) { | 481 if (!server_pipe.is_valid()) { |
| 477 LOG(ERROR) << "Invalid pipe"; | 482 LOG(ERROR) << "Invalid pipe"; |
| 478 StopArcInstance(); | 483 StopArcInstance(); |
| 479 return; | 484 return; |
| 480 } | 485 } |
| 481 | 486 |
| 482 mojom::ArcBridgeInstancePtr instance; | 487 mojom::ArcBridgeInstancePtr instance; |
| 483 instance.Bind(mojo::InterfacePtrInfo<mojom::ArcBridgeInstance>( | 488 instance.Bind(mojo::InterfacePtrInfo<mojom::ArcBridgeInstance>( |
| 484 std::move(server_pipe), 0u)); | 489 std::move(server_pipe), 0u)); |
| 485 arc_bridge_host_.reset(new ArcBridgeHostImpl(std::move(instance))); | 490 arc_bridge_host_.reset(new ArcBridgeHostImpl(std::move(instance))); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 626 observer_list_.RemoveObserver(observer); | 631 observer_list_.RemoveObserver(observer); |
| 627 } | 632 } |
| 628 | 633 |
| 629 // static | 634 // static |
| 630 std::unique_ptr<ArcSession> ArcSession::Create( | 635 std::unique_ptr<ArcSession> ArcSession::Create( |
| 631 const scoped_refptr<base::TaskRunner>& blocking_task_runner) { | 636 const scoped_refptr<base::TaskRunner>& blocking_task_runner) { |
| 632 return base::MakeUnique<ArcSessionImpl>(blocking_task_runner); | 637 return base::MakeUnique<ArcSessionImpl>(blocking_task_runner); |
| 633 } | 638 } |
| 634 | 639 |
| 635 } // namespace arc | 640 } // namespace arc |
| OLD | NEW |