1 // Copyright (c) 2011 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.
5 #include "sandbox/win/src/registry_dispatcher.h"
7 #include "base/win/scoped_handle.h"
8 #include "base/win/windows_version.h"
9 #include "sandbox/win/src/crosscall_client.h"
10 #include "sandbox/win/src/interception.h"
11 #include "sandbox/win/src/interceptors.h"
12 #include "sandbox/win/src/ipc_tags.h"
13 #include "sandbox/win/src/sandbox_nt_util.h"
14 #include "sandbox/win/src/policy_broker.h"
15 #include "sandbox/win/src/policy_params.h"
16 #include "sandbox/win/src/sandbox.h"
17 #include "sandbox/win/src/registry_interception.h"
18 #include "sandbox/win/src/registry_policy.h"
22 // Builds a path using the root directory and the name.
23 bool GetCompletePath(HANDLE root
, const base::string16
& name
,
24 base::string16
* complete_name
) {
26 if (!sandbox::GetPathFromHandle(root
, complete_name
))
29 *complete_name
+= L
"\\";
30 *complete_name
+= name
;
32 *complete_name
= name
;
42 RegistryDispatcher::RegistryDispatcher(PolicyBase
* policy_base
)
43 : policy_base_(policy_base
) {
44 static const IPCCall create_params
= {
52 reinterpret_cast<CallbackGeneric
>(&RegistryDispatcher::NtCreateKey
)};
54 static const IPCCall open_params
= {
55 {IPC_NTOPENKEY_TAG
, {WCHAR_TYPE
, UINT32_TYPE
, VOIDPTR_TYPE
, UINT32_TYPE
}},
56 reinterpret_cast<CallbackGeneric
>(&RegistryDispatcher::NtOpenKey
)};
58 ipc_calls_
.push_back(create_params
);
59 ipc_calls_
.push_back(open_params
);
62 bool RegistryDispatcher::SetupService(InterceptionManager
* manager
,
64 if (IPC_NTCREATEKEY_TAG
== service
)
65 return INTERCEPT_NT(manager
, NtCreateKey
, CREATE_KEY_ID
, 32);
67 if (IPC_NTOPENKEY_TAG
== service
) {
68 bool result
= INTERCEPT_NT(manager
, NtOpenKey
, OPEN_KEY_ID
, 16);
69 if (base::win::GetVersion() >= base::win::VERSION_WIN7
||
70 (base::win::GetVersion() == base::win::VERSION_VISTA
&&
71 base::win::OSInfo::GetInstance()->version_type() ==
72 base::win::SUITE_SERVER
))
73 result
&= INTERCEPT_NT(manager
, NtOpenKeyEx
, OPEN_KEY_EX_ID
, 20);
80 bool RegistryDispatcher::NtCreateKey(IPCInfo
* ipc
,
84 uint32 desired_access
,
86 uint32 create_options
) {
87 base::win::ScopedHandle root_handle
;
88 base::string16 real_path
= *name
;
90 // If there is a root directory, we need to duplicate the handle to make
91 // it valid in this process.
93 if (!::DuplicateHandle(ipc
->client_info
->process
, root
,
94 ::GetCurrentProcess(), &root
, 0, FALSE
,
95 DUPLICATE_SAME_ACCESS
))
98 root_handle
.Set(root
);
101 if (!GetCompletePath(root
, *name
, &real_path
))
104 const wchar_t* regname
= real_path
.c_str();
105 CountedParameterSet
<OpenKey
> params
;
106 params
[OpenKey::NAME
] = ParamPickerMake(regname
);
107 params
[OpenKey::ACCESS
] = ParamPickerMake(desired_access
);
109 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTCREATEKEY_TAG
,
114 ULONG disposition
= 0;
115 if (!RegistryPolicy::CreateKeyAction(result
, *ipc
->client_info
, *name
,
116 attributes
, root
, desired_access
,
117 title_index
, create_options
, &handle
,
118 &nt_status
, &disposition
)) {
119 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
123 // Return operation status on the IPC.
124 ipc
->return_info
.extended
[0].unsigned_int
= disposition
;
125 ipc
->return_info
.nt_status
= nt_status
;
126 ipc
->return_info
.handle
= handle
;
130 bool RegistryDispatcher::NtOpenKey(IPCInfo
* ipc
,
131 base::string16
* name
,
134 uint32 desired_access
) {
135 base::win::ScopedHandle root_handle
;
136 base::string16 real_path
= *name
;
138 // If there is a root directory, we need to duplicate the handle to make
139 // it valid in this process.
141 if (!::DuplicateHandle(ipc
->client_info
->process
, root
,
142 ::GetCurrentProcess(), &root
, 0, FALSE
,
143 DUPLICATE_SAME_ACCESS
))
145 root_handle
.Set(root
);
148 if (!GetCompletePath(root
, *name
, &real_path
))
151 const wchar_t* regname
= real_path
.c_str();
152 CountedParameterSet
<OpenKey
> params
;
153 params
[OpenKey::NAME
] = ParamPickerMake(regname
);
154 params
[OpenKey::ACCESS
] = ParamPickerMake(desired_access
);
156 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTOPENKEY_TAG
,
160 if (!RegistryPolicy::OpenKeyAction(result
, *ipc
->client_info
, *name
,
161 attributes
, root
, desired_access
, &handle
,
163 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
167 // Return operation status on the IPC.
168 ipc
->return_info
.nt_status
= nt_status
;
169 ipc
->return_info
.handle
= handle
;
173 } // namespace sandbox