Index: chrome_frame/module_utils.cc |
=================================================================== |
--- chrome_frame/module_utils.cc (revision 65236) |
+++ chrome_frame/module_utils.cc (working copy) |
@@ -4,30 +4,35 @@ |
#include "chrome_frame/module_utils.h" |
+#include <aclapi.h> |
#include <atlbase.h> |
+#include <atlsecurity.h> |
+#include <sddl.h> |
+ |
#include "base/file_path.h" |
#include "base/file_version_info.h" |
#include "base/logging.h" |
#include "base/path_service.h" |
#include "base/shared_memory.h" |
+#include "base/sys_info.h" |
#include "base/utf_string_conversions.h" |
#include "base/version.h" |
+#include "chrome_frame/utils.h" |
-const char kSharedMemoryName[] = "ChromeFrameVersionBeacon"; |
+const wchar_t kSharedMemoryName[] = L"ChromeFrameVersionBeacon_"; |
const uint32 kSharedMemorySize = 128; |
const uint32 kSharedMemoryLockTimeoutMs = 1000; |
// static |
DllRedirector::DllRedirector() : first_module_handle_(NULL) { |
- // TODO(robertshield): Correctly construct the profile name here. Also allow |
- // for overrides to be taken from the environment. |
- shared_memory_.reset(new base::SharedMemory(ASCIIToWide(kSharedMemoryName))); |
+ // TODO(robertshield): Allow for overrides to be taken from the environment. |
+ std::wstring beacon_name(kSharedMemoryName); |
+ beacon_name += GetHostProcessName(false); |
+ shared_memory_.reset(new base::SharedMemory(beacon_name)); |
} |
DllRedirector::DllRedirector(const char* shared_memory_name) |
: shared_memory_name_(shared_memory_name), first_module_handle_(NULL) { |
- // TODO(robertshield): Correctly construct the profile name here. Also allow |
- // for overrides to be taken from the environment. |
shared_memory_.reset(new base::SharedMemory(ASCIIToWide(shared_memory_name))); |
} |
@@ -41,6 +46,70 @@ |
UnregisterAsFirstCFModule(); |
} |
+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.
|
+ DCHECK(sec_attr); |
+ int32 major_version, minor_version, fix_version; |
+ base::SysInfo::OperatingSystemVersionNumbers(&major_version, |
+ &minor_version, |
+ &fix_version); |
+ if (major_version < 6) { |
+ // Don't bother with changing ACLs on pre-vista. |
+ return false; |
+ } |
+ |
+ bool success = false; |
+ |
+ // Fill out the rest of the security descriptor from the process token. |
+ CAccessToken token; |
+ if (token.GetProcessToken(TOKEN_QUERY)) { |
+ CSecurityDesc security_desc; |
+ 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.
|
+ CSid sid_owner; |
+ if (token.GetOwner(&sid_owner)) { |
+ security_desc.SetOwner(sid_owner); |
+ } else { |
+ 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.
|
+ } |
+ CSid sid_group; |
+ if (token.GetPrimaryGroup(&sid_group)) { |
+ security_desc.SetGroup(sid_group); |
+ } else { |
+ 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.
|
+ } |
+ CDacl dacl; |
+ if (token.GetDefaultDacl(&dacl)) { |
+ // Add an access control entry mask for the current user. |
+ // This is what grants this user access from lower integrity levels. |
+ CSid sid_user; |
+ if (token.GetUser(&sid_user)) { |
+ success = dacl.AddAllowedAce(sid_user, MUTEX_ALL_ACCESS); |
+ security_desc.SetDacl(dacl); |
+ sec_attr->Set(security_desc); |
+ } |
+ } |
+ } |
+ } |
+ |
+ return success; |
+} |
+ |
+bool DllRedirector::SetFileMappingToReadOnly(base::SharedMemoryHandle mapping) { |
+ bool success = false; |
+ |
+ CAccessToken token; |
+ if (token.GetProcessToken(TOKEN_QUERY)) { |
+ CSid sid_user; |
+ if (token.GetUser(&sid_user)) { |
+ CDacl dacl; |
+ dacl.AddAllowedAce(sid_user, STANDARD_RIGHTS_READ | FILE_MAP_READ); |
+ success = AtlSetDacl(mapping, SE_KERNEL_OBJECT, dacl); |
+ } |
+ } |
+ |
+ return success; |
+} |
+ |
+ |
bool DllRedirector::RegisterAsFirstCFModule() { |
DCHECK(first_module_handle_ == NULL); |
@@ -50,8 +119,15 @@ |
// We sadly can't use the autolock here since we want to have a timeout. |
// Be careful not to return while holding the lock. Also, attempt to do as |
// little as possible while under this lock. |
- bool lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs); |
+ bool lock_acquired = false; |
+ CSecurityAttributes sec_attr; |
+ if (GetLockSecurityAttributes(&sec_attr)) { |
+ lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs, &sec_attr); |
+ } else { |
+ lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs, NULL); |
+ } |
+ |
if (!lock_acquired) { |
// We couldn't get the lock in a reasonable amount of time, so fall |
// back to loading our current version. We return true to indicate that the |
@@ -66,7 +142,13 @@ |
false, // open_existing |
kSharedMemorySize); |
- if (!result) { |
+ if (result) { |
+ // We created the beacon, now we need to mutate the security attributes |
+ // on the shared memory to allow read-only access and let low-integrity |
+ // processes open it. |
+ bool acls_set = SetFileMappingToReadOnly(shared_memory_->handle()); |
+ DCHECK(acls_set); |
+ } else { |
created_beacon = false; |
// We failed to create the shared memory segment, suggesting it may already |
@@ -123,7 +205,7 @@ |
void DllRedirector::UnregisterAsFirstCFModule() { |
if (base::SharedMemory::IsHandleValid(shared_memory_->handle())) { |
- bool lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs); |
+ bool lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs, NULL); |
if (lock_acquired) { |
// Free our handles. The last closed handle SHOULD result in it being |
// deleted. |
@@ -139,9 +221,8 @@ |
LPFNGETCLASSOBJECT proc_ptr = reinterpret_cast<LPFNGETCLASSOBJECT>( |
GetProcAddress(first_module_handle, "DllGetClassObject")); |
if (!proc_ptr) { |
- DLOG(ERROR) << "DllRedirector: Could get address of DllGetClassObject " |
- "from first loaded module, GLE: " |
- << GetLastError(); |
+ DPLOG(ERROR) << "DllRedirector: Could get address of DllGetClassObject " |
+ "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.
|
// Oh boink, the first module we loaded was somehow bogus, make ourselves |
// the first module again. |
first_module_handle = reinterpret_cast<HMODULE>(&__ImageBase); |
@@ -192,8 +273,8 @@ |
HMODULE hmodule = LoadLibrary(module_path.value().c_str()); |
if (hmodule == NULL) { |
- DLOG(ERROR) << "Could not load reported module version " |
- << version->GetString(); |
+ DPLOG(ERROR) << "Could not load reported module version " |
+ << version->GetString(); |
} |
return hmodule; |