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 | |
| 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 // SetLowBox and SetAppContainer are mutually exclusive. | |
| 341 if (appcontainer_list_.get()) | |
| 342 return SBOX_ERROR_UNEXPECTED_CALL; | |
| 343 | |
| 344 DCHECK(sid); | |
| 345 | |
| 346 if (lowbox_sid_) | |
|
rvargas (doing something else)
2015/02/28 01:10:06
nit: This should be an error.
Shrikant Kelkar
2015/02/28 01:55:41
Done.
| |
| 347 LocalFree(lowbox_sid_); | |
| 348 | |
| 349 if (!ConvertStringSidToSid(sid, &lowbox_sid_)) | |
|
rvargas (doing something else)
2015/02/28 01:10:06
The should be an OS version check here
Shrikant Kelkar
2015/02/28 01:55:42
Done.
| |
| 350 return SBOX_ERROR_GENERIC; | |
| 351 | |
| 352 return SBOX_ALL_OK; | |
| 353 } | |
| 354 | |
| 334 ResultCode PolicyBase::SetProcessMitigations( | 355 ResultCode PolicyBase::SetProcessMitigations( |
| 335 MitigationFlags flags) { | 356 MitigationFlags flags) { |
| 336 if (!CanSetProcessMitigationsPreStartup(flags)) | 357 if (!CanSetProcessMitigationsPreStartup(flags)) |
| 337 return SBOX_ERROR_BAD_PARAMS; | 358 return SBOX_ERROR_BAD_PARAMS; |
| 338 mitigations_ = flags; | 359 mitigations_ = flags; |
| 339 return SBOX_ALL_OK; | 360 return SBOX_ALL_OK; |
| 340 } | 361 } |
| 341 | 362 |
| 342 MitigationFlags PolicyBase::GetProcessMitigations() { | 363 MitigationFlags PolicyBase::GetProcessMitigations() { |
| 343 return mitigations_; | 364 return mitigations_; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 441 return SBOX_ERROR_GENERIC; | 462 return SBOX_ERROR_GENERIC; |
| 442 } | 463 } |
| 443 *job = job_obj.Detach(); | 464 *job = job_obj.Detach(); |
| 444 } else { | 465 } else { |
| 445 *job = NULL; | 466 *job = NULL; |
| 446 } | 467 } |
| 447 return SBOX_ALL_OK; | 468 return SBOX_ALL_OK; |
| 448 } | 469 } |
| 449 | 470 |
| 450 ResultCode PolicyBase::MakeTokens(HANDLE* initial, HANDLE* lockdown) { | 471 ResultCode PolicyBase::MakeTokens(HANDLE* initial, HANDLE* lockdown) { |
| 472 if (appcontainer_list_.get() && | |
| 473 appcontainer_list_->HasAppContainer() && | |
|
rvargas (doing something else)
2015/02/28 01:10:06
nit: send this to the previous line
Shrikant Kelkar
2015/02/28 01:55:42
Done.
| |
| 474 lowbox_sid_) | |
|
rvargas (doing something else)
2015/02/28 01:10:06
nit : requires {}
Shrikant Kelkar
2015/02/28 01:55:42
Done.
| |
| 475 return SBOX_ERROR_UNEXPECTED_CALL; | |
|
rvargas (doing something else)
2015/02/28 01:10:06
SBOX_ERROR_BAD_PARAMS ?
Shrikant Kelkar
2015/02/28 01:55:42
Done.
| |
| 476 | |
| 451 // Create the 'naked' token. This will be the permanent token associated | 477 // Create the 'naked' token. This will be the permanent token associated |
| 452 // with the process and therefore with any thread that is not impersonating. | 478 // with the process and therefore with any thread that is not impersonating. |
| 453 DWORD result = CreateRestrictedToken(lockdown, lockdown_level_, | 479 DWORD result = CreateRestrictedToken(lockdown, lockdown_level_, |
| 454 integrity_level_, PRIMARY); | 480 integrity_level_, PRIMARY); |
| 455 if (ERROR_SUCCESS != result) | 481 if (ERROR_SUCCESS != result) |
| 456 return SBOX_ERROR_GENERIC; | 482 return SBOX_ERROR_GENERIC; |
| 457 | 483 |
| 458 // If we're launching on the alternate desktop we need to make sure the | 484 // 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 | 485 // 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 | 486 // integrity level. So, we lower the label on the desktop process if it's |
| 461 // not already low enough for our process. | 487 // not already low enough for our process. |
| 462 if (alternate_desktop_handle_ && use_alternate_desktop_ && | 488 if (alternate_desktop_handle_ && use_alternate_desktop_ && |
| 463 integrity_level_ != INTEGRITY_LEVEL_LAST && | 489 integrity_level_ != INTEGRITY_LEVEL_LAST && |
| 464 alternate_desktop_integrity_level_label_ < integrity_level_ && | 490 alternate_desktop_integrity_level_label_ < integrity_level_ && |
| 465 base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) { | 491 base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) { |
| 466 // Integrity label enum is reversed (higher level is a lower value). | 492 // Integrity label enum is reversed (higher level is a lower value). |
| 467 static_assert(INTEGRITY_LEVEL_SYSTEM < INTEGRITY_LEVEL_UNTRUSTED, | 493 static_assert(INTEGRITY_LEVEL_SYSTEM < INTEGRITY_LEVEL_UNTRUSTED, |
| 468 "Integrity level ordering reversed."); | 494 "Integrity level ordering reversed."); |
| 469 result = SetObjectIntegrityLabel(alternate_desktop_handle_, | 495 result = SetObjectIntegrityLabel(alternate_desktop_handle_, |
| 470 SE_WINDOW_OBJECT, | 496 SE_WINDOW_OBJECT, |
| 471 L"", | 497 L"", |
| 472 GetIntegrityLevelString(integrity_level_)); | 498 GetIntegrityLevelString(integrity_level_)); |
| 473 if (ERROR_SUCCESS != result) | 499 if (ERROR_SUCCESS != result) |
| 474 return SBOX_ERROR_GENERIC; | 500 return SBOX_ERROR_GENERIC; |
| 475 | 501 |
| 476 alternate_desktop_integrity_level_label_ = integrity_level_; | 502 alternate_desktop_integrity_level_label_ = integrity_level_; |
| 477 } | 503 } |
| 478 | 504 |
| 505 // We are maintaining two approaches this time and making them mutually | |
|
rvargas (doing something else)
2015/02/28 01:10:06
nit: this time? (aka, remove)
rvargas (doing something else)
2015/02/28 01:10:06
nit: we are not making them mutually exclusive...
Shrikant Kelkar
2015/02/28 01:55:41
Done.
Shrikant Kelkar
2015/02/28 01:55:42
Done.
| |
| 506 // exclusive. One is to start appcontainer process through StartupInfoEx | |
|
rvargas (doing something else)
2015/02/28 01:10:06
nit: start an AppContainer
Shrikant Kelkar
2015/02/28 01:55:42
Done.
| |
| 507 // and other is by attaching LowBox token after process creation. | |
|
rvargas (doing something else)
2015/02/28 01:10:06
nit: We don't attach a token, we replace the token
Shrikant Kelkar
2015/02/28 01:55:42
Done.
| |
| 479 if (appcontainer_list_.get() && appcontainer_list_->HasAppContainer()) { | 508 if (appcontainer_list_.get() && appcontainer_list_->HasAppContainer()) { |
| 480 // Windows refuses to work with an impersonation token. See SetAppContainer | 509 // Windows refuses to work with an impersonation token. See SetAppContainer |
| 481 // implementation for more details. | 510 // implementation for more details. |
| 482 if (lockdown_level_ < USER_LIMITED || lockdown_level_ != initial_level_) | 511 if (lockdown_level_ < USER_LIMITED || lockdown_level_ != initial_level_) |
| 483 return SBOX_ERROR_CANNOT_INIT_APPCONTAINER; | 512 return SBOX_ERROR_CANNOT_INIT_APPCONTAINER; |
| 484 | 513 |
| 485 *initial = INVALID_HANDLE_VALUE; | 514 *initial = INVALID_HANDLE_VALUE; |
| 486 return SBOX_ALL_OK; | 515 return SBOX_ALL_OK; |
| 516 } else if (lowbox_sid_) { | |
| 517 NtCreateLowBoxToken CreateLowBox = NULL; | |
| 518 ResolveNTFunctionPtr("NtCreateLowBoxToken", &CreateLowBox); | |
| 519 | |
| 520 HANDLE token_lowbox = NULL; | |
| 521 | |
|
rvargas (doing something else)
2015/02/28 01:10:06
nit: remove empty line. In fact, move line 520 to
Shrikant Kelkar
2015/02/28 01:55:42
Done.
| |
| 522 OBJECT_ATTRIBUTES obj_attr; | |
| 523 InitializeObjectAttributes(&obj_attr, NULL, 0, NULL, NULL); | |
| 524 | |
| 525 NTSTATUS status = CreateLowBox(&token_lowbox, | |
| 526 *lockdown, | |
|
rvargas (doing something else)
2015/02/28 01:10:06
nit: we can fit more arguments per line here...
Shrikant Kelkar
2015/02/28 01:55:42
Done.
| |
| 527 TOKEN_ALL_ACCESS, | |
| 528 &obj_attr, | |
| 529 lowbox_sid_, | |
| 530 0, | |
| 531 NULL, | |
| 532 0, | |
| 533 NULL); | |
| 534 if (!NT_SUCCESS(status)) { | |
|
rvargas (doing something else)
2015/02/28 01:10:06
nit: no {}
Shrikant Kelkar
2015/02/28 01:55:41
Done.
| |
| 535 return SBOX_ERROR_GENERIC; | |
| 536 } | |
| 537 DCHECK(token_lowbox); | |
| 538 ::CloseHandle(*lockdown); | |
| 539 *lockdown = token_lowbox; | |
| 487 } | 540 } |
| 488 | 541 |
| 489 // Create the 'better' token. We use this token as the one that the main | 542 // 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 | 543 // thread uses when booting up the process. It should contain most of |
| 491 // what we need (before reaching main( )) | 544 // what we need (before reaching main( )) |
| 492 result = CreateRestrictedToken(initial, initial_level_, | 545 result = CreateRestrictedToken(initial, initial_level_, |
| 493 integrity_level_, IMPERSONATION); | 546 integrity_level_, IMPERSONATION); |
| 494 if (ERROR_SUCCESS != result) { | 547 if (ERROR_SUCCESS != result) { |
| 495 ::CloseHandle(*lockdown); | 548 ::CloseHandle(*lockdown); |
| 496 return SBOX_ERROR_GENERIC; | 549 return SBOX_ERROR_GENERIC; |
| 497 } | 550 } |
| 498 return SBOX_ALL_OK; | 551 return SBOX_ALL_OK; |
| 499 } | 552 } |
| 500 | 553 |
| 501 const AppContainerAttributes* PolicyBase::GetAppContainer() const { | 554 const AppContainerAttributes* PolicyBase::GetAppContainer() const { |
| 502 if (!appcontainer_list_.get() || !appcontainer_list_->HasAppContainer()) | 555 if (!appcontainer_list_.get() || !appcontainer_list_->HasAppContainer()) |
| 503 return NULL; | 556 return NULL; |
| 504 | 557 |
| 505 return appcontainer_list_.get(); | 558 return appcontainer_list_.get(); |
| 506 } | 559 } |
| 507 | 560 |
| 561 const PSID PolicyBase::GetLowBoxSid() const { | |
| 562 return lowbox_sid_; | |
| 563 } | |
| 564 | |
| 508 bool PolicyBase::AddTarget(TargetProcess* target) { | 565 bool PolicyBase::AddTarget(TargetProcess* target) { |
| 509 if (NULL != policy_) | 566 if (NULL != policy_) |
| 510 policy_maker_->Done(); | 567 policy_maker_->Done(); |
| 511 | 568 |
| 512 if (!ApplyProcessMitigationsToSuspendedProcess(target->Process(), | 569 if (!ApplyProcessMitigationsToSuspendedProcess(target->Process(), |
| 513 mitigations_)) { | 570 mitigations_)) { |
| 514 return false; | 571 return false; |
| 515 } | 572 } |
| 516 | 573 |
| 517 if (!SetupAllInterceptions(target)) | 574 if (!SetupAllInterceptions(target)) |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 740 break; | 797 break; |
| 741 } | 798 } |
| 742 | 799 |
| 743 default: { return SBOX_ERROR_UNSUPPORTED; } | 800 default: { return SBOX_ERROR_UNSUPPORTED; } |
| 744 } | 801 } |
| 745 | 802 |
| 746 return SBOX_ALL_OK; | 803 return SBOX_ALL_OK; |
| 747 } | 804 } |
| 748 | 805 |
| 749 } // namespace sandbox | 806 } // namespace sandbox |
| OLD | NEW |