named_pipe_dispatcher.cc 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // Copyright (c) 2013 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/named_pipe_dispatcher.h"
  5. #include <stdint.h>
  6. #include "base/strings/string_split.h"
  7. #include "base/strings/string_util.h"
  8. #include "sandbox/win/src/crosscall_client.h"
  9. #include "sandbox/win/src/interception.h"
  10. #include "sandbox/win/src/interceptors.h"
  11. #include "sandbox/win/src/ipc_tags.h"
  12. #include "sandbox/win/src/named_pipe_interception.h"
  13. #include "sandbox/win/src/named_pipe_policy.h"
  14. #include "sandbox/win/src/policy_broker.h"
  15. #include "sandbox/win/src/policy_params.h"
  16. #include "sandbox/win/src/sandbox.h"
  17. namespace sandbox {
  18. NamedPipeDispatcher::NamedPipeDispatcher(PolicyBase* policy_base)
  19. : policy_base_(policy_base) {
  20. static const IPCCall create_params = {
  21. {IpcTag::CREATENAMEDPIPEW,
  22. {WCHAR_TYPE, UINT32_TYPE, UINT32_TYPE, UINT32_TYPE, UINT32_TYPE,
  23. UINT32_TYPE, UINT32_TYPE}},
  24. reinterpret_cast<CallbackGeneric>(&NamedPipeDispatcher::CreateNamedPipe)};
  25. ipc_calls_.push_back(create_params);
  26. }
  27. bool NamedPipeDispatcher::SetupService(InterceptionManager* manager,
  28. IpcTag service) {
  29. if (IpcTag::CREATENAMEDPIPEW == service)
  30. return INTERCEPT_EAT(manager, kKerneldllName, CreateNamedPipeW,
  31. CREATE_NAMED_PIPE_ID, 36);
  32. return false;
  33. }
  34. bool NamedPipeDispatcher::CreateNamedPipe(IPCInfo* ipc,
  35. std::wstring* name,
  36. uint32_t open_mode,
  37. uint32_t pipe_mode,
  38. uint32_t max_instances,
  39. uint32_t out_buffer_size,
  40. uint32_t in_buffer_size,
  41. uint32_t default_timeout) {
  42. ipc->return_info.win32_result = ERROR_ACCESS_DENIED;
  43. ipc->return_info.handle = INVALID_HANDLE_VALUE;
  44. base::StringPiece16 dotdot(u"..");
  45. for (const base::StringPiece16& path :
  46. base::SplitStringPiece(base::AsStringPiece16(*name), u"/",
  47. base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
  48. for (const base::StringPiece16& inner : base::SplitStringPiece(
  49. path, u"\\", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
  50. if (inner == dotdot)
  51. return true;
  52. }
  53. }
  54. const wchar_t* pipe_name = name->c_str();
  55. CountedParameterSet<NameBased> params;
  56. params[NameBased::NAME] = ParamPickerMake(pipe_name);
  57. EvalResult eval =
  58. policy_base_->EvalPolicy(IpcTag::CREATENAMEDPIPEW, params.GetBase());
  59. // "For file I/O, the "\\?\" prefix to a path string tells the Windows APIs to
  60. // disable all string parsing and to send the string that follows it straight
  61. // to the file system."
  62. // http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx
  63. // This ensures even if there is a path traversal in the pipe name, and it is
  64. // able to get past the checks above, it will still not be allowed to escape
  65. // our allowed namespace.
  66. if (name->compare(0, 4, L"\\\\.\\") == 0)
  67. name->replace(0, 4, L"\\\\\?\\");
  68. HANDLE pipe;
  69. DWORD ret = NamedPipePolicy::CreateNamedPipeAction(
  70. eval, *ipc->client_info, *name, open_mode, pipe_mode, max_instances,
  71. out_buffer_size, in_buffer_size, default_timeout, &pipe);
  72. ipc->return_info.win32_result = ret;
  73. ipc->return_info.handle = pipe;
  74. return true;
  75. }
  76. } // namespace sandbox