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 |