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 std::wstring
& name
,
24 std::wstring
* 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
= {
45 {IPC_NTCREATEKEY_TAG
, WCHAR_TYPE
, ULONG_TYPE
, VOIDPTR_TYPE
, ULONG_TYPE
,
46 ULONG_TYPE
, ULONG_TYPE
},
47 reinterpret_cast<CallbackGeneric
>(&RegistryDispatcher::NtCreateKey
)
50 static const IPCCall open_params
= {
51 {IPC_NTOPENKEY_TAG
, WCHAR_TYPE
, ULONG_TYPE
, VOIDPTR_TYPE
, ULONG_TYPE
},
52 reinterpret_cast<CallbackGeneric
>(&RegistryDispatcher::NtOpenKey
)
55 ipc_calls_
.push_back(create_params
);
56 ipc_calls_
.push_back(open_params
);
59 bool RegistryDispatcher::SetupService(InterceptionManager
* manager
,
61 if (IPC_NTCREATEKEY_TAG
== service
)
62 return INTERCEPT_NT(manager
, NtCreateKey
, CREATE_KEY_ID
, 32);
64 if (IPC_NTOPENKEY_TAG
== service
) {
65 bool result
= INTERCEPT_NT(manager
, NtOpenKey
, OPEN_KEY_ID
, 16);
66 if (base::win::GetVersion() >= base::win::VERSION_WIN7
)
67 result
&= INTERCEPT_NT(manager
, NtOpenKeyEx
, OPEN_KEY_EX_ID
, 20);
74 bool RegistryDispatcher::NtCreateKey(
75 IPCInfo
* ipc
, std::wstring
* name
, DWORD attributes
, HANDLE root
,
76 DWORD desired_access
, DWORD title_index
, DWORD create_options
) {
77 base::win::ScopedHandle root_handle
;
78 std::wstring real_path
= *name
;
80 // If there is a root directory, we need to duplicate the handle to make
81 // it valid in this process.
83 if (!::DuplicateHandle(ipc
->client_info
->process
, root
,
84 ::GetCurrentProcess(), &root
, 0, FALSE
,
85 DUPLICATE_SAME_ACCESS
))
88 root_handle
.Set(root
);
91 if (!GetCompletePath(root
, *name
, &real_path
))
94 const wchar_t* regname
= real_path
.c_str();
95 CountedParameterSet
<OpenKey
> params
;
96 params
[OpenKey::NAME
] = ParamPickerMake(regname
);
97 params
[OpenKey::ACCESS
] = ParamPickerMake(desired_access
);
99 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTCREATEKEY_TAG
,
104 ULONG disposition
= 0;
105 if (!RegistryPolicy::CreateKeyAction(result
, *ipc
->client_info
, *name
,
106 attributes
, root
, desired_access
,
107 title_index
, create_options
, &handle
,
108 &nt_status
, &disposition
)) {
109 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
113 // Return operation status on the IPC.
114 ipc
->return_info
.extended
[0].unsigned_int
= disposition
;
115 ipc
->return_info
.nt_status
= nt_status
;
116 ipc
->return_info
.handle
= handle
;
120 bool RegistryDispatcher::NtOpenKey(IPCInfo
* ipc
, std::wstring
* name
,
121 DWORD attributes
, HANDLE root
,
122 DWORD desired_access
) {
123 base::win::ScopedHandle root_handle
;
124 std::wstring real_path
= *name
;
126 // If there is a root directory, we need to duplicate the handle to make
127 // it valid in this process.
129 if (!::DuplicateHandle(ipc
->client_info
->process
, root
,
130 ::GetCurrentProcess(), &root
, 0, FALSE
,
131 DUPLICATE_SAME_ACCESS
))
133 root_handle
.Set(root
);
136 if (!GetCompletePath(root
, *name
, &real_path
))
139 const wchar_t* regname
= real_path
.c_str();
140 CountedParameterSet
<OpenKey
> params
;
141 params
[OpenKey::NAME
] = ParamPickerMake(regname
);
142 params
[OpenKey::ACCESS
] = ParamPickerMake(desired_access
);
144 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTOPENKEY_TAG
,
148 if (!RegistryPolicy::OpenKeyAction(result
, *ipc
->client_info
, *name
,
149 attributes
, root
, desired_access
, &handle
,
151 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
155 // Return operation status on the IPC.
156 ipc
->return_info
.nt_status
= nt_status
;
157 ipc
->return_info
.handle
= handle
;
161 } // namespace sandbox