Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(185)

Side by Side Diff: sandbox/win/src/process_thread_dispatcher.cc

Issue 1851213002: Remove sandbox on Windows. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix nacl compile issues Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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/process_thread_dispatcher.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include "base/logging.h"
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/policy_broker.h"
16 #include "sandbox/win/src/policy_params.h"
17 #include "sandbox/win/src/process_thread_interception.h"
18 #include "sandbox/win/src/process_thread_policy.h"
19 #include "sandbox/win/src/sandbox.h"
20
21 namespace {
22
23 // Extracts the application name from a command line.
24 //
25 // The application name is the first element of the command line. If
26 // there is no quotes, the first element is delimited by the first space.
27 // If there are quotes, the first element is delimited by the quotes.
28 //
29 // The create process call is smarter than us. It tries really hard to launch
30 // the process even if the command line is wrong. For example:
31 // "c:\program files\test param" will first try to launch c:\program.exe then
32 // c:\program files\test.exe. We don't do that, we stop after at the first
33 // space when there is no quotes.
34 base::string16 GetPathFromCmdLine(const base::string16 &cmd_line) {
35 base::string16 exe_name;
36 // Check if it starts with '"'.
37 if (cmd_line[0] == L'\"') {
38 // Find the position of the second '"', this terminates the path.
39 base::string16::size_type pos = cmd_line.find(L'\"', 1);
40 if (base::string16::npos == pos)
41 return cmd_line;
42 exe_name = cmd_line.substr(1, pos - 1);
43 } else {
44 // There is no '"', that means that the appname is terminated at the
45 // first space.
46 base::string16::size_type pos = cmd_line.find(L' ');
47 if (base::string16::npos == pos) {
48 // There is no space, the cmd_line contains only the app_name
49 exe_name = cmd_line;
50 } else {
51 exe_name = cmd_line.substr(0, pos);
52 }
53 }
54
55 return exe_name;
56 }
57
58 // Returns true is the path in parameter is relative. False if it's
59 // absolute.
60 bool IsPathRelative(const base::string16 &path) {
61 // A path is Relative if it's not a UNC path beginnning with \\ or a
62 // path beginning with a drive. (i.e. X:\)
63 if (path.find(L"\\\\") == 0 || path.find(L":\\") == 1)
64 return false;
65 return true;
66 }
67
68 // Converts a relative path to an absolute path.
69 bool ConvertToAbsolutePath(const base::string16& child_current_directory,
70 bool use_env_path, base::string16 *path) {
71 wchar_t file_buffer[MAX_PATH];
72 wchar_t *file_part = NULL;
73
74 // Here we should start by looking at the path where the child application was
75 // started. We don't have this information yet.
76 DWORD result = 0;
77 if (use_env_path) {
78 // Try with the complete path
79 result = ::SearchPath(NULL, path->c_str(), NULL, MAX_PATH, file_buffer,
80 &file_part);
81 }
82
83 if (0 == result) {
84 // Try with the current directory of the child
85 result = ::SearchPath(child_current_directory.c_str(), path->c_str(), NULL,
86 MAX_PATH, file_buffer, &file_part);
87 }
88
89 if (0 == result || result >= MAX_PATH)
90 return false;
91
92 *path = file_buffer;
93 return true;
94 }
95
96 } // namespace
97 namespace sandbox {
98
99 ThreadProcessDispatcher::ThreadProcessDispatcher(PolicyBase* policy_base)
100 : policy_base_(policy_base) {
101 static const IPCCall open_thread = {
102 {IPC_NTOPENTHREAD_TAG, {UINT32_TYPE, UINT32_TYPE}},
103 reinterpret_cast<CallbackGeneric>(
104 &ThreadProcessDispatcher::NtOpenThread)};
105
106 static const IPCCall open_process = {
107 {IPC_NTOPENPROCESS_TAG, {UINT32_TYPE, UINT32_TYPE}},
108 reinterpret_cast<CallbackGeneric>(
109 &ThreadProcessDispatcher::NtOpenProcess)};
110
111 static const IPCCall process_token = {
112 {IPC_NTOPENPROCESSTOKEN_TAG, {VOIDPTR_TYPE, UINT32_TYPE}},
113 reinterpret_cast<CallbackGeneric>(
114 &ThreadProcessDispatcher::NtOpenProcessToken)};
115
116 static const IPCCall process_tokenex = {
117 {IPC_NTOPENPROCESSTOKENEX_TAG, {VOIDPTR_TYPE, UINT32_TYPE, UINT32_TYPE}},
118 reinterpret_cast<CallbackGeneric>(
119 &ThreadProcessDispatcher::NtOpenProcessTokenEx)};
120
121 static const IPCCall create_params = {
122 {IPC_CREATEPROCESSW_TAG,
123 {WCHAR_TYPE, WCHAR_TYPE, WCHAR_TYPE, INOUTPTR_TYPE}},
124 reinterpret_cast<CallbackGeneric>(
125 &ThreadProcessDispatcher::CreateProcessW)};
126
127 // NOTE(liamjm): 2nd param is size_t: Using VOIDPTR_TYPE as they are
128 // the same size on windows.
129 static_assert(sizeof(size_t) == sizeof(void*),
130 "VOIDPTR_TYPE not same size as size_t");
131 static const IPCCall create_thread_params = {
132 {IPC_CREATETHREAD_TAG,
133 {VOIDPTR_TYPE, VOIDPTR_TYPE, VOIDPTR_TYPE, UINT32_TYPE}},
134 reinterpret_cast<CallbackGeneric>(
135 &ThreadProcessDispatcher::CreateThread)};
136
137 ipc_calls_.push_back(open_thread);
138 ipc_calls_.push_back(open_process);
139 ipc_calls_.push_back(process_token);
140 ipc_calls_.push_back(process_tokenex);
141 ipc_calls_.push_back(create_params);
142 ipc_calls_.push_back(create_thread_params);
143 }
144
145 bool ThreadProcessDispatcher::SetupService(InterceptionManager* manager,
146 int service) {
147 switch (service) {
148 case IPC_NTOPENTHREAD_TAG:
149 case IPC_NTOPENPROCESS_TAG:
150 case IPC_NTOPENPROCESSTOKEN_TAG:
151 case IPC_NTOPENPROCESSTOKENEX_TAG:
152 case IPC_CREATETHREAD_TAG:
153 // There is no explicit policy for these services.
154 NOTREACHED();
155 return false;
156
157 case IPC_CREATEPROCESSW_TAG:
158 return INTERCEPT_EAT(manager, kKerneldllName, CreateProcessW,
159 CREATE_PROCESSW_ID, 44) &&
160 INTERCEPT_EAT(manager, L"kernel32.dll", CreateProcessA,
161 CREATE_PROCESSA_ID, 44);
162
163 default:
164 return false;
165 }
166 }
167
168 bool ThreadProcessDispatcher::NtOpenThread(IPCInfo* ipc,
169 uint32_t desired_access,
170 uint32_t thread_id) {
171 HANDLE handle;
172 NTSTATUS ret = ProcessPolicy::OpenThreadAction(*ipc->client_info,
173 desired_access, thread_id,
174 &handle);
175 ipc->return_info.nt_status = ret;
176 ipc->return_info.handle = handle;
177 return true;
178 }
179
180 bool ThreadProcessDispatcher::NtOpenProcess(IPCInfo* ipc,
181 uint32_t desired_access,
182 uint32_t process_id) {
183 HANDLE handle;
184 NTSTATUS ret = ProcessPolicy::OpenProcessAction(*ipc->client_info,
185 desired_access, process_id,
186 &handle);
187 ipc->return_info.nt_status = ret;
188 ipc->return_info.handle = handle;
189 return true;
190 }
191
192 bool ThreadProcessDispatcher::NtOpenProcessToken(IPCInfo* ipc,
193 HANDLE process,
194 uint32_t desired_access) {
195 HANDLE handle;
196 NTSTATUS ret = ProcessPolicy::OpenProcessTokenAction(*ipc->client_info,
197 process, desired_access,
198 &handle);
199 ipc->return_info.nt_status = ret;
200 ipc->return_info.handle = handle;
201 return true;
202 }
203
204 bool ThreadProcessDispatcher::NtOpenProcessTokenEx(IPCInfo* ipc,
205 HANDLE process,
206 uint32_t desired_access,
207 uint32_t attributes) {
208 HANDLE handle;
209 NTSTATUS ret = ProcessPolicy::OpenProcessTokenExAction(*ipc->client_info,
210 process,
211 desired_access,
212 attributes, &handle);
213 ipc->return_info.nt_status = ret;
214 ipc->return_info.handle = handle;
215 return true;
216 }
217
218 bool ThreadProcessDispatcher::CreateProcessW(IPCInfo* ipc, base::string16* name,
219 base::string16* cmd_line,
220 base::string16* cur_dir,
221 CountedBuffer* info) {
222 if (sizeof(PROCESS_INFORMATION) != info->Size())
223 return false;
224
225 // Check if there is an application name.
226 base::string16 exe_name;
227 if (!name->empty())
228 exe_name = *name;
229 else
230 exe_name = GetPathFromCmdLine(*cmd_line);
231
232 if (IsPathRelative(exe_name)) {
233 if (!ConvertToAbsolutePath(*cur_dir, name->empty(), &exe_name)) {
234 // Cannot find the path. Maybe the file does not exist.
235 ipc->return_info.win32_result = ERROR_FILE_NOT_FOUND;
236 return true;
237 }
238 }
239
240 const wchar_t* const_exe_name = exe_name.c_str();
241 CountedParameterSet<NameBased> params;
242 params[NameBased::NAME] = ParamPickerMake(const_exe_name);
243
244 EvalResult eval = policy_base_->EvalPolicy(IPC_CREATEPROCESSW_TAG,
245 params.GetBase());
246
247 PROCESS_INFORMATION* proc_info =
248 reinterpret_cast<PROCESS_INFORMATION*>(info->Buffer());
249 // Here we force the app_name to be the one we used for the policy lookup.
250 // If our logic was wrong, at least we wont allow create a random process.
251 DWORD ret = ProcessPolicy::CreateProcessWAction(eval, *ipc->client_info,
252 exe_name, *cmd_line,
253 proc_info);
254
255 ipc->return_info.win32_result = ret;
256 return true;
257 }
258
259 bool ThreadProcessDispatcher::CreateThread(IPCInfo* ipc,
260 SIZE_T stack_size,
261 LPTHREAD_START_ROUTINE start_address,
262 LPVOID parameter,
263 DWORD creation_flags) {
264 if (!start_address) {
265 return false;
266 }
267
268 HANDLE handle;
269 DWORD ret = ProcessPolicy::CreateThreadAction(*ipc->client_info, stack_size,
270 start_address, parameter,
271 creation_flags, NULL, &handle);
272
273 ipc->return_info.nt_status = ret;
274 ipc->return_info.handle = handle;
275 return true;
276 }
277
278 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/win/src/process_thread_dispatcher.h ('k') | sandbox/win/src/process_thread_interception.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698