Chromium Code Reviews| 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/sandbox_policy_base.h" | 5 #include "sandbox/win/src/sandbox_policy_base.h" |
| 6 | 6 |
| 7 #include <sddl.h> | 7 #include <sddl.h> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 91 use_alternate_winstation_(false), | 91 use_alternate_winstation_(false), |
| 92 file_system_init_(false), | 92 file_system_init_(false), |
| 93 relaxed_interceptions_(true), | 93 relaxed_interceptions_(true), |
| 94 stdout_handle_(INVALID_HANDLE_VALUE), | 94 stdout_handle_(INVALID_HANDLE_VALUE), |
| 95 stderr_handle_(INVALID_HANDLE_VALUE), | 95 stderr_handle_(INVALID_HANDLE_VALUE), |
| 96 integrity_level_(INTEGRITY_LEVEL_LAST), | 96 integrity_level_(INTEGRITY_LEVEL_LAST), |
| 97 delayed_integrity_level_(INTEGRITY_LEVEL_LAST), | 97 delayed_integrity_level_(INTEGRITY_LEVEL_LAST), |
| 98 mitigations_(0), | 98 mitigations_(0), |
| 99 delayed_mitigations_(0), | 99 delayed_mitigations_(0), |
| 100 policy_maker_(NULL), | 100 policy_maker_(NULL), |
| 101 policy_(NULL) { | 101 policy_(NULL), |
| 102 lowbox_sid_(NULL) { | |
| 102 ::InitializeCriticalSection(&lock_); | 103 ::InitializeCriticalSection(&lock_); |
| 103 // Initialize the IPC dispatcher array. | 104 // Initialize the IPC dispatcher array. |
| 104 memset(&ipc_targets_, NULL, sizeof(ipc_targets_)); | 105 memset(&ipc_targets_, NULL, sizeof(ipc_targets_)); |
| 105 Dispatcher* dispatcher = NULL; | 106 Dispatcher* dispatcher = NULL; |
| 106 | 107 |
| 107 dispatcher = new FilesystemDispatcher(this); | 108 dispatcher = new FilesystemDispatcher(this); |
| 108 ipc_targets_[IPC_NTCREATEFILE_TAG] = dispatcher; | 109 ipc_targets_[IPC_NTCREATEFILE_TAG] = dispatcher; |
| 109 ipc_targets_[IPC_NTOPENFILE_TAG] = dispatcher; | 110 ipc_targets_[IPC_NTOPENFILE_TAG] = dispatcher; |
| 110 ipc_targets_[IPC_NTSETINFO_RENAME_TAG] = dispatcher; | 111 ipc_targets_[IPC_NTSETINFO_RENAME_TAG] = dispatcher; |
| 111 ipc_targets_[IPC_NTQUERYATTRIBUTESFILE_TAG] = dispatcher; | 112 ipc_targets_[IPC_NTQUERYATTRIBUTESFILE_TAG] = dispatcher; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 145 delete target; | 146 delete target; |
| 146 } | 147 } |
| 147 delete ipc_targets_[IPC_NTCREATEFILE_TAG]; | 148 delete ipc_targets_[IPC_NTCREATEFILE_TAG]; |
| 148 delete ipc_targets_[IPC_CREATENAMEDPIPEW_TAG]; | 149 delete ipc_targets_[IPC_CREATENAMEDPIPEW_TAG]; |
| 149 delete ipc_targets_[IPC_NTOPENTHREAD_TAG]; | 150 delete ipc_targets_[IPC_NTOPENTHREAD_TAG]; |
| 150 delete ipc_targets_[IPC_CREATEEVENT_TAG]; | 151 delete ipc_targets_[IPC_CREATEEVENT_TAG]; |
| 151 delete ipc_targets_[IPC_NTCREATEKEY_TAG]; | 152 delete ipc_targets_[IPC_NTCREATEKEY_TAG]; |
| 152 delete ipc_targets_[IPC_DUPLICATEHANDLEPROXY_TAG]; | 153 delete ipc_targets_[IPC_DUPLICATEHANDLEPROXY_TAG]; |
| 153 delete policy_maker_; | 154 delete policy_maker_; |
| 154 delete policy_; | 155 delete policy_; |
| 156 | |
| 157 if (lowbox_sid_) | |
| 158 LocalFree(lowbox_sid_); | |
| 159 | |
|
cpu_(ooo_6.6-7.5)
2015/02/28 02:13:53
::LocalFree() or at least we seem to be consistent
Shrikant Kelkar
2015/02/28 02:33:47
Done.
| |
| 155 ::DeleteCriticalSection(&lock_); | 160 ::DeleteCriticalSection(&lock_); |
| 156 } | 161 } |
| 157 | 162 |
| 158 void PolicyBase::AddRef() { | 163 void PolicyBase::AddRef() { |
| 159 ::InterlockedIncrement(&ref_count); | 164 ::InterlockedIncrement(&ref_count); |
| 160 } | 165 } |
| 161 | 166 |
| 162 void PolicyBase::Release() { | 167 void PolicyBase::Release() { |
| 163 if (0 == ::InterlockedDecrement(&ref_count)) | 168 if (0 == ::InterlockedDecrement(&ref_count)) |
| 164 delete this; | 169 delete this; |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 324 return rv; | 329 return rv; |
| 325 | 330 |
| 326 return SBOX_ALL_OK; | 331 return SBOX_ALL_OK; |
| 327 } | 332 } |
| 328 | 333 |
| 329 ResultCode PolicyBase::SetCapability(const wchar_t* sid) { | 334 ResultCode PolicyBase::SetCapability(const wchar_t* sid) { |
| 330 capabilities_.push_back(sid); | 335 capabilities_.push_back(sid); |
| 331 return SBOX_ALL_OK; | 336 return SBOX_ALL_OK; |
| 332 } | 337 } |
| 333 | 338 |
| 339 ResultCode PolicyBase::SetLowBox(const wchar_t* sid) { | |
| 340 if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8) | |
|
cpu_(ooo_6.6-7.5)
2015/02/28 02:13:53
why the long form instead of the GetVersinon() one
Shrikant Kelkar
2015/02/28 02:33:47
Copied from earlier usage within this file. like l
| |
| 341 return SBOX_ERROR_UNEXPECTED_CALL; | |
|
cpu_(ooo_6.6-7.5)
2015/02/28 02:13:53
return SBOX_ERROR_UNSUPPORTED
rvargas (doing something else)
2015/02/28 02:23:08
I'm not sure what is the right thing to do, but no
Shrikant Kelkar
2015/02/28 02:33:46
Acknowledged.
Shrikant Kelkar
2015/02/28 02:33:47
Done.
| |
| 342 | |
| 343 // SetLowBox and SetAppContainer are mutually exclusive. | |
| 344 if (appcontainer_list_.get()) | |
| 345 return SBOX_ERROR_UNEXPECTED_CALL; | |
|
rvargas (doing something else)
2015/02/28 02:23:08
On the other hand, unsupported looks like a good c
Shrikant Kelkar
2015/02/28 02:33:47
Done.
| |
| 346 | |
| 347 DCHECK(sid); | |
| 348 | |
| 349 if (lowbox_sid_) | |
| 350 return SBOX_ERROR_BAD_PARAMS; | |
| 351 | |
| 352 if (!ConvertStringSidToSid(sid, &lowbox_sid_)) | |
| 353 return SBOX_ERROR_GENERIC; | |
| 354 | |
| 355 return SBOX_ALL_OK; | |
| 356 } | |
| 357 | |
| 334 ResultCode PolicyBase::SetProcessMitigations( | 358 ResultCode PolicyBase::SetProcessMitigations( |
| 335 MitigationFlags flags) { | 359 MitigationFlags flags) { |
| 336 if (!CanSetProcessMitigationsPreStartup(flags)) | 360 if (!CanSetProcessMitigationsPreStartup(flags)) |
| 337 return SBOX_ERROR_BAD_PARAMS; | 361 return SBOX_ERROR_BAD_PARAMS; |
| 338 mitigations_ = flags; | 362 mitigations_ = flags; |
| 339 return SBOX_ALL_OK; | 363 return SBOX_ALL_OK; |
| 340 } | 364 } |
| 341 | 365 |
| 342 MitigationFlags PolicyBase::GetProcessMitigations() { | 366 MitigationFlags PolicyBase::GetProcessMitigations() { |
| 343 return mitigations_; | 367 return mitigations_; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 441 return SBOX_ERROR_GENERIC; | 465 return SBOX_ERROR_GENERIC; |
| 442 } | 466 } |
| 443 *job = job_obj.Detach(); | 467 *job = job_obj.Detach(); |
| 444 } else { | 468 } else { |
| 445 *job = NULL; | 469 *job = NULL; |
| 446 } | 470 } |
| 447 return SBOX_ALL_OK; | 471 return SBOX_ALL_OK; |
| 448 } | 472 } |
| 449 | 473 |
| 450 ResultCode PolicyBase::MakeTokens(HANDLE* initial, HANDLE* lockdown) { | 474 ResultCode PolicyBase::MakeTokens(HANDLE* initial, HANDLE* lockdown) { |
| 475 if (appcontainer_list_.get() && appcontainer_list_->HasAppContainer() && | |
| 476 lowbox_sid_) { | |
|
cpu_(ooo_6.6-7.5)
2015/02/28 02:13:53
is there a way to trigger this check while bypassi
| |
| 477 return SBOX_ERROR_BAD_PARAMS; | |
| 478 } | |
| 479 | |
| 451 // Create the 'naked' token. This will be the permanent token associated | 480 // Create the 'naked' token. This will be the permanent token associated |
| 452 // with the process and therefore with any thread that is not impersonating. | 481 // with the process and therefore with any thread that is not impersonating. |
| 453 DWORD result = CreateRestrictedToken(lockdown, lockdown_level_, | 482 DWORD result = CreateRestrictedToken(lockdown, lockdown_level_, |
| 454 integrity_level_, PRIMARY); | 483 integrity_level_, PRIMARY); |
| 455 if (ERROR_SUCCESS != result) | 484 if (ERROR_SUCCESS != result) |
| 456 return SBOX_ERROR_GENERIC; | 485 return SBOX_ERROR_GENERIC; |
| 457 | 486 |
| 458 // If we're launching on the alternate desktop we need to make sure the | 487 // If we're launching on the alternate desktop we need to make sure the |
| 459 // integrity label on the object is no higher than the sandboxed process's | 488 // integrity label on the object is no higher than the sandboxed process's |
| 460 // integrity level. So, we lower the label on the desktop process if it's | 489 // integrity level. So, we lower the label on the desktop process if it's |
| 461 // not already low enough for our process. | 490 // not already low enough for our process. |
| 462 if (alternate_desktop_handle_ && use_alternate_desktop_ && | 491 if (alternate_desktop_handle_ && use_alternate_desktop_ && |
| 463 integrity_level_ != INTEGRITY_LEVEL_LAST && | 492 integrity_level_ != INTEGRITY_LEVEL_LAST && |
| 464 alternate_desktop_integrity_level_label_ < integrity_level_ && | 493 alternate_desktop_integrity_level_label_ < integrity_level_ && |
| 465 base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) { | 494 base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) { |
| 466 // Integrity label enum is reversed (higher level is a lower value). | 495 // Integrity label enum is reversed (higher level is a lower value). |
| 467 static_assert(INTEGRITY_LEVEL_SYSTEM < INTEGRITY_LEVEL_UNTRUSTED, | 496 static_assert(INTEGRITY_LEVEL_SYSTEM < INTEGRITY_LEVEL_UNTRUSTED, |
| 468 "Integrity level ordering reversed."); | 497 "Integrity level ordering reversed."); |
| 469 result = SetObjectIntegrityLabel(alternate_desktop_handle_, | 498 result = SetObjectIntegrityLabel(alternate_desktop_handle_, |
| 470 SE_WINDOW_OBJECT, | 499 SE_WINDOW_OBJECT, |
| 471 L"", | 500 L"", |
| 472 GetIntegrityLevelString(integrity_level_)); | 501 GetIntegrityLevelString(integrity_level_)); |
| 473 if (ERROR_SUCCESS != result) | 502 if (ERROR_SUCCESS != result) |
| 474 return SBOX_ERROR_GENERIC; | 503 return SBOX_ERROR_GENERIC; |
| 475 | 504 |
| 476 alternate_desktop_integrity_level_label_ = integrity_level_; | 505 alternate_desktop_integrity_level_label_ = integrity_level_; |
| 477 } | 506 } |
| 478 | 507 |
| 508 // We are maintaining two mutually exclusive approaches. One is to start an | |
| 509 // AppContainer process through StartupInfoEx and other is by replacing | |
|
rvargas (doing something else)
2015/02/28 02:23:08
nit: remove "by"?
Shrikant Kelkar
2015/02/28 02:33:47
Done.
| |
| 510 // existing token with LowBox token after process creation. | |
| 479 if (appcontainer_list_.get() && appcontainer_list_->HasAppContainer()) { | 511 if (appcontainer_list_.get() && appcontainer_list_->HasAppContainer()) { |
| 480 // Windows refuses to work with an impersonation token. See SetAppContainer | 512 // Windows refuses to work with an impersonation token. See SetAppContainer |
| 481 // implementation for more details. | 513 // implementation for more details. |
| 482 if (lockdown_level_ < USER_LIMITED || lockdown_level_ != initial_level_) | 514 if (lockdown_level_ < USER_LIMITED || lockdown_level_ != initial_level_) |
| 483 return SBOX_ERROR_CANNOT_INIT_APPCONTAINER; | 515 return SBOX_ERROR_CANNOT_INIT_APPCONTAINER; |
| 484 | 516 |
| 485 *initial = INVALID_HANDLE_VALUE; | 517 *initial = INVALID_HANDLE_VALUE; |
| 486 return SBOX_ALL_OK; | 518 return SBOX_ALL_OK; |
| 519 } else if (lowbox_sid_) { | |
| 520 NtCreateLowBoxToken CreateLowBox = NULL; | |
|
cpu_(ooo_6.6-7.5)
2015/02/28 02:13:53
function should be named CreateLowBoxToken, or is
Shrikant Kelkar
2015/02/28 02:33:47
Done.
| |
| 521 ResolveNTFunctionPtr("NtCreateLowBoxToken", &CreateLowBox); | |
| 522 | |
| 523 OBJECT_ATTRIBUTES obj_attr; | |
| 524 InitializeObjectAttributes(&obj_attr, NULL, 0, NULL, NULL); | |
| 525 HANDLE token_lowbox = NULL; | |
| 526 | |
|
rvargas (doing something else)
2015/02/28 02:23:08
nit: move the empty line above the previous line.
Shrikant Kelkar
2015/02/28 02:33:47
Done.
rvargas (doing something else)
2015/02/28 02:48:05
Don't see it (the variable declaration should be t
Shrikant Kelkar
2015/03/01 00:31:43
Done.
| |
| 527 NTSTATUS status = CreateLowBox(&token_lowbox, *lockdown, TOKEN_ALL_ACCESS, | |
| 528 &obj_attr, lowbox_sid_, 0, NULL, 0, NULL); | |
| 529 if (!NT_SUCCESS(status)) | |
| 530 return SBOX_ERROR_GENERIC; | |
| 531 | |
| 532 DCHECK(token_lowbox); | |
| 533 ::CloseHandle(*lockdown); | |
| 534 *lockdown = token_lowbox; | |
| 487 } | 535 } |
| 488 | 536 |
| 489 // Create the 'better' token. We use this token as the one that the main | 537 // Create the 'better' token. We use this token as the one that the main |
| 490 // thread uses when booting up the process. It should contain most of | 538 // thread uses when booting up the process. It should contain most of |
| 491 // what we need (before reaching main( )) | 539 // what we need (before reaching main( )) |
| 492 result = CreateRestrictedToken(initial, initial_level_, | 540 result = CreateRestrictedToken(initial, initial_level_, |
| 493 integrity_level_, IMPERSONATION); | 541 integrity_level_, IMPERSONATION); |
| 494 if (ERROR_SUCCESS != result) { | 542 if (ERROR_SUCCESS != result) { |
| 495 ::CloseHandle(*lockdown); | 543 ::CloseHandle(*lockdown); |
| 496 return SBOX_ERROR_GENERIC; | 544 return SBOX_ERROR_GENERIC; |
| 497 } | 545 } |
| 498 return SBOX_ALL_OK; | 546 return SBOX_ALL_OK; |
| 499 } | 547 } |
| 500 | 548 |
| 501 const AppContainerAttributes* PolicyBase::GetAppContainer() const { | 549 const AppContainerAttributes* PolicyBase::GetAppContainer() const { |
| 502 if (!appcontainer_list_.get() || !appcontainer_list_->HasAppContainer()) | 550 if (!appcontainer_list_.get() || !appcontainer_list_->HasAppContainer()) |
| 503 return NULL; | 551 return NULL; |
| 504 | 552 |
| 505 return appcontainer_list_.get(); | 553 return appcontainer_list_.get(); |
| 506 } | 554 } |
| 507 | 555 |
| 556 const PSID PolicyBase::GetLowBoxSid() const { | |
| 557 return lowbox_sid_; | |
| 558 } | |
| 559 | |
| 508 bool PolicyBase::AddTarget(TargetProcess* target) { | 560 bool PolicyBase::AddTarget(TargetProcess* target) { |
| 509 if (NULL != policy_) | 561 if (NULL != policy_) |
| 510 policy_maker_->Done(); | 562 policy_maker_->Done(); |
| 511 | 563 |
| 512 if (!ApplyProcessMitigationsToSuspendedProcess(target->Process(), | 564 if (!ApplyProcessMitigationsToSuspendedProcess(target->Process(), |
| 513 mitigations_)) { | 565 mitigations_)) { |
| 514 return false; | 566 return false; |
| 515 } | 567 } |
| 516 | 568 |
| 517 if (!SetupAllInterceptions(target)) | 569 if (!SetupAllInterceptions(target)) |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 740 break; | 792 break; |
| 741 } | 793 } |
| 742 | 794 |
| 743 default: { return SBOX_ERROR_UNSUPPORTED; } | 795 default: { return SBOX_ERROR_UNSUPPORTED; } |
| 744 } | 796 } |
| 745 | 797 |
| 746 return SBOX_ALL_OK; | 798 return SBOX_ALL_OK; |
| 747 } | 799 } |
| 748 | 800 |
| 749 } // namespace sandbox | 801 } // namespace sandbox |
| OLD | NEW |