OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "sandbox/win/src/target_process.h" | 5 #include "sandbox/win/src/target_process.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
9 #include "base/win/pe_image.h" | 9 #include "base/win/pe_image.h" |
10 #include "base/win/startup_information.h" | 10 #include "base/win/startup_information.h" |
11 #include "base/win/windows_version.h" | 11 #include "base/win/windows_version.h" |
12 #include "sandbox/win/src/crosscall_server.h" | 12 #include "sandbox/win/src/crosscall_server.h" |
13 #include "sandbox/win/src/crosscall_client.h" | 13 #include "sandbox/win/src/crosscall_client.h" |
14 #include "sandbox/win/src/policy_low_level.h" | 14 #include "sandbox/win/src/policy_low_level.h" |
15 #include "sandbox/win/src/sandbox_types.h" | 15 #include "sandbox/win/src/sandbox_types.h" |
16 #include "sandbox/win/src/sharedmem_ipc_server.h" | 16 #include "sandbox/win/src/sharedmem_ipc_server.h" |
17 #include "sandbox/win/src/win_utils.h" | |
17 | 18 |
18 namespace { | 19 namespace { |
19 | 20 |
20 void CopyPolicyToTarget(const void* source, size_t size, void* dest) { | 21 void CopyPolicyToTarget(const void* source, size_t size, void* dest) { |
21 if (!source || !size) | 22 if (!source || !size) |
22 return; | 23 return; |
23 memcpy(dest, source, size); | 24 memcpy(dest, source, size); |
24 sandbox::PolicyGlobal* policy = | 25 sandbox::PolicyGlobal* policy = |
25 reinterpret_cast<sandbox::PolicyGlobal*>(dest); | 26 reinterpret_cast<sandbox::PolicyGlobal*>(dest); |
26 | 27 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 // ipc_server_ references our process handle, so make sure the former is shut | 107 // ipc_server_ references our process handle, so make sure the former is shut |
107 // down before the latter is closed (by ScopedProcessInformation). | 108 // down before the latter is closed (by ScopedProcessInformation). |
108 ipc_server_.reset(); | 109 ipc_server_.reset(); |
109 } | 110 } |
110 | 111 |
111 // Creates the target (child) process suspended and assigns it to the job | 112 // Creates the target (child) process suspended and assigns it to the job |
112 // object. | 113 // object. |
113 DWORD TargetProcess::Create(const wchar_t* exe_path, | 114 DWORD TargetProcess::Create(const wchar_t* exe_path, |
114 const wchar_t* command_line, | 115 const wchar_t* command_line, |
115 bool inherit_handles, | 116 bool inherit_handles, |
117 bool set_lockdown_token_after_create, | |
116 const base::win::StartupInformation& startup_info, | 118 const base::win::StartupInformation& startup_info, |
117 base::win::ScopedProcessInformation* target_info) { | 119 base::win::ScopedProcessInformation* target_info) { |
120 if (set_lockdown_token_after_create && | |
121 base::win::GetVersion() < base::win::VERSION_WIN8) { | |
122 // We don't allow set_lockdown_token_after_create below Windows 8. | |
123 return ERROR_INVALID_PARAMETER; | |
124 } | |
125 | |
118 exe_name_.reset(_wcsdup(exe_path)); | 126 exe_name_.reset(_wcsdup(exe_path)); |
119 | 127 |
120 // the command line needs to be writable by CreateProcess(). | 128 // the command line needs to be writable by CreateProcess(). |
121 scoped_ptr<wchar_t, base::FreeDeleter> cmd_line(_wcsdup(command_line)); | 129 scoped_ptr<wchar_t, base::FreeDeleter> cmd_line(_wcsdup(command_line)); |
122 | 130 |
123 // Start the target process suspended. | 131 // Start the target process suspended. |
124 DWORD flags = | 132 DWORD flags = |
125 CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT | DETACHED_PROCESS; | 133 CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT | DETACHED_PROCESS; |
126 | 134 |
127 if (startup_info.has_extended_startup_info()) | 135 if (startup_info.has_extended_startup_info()) |
128 flags |= EXTENDED_STARTUPINFO_PRESENT; | 136 flags |= EXTENDED_STARTUPINFO_PRESENT; |
129 | 137 |
130 if (job_ && base::win::GetVersion() < base::win::VERSION_WIN8) { | 138 if (job_ && base::win::GetVersion() < base::win::VERSION_WIN8) { |
131 // Windows 8 implements nested jobs, but for older systems we need to | 139 // Windows 8 implements nested jobs, but for older systems we need to |
132 // break out of any job we're in to enforce our restrictions. | 140 // break out of any job we're in to enforce our restrictions. |
133 flags |= CREATE_BREAKAWAY_FROM_JOB; | 141 flags |= CREATE_BREAKAWAY_FROM_JOB; |
134 } | 142 } |
135 | 143 |
144 base::win::ScopedHandle scoped_lockdown_token(lockdown_token_.Take()); | |
136 PROCESS_INFORMATION temp_process_info = {}; | 145 PROCESS_INFORMATION temp_process_info = {}; |
137 if (!::CreateProcessAsUserW(lockdown_token_.Get(), | 146 if (!set_lockdown_token_after_create) { |
rvargas (doing something else)
2015/02/28 01:10:06
nit: if (set_lockdown_token_after_create)
Shrikant Kelkar
2015/02/28 01:55:42
Done.
| |
138 exe_path, | 147 if (!::CreateProcessAsUserW(scoped_lockdown_token.Get(), |
139 cmd_line.get(), | 148 exe_path, |
140 NULL, // No security attribute. | 149 cmd_line.get(), |
141 NULL, // No thread attribute. | 150 NULL, // No security attribute. |
142 inherit_handles, | 151 NULL, // No thread attribute. |
143 flags, | 152 inherit_handles, |
144 NULL, // Use the environment of the caller. | 153 flags, |
145 NULL, // Use current directory of the caller. | 154 NULL, // Use the environment of the caller. |
146 startup_info.startup_info(), | 155 NULL, // Use current directory of the caller. |
147 &temp_process_info)) { | 156 startup_info.startup_info(), |
148 return ::GetLastError(); | 157 &temp_process_info)) { |
158 return ::GetLastError(); | |
159 } | |
160 } else { | |
161 // Our approach is to first create process with a default token and then | |
rvargas (doing something else)
2015/02/28 01:10:07
nit: remove "our approach"
Shrikant Kelkar
2015/02/28 01:55:42
Done.
| |
162 // replace it later, after setting primary thread token. This is required | |
163 // for setting an appcontainer token along with an impersonation token. | |
rvargas (doing something else)
2015/02/28 01:10:06
nit: AppContainer
Shrikant Kelkar
2015/02/28 01:55:42
Done.
| |
164 if (!::CreateProcess(exe_path, | |
165 cmd_line.get(), | |
166 NULL, // No security attribute. | |
167 NULL, // No thread attribute. | |
168 inherit_handles, | |
169 flags, | |
170 NULL, // Use the environment of the caller. | |
171 NULL, // Use current directory of the caller. | |
172 startup_info.startup_info(), | |
173 &temp_process_info)) { | |
174 return ::GetLastError(); | |
175 } | |
149 } | 176 } |
150 base::win::ScopedProcessInformation process_info(temp_process_info); | 177 base::win::ScopedProcessInformation process_info(temp_process_info); |
151 lockdown_token_.Close(); | |
152 | 178 |
153 DWORD win_result = ERROR_SUCCESS; | 179 DWORD win_result = ERROR_SUCCESS; |
154 | 180 |
155 if (job_) { | 181 if (job_) { |
156 // Assign the suspended target to the windows job object. | 182 // Assign the suspended target to the windows job object. |
157 if (!::AssignProcessToJobObject(job_, process_info.process_handle())) { | 183 if (!::AssignProcessToJobObject(job_, process_info.process_handle())) { |
158 win_result = ::GetLastError(); | 184 win_result = ::GetLastError(); |
159 ::TerminateProcess(process_info.process_handle(), 0); | 185 ::TerminateProcess(process_info.process_handle(), 0); |
160 return win_result; | 186 return win_result; |
161 } | 187 } |
162 } | 188 } |
163 | 189 |
164 if (initial_token_.IsValid()) { | 190 if (initial_token_.IsValid()) { |
165 // Change the token of the main thread of the new process for the | 191 // Change the token of the main thread of the new process for the |
166 // impersonation token with more rights. This allows the target to start; | 192 // impersonation token with more rights. This allows the target to start; |
167 // otherwise it will crash too early for us to help. | 193 // otherwise it will crash too early for us to help. |
168 HANDLE temp_thread = process_info.thread_handle(); | 194 HANDLE temp_thread = process_info.thread_handle(); |
169 if (!::SetThreadToken(&temp_thread, initial_token_.Get())) { | 195 if (!::SetThreadToken(&temp_thread, initial_token_.Get())) { |
170 win_result = ::GetLastError(); | 196 win_result = ::GetLastError(); |
171 // It might be a security breach if we let the target run outside the job | 197 // It might be a security breach if we let the target run outside the job |
172 // so kill it before it causes damage. | 198 // so kill it before it causes damage. |
173 ::TerminateProcess(process_info.process_handle(), 0); | 199 ::TerminateProcess(process_info.process_handle(), 0); |
174 return win_result; | 200 return win_result; |
175 } | 201 } |
176 initial_token_.Close(); | 202 initial_token_.Close(); |
177 } | 203 } |
178 | 204 |
205 if (set_lockdown_token_after_create) { | |
206 PROCESS_ACCESS_TOKEN process_access_token; | |
207 process_access_token.thread = process_info.thread_handle(); | |
208 process_access_token.token = scoped_lockdown_token.Get(); | |
209 | |
210 NtSetInformationProcess SetInformationProcess = NULL; | |
211 ResolveNTFunctionPtr("NtSetInformationProcess", &SetInformationProcess); | |
212 | |
213 NTSTATUS status = SetInformationProcess( | |
214 process_info.process_handle(), | |
215 static_cast<PROCESS_INFORMATION_CLASS>(NtProcessInformationAccessToken), | |
216 &process_access_token, | |
217 sizeof(process_access_token)); | |
218 if (!NT_SUCCESS(status)) { | |
219 win_result = ::GetLastError(); | |
220 ::TerminateProcess(process_info.process_handle(), 0); // exit code | |
221 return win_result; | |
222 } | |
223 } | |
224 | |
179 CONTEXT context; | 225 CONTEXT context; |
180 context.ContextFlags = CONTEXT_ALL; | 226 context.ContextFlags = CONTEXT_ALL; |
181 if (!::GetThreadContext(process_info.thread_handle(), &context)) { | 227 if (!::GetThreadContext(process_info.thread_handle(), &context)) { |
182 win_result = ::GetLastError(); | 228 win_result = ::GetLastError(); |
183 ::TerminateProcess(process_info.process_handle(), 0); | 229 ::TerminateProcess(process_info.process_handle(), 0); |
184 return win_result; | 230 return win_result; |
185 } | 231 } |
186 | 232 |
187 #if defined(_WIN64) | 233 #if defined(_WIN64) |
188 void* entry_point = reinterpret_cast<void*>(context.Rcx); | 234 void* entry_point = reinterpret_cast<void*>(context.Rcx); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
330 TargetProcess* MakeTestTargetProcess(HANDLE process, HMODULE base_address) { | 376 TargetProcess* MakeTestTargetProcess(HANDLE process, HMODULE base_address) { |
331 TargetProcess* target = new TargetProcess(NULL, NULL, NULL, NULL); | 377 TargetProcess* target = new TargetProcess(NULL, NULL, NULL, NULL); |
332 PROCESS_INFORMATION process_info = {}; | 378 PROCESS_INFORMATION process_info = {}; |
333 process_info.hProcess = process; | 379 process_info.hProcess = process; |
334 target->sandbox_process_info_.Set(process_info); | 380 target->sandbox_process_info_.Set(process_info); |
335 target->base_address_ = base_address; | 381 target->base_address_ = base_address; |
336 return target; | 382 return target; |
337 } | 383 } |
338 | 384 |
339 } // namespace sandbox | 385 } // namespace sandbox |
OLD | NEW |