1 // Copyright (c) 2006-2008 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/registry_interception.h"
6
7 #include <stdint.h>
8
9 #include "sandbox/win/src/crosscall_client.h"
10 #include "sandbox/win/src/ipc_tags.h"
11 #include "sandbox/win/src/policy_params.h"
12 #include "sandbox/win/src/policy_target.h"
13 #include "sandbox/win/src/sandbox_factory.h"
14 #include "sandbox/win/src/sandbox_nt_util.h"
15 #include "sandbox/win/src/sharedmem_ipc_client.h"
16 #include "sandbox/win/src/target_services.h"
17 #include "mozilla/sandboxing/sandboxLogging.h"
18
19 namespace sandbox {
20
TargetNtCreateKey(NtCreateKeyFunction orig_CreateKey,PHANDLE key,ACCESS_MASK desired_access,POBJECT_ATTRIBUTES object_attributes,ULONG title_index,PUNICODE_STRING class_name,ULONG create_options,PULONG disposition)21 NTSTATUS WINAPI TargetNtCreateKey(NtCreateKeyFunction orig_CreateKey,
22 PHANDLE key, ACCESS_MASK desired_access,
23 POBJECT_ATTRIBUTES object_attributes,
24 ULONG title_index, PUNICODE_STRING class_name,
25 ULONG create_options, PULONG disposition) {
26 // Check if the process can create it first.
27 NTSTATUS status = orig_CreateKey(key, desired_access, object_attributes,
28 title_index, class_name, create_options,
29 disposition);
30 if (NT_SUCCESS(status))
31 return status;
32
33 if (STATUS_OBJECT_NAME_NOT_FOUND != status) {
34 mozilla::sandboxing::LogBlocked("NtCreateKey",
35 object_attributes->ObjectName->Buffer,
36 object_attributes->ObjectName->Length);
37 }
38
39 // We don't trust that the IPC can work this early.
40 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
41 return status;
42
43 do {
44 if (!ValidParameter(key, sizeof(HANDLE), WRITE))
45 break;
46
47 if (disposition && !ValidParameter(disposition, sizeof(ULONG), WRITE))
48 break;
49
50 // At this point we don't support class_name.
51 if (class_name && class_name->Buffer && class_name->Length)
52 break;
53
54 // We don't support creating link keys, volatile keys and backup/restore.
55 if (create_options)
56 break;
57
58 void* memory = GetGlobalIPCMemory();
59 if (NULL == memory)
60 break;
61
62 wchar_t* name;
63 uint32_t attributes = 0;
64 HANDLE root_directory = 0;
65 NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes,
66 &root_directory);
67 if (!NT_SUCCESS(ret) || NULL == name)
68 break;
69
70 uint32_t desired_access_uint32 = desired_access;
71 CountedParameterSet<OpenKey> params;
72 params[OpenKey::ACCESS] = ParamPickerMake(desired_access_uint32);
73
74 wchar_t* full_name = NULL;
75
76 if (root_directory) {
77 ret = sandbox::AllocAndGetFullPath(root_directory, name, &full_name);
78 if (!NT_SUCCESS(ret) || NULL == full_name)
79 break;
80 params[OpenKey::NAME] = ParamPickerMake(full_name);
81 } else {
82 params[OpenKey::NAME] = ParamPickerMake(name);
83 }
84
85 bool query_broker = QueryBroker(IPC_NTCREATEKEY_TAG, params.GetBase());
86
87 if (full_name != NULL)
88 operator delete(full_name, NT_ALLOC);
89
90 if (!query_broker)
91 break;
92
93 SharedMemIPCClient ipc(memory);
94 CrossCallReturn answer = {0};
95
96 ResultCode code = CrossCall(ipc, IPC_NTCREATEKEY_TAG, name, attributes,
97 root_directory, desired_access, title_index,
98 create_options, &answer);
99
100 operator delete(name, NT_ALLOC);
101
102 if (SBOX_ALL_OK != code)
103 break;
104
105 if (!NT_SUCCESS(answer.nt_status))
106 // TODO(nsylvain): We should return answer.nt_status here instead
107 // of status. We can do this only after we checked the policy.
108 // otherwise we will returns ACCESS_DENIED for all paths
109 // that are not specified by a policy, even though your token allows
110 // access to that path, and the original call had a more meaningful
111 // error. Bug 4369
112 break;
113
114 __try {
115 *key = answer.handle;
116
117 if (disposition)
118 *disposition = answer.extended[0].unsigned_int;
119
120 status = answer.nt_status;
121 } __except(EXCEPTION_EXECUTE_HANDLER) {
122 break;
123 }
124 mozilla::sandboxing::LogAllowed("NtCreateKey",
125 object_attributes->ObjectName->Buffer,
126 object_attributes->ObjectName->Length);
127 } while (false);
128
129 return status;
130 }
131
CommonNtOpenKey(NTSTATUS status,PHANDLE key,ACCESS_MASK desired_access,POBJECT_ATTRIBUTES object_attributes)132 NTSTATUS WINAPI CommonNtOpenKey(NTSTATUS status, PHANDLE key,
133 ACCESS_MASK desired_access,
134 POBJECT_ATTRIBUTES object_attributes) {
135 // We don't trust that the IPC can work this early.
136 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
137 return status;
138
139 do {
140 if (!ValidParameter(key, sizeof(HANDLE), WRITE))
141 break;
142
143 void* memory = GetGlobalIPCMemory();
144 if (NULL == memory)
145 break;
146
147 wchar_t* name;
148 uint32_t attributes;
149 HANDLE root_directory;
150 NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes,
151 &root_directory);
152 if (!NT_SUCCESS(ret) || NULL == name)
153 break;
154
155 uint32_t desired_access_uint32 = desired_access;
156 CountedParameterSet<OpenKey> params;
157 params[OpenKey::ACCESS] = ParamPickerMake(desired_access_uint32);
158
159 wchar_t* full_name = NULL;
160
161 if (root_directory) {
162 ret = sandbox::AllocAndGetFullPath(root_directory, name, &full_name);
163 if (!NT_SUCCESS(ret) || NULL == full_name)
164 break;
165 params[OpenKey::NAME] = ParamPickerMake(full_name);
166 } else {
167 params[OpenKey::NAME] = ParamPickerMake(name);
168 }
169
170 bool query_broker = QueryBroker(IPC_NTOPENKEY_TAG, params.GetBase());
171
172 if (full_name != NULL)
173 operator delete(full_name, NT_ALLOC);
174
175 if (!query_broker)
176 break;
177
178 SharedMemIPCClient ipc(memory);
179 CrossCallReturn answer = {0};
180 ResultCode code = CrossCall(ipc, IPC_NTOPENKEY_TAG, name, attributes,
181 root_directory, desired_access, &answer);
182
183 operator delete(name, NT_ALLOC);
184
185 if (SBOX_ALL_OK != code)
186 break;
187
188 if (!NT_SUCCESS(answer.nt_status))
189 // TODO(nsylvain): We should return answer.nt_status here instead
190 // of status. We can do this only after we checked the policy.
191 // otherwise we will returns ACCESS_DENIED for all paths
192 // that are not specified by a policy, even though your token allows
193 // access to that path, and the original call had a more meaningful
194 // error. Bug 4369
195 break;
196
197 __try {
198 *key = answer.handle;
199 status = answer.nt_status;
200 } __except(EXCEPTION_EXECUTE_HANDLER) {
201 break;
202 }
203 mozilla::sandboxing::LogAllowed("NtOpenKey[Ex]",
204 object_attributes->ObjectName->Buffer,
205 object_attributes->ObjectName->Length);
206 } while (false);
207
208 return status;
209 }
210
TargetNtOpenKey(NtOpenKeyFunction orig_OpenKey,PHANDLE key,ACCESS_MASK desired_access,POBJECT_ATTRIBUTES object_attributes)211 NTSTATUS WINAPI TargetNtOpenKey(NtOpenKeyFunction orig_OpenKey, PHANDLE key,
212 ACCESS_MASK desired_access,
213 POBJECT_ATTRIBUTES object_attributes) {
214 // Check if the process can open it first.
215 NTSTATUS status = orig_OpenKey(key, desired_access, object_attributes);
216 if (NT_SUCCESS(status))
217 return status;
218
219 if (STATUS_OBJECT_NAME_NOT_FOUND != status) {
220 mozilla::sandboxing::LogBlocked("NtOpenKey",
221 object_attributes->ObjectName->Buffer,
222 object_attributes->ObjectName->Length);
223 }
224
225 return CommonNtOpenKey(status, key, desired_access, object_attributes);
226 }
227
TargetNtOpenKeyEx(NtOpenKeyExFunction orig_OpenKeyEx,PHANDLE key,ACCESS_MASK desired_access,POBJECT_ATTRIBUTES object_attributes,ULONG open_options)228 NTSTATUS WINAPI TargetNtOpenKeyEx(NtOpenKeyExFunction orig_OpenKeyEx,
229 PHANDLE key, ACCESS_MASK desired_access,
230 POBJECT_ATTRIBUTES object_attributes,
231 ULONG open_options) {
232 // Check if the process can open it first.
233 NTSTATUS status = orig_OpenKeyEx(key, desired_access, object_attributes,
234 open_options);
235
236 // We do not support open_options at this time. The 2 current known values
237 // are REG_OPTION_CREATE_LINK, to open a symbolic link, and
238 // REG_OPTION_BACKUP_RESTORE to open the key with special privileges.
239 if (NT_SUCCESS(status) || open_options != 0)
240 return status;
241
242 if (STATUS_OBJECT_NAME_NOT_FOUND != status) {
243 mozilla::sandboxing::LogBlocked("NtOpenKeyEx",
244 object_attributes->ObjectName->Buffer,
245 object_attributes->ObjectName->Length);
246 }
247
248 return CommonNtOpenKey(status, key, desired_access, object_attributes);
249 }
250
251 } // namespace sandbox
252