1 // Copyright (c) 2011 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.
5 #include "sandbox/win/src/process_thread_policy.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "sandbox/win/src/ipc_tags.h"
11 #include "sandbox/win/src/nt_internals.h"
12 #include "sandbox/win/src/policy_engine_opcodes.h"
13 #include "sandbox/win/src/policy_params.h"
14 #include "sandbox/win/src/sandbox_types.h"
15 #include "sandbox/win/src/win_utils.h"
19 // These are the only safe rights that can be given to a sandboxed
20 // process for the process created by the broker. All others are potential
21 // vectors of privilege elevation.
22 const DWORD kProcessRights
= SYNCHRONIZE
|
23 PROCESS_QUERY_INFORMATION
|
24 PROCESS_QUERY_LIMITED_INFORMATION
|
26 PROCESS_SUSPEND_RESUME
;
28 const DWORD kThreadRights
= SYNCHRONIZE
|
30 THREAD_SUSPEND_RESUME
|
31 THREAD_QUERY_INFORMATION
|
32 THREAD_QUERY_LIMITED_INFORMATION
|
33 THREAD_SET_LIMITED_INFORMATION
;
35 // Creates a child process and duplicates the handles to 'target_process'. The
36 // remaining parameters are the same as CreateProcess().
37 BOOL
CreateProcessExWHelper(HANDLE target_process
, BOOL give_full_access
,
38 LPCWSTR lpApplicationName
, LPWSTR lpCommandLine
,
39 LPSECURITY_ATTRIBUTES lpProcessAttributes
,
40 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
41 BOOL bInheritHandles
, DWORD dwCreationFlags
,
42 LPVOID lpEnvironment
, LPCWSTR lpCurrentDirectory
,
43 LPSTARTUPINFOW lpStartupInfo
,
44 LPPROCESS_INFORMATION lpProcessInformation
) {
45 if (!::CreateProcessW(lpApplicationName
, lpCommandLine
, lpProcessAttributes
,
46 lpThreadAttributes
, bInheritHandles
, dwCreationFlags
,
47 lpEnvironment
, lpCurrentDirectory
, lpStartupInfo
,
48 lpProcessInformation
)) {
52 DWORD process_access
= kProcessRights
;
53 DWORD thread_access
= kThreadRights
;
54 if (give_full_access
) {
55 process_access
= PROCESS_ALL_ACCESS
;
56 thread_access
= THREAD_ALL_ACCESS
;
58 if (!::DuplicateHandle(::GetCurrentProcess(), lpProcessInformation
->hProcess
,
59 target_process
, &lpProcessInformation
->hProcess
,
60 process_access
, FALSE
, DUPLICATE_CLOSE_SOURCE
)) {
61 ::CloseHandle(lpProcessInformation
->hThread
);
64 if (!::DuplicateHandle(::GetCurrentProcess(), lpProcessInformation
->hThread
,
65 target_process
, &lpProcessInformation
->hThread
,
66 thread_access
, FALSE
, DUPLICATE_CLOSE_SOURCE
)) {
76 bool ProcessPolicy::GenerateRules(const wchar_t* name
,
77 TargetPolicy::Semantics semantics
,
78 LowLevelPolicy
* policy
) {
79 scoped_ptr
<PolicyRule
> process
;
81 case TargetPolicy::PROCESS_MIN_EXEC
: {
82 process
.reset(new PolicyRule(GIVE_READONLY
));
85 case TargetPolicy::PROCESS_ALL_EXEC
: {
86 process
.reset(new PolicyRule(GIVE_ALLACCESS
));
94 if (!process
->AddStringMatch(IF
, NameBased::NAME
, name
, CASE_INSENSITIVE
)) {
97 if (!policy
->AddRule(IPC_CREATEPROCESSW_TAG
, process
.get())) {
103 NTSTATUS
ProcessPolicy::OpenThreadAction(const ClientInfo
& client_info
,
104 uint32 desired_access
,
109 NtOpenThreadFunction NtOpenThread
= NULL
;
110 ResolveNTFunctionPtr("NtOpenThread", &NtOpenThread
);
112 OBJECT_ATTRIBUTES attributes
= {0};
113 attributes
.Length
= sizeof(attributes
);
114 CLIENT_ID client_id
= {0};
115 client_id
.UniqueProcess
= reinterpret_cast<PVOID
>(
116 static_cast<ULONG_PTR
>(client_info
.process_id
));
117 client_id
.UniqueThread
=
118 reinterpret_cast<PVOID
>(static_cast<ULONG_PTR
>(thread_id
));
121 NTSTATUS status
= NtOpenThread(&local_handle
, desired_access
, &attributes
,
123 if (NT_SUCCESS(status
)) {
124 if (!::DuplicateHandle(::GetCurrentProcess(), local_handle
,
125 client_info
.process
, handle
, 0, FALSE
,
126 DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
)) {
127 return STATUS_ACCESS_DENIED
;
134 NTSTATUS
ProcessPolicy::OpenProcessAction(const ClientInfo
& client_info
,
135 uint32 desired_access
,
140 NtOpenProcessFunction NtOpenProcess
= NULL
;
141 ResolveNTFunctionPtr("NtOpenProcess", &NtOpenProcess
);
143 if (client_info
.process_id
!= process_id
)
144 return STATUS_ACCESS_DENIED
;
146 OBJECT_ATTRIBUTES attributes
= {0};
147 attributes
.Length
= sizeof(attributes
);
148 CLIENT_ID client_id
= {0};
149 client_id
.UniqueProcess
= reinterpret_cast<PVOID
>(
150 static_cast<ULONG_PTR
>(client_info
.process_id
));
152 NTSTATUS status
= NtOpenProcess(&local_handle
, desired_access
, &attributes
,
154 if (NT_SUCCESS(status
)) {
155 if (!::DuplicateHandle(::GetCurrentProcess(), local_handle
,
156 client_info
.process
, handle
, 0, FALSE
,
157 DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
)) {
158 return STATUS_ACCESS_DENIED
;
165 NTSTATUS
ProcessPolicy::OpenProcessTokenAction(const ClientInfo
& client_info
,
167 uint32 desired_access
,
170 NtOpenProcessTokenFunction NtOpenProcessToken
= NULL
;
171 ResolveNTFunctionPtr("NtOpenProcessToken", &NtOpenProcessToken
);
173 if (CURRENT_PROCESS
!= process
)
174 return STATUS_ACCESS_DENIED
;
177 NTSTATUS status
= NtOpenProcessToken(client_info
.process
, desired_access
,
179 if (NT_SUCCESS(status
)) {
180 if (!::DuplicateHandle(::GetCurrentProcess(), local_handle
,
181 client_info
.process
, handle
, 0, FALSE
,
182 DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
)) {
183 return STATUS_ACCESS_DENIED
;
189 NTSTATUS
ProcessPolicy::OpenProcessTokenExAction(const ClientInfo
& client_info
,
191 uint32 desired_access
,
195 NtOpenProcessTokenExFunction NtOpenProcessTokenEx
= NULL
;
196 ResolveNTFunctionPtr("NtOpenProcessTokenEx", &NtOpenProcessTokenEx
);
198 if (CURRENT_PROCESS
!= process
)
199 return STATUS_ACCESS_DENIED
;
202 NTSTATUS status
= NtOpenProcessTokenEx(client_info
.process
, desired_access
,
203 attributes
, &local_handle
);
204 if (NT_SUCCESS(status
)) {
205 if (!::DuplicateHandle(::GetCurrentProcess(), local_handle
,
206 client_info
.process
, handle
, 0, FALSE
,
207 DUPLICATE_CLOSE_SOURCE
| DUPLICATE_SAME_ACCESS
)) {
208 return STATUS_ACCESS_DENIED
;
214 DWORD
ProcessPolicy::CreateProcessWAction(EvalResult eval_result
,
215 const ClientInfo
& client_info
,
216 const base::string16
&app_name
,
217 const base::string16
&command_line
,
218 PROCESS_INFORMATION
* process_info
) {
219 // The only action supported is ASK_BROKER which means create the process.
220 if (GIVE_ALLACCESS
!= eval_result
&& GIVE_READONLY
!= eval_result
) {
221 return ERROR_ACCESS_DENIED
;
224 STARTUPINFO startup_info
= {0};
225 startup_info
.cb
= sizeof(startup_info
);
226 scoped_ptr
<wchar_t, base::FreeDeleter
>
227 cmd_line(_wcsdup(command_line
.c_str()));
229 BOOL should_give_full_access
= (GIVE_ALLACCESS
== eval_result
);
230 if (!CreateProcessExWHelper(client_info
.process
, should_give_full_access
,
231 app_name
.c_str(), cmd_line
.get(), NULL
, NULL
,
232 FALSE
, 0, NULL
, NULL
, &startup_info
,
234 return ERROR_ACCESS_DENIED
;
236 return ERROR_SUCCESS
;
239 } // namespace sandbox