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