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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
127 if (startup_info.has_extended_startup_info()) | 128 if (startup_info.has_extended_startup_info()) |
128 flags |= EXTENDED_STARTUPINFO_PRESENT; | 129 flags |= EXTENDED_STARTUPINFO_PRESENT; |
129 | 130 |
130 if (job_ && base::win::GetVersion() < base::win::VERSION_WIN8) { | 131 if (job_ && base::win::GetVersion() < base::win::VERSION_WIN8) { |
131 // Windows 8 implements nested jobs, but for older systems we need to | 132 // 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. | 133 // break out of any job we're in to enforce our restrictions. |
133 flags |= CREATE_BREAKAWAY_FROM_JOB; | 134 flags |= CREATE_BREAKAWAY_FROM_JOB; |
134 } | 135 } |
135 | 136 |
136 PROCESS_INFORMATION temp_process_info = {}; | 137 PROCESS_INFORMATION temp_process_info = {}; |
137 if (!::CreateProcessAsUserW(lockdown_token_.Get(), | 138 if (base::win::GetVersion() < base::win::VERSION_WIN8) { |
138 exe_path, | 139 if (!::CreateProcessAsUserW(lockdown_token_.Get(), |
forshaw
2015/02/20 11:38:02
There was some discussion about doing this trick f
Shrikant Kelkar
2015/02/21 02:32:41
No, I haven't tested on other platforms. But to be
| |
139 cmd_line.get(), | 140 exe_path, |
140 NULL, // No security attribute. | 141 cmd_line.get(), |
141 NULL, // No thread attribute. | 142 NULL, // No security attribute. |
142 inherit_handles, | 143 NULL, // No thread attribute. |
143 flags, | 144 inherit_handles, |
144 NULL, // Use the environment of the caller. | 145 flags, |
145 NULL, // Use current directory of the caller. | 146 NULL, // Use the environment of the caller. |
146 startup_info.startup_info(), | 147 NULL, // Use current directory of the caller. |
147 &temp_process_info)) { | 148 startup_info.startup_info(), |
148 return ::GetLastError(); | 149 &temp_process_info)) { |
150 return ::GetLastError(); | |
151 } | |
152 lockdown_token_.Close(); | |
153 } else { | |
154 // For Windows 8 and above we will first create process with default token | |
rvargas (doing something else)
2015/02/21 01:01:22
nit: create the process with a default... later, a
Shrikant Kelkar
2015/02/21 02:32:41
Done.
| |
155 // and then replace it later after setting primary thread token. This is | |
156 // required for setting app container token along with impersonation one. | |
157 if (!::CreateProcess(exe_path, | |
158 cmd_line.get(), | |
159 NULL, // No security attribute. | |
160 NULL, // No thread attribute. | |
161 inherit_handles, | |
162 flags, | |
163 NULL, // Use the environment of the caller. | |
164 NULL, // Use current directory of the caller. | |
165 startup_info.startup_info(), | |
166 &temp_process_info)) { | |
167 return ::GetLastError(); | |
168 } | |
149 } | 169 } |
150 base::win::ScopedProcessInformation process_info(temp_process_info); | 170 base::win::ScopedProcessInformation process_info(temp_process_info); |
151 lockdown_token_.Close(); | |
152 | 171 |
153 DWORD win_result = ERROR_SUCCESS; | 172 DWORD win_result = ERROR_SUCCESS; |
154 | 173 |
155 if (job_) { | 174 if (job_) { |
156 // Assign the suspended target to the windows job object. | 175 // Assign the suspended target to the windows job object. |
157 if (!::AssignProcessToJobObject(job_, process_info.process_handle())) { | 176 if (!::AssignProcessToJobObject(job_, process_info.process_handle())) { |
158 win_result = ::GetLastError(); | 177 win_result = ::GetLastError(); |
159 ::TerminateProcess(process_info.process_handle(), 0); | 178 ::TerminateProcess(process_info.process_handle(), 0); |
160 return win_result; | 179 return win_result; |
161 } | 180 } |
162 } | 181 } |
163 | 182 |
164 if (initial_token_.IsValid()) { | 183 if (initial_token_.IsValid()) { |
165 // Change the token of the main thread of the new process for the | 184 // 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; | 185 // impersonation token with more rights. This allows the target to start; |
167 // otherwise it will crash too early for us to help. | 186 // otherwise it will crash too early for us to help. |
168 HANDLE temp_thread = process_info.thread_handle(); | 187 HANDLE temp_thread = process_info.thread_handle(); |
169 if (!::SetThreadToken(&temp_thread, initial_token_.Get())) { | 188 if (!::SetThreadToken(&temp_thread, initial_token_.Get())) { |
170 win_result = ::GetLastError(); | 189 win_result = ::GetLastError(); |
171 // It might be a security breach if we let the target run outside the job | 190 // It might be a security breach if we let the target run outside the job |
172 // so kill it before it causes damage. | 191 // so kill it before it causes damage. |
173 ::TerminateProcess(process_info.process_handle(), 0); | 192 ::TerminateProcess(process_info.process_handle(), 0); |
174 return win_result; | 193 return win_result; |
175 } | 194 } |
176 initial_token_.Close(); | 195 initial_token_.Close(); |
177 } | 196 } |
178 | 197 |
198 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { | |
199 PROCESS_ACCESS_TOKEN process_access_token; | |
200 process_access_token.thread = process_info.thread_handle(); | |
201 process_access_token.token = lockdown_token_.Get(); | |
202 | |
203 NtSetInformationProcess SetInformationProcess = NULL; | |
204 ResolveNTFunctionPtr("NtSetInformationProcess", &SetInformationProcess); | |
205 | |
206 NTSTATUS status = SetInformationProcess( | |
207 process_info.process_handle(), | |
208 static_cast<PROCESS_INFORMATION_CLASS>(NtProcessInformationAccessToken), | |
209 &process_access_token, | |
210 sizeof(process_access_token)); | |
211 if (!NT_SUCCESS(status)) { | |
forshaw
2015/02/20 11:38:02
Missing a call to lockdown_token_.Close() for this
Will Harris
2015/02/21 01:13:15
This should get closed in TargetProcess descructor
rvargas (doing something else)
2015/02/21 01:26:01
Yes, not leaking. I thought that for some reason w
Shrikant Kelkar
2015/02/21 02:32:41
Done.
Shrikant Kelkar
2015/02/21 02:32:41
Done.
Shrikant Kelkar
2015/02/21 02:32:41
Done.
| |
212 win_result = ::GetLastError(); | |
213 ::TerminateProcess(process_info.process_handle(), 0); // exit code | |
214 return win_result; | |
215 } | |
216 } | |
217 | |
179 CONTEXT context; | 218 CONTEXT context; |
180 context.ContextFlags = CONTEXT_ALL; | 219 context.ContextFlags = CONTEXT_ALL; |
181 if (!::GetThreadContext(process_info.thread_handle(), &context)) { | 220 if (!::GetThreadContext(process_info.thread_handle(), &context)) { |
182 win_result = ::GetLastError(); | 221 win_result = ::GetLastError(); |
183 ::TerminateProcess(process_info.process_handle(), 0); | 222 ::TerminateProcess(process_info.process_handle(), 0); |
184 return win_result; | 223 return win_result; |
185 } | 224 } |
186 | 225 |
187 #if defined(_WIN64) | 226 #if defined(_WIN64) |
188 void* entry_point = reinterpret_cast<void*>(context.Rcx); | 227 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) { | 369 TargetProcess* MakeTestTargetProcess(HANDLE process, HMODULE base_address) { |
331 TargetProcess* target = new TargetProcess(NULL, NULL, NULL, NULL); | 370 TargetProcess* target = new TargetProcess(NULL, NULL, NULL, NULL); |
332 PROCESS_INFORMATION process_info = {}; | 371 PROCESS_INFORMATION process_info = {}; |
333 process_info.hProcess = process; | 372 process_info.hProcess = process; |
334 target->sandbox_process_info_.Set(process_info); | 373 target->sandbox_process_info_.Set(process_info); |
335 target->base_address_ = base_address; | 374 target->base_address_ = base_address; |
336 return target; | 375 return target; |
337 } | 376 } |
338 | 377 |
339 } // namespace sandbox | 378 } // namespace sandbox |
OLD | NEW |