startup_information_helper.cc 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. // Copyright 2020 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.
  4. #include "sandbox/win/src/startup_information_helper.h"
  5. #include <Windows.h>
  6. #include <algorithm>
  7. #include <vector>
  8. #include "base/check.h"
  9. #include "base/memory/scoped_refptr.h"
  10. #include "base/win/startup_information.h"
  11. #include "base/win/windows_version.h"
  12. #include "sandbox/win/src/app_container.h"
  13. #include "sandbox/win/src/nt_internals.h"
  14. #include "sandbox/win/src/security_capabilities.h"
  15. #include "sandbox/win/src/win_utils.h"
  16. namespace sandbox {
  17. using base::win::StartupInformation;
  18. StartupInformationHelper::StartupInformationHelper() {}
  19. StartupInformationHelper::~StartupInformationHelper() {}
  20. void StartupInformationHelper::UpdateFlags(DWORD flags) {
  21. startup_info_.startup_info()->dwFlags |= flags;
  22. }
  23. void StartupInformationHelper::SetDesktop(std::wstring desktop) {
  24. desktop_ = desktop;
  25. if (!desktop_.empty()) {
  26. startup_info_.startup_info()->lpDesktop =
  27. const_cast<wchar_t*>(desktop_.c_str());
  28. } else {
  29. startup_info_.startup_info()->lpDesktop = nullptr;
  30. }
  31. }
  32. void StartupInformationHelper::SetMitigations(MitigationFlags flags) {
  33. ConvertProcessMitigationsToPolicy(flags, &mitigations_[0],
  34. &mitigations_size_);
  35. ConvertProcessMitigationsToComponentFilter(flags, &component_filter_);
  36. }
  37. void StartupInformationHelper::SetRestrictChildProcessCreation(bool restrict) {
  38. DCHECK(base::win::GetVersion() >= base::win::Version::WIN10_TH2);
  39. restrict_child_process_creation_ = restrict;
  40. }
  41. void StartupInformationHelper::SetStdHandles(HANDLE stdout_handle,
  42. HANDLE stderr_handle) {
  43. stdout_handle_ = stdout_handle;
  44. AddInheritedHandle(stdout_handle);
  45. stderr_handle_ = stderr_handle;
  46. if (stderr_handle != stdout_handle)
  47. AddInheritedHandle(stderr_handle);
  48. }
  49. void StartupInformationHelper::AddInheritedHandle(HANDLE handle) {
  50. if (handle != INVALID_HANDLE_VALUE) {
  51. auto it = std::find(inherited_handle_list_.begin(),
  52. inherited_handle_list_.end(), handle);
  53. if (it == inherited_handle_list_.end())
  54. inherited_handle_list_.push_back(handle);
  55. }
  56. }
  57. void StartupInformationHelper::SetAppContainer(
  58. scoped_refptr<AppContainer> container) {
  59. // Only supported for Windows 8+.
  60. DCHECK(base::win::GetVersion() >= base::win::Version::WIN8);
  61. // LowPrivilegeAppContainer only supported for Windows 10+
  62. DCHECK(!container->GetEnableLowPrivilegeAppContainer() ||
  63. base::win::GetVersion() >= base::win::Version::WIN10_RS1);
  64. app_container_ = container;
  65. security_capabilities_ = app_container_->GetSecurityCapabilities();
  66. }
  67. void StartupInformationHelper::AddJobToAssociate(HANDLE job_handle) {
  68. job_handle_list_.push_back(job_handle);
  69. }
  70. int StartupInformationHelper::CountAttributes() {
  71. int attribute_count = 0;
  72. if (mitigations_[0] || mitigations_[1])
  73. ++attribute_count;
  74. if (component_filter_.ComponentFlags)
  75. ++attribute_count;
  76. if (restrict_child_process_creation_)
  77. ++attribute_count;
  78. if (!inherited_handle_list_.empty())
  79. ++attribute_count;
  80. if (app_container_ &&
  81. app_container_->GetAppContainerType() != AppContainerType::kLowbox) {
  82. ++attribute_count;
  83. if (app_container_->GetEnableLowPrivilegeAppContainer())
  84. ++attribute_count;
  85. }
  86. if (!job_handle_list_.empty())
  87. ++attribute_count;
  88. return attribute_count;
  89. }
  90. bool StartupInformationHelper::BuildStartupInformation() {
  91. // When adding new attributes, any memory referenced needs to have the
  92. // same lifetime as startup_info_. This is why we use members below.
  93. auto expected_attributes = CountAttributes();
  94. if (!startup_info_.InitializeProcThreadAttributeList(expected_attributes))
  95. return false;
  96. if (mitigations_[0] || mitigations_[1]) {
  97. if (!startup_info_.UpdateProcThreadAttribute(
  98. PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &mitigations_[0],
  99. mitigations_size_)) {
  100. return false;
  101. }
  102. expected_attributes--;
  103. }
  104. if (component_filter_.ComponentFlags) {
  105. if (!startup_info_.UpdateProcThreadAttribute(
  106. PROC_THREAD_ATTRIBUTE_COMPONENT_FILTER, &component_filter_,
  107. sizeof(component_filter_)) &&
  108. ::GetLastError() != ERROR_NOT_SUPPORTED) {
  109. return false;
  110. }
  111. expected_attributes--;
  112. }
  113. if (restrict_child_process_creation_) {
  114. child_process_creation_ = PROCESS_CREATION_CHILD_PROCESS_RESTRICTED;
  115. if (!startup_info_.UpdateProcThreadAttribute(
  116. PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY,
  117. &child_process_creation_, sizeof(child_process_creation_))) {
  118. return false;
  119. }
  120. expected_attributes--;
  121. }
  122. if (inherited_handle_list_.size()) {
  123. if (!startup_info_.UpdateProcThreadAttribute(
  124. PROC_THREAD_ATTRIBUTE_HANDLE_LIST, &inherited_handle_list_[0],
  125. sizeof(HANDLE) * inherited_handle_list_.size())) {
  126. return false;
  127. }
  128. startup_info_.startup_info()->dwFlags |= STARTF_USESTDHANDLES;
  129. startup_info_.startup_info()->hStdInput = INVALID_HANDLE_VALUE;
  130. startup_info_.startup_info()->hStdOutput = stdout_handle_;
  131. startup_info_.startup_info()->hStdError = stderr_handle_;
  132. // Allowing inheritance of handles is only secure now that we
  133. // have limited which handles will be inherited.
  134. inherit_handles_ = true;
  135. expected_attributes--;
  136. }
  137. if (!job_handle_list_.empty()) {
  138. if (!startup_info_.UpdateProcThreadAttribute(
  139. PROC_THREAD_ATTRIBUTE_JOB_LIST, &job_handle_list_[0],
  140. sizeof(HANDLE) * job_handle_list_.size())) {
  141. return false;
  142. }
  143. expected_attributes--;
  144. }
  145. if (app_container_ &&
  146. app_container_->GetAppContainerType() != AppContainerType::kLowbox) {
  147. if (!startup_info_.UpdateProcThreadAttribute(
  148. PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES,
  149. security_capabilities_.get(), sizeof(SECURITY_CAPABILITIES))) {
  150. return false;
  151. }
  152. expected_attributes--;
  153. if (app_container_->GetEnableLowPrivilegeAppContainer()) {
  154. all_applications_package_policy_ =
  155. PROCESS_CREATION_ALL_APPLICATION_PACKAGES_OPT_OUT;
  156. if (!startup_info_.UpdateProcThreadAttribute(
  157. PROC_THREAD_ATTRIBUTE_ALL_APPLICATION_PACKAGES_POLICY,
  158. &all_applications_package_policy_,
  159. sizeof(all_applications_package_policy_))) {
  160. return false;
  161. }
  162. expected_attributes--;
  163. }
  164. }
  165. CHECK(expected_attributes == 0);
  166. return true;
  167. }
  168. } // namespace sandbox