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/stl_util.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/win/windows_version.h"
15 #include "sandbox/win/src/app_container.h"
16 #include "sandbox/win/src/filesystem_dispatcher.h"
17 #include "sandbox/win/src/filesystem_policy.h"
18 #include "sandbox/win/src/handle_dispatcher.h"
19 #include "sandbox/win/src/handle_policy.h"
20 #include "sandbox/win/src/job.h"
21 #include "sandbox/win/src/interception.h"
22 #include "sandbox/win/src/process_mitigations.h"
23 #include "sandbox/win/src/named_pipe_dispatcher.h"
24 #include "sandbox/win/src/named_pipe_policy.h"
25 #include "sandbox/win/src/policy_broker.h"
26 #include "sandbox/win/src/policy_engine_processor.h"
27 #include "sandbox/win/src/policy_low_level.h"
28 #include "sandbox/win/src/process_mitigations_win32k_dispatcher.h"
29 #include "sandbox/win/src/process_mitigations_win32k_policy.h"
30 #include "sandbox/win/src/process_thread_dispatcher.h"
31 #include "sandbox/win/src/process_thread_policy.h"
32 #include "sandbox/win/src/registry_dispatcher.h"
33 #include "sandbox/win/src/registry_policy.h"
34 #include "sandbox/win/src/restricted_token_utils.h"
35 #include "sandbox/win/src/sandbox_policy.h"
36 #include "sandbox/win/src/sandbox_utils.h"
37 #include "sandbox/win/src/sync_dispatcher.h"
38 #include "sandbox/win/src/sync_policy.h"
39 #include "sandbox/win/src/target_process.h"
40 #include "sandbox/win/src/window.h"
44 // The standard windows size for one memory page.
45 const size_t kOneMemPage
= 4096;
46 // The IPC and Policy shared memory sizes.
47 const size_t kIPCMemSize
= kOneMemPage
* 2;
48 const size_t kPolMemSize
= kOneMemPage
* 14;
50 // Helper function to allocate space (on the heap) for policy.
51 sandbox::PolicyGlobal
* MakeBrokerPolicyMemory() {
52 const size_t kTotalPolicySz
= kPolMemSize
;
53 sandbox::PolicyGlobal
* policy
= static_cast<sandbox::PolicyGlobal
*>
54 (::operator new(kTotalPolicySz
));
56 memset(policy
, 0, kTotalPolicySz
);
57 policy
->data_size
= kTotalPolicySz
- sizeof(sandbox::PolicyGlobal
);
61 bool IsInheritableHandle(HANDLE handle
) {
64 if (handle
== INVALID_HANDLE_VALUE
)
66 // File handles (FILE_TYPE_DISK) and pipe handles are known to be
67 // inheritable. Console handles (FILE_TYPE_CHAR) are not
68 // inheritable via PROC_THREAD_ATTRIBUTE_HANDLE_LIST.
69 DWORD handle_type
= GetFileType(handle
);
70 return handle_type
== FILE_TYPE_DISK
|| handle_type
== FILE_TYPE_PIPE
;
73 HANDLE
CreateLowBoxObjectDirectory(PSID lowbox_sid
) {
75 if (!::ProcessIdToSessionId(::GetCurrentProcessId(), &session_id
))
78 LPWSTR sid_string
= NULL
;
79 if (!::ConvertSidToStringSid(lowbox_sid
, &sid_string
))
82 base::string16 directory_path
= base::StringPrintf(
83 L
"\\Sessions\\%d\\AppContainerNamedObjects\\%ls",
84 session_id
, sid_string
).c_str();
85 ::LocalFree(sid_string
);
87 NtCreateDirectoryObjectFunction CreateObjectDirectory
= NULL
;
88 ResolveNTFunctionPtr("NtCreateDirectoryObject", &CreateObjectDirectory
);
90 OBJECT_ATTRIBUTES obj_attr
;
91 UNICODE_STRING obj_name
;
92 sandbox::InitObjectAttribs(directory_path
,
93 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
100 NTSTATUS status
= CreateObjectDirectory(&handle
,
101 DIRECTORY_ALL_ACCESS
,
104 if (!NT_SUCCESS(status
))
114 SANDBOX_INTERCEPT IntegrityLevel g_shared_delayed_integrity_level
;
115 SANDBOX_INTERCEPT MitigationFlags g_shared_delayed_mitigations
;
117 // Initializes static members.
118 HWINSTA
PolicyBase::alternate_winstation_handle_
= NULL
;
119 HDESK
PolicyBase::alternate_desktop_handle_
= NULL
;
120 IntegrityLevel
PolicyBase::alternate_desktop_integrity_level_label_
=
121 INTEGRITY_LEVEL_SYSTEM
;
123 PolicyBase::PolicyBase()
125 lockdown_level_(USER_LOCKDOWN
),
126 initial_level_(USER_LOCKDOWN
),
127 job_level_(JOB_LOCKDOWN
),
130 use_alternate_desktop_(false),
131 use_alternate_winstation_(false),
132 file_system_init_(false),
133 relaxed_interceptions_(true),
134 stdout_handle_(INVALID_HANDLE_VALUE
),
135 stderr_handle_(INVALID_HANDLE_VALUE
),
136 integrity_level_(INTEGRITY_LEVEL_LAST
),
137 delayed_integrity_level_(INTEGRITY_LEVEL_LAST
),
139 delayed_mitigations_(0),
143 ::InitializeCriticalSection(&lock_
);
144 // Initialize the IPC dispatcher array.
145 memset(&ipc_targets_
, NULL
, sizeof(ipc_targets_
));
146 Dispatcher
* dispatcher
= NULL
;
148 dispatcher
= new FilesystemDispatcher(this);
149 ipc_targets_
[IPC_NTCREATEFILE_TAG
] = dispatcher
;
150 ipc_targets_
[IPC_NTOPENFILE_TAG
] = dispatcher
;
151 ipc_targets_
[IPC_NTSETINFO_RENAME_TAG
] = dispatcher
;
152 ipc_targets_
[IPC_NTQUERYATTRIBUTESFILE_TAG
] = dispatcher
;
153 ipc_targets_
[IPC_NTQUERYFULLATTRIBUTESFILE_TAG
] = dispatcher
;
155 dispatcher
= new NamedPipeDispatcher(this);
156 ipc_targets_
[IPC_CREATENAMEDPIPEW_TAG
] = dispatcher
;
158 dispatcher
= new ThreadProcessDispatcher(this);
159 ipc_targets_
[IPC_NTOPENTHREAD_TAG
] = dispatcher
;
160 ipc_targets_
[IPC_NTOPENPROCESS_TAG
] = dispatcher
;
161 ipc_targets_
[IPC_CREATEPROCESSW_TAG
] = dispatcher
;
162 ipc_targets_
[IPC_NTOPENPROCESSTOKEN_TAG
] = dispatcher
;
163 ipc_targets_
[IPC_NTOPENPROCESSTOKENEX_TAG
] = dispatcher
;
165 dispatcher
= new SyncDispatcher(this);
166 ipc_targets_
[IPC_CREATEEVENT_TAG
] = dispatcher
;
167 ipc_targets_
[IPC_OPENEVENT_TAG
] = dispatcher
;
169 dispatcher
= new RegistryDispatcher(this);
170 ipc_targets_
[IPC_NTCREATEKEY_TAG
] = dispatcher
;
171 ipc_targets_
[IPC_NTOPENKEY_TAG
] = dispatcher
;
173 dispatcher
= new HandleDispatcher(this);
174 ipc_targets_
[IPC_DUPLICATEHANDLEPROXY_TAG
] = dispatcher
;
176 dispatcher
= new ProcessMitigationsWin32KDispatcher(this);
177 ipc_targets_
[IPC_GDI_GDIDLLINITIALIZE_TAG
] = dispatcher
;
178 ipc_targets_
[IPC_GDI_GETSTOCKOBJECT_TAG
] = dispatcher
;
179 ipc_targets_
[IPC_USER_REGISTERCLASSW_TAG
] = dispatcher
;
182 PolicyBase::~PolicyBase() {
183 ClearSharedHandles();
185 TargetSet::iterator it
;
186 for (it
= targets_
.begin(); it
!= targets_
.end(); ++it
) {
187 TargetProcess
* target
= (*it
);
190 delete ipc_targets_
[IPC_NTCREATEFILE_TAG
];
191 delete ipc_targets_
[IPC_CREATENAMEDPIPEW_TAG
];
192 delete ipc_targets_
[IPC_NTOPENTHREAD_TAG
];
193 delete ipc_targets_
[IPC_CREATEEVENT_TAG
];
194 delete ipc_targets_
[IPC_NTCREATEKEY_TAG
];
195 delete ipc_targets_
[IPC_DUPLICATEHANDLEPROXY_TAG
];
196 delete policy_maker_
;
200 ::LocalFree(lowbox_sid_
);
202 ::DeleteCriticalSection(&lock_
);
205 void PolicyBase::AddRef() {
206 ::InterlockedIncrement(&ref_count
);
209 void PolicyBase::Release() {
210 if (0 == ::InterlockedDecrement(&ref_count
))
214 ResultCode
PolicyBase::SetTokenLevel(TokenLevel initial
, TokenLevel lockdown
) {
215 if (initial
< lockdown
) {
216 return SBOX_ERROR_BAD_PARAMS
;
218 initial_level_
= initial
;
219 lockdown_level_
= lockdown
;
223 TokenLevel
PolicyBase::GetInitialTokenLevel() const {
224 return initial_level_
;
227 TokenLevel
PolicyBase::GetLockdownTokenLevel() const{
228 return lockdown_level_
;
231 ResultCode
PolicyBase::SetJobLevel(JobLevel job_level
, uint32 ui_exceptions
) {
232 if (memory_limit_
&& job_level
== JOB_NONE
) {
233 return SBOX_ERROR_BAD_PARAMS
;
235 job_level_
= job_level
;
236 ui_exceptions_
= ui_exceptions
;
240 ResultCode
PolicyBase::SetJobMemoryLimit(size_t memory_limit
) {
241 if (memory_limit
&& job_level_
== JOB_NONE
) {
242 return SBOX_ERROR_BAD_PARAMS
;
244 memory_limit_
= memory_limit
;
248 ResultCode
PolicyBase::SetAlternateDesktop(bool alternate_winstation
) {
249 use_alternate_desktop_
= true;
250 use_alternate_winstation_
= alternate_winstation
;
251 return CreateAlternateDesktop(alternate_winstation
);
254 base::string16
PolicyBase::GetAlternateDesktop() const {
255 // No alternate desktop or winstation. Return an empty string.
256 if (!use_alternate_desktop_
&& !use_alternate_winstation_
) {
257 return base::string16();
260 // The desktop and winstation should have been created by now.
261 // If we hit this scenario, it means that the user ignored the failure
262 // during SetAlternateDesktop, so we ignore it here too.
263 if (use_alternate_desktop_
&& !alternate_desktop_handle_
) {
264 return base::string16();
266 if (use_alternate_winstation_
&& (!alternate_desktop_handle_
||
267 !alternate_winstation_handle_
)) {
268 return base::string16();
271 return GetFullDesktopName(alternate_winstation_handle_
,
272 alternate_desktop_handle_
);
275 ResultCode
PolicyBase::CreateAlternateDesktop(bool alternate_winstation
) {
276 if (alternate_winstation
) {
277 // Previously called with alternate_winstation = false?
278 if (!alternate_winstation_handle_
&& alternate_desktop_handle_
)
279 return SBOX_ERROR_UNSUPPORTED
;
281 // Check if it's already created.
282 if (alternate_winstation_handle_
&& alternate_desktop_handle_
)
285 DCHECK(!alternate_winstation_handle_
);
286 // Create the window station.
287 ResultCode result
= CreateAltWindowStation(&alternate_winstation_handle_
);
288 if (SBOX_ALL_OK
!= result
)
291 // Verify that everything is fine.
292 if (!alternate_winstation_handle_
||
293 GetWindowObjectName(alternate_winstation_handle_
).empty())
294 return SBOX_ERROR_CANNOT_CREATE_DESKTOP
;
296 // Create the destkop.
297 result
= CreateAltDesktop(alternate_winstation_handle_
,
298 &alternate_desktop_handle_
);
299 if (SBOX_ALL_OK
!= result
)
302 // Verify that everything is fine.
303 if (!alternate_desktop_handle_
||
304 GetWindowObjectName(alternate_desktop_handle_
).empty())
305 return SBOX_ERROR_CANNOT_CREATE_DESKTOP
;
307 // Previously called with alternate_winstation = true?
308 if (alternate_winstation_handle_
)
309 return SBOX_ERROR_UNSUPPORTED
;
311 // Check if it already exists.
312 if (alternate_desktop_handle_
)
315 // Create the destkop.
316 ResultCode result
= CreateAltDesktop(NULL
, &alternate_desktop_handle_
);
317 if (SBOX_ALL_OK
!= result
)
320 // Verify that everything is fine.
321 if (!alternate_desktop_handle_
||
322 GetWindowObjectName(alternate_desktop_handle_
).empty())
323 return SBOX_ERROR_CANNOT_CREATE_DESKTOP
;
329 void PolicyBase::DestroyAlternateDesktop() {
330 if (alternate_desktop_handle_
) {
331 ::CloseDesktop(alternate_desktop_handle_
);
332 alternate_desktop_handle_
= NULL
;
335 if (alternate_winstation_handle_
) {
336 ::CloseWindowStation(alternate_winstation_handle_
);
337 alternate_winstation_handle_
= NULL
;
341 ResultCode
PolicyBase::SetIntegrityLevel(IntegrityLevel integrity_level
) {
342 integrity_level_
= integrity_level
;
346 IntegrityLevel
PolicyBase::GetIntegrityLevel() const {
347 return integrity_level_
;
350 ResultCode
PolicyBase::SetDelayedIntegrityLevel(
351 IntegrityLevel integrity_level
) {
352 delayed_integrity_level_
= integrity_level
;
356 ResultCode
PolicyBase::SetAppContainer(const wchar_t* sid
) {
357 if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8
)
360 // SetLowBox and SetAppContainer are mutually exclusive.
362 return SBOX_ERROR_UNSUPPORTED
;
364 // Windows refuses to work with an impersonation token for a process inside
365 // an AppContainer. If the caller wants to use a more privileged initial
366 // token, or if the lockdown level will prevent the process from starting,
367 // we have to fail the operation.
368 if (lockdown_level_
< USER_LIMITED
|| lockdown_level_
!= initial_level_
)
369 return SBOX_ERROR_CANNOT_INIT_APPCONTAINER
;
371 DCHECK(!appcontainer_list_
.get());
372 appcontainer_list_
.reset(new AppContainerAttributes
);
373 ResultCode rv
= appcontainer_list_
->SetAppContainer(sid
, capabilities_
);
374 if (rv
!= SBOX_ALL_OK
)
380 ResultCode
PolicyBase::SetCapability(const wchar_t* sid
) {
381 capabilities_
.push_back(sid
);
385 ResultCode
PolicyBase::SetLowBox(const wchar_t* sid
) {
386 if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8
)
387 return SBOX_ERROR_UNSUPPORTED
;
389 // SetLowBox and SetAppContainer are mutually exclusive.
390 if (appcontainer_list_
.get())
391 return SBOX_ERROR_UNSUPPORTED
;
396 return SBOX_ERROR_BAD_PARAMS
;
398 if (!ConvertStringSidToSid(sid
, &lowbox_sid_
))
399 return SBOX_ERROR_GENERIC
;
404 ResultCode
PolicyBase::SetProcessMitigations(
405 MitigationFlags flags
) {
406 if (!CanSetProcessMitigationsPreStartup(flags
))
407 return SBOX_ERROR_BAD_PARAMS
;
408 mitigations_
= flags
;
412 MitigationFlags
PolicyBase::GetProcessMitigations() {
416 ResultCode
PolicyBase::SetDelayedProcessMitigations(
417 MitigationFlags flags
) {
418 if (!CanSetProcessMitigationsPostStartup(flags
))
419 return SBOX_ERROR_BAD_PARAMS
;
420 delayed_mitigations_
= flags
;
424 MitigationFlags
PolicyBase::GetDelayedProcessMitigations() const {
425 return delayed_mitigations_
;
428 void PolicyBase::SetStrictInterceptions() {
429 relaxed_interceptions_
= false;
432 ResultCode
PolicyBase::SetStdoutHandle(HANDLE handle
) {
433 if (!IsInheritableHandle(handle
))
434 return SBOX_ERROR_BAD_PARAMS
;
435 stdout_handle_
= handle
;
439 ResultCode
PolicyBase::SetStderrHandle(HANDLE handle
) {
440 if (!IsInheritableHandle(handle
))
441 return SBOX_ERROR_BAD_PARAMS
;
442 stderr_handle_
= handle
;
446 ResultCode
PolicyBase::AddRule(SubSystem subsystem
,
448 const wchar_t* pattern
) {
449 ResultCode result
= AddRuleInternal(subsystem
, semantics
, pattern
);
450 LOG_IF(ERROR
, result
!= SBOX_ALL_OK
) << "Failed to add sandbox rule."
451 << " error = " << result
452 << ", subsystem = " << subsystem
453 << ", semantics = " << semantics
454 << ", pattern = '" << pattern
<< "'";
458 ResultCode
PolicyBase::AddDllToUnload(const wchar_t* dll_name
) {
459 blacklisted_dlls_
.push_back(dll_name
);
463 ResultCode
PolicyBase::AddKernelObjectToClose(const base::char16
* handle_type
,
464 const base::char16
* handle_name
) {
465 return handle_closer_
.AddHandle(handle_type
, handle_name
);
468 void* PolicyBase::AddHandleToShare(HANDLE handle
) {
469 if (base::win::GetVersion() < base::win::VERSION_VISTA
)
475 HANDLE duped_handle
= nullptr;
476 if (!::DuplicateHandle(::GetCurrentProcess(), handle
, ::GetCurrentProcess(),
477 &duped_handle
, 0, TRUE
, DUPLICATE_SAME_ACCESS
)) {
480 handles_to_share_
.push_back(new base::win::ScopedHandle(duped_handle
));
484 const HandleList
& PolicyBase::GetHandlesBeingShared() {
485 return handles_to_share_
;
488 void PolicyBase::ClearSharedHandles() {
489 STLDeleteElements(&handles_to_share_
);
492 // When an IPC is ready in any of the targets we get called. We manage an array
493 // of IPC dispatchers which are keyed on the IPC tag so we normally delegate
494 // to the appropriate dispatcher unless we can handle the IPC call ourselves.
495 Dispatcher
* PolicyBase::OnMessageReady(IPCParams
* ipc
,
496 CallbackGeneric
* callback
) {
498 static const IPCParams ping1
= {IPC_PING1_TAG
, {UINT32_TYPE
}};
499 static const IPCParams ping2
= {IPC_PING2_TAG
, {INOUTPTR_TYPE
}};
501 if (ping1
.Matches(ipc
) || ping2
.Matches(ipc
)) {
502 *callback
= reinterpret_cast<CallbackGeneric
>(
503 static_cast<Callback1
>(&PolicyBase::Ping
));
507 Dispatcher
* dispatch
= GetDispatcher(ipc
->ipc_tag
);
512 return dispatch
->OnMessageReady(ipc
, callback
);
515 // Delegate to the appropriate dispatcher.
516 bool PolicyBase::SetupService(InterceptionManager
* manager
, int service
) {
517 if (IPC_PING1_TAG
== service
|| IPC_PING2_TAG
== service
)
520 Dispatcher
* dispatch
= GetDispatcher(service
);
525 return dispatch
->SetupService(manager
, service
);
528 ResultCode
PolicyBase::MakeJobObject(HANDLE
* job
) {
529 if (job_level_
!= JOB_NONE
) {
530 // Create the windows job object.
532 DWORD result
= job_obj
.Init(job_level_
, NULL
, ui_exceptions_
,
534 if (ERROR_SUCCESS
!= result
) {
535 return SBOX_ERROR_GENERIC
;
537 *job
= job_obj
.Detach();
544 ResultCode
PolicyBase::MakeTokens(base::win::ScopedHandle
* initial
,
545 base::win::ScopedHandle
* lockdown
) {
546 if (appcontainer_list_
.get() && appcontainer_list_
->HasAppContainer() &&
548 return SBOX_ERROR_BAD_PARAMS
;
551 // Create the 'naked' token. This will be the permanent token associated
552 // with the process and therefore with any thread that is not impersonating.
554 DWORD result
= CreateRestrictedToken(&temp_handle
, lockdown_level_
,
555 integrity_level_
, PRIMARY
);
556 if (ERROR_SUCCESS
!= result
)
557 return SBOX_ERROR_GENERIC
;
559 lockdown
->Set(temp_handle
);
561 // If we're launching on the alternate desktop we need to make sure the
562 // integrity label on the object is no higher than the sandboxed process's
563 // integrity level. So, we lower the label on the desktop process if it's
564 // not already low enough for our process.
565 if (alternate_desktop_handle_
&& use_alternate_desktop_
&&
566 integrity_level_
!= INTEGRITY_LEVEL_LAST
&&
567 alternate_desktop_integrity_level_label_
< integrity_level_
&&
568 base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA
) {
569 // Integrity label enum is reversed (higher level is a lower value).
570 static_assert(INTEGRITY_LEVEL_SYSTEM
< INTEGRITY_LEVEL_UNTRUSTED
,
571 "Integrity level ordering reversed.");
572 result
= SetObjectIntegrityLabel(alternate_desktop_handle_
,
575 GetIntegrityLevelString(integrity_level_
));
576 if (ERROR_SUCCESS
!= result
)
577 return SBOX_ERROR_GENERIC
;
579 alternate_desktop_integrity_level_label_
= integrity_level_
;
582 // We are maintaining two mutually exclusive approaches. One is to start an
583 // AppContainer process through StartupInfoEx and other is replacing
584 // existing token with LowBox token after process creation.
585 if (appcontainer_list_
.get() && appcontainer_list_
->HasAppContainer()) {
586 // Windows refuses to work with an impersonation token. See SetAppContainer
587 // implementation for more details.
588 if (lockdown_level_
< USER_LIMITED
|| lockdown_level_
!= initial_level_
)
589 return SBOX_ERROR_CANNOT_INIT_APPCONTAINER
;
591 *initial
= base::win::ScopedHandle();
596 NtCreateLowBoxToken CreateLowBoxToken
= NULL
;
597 ResolveNTFunctionPtr("NtCreateLowBoxToken", &CreateLowBoxToken
);
598 OBJECT_ATTRIBUTES obj_attr
;
599 InitializeObjectAttributes(&obj_attr
, NULL
, 0, NULL
, NULL
);
600 HANDLE token_lowbox
= NULL
;
602 if (!lowbox_directory_
.IsValid())
603 lowbox_directory_
.Set(CreateLowBoxObjectDirectory(lowbox_sid_
));
604 DCHECK(lowbox_directory_
.IsValid());
606 // The order of handles isn't important in the CreateLowBoxToken call.
607 // The kernel will maintain a reference to the object directory handle.
608 HANDLE saved_handles
[1] = {lowbox_directory_
.Get()};
609 DWORD saved_handles_count
= lowbox_directory_
.IsValid() ? 1 : 0;
611 NTSTATUS status
= CreateLowBoxToken(&token_lowbox
, lockdown
->Get(),
612 TOKEN_ALL_ACCESS
, &obj_attr
,
613 lowbox_sid_
, 0, NULL
,
614 saved_handles_count
, saved_handles
);
615 if (!NT_SUCCESS(status
))
616 return SBOX_ERROR_GENERIC
;
618 DCHECK(token_lowbox
);
619 lockdown
->Set(token_lowbox
);
622 // Create the 'better' token. We use this token as the one that the main
623 // thread uses when booting up the process. It should contain most of
624 // what we need (before reaching main( ))
625 result
= CreateRestrictedToken(&temp_handle
, initial_level_
,
626 integrity_level_
, IMPERSONATION
);
627 if (ERROR_SUCCESS
!= result
)
628 return SBOX_ERROR_GENERIC
;
630 initial
->Set(temp_handle
);
634 const AppContainerAttributes
* PolicyBase::GetAppContainer() const {
635 if (!appcontainer_list_
.get() || !appcontainer_list_
->HasAppContainer())
638 return appcontainer_list_
.get();
641 const PSID
PolicyBase::GetLowBoxSid() const {
645 bool PolicyBase::AddTarget(TargetProcess
* target
) {
647 policy_maker_
->Done();
649 if (!ApplyProcessMitigationsToSuspendedProcess(target
->Process(),
654 if (!SetupAllInterceptions(target
))
657 if (!SetupHandleCloser(target
))
660 // Initialize the sandbox infrastructure for the target.
661 if (ERROR_SUCCESS
!= target
->Init(this, policy_
, kIPCMemSize
, kPolMemSize
))
664 g_shared_delayed_integrity_level
= delayed_integrity_level_
;
665 ResultCode ret
= target
->TransferVariable(
666 "g_shared_delayed_integrity_level",
667 &g_shared_delayed_integrity_level
,
668 sizeof(g_shared_delayed_integrity_level
));
669 g_shared_delayed_integrity_level
= INTEGRITY_LEVEL_LAST
;
670 if (SBOX_ALL_OK
!= ret
)
673 // Add in delayed mitigations and pseudo-mitigations enforced at startup.
674 g_shared_delayed_mitigations
= delayed_mitigations_
|
675 FilterPostStartupProcessMitigations(mitigations_
);
676 if (!CanSetProcessMitigationsPostStartup(g_shared_delayed_mitigations
))
679 ret
= target
->TransferVariable("g_shared_delayed_mitigations",
680 &g_shared_delayed_mitigations
,
681 sizeof(g_shared_delayed_mitigations
));
682 g_shared_delayed_mitigations
= 0;
683 if (SBOX_ALL_OK
!= ret
)
686 AutoLock
lock(&lock_
);
687 targets_
.push_back(target
);
691 bool PolicyBase::OnJobEmpty(HANDLE job
) {
692 AutoLock
lock(&lock_
);
693 TargetSet::iterator it
;
694 for (it
= targets_
.begin(); it
!= targets_
.end(); ++it
) {
695 if ((*it
)->Job() == job
)
698 if (it
== targets_
.end()) {
701 TargetProcess
* target
= *it
;
707 EvalResult
PolicyBase::EvalPolicy(int service
,
708 CountedParameterSetBase
* params
) {
709 if (NULL
!= policy_
) {
710 if (NULL
== policy_
->entry
[service
]) {
711 // There is no policy for this particular service. This is not a big
715 for (int i
= 0; i
< params
->count
; i
++) {
716 if (!params
->parameters
[i
].IsValid()) {
721 PolicyProcessor
pol_evaluator(policy_
->entry
[service
]);
722 PolicyResult result
= pol_evaluator
.Evaluate(kShortEval
,
725 if (POLICY_MATCH
== result
) {
726 return pol_evaluator
.GetAction();
728 DCHECK(POLICY_ERROR
!= result
);
734 HANDLE
PolicyBase::GetStdoutHandle() {
735 return stdout_handle_
;
738 HANDLE
PolicyBase::GetStderrHandle() {
739 return stderr_handle_
;
742 // We service IPC_PING_TAG message which is a way to test a round trip of the
743 // IPC subsystem. We receive a integer cookie and we are expected to return the
744 // cookie times two (or three) and the current tick count.
745 bool PolicyBase::Ping(IPCInfo
* ipc
, void* arg1
) {
746 switch (ipc
->ipc_tag
) {
747 case IPC_PING1_TAG
: {
748 IPCInt
ipc_int(arg1
);
749 uint32 cookie
= ipc_int
.As32Bit();
750 ipc
->return_info
.extended_count
= 2;
751 ipc
->return_info
.extended
[0].unsigned_int
= ::GetTickCount();
752 ipc
->return_info
.extended
[1].unsigned_int
= 2 * cookie
;
755 case IPC_PING2_TAG
: {
756 CountedBuffer
* io_buffer
= reinterpret_cast<CountedBuffer
*>(arg1
);
757 if (sizeof(uint32
) != io_buffer
->Size())
760 uint32
* cookie
= reinterpret_cast<uint32
*>(io_buffer
->Buffer());
761 *cookie
= (*cookie
) * 3;
764 default: return false;
768 Dispatcher
* PolicyBase::GetDispatcher(int ipc_tag
) {
769 if (ipc_tag
>= IPC_LAST_TAG
|| ipc_tag
<= IPC_UNUSED_TAG
)
772 return ipc_targets_
[ipc_tag
];
775 bool PolicyBase::SetupAllInterceptions(TargetProcess
* target
) {
776 InterceptionManager
manager(target
, relaxed_interceptions_
);
779 for (int i
= 0; i
< IPC_LAST_TAG
; i
++) {
780 if (policy_
->entry
[i
] && !ipc_targets_
[i
]->SetupService(&manager
, i
))
785 if (!blacklisted_dlls_
.empty()) {
786 std::vector
<base::string16
>::iterator it
= blacklisted_dlls_
.begin();
787 for (; it
!= blacklisted_dlls_
.end(); ++it
) {
788 manager
.AddToUnloadModules(it
->c_str());
792 if (!SetupBasicInterceptions(&manager
))
795 if (!manager
.InitializeInterceptions())
798 // Finally, setup imports on the target so the interceptions can work.
799 return SetupNtdllImports(target
);
802 bool PolicyBase::SetupHandleCloser(TargetProcess
* target
) {
803 return handle_closer_
.InitializeTargetHandles(target
);
806 ResultCode
PolicyBase::AddRuleInternal(SubSystem subsystem
,
808 const wchar_t* pattern
) {
809 if (NULL
== policy_
) {
810 policy_
= MakeBrokerPolicyMemory();
812 policy_maker_
= new LowLevelPolicy(policy_
);
813 DCHECK(policy_maker_
);
818 if (!file_system_init_
) {
819 if (!FileSystemPolicy::SetInitialRules(policy_maker_
))
820 return SBOX_ERROR_BAD_PARAMS
;
821 file_system_init_
= true;
823 if (!FileSystemPolicy::GenerateRules(pattern
, semantics
, policy_maker_
)) {
825 return SBOX_ERROR_BAD_PARAMS
;
830 if (!SyncPolicy::GenerateRules(pattern
, semantics
, policy_maker_
)) {
832 return SBOX_ERROR_BAD_PARAMS
;
836 case SUBSYS_PROCESS
: {
837 if (lockdown_level_
< USER_INTERACTIVE
&&
838 TargetPolicy::PROCESS_ALL_EXEC
== semantics
) {
839 // This is unsupported. This is a huge security risk to give full access
840 // to a process handle.
841 return SBOX_ERROR_UNSUPPORTED
;
843 if (!ProcessPolicy::GenerateRules(pattern
, semantics
, policy_maker_
)) {
845 return SBOX_ERROR_BAD_PARAMS
;
849 case SUBSYS_NAMED_PIPES
: {
850 if (!NamedPipePolicy::GenerateRules(pattern
, semantics
, policy_maker_
)) {
852 return SBOX_ERROR_BAD_PARAMS
;
856 case SUBSYS_REGISTRY
: {
857 if (!RegistryPolicy::GenerateRules(pattern
, semantics
, policy_maker_
)) {
859 return SBOX_ERROR_BAD_PARAMS
;
863 case SUBSYS_HANDLES
: {
864 if (!HandlePolicy::GenerateRules(pattern
, semantics
, policy_maker_
)) {
866 return SBOX_ERROR_BAD_PARAMS
;
871 case SUBSYS_WIN32K_LOCKDOWN
: {
872 if (!ProcessMitigationsWin32KLockdownPolicy::GenerateRules(
873 pattern
, semantics
, policy_maker_
)) {
875 return SBOX_ERROR_BAD_PARAMS
;
880 default: { return SBOX_ERROR_UNSUPPORTED
; }
886 } // namespace sandbox