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