top_level_dispatcher.cc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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
  3. // found in the LICENSE file.
  4. #include "sandbox/win/src/top_level_dispatcher.h"
  5. #include <stdint.h>
  6. #include <string.h>
  7. #include "base/check.h"
  8. #include "base/notreached.h"
  9. #include "sandbox/win/src/crosscall_server.h"
  10. #include "sandbox/win/src/filesystem_dispatcher.h"
  11. #include "sandbox/win/src/interception.h"
  12. #include "sandbox/win/src/internal_types.h"
  13. #include "sandbox/win/src/ipc_tags.h"
  14. #include "sandbox/win/src/named_pipe_dispatcher.h"
  15. #include "sandbox/win/src/process_mitigations_win32k_dispatcher.h"
  16. #include "sandbox/win/src/process_thread_dispatcher.h"
  17. #include "sandbox/win/src/sandbox_policy_base.h"
  18. #include "sandbox/win/src/signed_dispatcher.h"
  19. #include "sandbox/win/src/socket_dispatcher.h"
  20. namespace sandbox {
  21. TopLevelDispatcher::TopLevelDispatcher(PolicyBase* policy) : policy_(policy) {
  22. // Initialize the IPC dispatcher array.
  23. memset(ipc_targets_, 0, sizeof(ipc_targets_));
  24. Dispatcher* dispatcher;
  25. dispatcher = new FilesystemDispatcher(policy_);
  26. ipc_targets_[static_cast<size_t>(IpcTag::NTCREATEFILE)] = dispatcher;
  27. ipc_targets_[static_cast<size_t>(IpcTag::NTOPENFILE)] = dispatcher;
  28. ipc_targets_[static_cast<size_t>(IpcTag::NTSETINFO_RENAME)] = dispatcher;
  29. ipc_targets_[static_cast<size_t>(IpcTag::NTQUERYATTRIBUTESFILE)] = dispatcher;
  30. ipc_targets_[static_cast<size_t>(IpcTag::NTQUERYFULLATTRIBUTESFILE)] =
  31. dispatcher;
  32. filesystem_dispatcher_.reset(dispatcher);
  33. dispatcher = new NamedPipeDispatcher(policy_);
  34. ipc_targets_[static_cast<size_t>(IpcTag::CREATENAMEDPIPEW)] = dispatcher;
  35. named_pipe_dispatcher_.reset(dispatcher);
  36. dispatcher = new ThreadProcessDispatcher();
  37. ipc_targets_[static_cast<size_t>(IpcTag::NTOPENTHREAD)] = dispatcher;
  38. ipc_targets_[static_cast<size_t>(IpcTag::NTOPENPROCESS)] = dispatcher;
  39. ipc_targets_[static_cast<size_t>(IpcTag::NTOPENPROCESSTOKEN)] = dispatcher;
  40. ipc_targets_[static_cast<size_t>(IpcTag::NTOPENPROCESSTOKENEX)] = dispatcher;
  41. ipc_targets_[static_cast<size_t>(IpcTag::CREATETHREAD)] = dispatcher;
  42. thread_process_dispatcher_.reset(dispatcher);
  43. dispatcher = new ProcessMitigationsWin32KDispatcher(policy_);
  44. ipc_targets_[static_cast<size_t>(IpcTag::GDI_GDIDLLINITIALIZE)] = dispatcher;
  45. ipc_targets_[static_cast<size_t>(IpcTag::GDI_GETSTOCKOBJECT)] = dispatcher;
  46. ipc_targets_[static_cast<size_t>(IpcTag::USER_REGISTERCLASSW)] = dispatcher;
  47. process_mitigations_win32k_dispatcher_.reset(dispatcher);
  48. dispatcher = new SignedDispatcher(policy_);
  49. ipc_targets_[static_cast<size_t>(IpcTag::NTCREATESECTION)] = dispatcher;
  50. signed_dispatcher_.reset(dispatcher);
  51. dispatcher = new SocketDispatcher(policy_);
  52. ipc_targets_[static_cast<size_t>(IpcTag::WS2SOCKET)] = dispatcher;
  53. socket_dispatcher_.reset(dispatcher);
  54. }
  55. TopLevelDispatcher::~TopLevelDispatcher() {}
  56. // When an IPC is ready in any of the targets we get called. We manage an array
  57. // of IPC dispatchers which are keyed on the IPC tag so we normally delegate
  58. // to the appropriate dispatcher unless we can handle the IPC call ourselves.
  59. Dispatcher* TopLevelDispatcher::OnMessageReady(IPCParams* ipc,
  60. CallbackGeneric* callback) {
  61. DCHECK(callback);
  62. static const IPCParams ping1 = {IpcTag::PING1, {UINT32_TYPE}};
  63. static const IPCParams ping2 = {IpcTag::PING2, {INOUTPTR_TYPE}};
  64. if (ping1.Matches(ipc) || ping2.Matches(ipc)) {
  65. *callback = reinterpret_cast<CallbackGeneric>(
  66. static_cast<Callback1>(&TopLevelDispatcher::Ping));
  67. return this;
  68. }
  69. Dispatcher* dispatcher = GetDispatcher(ipc->ipc_tag);
  70. if (!dispatcher) {
  71. NOTREACHED();
  72. return nullptr;
  73. }
  74. return dispatcher->OnMessageReady(ipc, callback);
  75. }
  76. // Delegate to the appropriate dispatcher.
  77. bool TopLevelDispatcher::SetupService(InterceptionManager* manager,
  78. IpcTag service) {
  79. if (IpcTag::PING1 == service || IpcTag::PING2 == service)
  80. return true;
  81. Dispatcher* dispatcher = GetDispatcher(service);
  82. if (!dispatcher) {
  83. NOTREACHED();
  84. return false;
  85. }
  86. return dispatcher->SetupService(manager, service);
  87. }
  88. // We service PING message which is a way to test a round trip of the
  89. // IPC subsystem. We receive a integer cookie and we are expected to return the
  90. // cookie times two (or three) and the current tick count.
  91. bool TopLevelDispatcher::Ping(IPCInfo* ipc, void* arg1) {
  92. switch (ipc->ipc_tag) {
  93. case IpcTag::PING1: {
  94. IPCInt ipc_int(arg1);
  95. uint32_t cookie = ipc_int.As32Bit();
  96. ipc->return_info.extended_count = 2;
  97. ipc->return_info.extended[0].unsigned_int = ::GetTickCount();
  98. ipc->return_info.extended[1].unsigned_int = 2 * cookie;
  99. return true;
  100. }
  101. case IpcTag::PING2: {
  102. CountedBuffer* io_buffer = reinterpret_cast<CountedBuffer*>(arg1);
  103. if (sizeof(uint32_t) != io_buffer->Size())
  104. return false;
  105. uint32_t* cookie = reinterpret_cast<uint32_t*>(io_buffer->Buffer());
  106. *cookie = (*cookie) * 3;
  107. return true;
  108. }
  109. default:
  110. return false;
  111. }
  112. }
  113. Dispatcher* TopLevelDispatcher::GetDispatcher(IpcTag ipc_tag) {
  114. if (ipc_tag >= IpcTag::LAST || ipc_tag <= IpcTag::UNUSED)
  115. return nullptr;
  116. return ipc_targets_[static_cast<size_t>(ipc_tag)];
  117. }
  118. } // namespace sandbox