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
3 // found in the LICENSE file.
5 #include "sandbox/win/src/sandbox_policy_base.h"
9 #include "base/basictypes.h"
10 #include "base/callback.h"
11 #include "base/logging.h"
12 #include "base/win/windows_version.h"
13 #include "sandbox/win/src/app_container.h"
14 #include "sandbox/win/src/filesystem_dispatcher.h"
15 #include "sandbox/win/src/filesystem_policy.h"
16 #include "sandbox/win/src/handle_dispatcher.h"
17 #include "sandbox/win/src/handle_policy.h"
18 #include "sandbox/win/src/job.h"
19 #include "sandbox/win/src/interception.h"
20 #include "sandbox/win/src/process_mitigations.h"
21 #include "sandbox/win/src/named_pipe_dispatcher.h"
22 #include "sandbox/win/src/named_pipe_policy.h"
23 #include "sandbox/win/src/policy_broker.h"
24 #include "sandbox/win/src/policy_engine_processor.h"
25 #include "sandbox/win/src/policy_low_level.h"
26 #include "sandbox/win/src/process_mitigations_win32k_dispatcher.h"
27 #include "sandbox/win/src/process_mitigations_win32k_policy.h"
28 #include "sandbox/win/src/process_thread_dispatcher.h"
29 #include "sandbox/win/src/process_thread_policy.h"
30 #include "sandbox/win/src/registry_dispatcher.h"
31 #include "sandbox/win/src/registry_policy.h"
32 #include "sandbox/win/src/restricted_token_utils.h"
33 #include "sandbox/win/src/sandbox_policy.h"
34 #include "sandbox/win/src/sync_dispatcher.h"
35 #include "sandbox/win/src/sync_policy.h"
36 #include "sandbox/win/src/target_process.h"
37 #include "sandbox/win/src/window.h"
41 // The standard windows size for one memory page.
42 const size_t kOneMemPage
= 4096;
43 // The IPC and Policy shared memory sizes.
44 const size_t kIPCMemSize
= kOneMemPage
* 2;
45 const size_t kPolMemSize
= kOneMemPage
* 14;
47 // Helper function to allocate space (on the heap) for policy.
48 sandbox::PolicyGlobal
* MakeBrokerPolicyMemory() {
49 const size_t kTotalPolicySz
= kPolMemSize
;
50 sandbox::PolicyGlobal
* policy
= static_cast<sandbox::PolicyGlobal
*>
51 (::operator new(kTotalPolicySz
));
53 memset(policy
, 0, kTotalPolicySz
);
54 policy
->data_size
= kTotalPolicySz
- sizeof(sandbox::PolicyGlobal
);
58 bool IsInheritableHandle(HANDLE handle
) {
61 if (handle
== INVALID_HANDLE_VALUE
)
63 // File handles (FILE_TYPE_DISK) and pipe handles are known to be
64 // inheritable. Console handles (FILE_TYPE_CHAR) are not
65 // inheritable via PROC_THREAD_ATTRIBUTE_HANDLE_LIST.
66 DWORD handle_type
= GetFileType(handle
);
67 return handle_type
== FILE_TYPE_DISK
|| handle_type
== FILE_TYPE_PIPE
;
74 SANDBOX_INTERCEPT IntegrityLevel g_shared_delayed_integrity_level
;
75 SANDBOX_INTERCEPT MitigationFlags g_shared_delayed_mitigations
;
77 // Initializes static members.
78 HWINSTA
PolicyBase::alternate_winstation_handle_
= NULL
;
79 HDESK
PolicyBase::alternate_desktop_handle_
= NULL
;
80 IntegrityLevel
PolicyBase::alternate_desktop_integrity_level_label_
=
81 INTEGRITY_LEVEL_SYSTEM
;
83 PolicyBase::PolicyBase()
85 lockdown_level_(USER_LOCKDOWN
),
86 initial_level_(USER_LOCKDOWN
),
87 job_level_(JOB_LOCKDOWN
),
90 use_alternate_desktop_(false),
91 use_alternate_winstation_(false),
92 file_system_init_(false),
93 relaxed_interceptions_(true),
94 stdout_handle_(INVALID_HANDLE_VALUE
),
95 stderr_handle_(INVALID_HANDLE_VALUE
),
96 integrity_level_(INTEGRITY_LEVEL_LAST
),
97 delayed_integrity_level_(INTEGRITY_LEVEL_LAST
),
99 delayed_mitigations_(0),
103 ::InitializeCriticalSection(&lock_
);
104 // Initialize the IPC dispatcher array.
105 memset(&ipc_targets_
, NULL
, sizeof(ipc_targets_
));
106 Dispatcher
* dispatcher
= NULL
;
108 dispatcher
= new FilesystemDispatcher(this);
109 ipc_targets_
[IPC_NTCREATEFILE_TAG
] = dispatcher
;
110 ipc_targets_
[IPC_NTOPENFILE_TAG
] = dispatcher
;
111 ipc_targets_
[IPC_NTSETINFO_RENAME_TAG
] = dispatcher
;
112 ipc_targets_
[IPC_NTQUERYATTRIBUTESFILE_TAG
] = dispatcher
;
113 ipc_targets_
[IPC_NTQUERYFULLATTRIBUTESFILE_TAG
] = dispatcher
;
115 dispatcher
= new NamedPipeDispatcher(this);
116 ipc_targets_
[IPC_CREATENAMEDPIPEW_TAG
] = dispatcher
;
118 dispatcher
= new ThreadProcessDispatcher(this);
119 ipc_targets_
[IPC_NTOPENTHREAD_TAG
] = dispatcher
;
120 ipc_targets_
[IPC_NTOPENPROCESS_TAG
] = dispatcher
;
121 ipc_targets_
[IPC_CREATEPROCESSW_TAG
] = dispatcher
;
122 ipc_targets_
[IPC_NTOPENPROCESSTOKEN_TAG
] = dispatcher
;
123 ipc_targets_
[IPC_NTOPENPROCESSTOKENEX_TAG
] = dispatcher
;
125 dispatcher
= new SyncDispatcher(this);
126 ipc_targets_
[IPC_CREATEEVENT_TAG
] = dispatcher
;
127 ipc_targets_
[IPC_OPENEVENT_TAG
] = dispatcher
;
129 dispatcher
= new RegistryDispatcher(this);
130 ipc_targets_
[IPC_NTCREATEKEY_TAG
] = dispatcher
;
131 ipc_targets_
[IPC_NTOPENKEY_TAG
] = dispatcher
;
133 dispatcher
= new HandleDispatcher(this);
134 ipc_targets_
[IPC_DUPLICATEHANDLEPROXY_TAG
] = dispatcher
;
136 dispatcher
= new ProcessMitigationsWin32KDispatcher(this);
137 ipc_targets_
[IPC_GDI_GDIDLLINITIALIZE_TAG
] = dispatcher
;
138 ipc_targets_
[IPC_GDI_GETSTOCKOBJECT_TAG
] = dispatcher
;
139 ipc_targets_
[IPC_USER_REGISTERCLASSW_TAG
] = dispatcher
;
142 PolicyBase::~PolicyBase() {
143 TargetSet::iterator it
;
144 for (it
= targets_
.begin(); it
!= targets_
.end(); ++it
) {
145 TargetProcess
* target
= (*it
);
148 delete ipc_targets_
[IPC_NTCREATEFILE_TAG
];
149 delete ipc_targets_
[IPC_CREATENAMEDPIPEW_TAG
];
150 delete ipc_targets_
[IPC_NTOPENTHREAD_TAG
];
151 delete ipc_targets_
[IPC_CREATEEVENT_TAG
];
152 delete ipc_targets_
[IPC_NTCREATEKEY_TAG
];
153 delete ipc_targets_
[IPC_DUPLICATEHANDLEPROXY_TAG
];
154 delete policy_maker_
;
158 ::LocalFree(lowbox_sid_
);
160 ::DeleteCriticalSection(&lock_
);
163 void PolicyBase::AddRef() {
164 ::InterlockedIncrement(&ref_count
);
167 void PolicyBase::Release() {
168 if (0 == ::InterlockedDecrement(&ref_count
))
172 ResultCode
PolicyBase::SetTokenLevel(TokenLevel initial
, TokenLevel lockdown
) {
173 if (initial
< lockdown
) {
174 return SBOX_ERROR_BAD_PARAMS
;
176 initial_level_
= initial
;
177 lockdown_level_
= lockdown
;
181 TokenLevel
PolicyBase::GetInitialTokenLevel() const {
182 return initial_level_
;
185 TokenLevel
PolicyBase::GetLockdownTokenLevel() const{
186 return lockdown_level_
;
189 ResultCode
PolicyBase::SetJobLevel(JobLevel job_level
, uint32 ui_exceptions
) {
190 if (memory_limit_
&& job_level
== JOB_NONE
) {
191 return SBOX_ERROR_BAD_PARAMS
;
193 job_level_
= job_level
;
194 ui_exceptions_
= ui_exceptions
;
198 ResultCode
PolicyBase::SetJobMemoryLimit(size_t memory_limit
) {
199 if (memory_limit
&& job_level_
== JOB_NONE
) {
200 return SBOX_ERROR_BAD_PARAMS
;
202 memory_limit_
= memory_limit
;
206 ResultCode
PolicyBase::SetAlternateDesktop(bool alternate_winstation
) {
207 use_alternate_desktop_
= true;
208 use_alternate_winstation_
= alternate_winstation
;
209 return CreateAlternateDesktop(alternate_winstation
);
212 base::string16
PolicyBase::GetAlternateDesktop() const {
213 // No alternate desktop or winstation. Return an empty string.
214 if (!use_alternate_desktop_
&& !use_alternate_winstation_
) {
215 return base::string16();
218 // The desktop and winstation should have been created by now.
219 // If we hit this scenario, it means that the user ignored the failure
220 // during SetAlternateDesktop, so we ignore it here too.
221 if (use_alternate_desktop_
&& !alternate_desktop_handle_
) {
222 return base::string16();
224 if (use_alternate_winstation_
&& (!alternate_desktop_handle_
||
225 !alternate_winstation_handle_
)) {
226 return base::string16();
229 return GetFullDesktopName(alternate_winstation_handle_
,
230 alternate_desktop_handle_
);
233 ResultCode
PolicyBase::CreateAlternateDesktop(bool alternate_winstation
) {
234 if (alternate_winstation
) {
235 // Previously called with alternate_winstation = false?
236 if (!alternate_winstation_handle_
&& alternate_desktop_handle_
)
237 return SBOX_ERROR_UNSUPPORTED
;
239 // Check if it's already created.
240 if (alternate_winstation_handle_
&& alternate_desktop_handle_
)
243 DCHECK(!alternate_winstation_handle_
);
244 // Create the window station.
245 ResultCode result
= CreateAltWindowStation(&alternate_winstation_handle_
);
246 if (SBOX_ALL_OK
!= result
)
249 // Verify that everything is fine.
250 if (!alternate_winstation_handle_
||
251 GetWindowObjectName(alternate_winstation_handle_
).empty())
252 return SBOX_ERROR_CANNOT_CREATE_DESKTOP
;
254 // Create the destkop.
255 result
= CreateAltDesktop(alternate_winstation_handle_
,
256 &alternate_desktop_handle_
);
257 if (SBOX_ALL_OK
!= result
)
260 // Verify that everything is fine.
261 if (!alternate_desktop_handle_
||
262 GetWindowObjectName(alternate_desktop_handle_
).empty())
263 return SBOX_ERROR_CANNOT_CREATE_DESKTOP
;
265 // Previously called with alternate_winstation = true?
266 if (alternate_winstation_handle_
)
267 return SBOX_ERROR_UNSUPPORTED
;
269 // Check if it already exists.
270 if (alternate_desktop_handle_
)
273 // Create the destkop.
274 ResultCode result
= CreateAltDesktop(NULL
, &alternate_desktop_handle_
);
275 if (SBOX_ALL_OK
!= result
)
278 // Verify that everything is fine.
279 if (!alternate_desktop_handle_
||
280 GetWindowObjectName(alternate_desktop_handle_
).empty())
281 return SBOX_ERROR_CANNOT_CREATE_DESKTOP
;
287 void PolicyBase::DestroyAlternateDesktop() {
288 if (alternate_desktop_handle_
) {
289 ::CloseDesktop(alternate_desktop_handle_
);
290 alternate_desktop_handle_
= NULL
;
293 if (alternate_winstation_handle_
) {
294 ::CloseWindowStation(alternate_winstation_handle_
);
295 alternate_winstation_handle_
= NULL
;
299 ResultCode
PolicyBase::SetIntegrityLevel(IntegrityLevel integrity_level
) {
300 integrity_level_
= integrity_level
;
304 IntegrityLevel
PolicyBase::GetIntegrityLevel() const {
305 return integrity_level_
;
308 ResultCode
PolicyBase::SetDelayedIntegrityLevel(
309 IntegrityLevel integrity_level
) {
310 delayed_integrity_level_
= integrity_level
;
314 ResultCode
PolicyBase::SetAppContainer(const wchar_t* sid
) {
315 if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8
)
318 // SetLowBox and SetAppContainer are mutually exclusive.
320 return SBOX_ERROR_UNSUPPORTED
;
322 // Windows refuses to work with an impersonation token for a process inside
323 // an AppContainer. If the caller wants to use a more privileged initial
324 // token, or if the lockdown level will prevent the process from starting,
325 // we have to fail the operation.
326 if (lockdown_level_
< USER_LIMITED
|| lockdown_level_
!= initial_level_
)
327 return SBOX_ERROR_CANNOT_INIT_APPCONTAINER
;
329 DCHECK(!appcontainer_list_
.get());
330 appcontainer_list_
.reset(new AppContainerAttributes
);
331 ResultCode rv
= appcontainer_list_
->SetAppContainer(sid
, capabilities_
);
332 if (rv
!= SBOX_ALL_OK
)
338 ResultCode
PolicyBase::SetCapability(const wchar_t* sid
) {
339 capabilities_
.push_back(sid
);
343 ResultCode
PolicyBase::SetLowBox(const wchar_t* sid
) {
344 if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8
)
345 return SBOX_ERROR_UNSUPPORTED
;
347 // SetLowBox and SetAppContainer are mutually exclusive.
348 if (appcontainer_list_
.get())
349 return SBOX_ERROR_UNSUPPORTED
;
354 return SBOX_ERROR_BAD_PARAMS
;
356 if (!ConvertStringSidToSid(sid
, &lowbox_sid_
))
357 return SBOX_ERROR_GENERIC
;
362 ResultCode
PolicyBase::SetProcessMitigations(
363 MitigationFlags flags
) {
364 if (!CanSetProcessMitigationsPreStartup(flags
))
365 return SBOX_ERROR_BAD_PARAMS
;
366 mitigations_
= flags
;
370 MitigationFlags
PolicyBase::GetProcessMitigations() {
374 ResultCode
PolicyBase::SetDelayedProcessMitigations(
375 MitigationFlags flags
) {
376 if (!CanSetProcessMitigationsPostStartup(flags
))
377 return SBOX_ERROR_BAD_PARAMS
;
378 delayed_mitigations_
= flags
;
382 MitigationFlags
PolicyBase::GetDelayedProcessMitigations() const {
383 return delayed_mitigations_
;
386 void PolicyBase::SetStrictInterceptions() {
387 relaxed_interceptions_
= false;
390 ResultCode
PolicyBase::SetStdoutHandle(HANDLE handle
) {
391 if (!IsInheritableHandle(handle
))
392 return SBOX_ERROR_BAD_PARAMS
;
393 stdout_handle_
= handle
;
397 ResultCode
PolicyBase::SetStderrHandle(HANDLE handle
) {
398 if (!IsInheritableHandle(handle
))
399 return SBOX_ERROR_BAD_PARAMS
;
400 stderr_handle_
= handle
;
404 ResultCode
PolicyBase::AddRule(SubSystem subsystem
,
406 const wchar_t* pattern
) {
407 ResultCode result
= AddRuleInternal(subsystem
, semantics
, pattern
);
408 LOG_IF(ERROR
, result
!= SBOX_ALL_OK
) << "Failed to add sandbox rule."
409 << " error = " << result
410 << ", subsystem = " << subsystem
411 << ", semantics = " << semantics
412 << ", pattern = '" << pattern
<< "'";
416 ResultCode
PolicyBase::AddDllToUnload(const wchar_t* dll_name
) {
417 blacklisted_dlls_
.push_back(dll_name
);
421 ResultCode
PolicyBase::AddKernelObjectToClose(const base::char16
* handle_type
,
422 const base::char16
* handle_name
) {
423 return handle_closer_
.AddHandle(handle_type
, handle_name
);
426 // When an IPC is ready in any of the targets we get called. We manage an array
427 // of IPC dispatchers which are keyed on the IPC tag so we normally delegate
428 // to the appropriate dispatcher unless we can handle the IPC call ourselves.
429 Dispatcher
* PolicyBase::OnMessageReady(IPCParams
* ipc
,
430 CallbackGeneric
* callback
) {
432 static const IPCParams ping1
= {IPC_PING1_TAG
, UINT32_TYPE
};
433 static const IPCParams ping2
= {IPC_PING2_TAG
, INOUTPTR_TYPE
};
435 if (ping1
.Matches(ipc
) || ping2
.Matches(ipc
)) {
436 *callback
= reinterpret_cast<CallbackGeneric
>(
437 static_cast<Callback1
>(&PolicyBase::Ping
));
441 Dispatcher
* dispatch
= GetDispatcher(ipc
->ipc_tag
);
446 return dispatch
->OnMessageReady(ipc
, callback
);
449 // Delegate to the appropriate dispatcher.
450 bool PolicyBase::SetupService(InterceptionManager
* manager
, int service
) {
451 if (IPC_PING1_TAG
== service
|| IPC_PING2_TAG
== service
)
454 Dispatcher
* dispatch
= GetDispatcher(service
);
459 return dispatch
->SetupService(manager
, service
);
462 ResultCode
PolicyBase::MakeJobObject(HANDLE
* job
) {
463 if (job_level_
!= JOB_NONE
) {
464 // Create the windows job object.
466 DWORD result
= job_obj
.Init(job_level_
, NULL
, ui_exceptions_
,
468 if (ERROR_SUCCESS
!= result
) {
469 return SBOX_ERROR_GENERIC
;
471 *job
= job_obj
.Detach();
478 ResultCode
PolicyBase::MakeTokens(HANDLE
* initial
, HANDLE
* lockdown
) {
479 if (appcontainer_list_
.get() && appcontainer_list_
->HasAppContainer() &&
481 return SBOX_ERROR_BAD_PARAMS
;
484 // Create the 'naked' token. This will be the permanent token associated
485 // with the process and therefore with any thread that is not impersonating.
486 DWORD result
= CreateRestrictedToken(lockdown
, lockdown_level_
,
487 integrity_level_
, PRIMARY
);
488 if (ERROR_SUCCESS
!= result
)
489 return SBOX_ERROR_GENERIC
;
491 // If we're launching on the alternate desktop we need to make sure the
492 // integrity label on the object is no higher than the sandboxed process's
493 // integrity level. So, we lower the label on the desktop process if it's
494 // not already low enough for our process.
495 if (alternate_desktop_handle_
&& use_alternate_desktop_
&&
496 integrity_level_
!= INTEGRITY_LEVEL_LAST
&&
497 alternate_desktop_integrity_level_label_
< integrity_level_
&&
498 base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA
) {
499 // Integrity label enum is reversed (higher level is a lower value).
500 static_assert(INTEGRITY_LEVEL_SYSTEM
< INTEGRITY_LEVEL_UNTRUSTED
,
501 "Integrity level ordering reversed.");
502 result
= SetObjectIntegrityLabel(alternate_desktop_handle_
,
505 GetIntegrityLevelString(integrity_level_
));
506 if (ERROR_SUCCESS
!= result
)
507 return SBOX_ERROR_GENERIC
;
509 alternate_desktop_integrity_level_label_
= integrity_level_
;
512 // We are maintaining two mutually exclusive approaches. One is to start an
513 // AppContainer process through StartupInfoEx and other is replacing
514 // existing token with LowBox token after process creation.
515 if (appcontainer_list_
.get() && appcontainer_list_
->HasAppContainer()) {
516 // Windows refuses to work with an impersonation token. See SetAppContainer
517 // implementation for more details.
518 if (lockdown_level_
< USER_LIMITED
|| lockdown_level_
!= initial_level_
)
519 return SBOX_ERROR_CANNOT_INIT_APPCONTAINER
;
521 *initial
= INVALID_HANDLE_VALUE
;
523 } else if (lowbox_sid_
) {
524 NtCreateLowBoxToken CreateLowBoxToken
= NULL
;
525 ResolveNTFunctionPtr("NtCreateLowBoxToken", &CreateLowBoxToken
);
526 OBJECT_ATTRIBUTES obj_attr
;
527 InitializeObjectAttributes(&obj_attr
, NULL
, 0, NULL
, NULL
);
528 HANDLE token_lowbox
= NULL
;
529 NTSTATUS status
= CreateLowBoxToken(&token_lowbox
, *lockdown
,
530 TOKEN_ALL_ACCESS
, &obj_attr
,
531 lowbox_sid_
, 0, NULL
, 0, NULL
);
532 if (!NT_SUCCESS(status
))
533 return SBOX_ERROR_GENERIC
;
535 DCHECK(token_lowbox
);
536 ::CloseHandle(*lockdown
);
537 *lockdown
= token_lowbox
;
540 // Create the 'better' token. We use this token as the one that the main
541 // thread uses when booting up the process. It should contain most of
542 // what we need (before reaching main( ))
543 result
= CreateRestrictedToken(initial
, initial_level_
,
544 integrity_level_
, IMPERSONATION
);
545 if (ERROR_SUCCESS
!= result
) {
546 ::CloseHandle(*lockdown
);
547 return SBOX_ERROR_GENERIC
;
552 const AppContainerAttributes
* PolicyBase::GetAppContainer() const {
553 if (!appcontainer_list_
.get() || !appcontainer_list_
->HasAppContainer())
556 return appcontainer_list_
.get();
559 const PSID
PolicyBase::GetLowBoxSid() const {
563 bool PolicyBase::AddTarget(TargetProcess
* target
) {
565 policy_maker_
->Done();
567 if (!ApplyProcessMitigationsToSuspendedProcess(target
->Process(),
572 if (!SetupAllInterceptions(target
))
575 if (!SetupHandleCloser(target
))
578 // Initialize the sandbox infrastructure for the target.
579 if (ERROR_SUCCESS
!= target
->Init(this, policy_
, kIPCMemSize
, kPolMemSize
))
582 g_shared_delayed_integrity_level
= delayed_integrity_level_
;
583 ResultCode ret
= target
->TransferVariable(
584 "g_shared_delayed_integrity_level",
585 &g_shared_delayed_integrity_level
,
586 sizeof(g_shared_delayed_integrity_level
));
587 g_shared_delayed_integrity_level
= INTEGRITY_LEVEL_LAST
;
588 if (SBOX_ALL_OK
!= ret
)
591 // Add in delayed mitigations and pseudo-mitigations enforced at startup.
592 g_shared_delayed_mitigations
= delayed_mitigations_
|
593 FilterPostStartupProcessMitigations(mitigations_
);
594 if (!CanSetProcessMitigationsPostStartup(g_shared_delayed_mitigations
))
597 ret
= target
->TransferVariable("g_shared_delayed_mitigations",
598 &g_shared_delayed_mitigations
,
599 sizeof(g_shared_delayed_mitigations
));
600 g_shared_delayed_mitigations
= 0;
601 if (SBOX_ALL_OK
!= ret
)
604 AutoLock
lock(&lock_
);
605 targets_
.push_back(target
);
609 bool PolicyBase::OnJobEmpty(HANDLE job
) {
610 AutoLock
lock(&lock_
);
611 TargetSet::iterator it
;
612 for (it
= targets_
.begin(); it
!= targets_
.end(); ++it
) {
613 if ((*it
)->Job() == job
)
616 if (it
== targets_
.end()) {
619 TargetProcess
* target
= *it
;
625 EvalResult
PolicyBase::EvalPolicy(int service
,
626 CountedParameterSetBase
* params
) {
627 if (NULL
!= policy_
) {
628 if (NULL
== policy_
->entry
[service
]) {
629 // There is no policy for this particular service. This is not a big
633 for (int i
= 0; i
< params
->count
; i
++) {
634 if (!params
->parameters
[i
].IsValid()) {
639 PolicyProcessor
pol_evaluator(policy_
->entry
[service
]);
640 PolicyResult result
= pol_evaluator
.Evaluate(kShortEval
,
643 if (POLICY_MATCH
== result
) {
644 return pol_evaluator
.GetAction();
646 DCHECK(POLICY_ERROR
!= result
);
652 HANDLE
PolicyBase::GetStdoutHandle() {
653 return stdout_handle_
;
656 HANDLE
PolicyBase::GetStderrHandle() {
657 return stderr_handle_
;
660 // We service IPC_PING_TAG message which is a way to test a round trip of the
661 // IPC subsystem. We receive a integer cookie and we are expected to return the
662 // cookie times two (or three) and the current tick count.
663 bool PolicyBase::Ping(IPCInfo
* ipc
, void* arg1
) {
664 switch (ipc
->ipc_tag
) {
665 case IPC_PING1_TAG
: {
666 IPCInt
ipc_int(arg1
);
667 uint32 cookie
= ipc_int
.As32Bit();
668 ipc
->return_info
.extended_count
= 2;
669 ipc
->return_info
.extended
[0].unsigned_int
= ::GetTickCount();
670 ipc
->return_info
.extended
[1].unsigned_int
= 2 * cookie
;
673 case IPC_PING2_TAG
: {
674 CountedBuffer
* io_buffer
= reinterpret_cast<CountedBuffer
*>(arg1
);
675 if (sizeof(uint32
) != io_buffer
->Size())
678 uint32
* cookie
= reinterpret_cast<uint32
*>(io_buffer
->Buffer());
679 *cookie
= (*cookie
) * 3;
682 default: return false;
686 Dispatcher
* PolicyBase::GetDispatcher(int ipc_tag
) {
687 if (ipc_tag
>= IPC_LAST_TAG
|| ipc_tag
<= IPC_UNUSED_TAG
)
690 return ipc_targets_
[ipc_tag
];
693 bool PolicyBase::SetupAllInterceptions(TargetProcess
* target
) {
694 InterceptionManager
manager(target
, relaxed_interceptions_
);
697 for (int i
= 0; i
< IPC_LAST_TAG
; i
++) {
698 if (policy_
->entry
[i
] && !ipc_targets_
[i
]->SetupService(&manager
, i
))
703 if (!blacklisted_dlls_
.empty()) {
704 std::vector
<base::string16
>::iterator it
= blacklisted_dlls_
.begin();
705 for (; it
!= blacklisted_dlls_
.end(); ++it
) {
706 manager
.AddToUnloadModules(it
->c_str());
710 if (!SetupBasicInterceptions(&manager
))
713 if (!manager
.InitializeInterceptions())
716 // Finally, setup imports on the target so the interceptions can work.
717 return SetupNtdllImports(target
);
720 bool PolicyBase::SetupHandleCloser(TargetProcess
* target
) {
721 return handle_closer_
.InitializeTargetHandles(target
);
724 ResultCode
PolicyBase::AddRuleInternal(SubSystem subsystem
,
726 const wchar_t* pattern
) {
727 if (NULL
== policy_
) {
728 policy_
= MakeBrokerPolicyMemory();
730 policy_maker_
= new LowLevelPolicy(policy_
);
731 DCHECK(policy_maker_
);
736 if (!file_system_init_
) {
737 if (!FileSystemPolicy::SetInitialRules(policy_maker_
))
738 return SBOX_ERROR_BAD_PARAMS
;
739 file_system_init_
= true;
741 if (!FileSystemPolicy::GenerateRules(pattern
, semantics
, policy_maker_
)) {
743 return SBOX_ERROR_BAD_PARAMS
;
748 if (!SyncPolicy::GenerateRules(pattern
, semantics
, policy_maker_
)) {
750 return SBOX_ERROR_BAD_PARAMS
;
754 case SUBSYS_PROCESS
: {
755 if (lockdown_level_
< USER_INTERACTIVE
&&
756 TargetPolicy::PROCESS_ALL_EXEC
== semantics
) {
757 // This is unsupported. This is a huge security risk to give full access
758 // to a process handle.
759 return SBOX_ERROR_UNSUPPORTED
;
761 if (!ProcessPolicy::GenerateRules(pattern
, semantics
, policy_maker_
)) {
763 return SBOX_ERROR_BAD_PARAMS
;
767 case SUBSYS_NAMED_PIPES
: {
768 if (!NamedPipePolicy::GenerateRules(pattern
, semantics
, policy_maker_
)) {
770 return SBOX_ERROR_BAD_PARAMS
;
774 case SUBSYS_REGISTRY
: {
775 if (!RegistryPolicy::GenerateRules(pattern
, semantics
, policy_maker_
)) {
777 return SBOX_ERROR_BAD_PARAMS
;
781 case SUBSYS_HANDLES
: {
782 if (!HandlePolicy::GenerateRules(pattern
, semantics
, policy_maker_
)) {
784 return SBOX_ERROR_BAD_PARAMS
;
789 case SUBSYS_WIN32K_LOCKDOWN
: {
790 if (!ProcessMitigationsWin32KLockdownPolicy::GenerateRules(
791 pattern
, semantics
, policy_maker_
)) {
793 return SBOX_ERROR_BAD_PARAMS
;
798 default: { return SBOX_ERROR_UNSUPPORTED
; }
804 } // namespace sandbox