OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome_frame/module_utils.h" | 5 #include "chrome_frame/module_utils.h" |
6 | 6 |
7 #include <aclapi.h> | |
7 #include <atlbase.h> | 8 #include <atlbase.h> |
9 #include <atlsecurity.h> | |
10 #include <sddl.h> | |
11 | |
8 #include "base/file_path.h" | 12 #include "base/file_path.h" |
9 #include "base/file_version_info.h" | 13 #include "base/file_version_info.h" |
10 #include "base/logging.h" | 14 #include "base/logging.h" |
11 #include "base/path_service.h" | 15 #include "base/path_service.h" |
12 #include "base/shared_memory.h" | 16 #include "base/shared_memory.h" |
17 #include "base/sys_info.h" | |
13 #include "base/utf_string_conversions.h" | 18 #include "base/utf_string_conversions.h" |
14 #include "base/version.h" | 19 #include "base/version.h" |
20 #include "chrome_frame/utils.h" | |
15 | 21 |
16 const char kSharedMemoryName[] = "ChromeFrameVersionBeacon"; | 22 const wchar_t kSharedMemoryName[] = L"ChromeFrameVersionBeacon_"; |
17 const uint32 kSharedMemorySize = 128; | 23 const uint32 kSharedMemorySize = 128; |
18 const uint32 kSharedMemoryLockTimeoutMs = 1000; | 24 const uint32 kSharedMemoryLockTimeoutMs = 1000; |
19 | 25 |
20 // static | 26 // static |
21 DllRedirector::DllRedirector() : first_module_handle_(NULL) { | 27 DllRedirector::DllRedirector() : first_module_handle_(NULL) { |
22 // TODO(robertshield): Correctly construct the profile name here. Also allow | 28 // TODO(robertshield): Allow for overrides to be taken from the environment. |
23 // for overrides to be taken from the environment. | 29 std::wstring beacon_name(kSharedMemoryName); |
24 shared_memory_.reset(new base::SharedMemory(ASCIIToWide(kSharedMemoryName))); | 30 beacon_name += GetHostProcessName(false); |
31 shared_memory_.reset(new base::SharedMemory(beacon_name)); | |
25 } | 32 } |
26 | 33 |
27 DllRedirector::DllRedirector(const char* shared_memory_name) | 34 DllRedirector::DllRedirector(const char* shared_memory_name) |
28 : shared_memory_name_(shared_memory_name), first_module_handle_(NULL) { | 35 : shared_memory_name_(shared_memory_name), first_module_handle_(NULL) { |
29 // TODO(robertshield): Correctly construct the profile name here. Also allow | |
30 // for overrides to be taken from the environment. | |
31 shared_memory_.reset(new base::SharedMemory(ASCIIToWide(shared_memory_name))); | 36 shared_memory_.reset(new base::SharedMemory(ASCIIToWide(shared_memory_name))); |
32 } | 37 } |
33 | 38 |
34 DllRedirector::~DllRedirector() { | 39 DllRedirector::~DllRedirector() { |
35 if (first_module_handle_) { | 40 if (first_module_handle_) { |
36 if (first_module_handle_ != reinterpret_cast<HMODULE>(&__ImageBase)) { | 41 if (first_module_handle_ != reinterpret_cast<HMODULE>(&__ImageBase)) { |
37 FreeLibrary(first_module_handle_); | 42 FreeLibrary(first_module_handle_); |
38 } | 43 } |
39 first_module_handle_ = NULL; | 44 first_module_handle_ = NULL; |
40 } | 45 } |
41 UnregisterAsFirstCFModule(); | 46 UnregisterAsFirstCFModule(); |
42 } | 47 } |
43 | 48 |
49 bool DllRedirector::GetLockSecurityAttributes(CSecurityAttributes* sec_attr) { | |
tommi (sloooow) - chröme
2010/11/15 19:33:30
change name to "BuildSecurityAttributesForLock" or
robertshield
2010/11/15 20:32:18
Done.
| |
50 DCHECK(sec_attr); | |
51 int32 major_version, minor_version, fix_version; | |
52 base::SysInfo::OperatingSystemVersionNumbers(&major_version, | |
53 &minor_version, | |
54 &fix_version); | |
55 if (major_version < 6) { | |
56 // Don't bother with changing ACLs on pre-vista. | |
57 return false; | |
58 } | |
59 | |
60 bool success = false; | |
61 | |
62 // Fill out the rest of the security descriptor from the process token. | |
63 CAccessToken token; | |
64 if (token.GetProcessToken(TOKEN_QUERY)) { | |
65 CSecurityDesc security_desc; | |
66 if (security_desc.FromString(L"S:(ML;;NW;;;LW)")) { | |
tommi (sloooow) - chröme
2010/11/15 19:33:30
Add a comment that explains what the string means
robertshield
2010/11/15 20:32:18
Done.
| |
67 CSid sid_owner; | |
68 if (token.GetOwner(&sid_owner)) { | |
69 security_desc.SetOwner(sid_owner); | |
70 } else { | |
71 NOTREACHED() << "Could not set owner."; | |
tommi (sloooow) - chröme
2010/11/15 19:33:30
set -> get
robertshield
2010/11/15 20:32:18
Done.
| |
72 } | |
73 CSid sid_group; | |
74 if (token.GetPrimaryGroup(&sid_group)) { | |
75 security_desc.SetGroup(sid_group); | |
76 } else { | |
77 NOTREACHED() << "Could not set group."; | |
tommi (sloooow) - chröme
2010/11/15 19:33:30
set -> get
robertshield
2010/11/15 20:32:18
Done.
| |
78 } | |
79 CDacl dacl; | |
80 if (token.GetDefaultDacl(&dacl)) { | |
81 // Add an access control entry mask for the current user. | |
82 // This is what grants this user access from lower integrity levels. | |
83 CSid sid_user; | |
84 if (token.GetUser(&sid_user)) { | |
85 success = dacl.AddAllowedAce(sid_user, MUTEX_ALL_ACCESS); | |
86 security_desc.SetDacl(dacl); | |
87 sec_attr->Set(security_desc); | |
88 } | |
89 } | |
90 } | |
91 } | |
92 | |
93 return success; | |
94 } | |
95 | |
96 bool DllRedirector::SetFileMappingToReadOnly(base::SharedMemoryHandle mapping) { | |
97 bool success = false; | |
98 | |
99 CAccessToken token; | |
100 if (token.GetProcessToken(TOKEN_QUERY)) { | |
101 CSid sid_user; | |
102 if (token.GetUser(&sid_user)) { | |
103 CDacl dacl; | |
104 dacl.AddAllowedAce(sid_user, STANDARD_RIGHTS_READ | FILE_MAP_READ); | |
105 success = AtlSetDacl(mapping, SE_KERNEL_OBJECT, dacl); | |
106 } | |
107 } | |
108 | |
109 return success; | |
110 } | |
111 | |
112 | |
44 bool DllRedirector::RegisterAsFirstCFModule() { | 113 bool DllRedirector::RegisterAsFirstCFModule() { |
45 DCHECK(first_module_handle_ == NULL); | 114 DCHECK(first_module_handle_ == NULL); |
46 | 115 |
47 // Build our own file version outside of the lock: | 116 // Build our own file version outside of the lock: |
48 scoped_ptr<Version> our_version(GetCurrentModuleVersion()); | 117 scoped_ptr<Version> our_version(GetCurrentModuleVersion()); |
49 | 118 |
50 // We sadly can't use the autolock here since we want to have a timeout. | 119 // We sadly can't use the autolock here since we want to have a timeout. |
51 // Be careful not to return while holding the lock. Also, attempt to do as | 120 // Be careful not to return while holding the lock. Also, attempt to do as |
52 // little as possible while under this lock. | 121 // little as possible while under this lock. |
53 bool lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs); | 122 |
123 bool lock_acquired = false; | |
124 CSecurityAttributes sec_attr; | |
125 if (GetLockSecurityAttributes(&sec_attr)) { | |
126 lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs, &sec_attr); | |
127 } else { | |
128 lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs, NULL); | |
129 } | |
54 | 130 |
55 if (!lock_acquired) { | 131 if (!lock_acquired) { |
56 // We couldn't get the lock in a reasonable amount of time, so fall | 132 // We couldn't get the lock in a reasonable amount of time, so fall |
57 // back to loading our current version. We return true to indicate that the | 133 // back to loading our current version. We return true to indicate that the |
58 // caller should not attempt to delegate to an already loaded version. | 134 // caller should not attempt to delegate to an already loaded version. |
59 dll_version_.swap(our_version); | 135 dll_version_.swap(our_version); |
60 first_module_handle_ = reinterpret_cast<HMODULE>(&__ImageBase); | 136 first_module_handle_ = reinterpret_cast<HMODULE>(&__ImageBase); |
61 return true; | 137 return true; |
62 } | 138 } |
63 | 139 |
64 bool created_beacon = true; | 140 bool created_beacon = true; |
65 bool result = shared_memory_->CreateNamed(shared_memory_name_.c_str(), | 141 bool result = shared_memory_->CreateNamed(shared_memory_name_.c_str(), |
66 false, // open_existing | 142 false, // open_existing |
67 kSharedMemorySize); | 143 kSharedMemorySize); |
68 | 144 |
69 if (!result) { | 145 if (result) { |
146 // We created the beacon, now we need to mutate the security attributes | |
147 // on the shared memory to allow read-only access and let low-integrity | |
148 // processes open it. | |
149 bool acls_set = SetFileMappingToReadOnly(shared_memory_->handle()); | |
150 DCHECK(acls_set); | |
151 } else { | |
70 created_beacon = false; | 152 created_beacon = false; |
71 | 153 |
72 // We failed to create the shared memory segment, suggesting it may already | 154 // We failed to create the shared memory segment, suggesting it may already |
73 // exist: try to create it read-only. | 155 // exist: try to create it read-only. |
74 result = shared_memory_->Open(shared_memory_name_.c_str(), | 156 result = shared_memory_->Open(shared_memory_name_.c_str(), |
75 true /* read_only */); | 157 true /* read_only */); |
76 } | 158 } |
77 | 159 |
78 if (result) { | 160 if (result) { |
79 // Map in the whole thing. | 161 // Map in the whole thing. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
116 } | 198 } |
117 | 199 |
118 // Matching Unlock. | 200 // Matching Unlock. |
119 shared_memory_->Unlock(); | 201 shared_memory_->Unlock(); |
120 | 202 |
121 return created_beacon; | 203 return created_beacon; |
122 } | 204 } |
123 | 205 |
124 void DllRedirector::UnregisterAsFirstCFModule() { | 206 void DllRedirector::UnregisterAsFirstCFModule() { |
125 if (base::SharedMemory::IsHandleValid(shared_memory_->handle())) { | 207 if (base::SharedMemory::IsHandleValid(shared_memory_->handle())) { |
126 bool lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs); | 208 bool lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs, NULL); |
127 if (lock_acquired) { | 209 if (lock_acquired) { |
128 // Free our handles. The last closed handle SHOULD result in it being | 210 // Free our handles. The last closed handle SHOULD result in it being |
129 // deleted. | 211 // deleted. |
130 shared_memory_->Close(); | 212 shared_memory_->Close(); |
131 shared_memory_->Unlock(); | 213 shared_memory_->Unlock(); |
132 } | 214 } |
133 } | 215 } |
134 } | 216 } |
135 | 217 |
136 LPFNGETCLASSOBJECT DllRedirector::GetDllGetClassObjectPtr() { | 218 LPFNGETCLASSOBJECT DllRedirector::GetDllGetClassObjectPtr() { |
137 HMODULE first_module_handle = GetFirstModule(); | 219 HMODULE first_module_handle = GetFirstModule(); |
138 | 220 |
139 LPFNGETCLASSOBJECT proc_ptr = reinterpret_cast<LPFNGETCLASSOBJECT>( | 221 LPFNGETCLASSOBJECT proc_ptr = reinterpret_cast<LPFNGETCLASSOBJECT>( |
140 GetProcAddress(first_module_handle, "DllGetClassObject")); | 222 GetProcAddress(first_module_handle, "DllGetClassObject")); |
141 if (!proc_ptr) { | 223 if (!proc_ptr) { |
142 DLOG(ERROR) << "DllRedirector: Could get address of DllGetClassObject " | 224 DPLOG(ERROR) << "DllRedirector: Could get address of DllGetClassObject " |
143 "from first loaded module, GLE: " | 225 "from first loaded module, GLE: "; |
tommi (sloooow) - chröme
2010/11/15 19:33:30
remove ", GLE: "
robertshield
2010/11/15 20:32:18
Done.
| |
144 << GetLastError(); | |
145 // Oh boink, the first module we loaded was somehow bogus, make ourselves | 226 // Oh boink, the first module we loaded was somehow bogus, make ourselves |
146 // the first module again. | 227 // the first module again. |
147 first_module_handle = reinterpret_cast<HMODULE>(&__ImageBase); | 228 first_module_handle = reinterpret_cast<HMODULE>(&__ImageBase); |
148 } | 229 } |
149 return proc_ptr; | 230 return proc_ptr; |
150 } | 231 } |
151 | 232 |
152 Version* DllRedirector::GetCurrentModuleVersion() { | 233 Version* DllRedirector::GetCurrentModuleVersion() { |
153 scoped_ptr<FileVersionInfo> file_version_info( | 234 scoped_ptr<FileVersionInfo> file_version_info( |
154 FileVersionInfo::CreateFileVersionInfoForCurrentModule()); | 235 FileVersionInfo::CreateFileVersionInfoForCurrentModule()); |
(...skipping 30 matching lines...) Expand all Loading... | |
185 PathService::Get(base::DIR_MODULE, &module_path); | 266 PathService::Get(base::DIR_MODULE, &module_path); |
186 DCHECK(!module_path.empty()); | 267 DCHECK(!module_path.empty()); |
187 | 268 |
188 FilePath module_name = module_path.BaseName(); | 269 FilePath module_name = module_path.BaseName(); |
189 module_path = module_path.DirName() | 270 module_path = module_path.DirName() |
190 .Append(ASCIIToWide(version->GetString())) | 271 .Append(ASCIIToWide(version->GetString())) |
191 .Append(module_name); | 272 .Append(module_name); |
192 | 273 |
193 HMODULE hmodule = LoadLibrary(module_path.value().c_str()); | 274 HMODULE hmodule = LoadLibrary(module_path.value().c_str()); |
194 if (hmodule == NULL) { | 275 if (hmodule == NULL) { |
195 DLOG(ERROR) << "Could not load reported module version " | 276 DPLOG(ERROR) << "Could not load reported module version " |
196 << version->GetString(); | 277 << version->GetString(); |
197 } | 278 } |
198 | 279 |
199 return hmodule; | 280 return hmodule; |
200 } | 281 } |
201 | 282 |
OLD | NEW |