Commit c44b59f5 authored by jochen@chromium.org's avatar jochen@chromium.org

Revert 245464 "Use an alternate mechanism for CreateFile calls i..."

ChromeCreateFileTest.CheckWriteAndReadParams crashes on Vista

> Use an alternate mechanism for CreateFile calls in Chrome
> 
> BUG=334379
> 
> Review URL: https://codereview.chromium.org/138593004

TBR=caitkp@chromium.org

Review URL: https://codereview.chromium.org/140783009

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@245501 0039d316-1c4b-4281-b951-d872f2087c98
parent 37f6edb3
...@@ -2478,13 +2478,6 @@ ...@@ -2478,13 +2478,6 @@
['enable_ipc_fuzzer==1', { ['enable_ipc_fuzzer==1', {
'defines': ['ENABLE_IPC_FUZZER=1'], 'defines': ['ENABLE_IPC_FUZZER=1'],
}], }],
['OS=="win" and component=="shared_library"', {
'dependencies': [
# All targets in a component build must depend on chrome_redirects,
# to ensure that certain calls go through it.
'<(DEPTH)/chrome_elf/chrome_elf.gyp:chrome_redirects',
],
}],
], # conditions for 'target_defaults' ], # conditions for 'target_defaults'
'target_conditions': [ 'target_conditions': [
['enable_wexit_time_destructors==1', { ['enable_wexit_time_destructors==1', {
......
...@@ -84,11 +84,6 @@ ...@@ -84,11 +84,6 @@
'../content/content.gyp:content_app_browser', '../content/content.gyp:content_app_browser',
], ],
'conditions': [ 'conditions': [
['OS=="win"', {
'dependencies': [
'<(DEPTH)/chrome_elf/chrome_elf.gyp:chrome_elf',
],
}],
['use_aura==1', { ['use_aura==1', {
'dependencies': [ 'dependencies': [
'../ui/compositor/compositor.gyp:compositor', '../ui/compositor/compositor.gyp:compositor',
...@@ -366,13 +361,6 @@ ...@@ -366,13 +361,6 @@
'app/chrome_main_delegate.cc', 'app/chrome_main_delegate.cc',
'app/chrome_main_delegate.h', 'app/chrome_main_delegate.h',
], ],
'conditions': [
['OS=="win"', {
'dependencies': [
'<(DEPTH)/chrome_elf/chrome_elf.gyp:chrome_elf',
],
}],
],
}, # target chrome_child_dll }, # target chrome_child_dll
], ],
}], }],
......
...@@ -512,7 +512,6 @@ ...@@ -512,7 +512,6 @@
'../base/base.gyp:base', '../base/base.gyp:base',
'../breakpad/breakpad.gyp:breakpad_handler', '../breakpad/breakpad.gyp:breakpad_handler',
'../breakpad/breakpad.gyp:breakpad_sender', '../breakpad/breakpad.gyp:breakpad_sender',
'../chrome_elf/chrome_elf.gyp:chrome_elf',
'../components/components.gyp:breakpad_component', '../components/components.gyp:breakpad_component',
'../components/components.gyp:policy', '../components/components.gyp:policy',
'../chrome_elf/chrome_elf.gyp:chrome_elf', '../chrome_elf/chrome_elf.gyp:chrome_elf',
......
...@@ -5,5 +5,4 @@ ...@@ -5,5 +5,4 @@
LIBRARY "chrome_elf.dll" LIBRARY "chrome_elf.dll"
EXPORTS EXPORTS
CreateFileW=chrome_redirects.CreateFileW
SignalChromeElf SignalChromeElf
...@@ -11,35 +11,6 @@ ...@@ -11,35 +11,6 @@
'blacklist.gypi', 'blacklist.gypi',
], ],
'targets': [ 'targets': [
{
'target_name': 'chrome_redirects',
'type': 'shared_library',
'include_dirs': [
'..',
],
'sources': [
'chrome_redirects.def',
],
'dependencies': [
'chrome_elf_lib',
],
'msvs_settings': {
'VCLinkerTool': {
'BaseAddress': '0x01c10000',
# Set /SUBSYSTEM:WINDOWS.
'SubSystem': '2',
},
},
'conditions': [
['component=="shared_library"', {
# In component builds, all targets depend on chrome_redirects by
# default. Remove it here to avoid a circular dependency.
'dependencies!': [
'../chrome_elf/chrome_elf.gyp:chrome_redirects',
],
}],
],
},
{ {
'target_name': 'chrome_elf', 'target_name': 'chrome_elf',
'type': 'shared_library', 'type': 'shared_library',
...@@ -54,12 +25,11 @@ ...@@ -54,12 +25,11 @@
'dependencies': [ 'dependencies': [
'blacklist', 'blacklist',
'chrome_elf_lib', 'chrome_elf_lib',
'chrome_redirects',
], ],
'msvs_settings': { 'msvs_settings': {
'VCLinkerTool': { 'VCLinkerTool': {
'BaseAddress': '0x01c20000', 'BaseAddress': '0x01c20000',
# Set /SUBSYSTEM:WINDOWS. # Set /SUBSYSTEM:WINDOWS for chrome_elf.dll (for consistency).
'SubSystem': '2', 'SubSystem': '2',
'AdditionalDependencies!': [ 'AdditionalDependencies!': [
'user32.lib', 'user32.lib',
...@@ -75,7 +45,6 @@ ...@@ -75,7 +45,6 @@
'type': 'executable', 'type': 'executable',
'sources': [ 'sources': [
'blacklist/test/blacklist_test.cc', 'blacklist/test/blacklist_test.cc',
'create_file/chrome_create_file_unittest.cc',
'elf_imports_unittest.cc', 'elf_imports_unittest.cc',
'ntdll_cache_unittest.cc', 'ntdll_cache_unittest.cc',
], ],
...@@ -104,23 +73,10 @@ ...@@ -104,23 +73,10 @@
'..', '..',
], ],
'sources': [ 'sources': [
'chrome_elf_constants.cc',
'chrome_elf_constants.h',
'chrome_elf_types.h', 'chrome_elf_types.h',
'create_file/chrome_create_file.cc',
'create_file/chrome_create_file.h',
'ntdll_cache.cc', 'ntdll_cache.cc',
'ntdll_cache.h', 'ntdll_cache.h',
], ],
'conditions': [
['component=="shared_library"', {
# In component builds, all targets depend on chrome_redirects by
# default. Remove it here to avoid a circular dependency.
'dependencies!': [
'../chrome_elf/chrome_elf.gyp:chrome_redirects',
],
}],
],
}, },
], ],
} }
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome_elf/chrome_elf_constants.h"
const wchar_t kUserDataDirName[] = L"User Data";
#if defined(GOOGLE_CHROME_BUILD)
const wchar_t kAppDataDirName[] = L"Google\\Chrome";
#else
const wchar_t kAppDataDirName[] = L"Chromium";
#endif
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// A handful of resource-like constants related to the ChromeELF.
#ifndef CHROME_ELF_CHROME_ELF_CONSTANTS_H_
#define CHROME_ELF_CHROME_ELF_CONSTANTS_H_
// directory names
extern const wchar_t kAppDataDirName[];
extern const wchar_t kUserDataDirName[];
#endif // CHROME_ELF_CHROME_ELF_CONSTANTS_H_
; Copyright 2014 The Chromium Authors. All rights reserved.
; Use of this source code is governed by a BSD-style license that can be
; found in the LICENSE file.
LIBRARY "chrome_redirects.dll"
EXPORTS
CreateFileW=CreateFileWRedirect
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome_elf/create_file/chrome_create_file.h"
#include <string>
#include "base/strings/string16.h"
#include "chrome_elf/chrome_elf_constants.h"
#include "chrome_elf/ntdll_cache.h"
#include "sandbox/win/src/nt_internals.h"
namespace {
// From ShlObj.h in the Windows SDK.
#define CSIDL_LOCAL_APPDATA 0x001c
typedef BOOL (WINAPI *PathIsUNCFunction)(
IN LPCWSTR path);
typedef BOOL (WINAPI *PathAppendFunction)(
IN LPWSTR path,
IN LPCWSTR more);
typedef BOOL (WINAPI *PathIsPrefixFunction)(
IN LPCWSTR prefix,
IN LPCWSTR path);
typedef HRESULT (WINAPI *SHGetFolderPathFunction)(
IN HWND hwnd_owner,
IN int folder,
IN HANDLE token,
IN DWORD flags,
OUT LPWSTR path);
PathIsUNCFunction g_path_is_unc_func;
PathAppendFunction g_path_append_func;
PathIsPrefixFunction g_path_is_prefix_func;
SHGetFolderPathFunction g_get_folder_func;
// Populates the g_*_func pointers to functions which will be used in
// ShouldBypass(). Chrome_elf cannot have a load-time dependency on shell32 or
// shlwapi as this would induce a load-time dependency on user32.dll. Instead,
// the addresses of the functions we need are retrieved the first time this
// method is called, and cached to avoid subsequent calls to GetProcAddress().
// It is assumed that the host process will never unload these functions.
// Returns true if all the functions needed are present.
bool PopulateShellFunctions() {
// Early exit if functions have already been populated.
if (g_path_is_unc_func && g_path_append_func &&
g_path_is_prefix_func && g_get_folder_func) {
return true;
}
// Get the addresses of the functions we need and store them for future use.
// These handles are intentionally leaked to ensure that these modules do not
// get unloaded.
HMODULE shell32 = ::LoadLibrary(L"shell32.dll");
HMODULE shlwapi = ::LoadLibrary(L"shlwapi.dll");
if (!shlwapi || !shell32)
return false;
g_path_is_unc_func = reinterpret_cast<PathIsUNCFunction>(
::GetProcAddress(shlwapi, "PathIsUNCW"));
g_path_append_func = reinterpret_cast<PathAppendFunction>(
::GetProcAddress(shlwapi, "PathAppendW"));
g_path_is_prefix_func = reinterpret_cast<PathIsPrefixFunction>(
::GetProcAddress(shlwapi, "PathIsPrefixW"));
g_get_folder_func = reinterpret_cast<SHGetFolderPathFunction>(
::GetProcAddress(shell32, "SHGetFolderPathW"));
return g_path_is_unc_func && g_path_append_func &&
g_path_is_prefix_func && g_get_folder_func;
}
} // namespace
HANDLE WINAPI CreateFileWRedirect(
LPCWSTR file_name,
DWORD desired_access,
DWORD share_mode,
LPSECURITY_ATTRIBUTES security_attributes,
DWORD creation_disposition,
DWORD flags_and_attributes,
HANDLE template_file) {
if (ShouldBypass(file_name)) {
return CreateFileNTDLL(file_name,
desired_access,
share_mode,
security_attributes,
creation_disposition,
flags_and_attributes,
template_file);
}
return CreateFile(file_name,
desired_access,
share_mode,
security_attributes,
creation_disposition,
flags_and_attributes,
template_file);
}
HANDLE CreateFileNTDLL(
LPCWSTR file_name,
DWORD desired_access,
DWORD share_mode,
LPSECURITY_ATTRIBUTES security_attributes,
DWORD creation_disposition,
DWORD flags_and_attributes,
HANDLE template_file) {
HANDLE file_handle = INVALID_HANDLE_VALUE;
NTSTATUS result = STATUS_UNSUCCESSFUL;
IO_STATUS_BLOCK io_status_block = {};
// Convert from Win32 domain to to NT creation disposition values.
switch (creation_disposition) {
case CREATE_NEW:
creation_disposition = FILE_CREATE;
break;
case CREATE_ALWAYS:
creation_disposition = FILE_OVERWRITE_IF;
break;
case OPEN_EXISTING:
creation_disposition = FILE_OPEN;
break;
case OPEN_ALWAYS:
creation_disposition = FILE_OPEN_IF;
break;
case TRUNCATE_EXISTING:
creation_disposition = FILE_OVERWRITE;
break;
default:
SetLastError(ERROR_INVALID_PARAMETER);
return INVALID_HANDLE_VALUE;
}
if (!g_ntdll_lookup["NtCreateFile"] ||
!g_ntdll_lookup["RtlInitUnicodeString"]) {
return INVALID_HANDLE_VALUE;
}
NtCreateFileFunction create_file =
reinterpret_cast<NtCreateFileFunction>(g_ntdll_lookup["NtCreateFile"]);
RtlInitUnicodeStringFunction init_unicode_string =
reinterpret_cast<RtlInitUnicodeStringFunction>(
g_ntdll_lookup["RtlInitUnicodeString"]);
UNICODE_STRING path_unicode_string;
// Format the path into an NT path. Arguably this should be done with
// RtlDosPathNameToNtPathName_U, but afaict this is equivalent for
// local paths. Using this with a UNC path name will almost certainly
// break in interesting ways.
base::string16 filename_string(L"\\??\\");
filename_string += file_name;
init_unicode_string(&path_unicode_string, filename_string.c_str());
OBJECT_ATTRIBUTES path_attributes = {};
InitializeObjectAttributes(&path_attributes,
&path_unicode_string,
OBJ_CASE_INSENSITIVE,
NULL, // No Root Directory
NULL); // No Security Descriptor
// Set create_options, desired_access, and flags_and_attributes to match those
// set by kernel32!CreateFile.
ULONG create_options = FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_ARCHIVE;
desired_access |= 0x100080;
flags_and_attributes &= 0x2FFA7;
result = create_file(&file_handle,
desired_access,
&path_attributes,
&io_status_block,
0, // Allocation size
flags_and_attributes,
share_mode,
creation_disposition,
create_options,
NULL,
0);
if (result != STATUS_SUCCESS) {
if (result == STATUS_OBJECT_NAME_COLLISION &&
creation_disposition == FILE_CREATE) {
SetLastError(ERROR_FILE_EXISTS);
}
return INVALID_HANDLE_VALUE;
}
if (creation_disposition == FILE_OPEN_IF) {
SetLastError(io_status_block.Information == FILE_OPENED ?
ERROR_ALREADY_EXISTS : ERROR_SUCCESS);
} else if (creation_disposition == FILE_OVERWRITE_IF) {
SetLastError(io_status_block.Information == FILE_OVERWRITTEN ?
ERROR_ALREADY_EXISTS : ERROR_SUCCESS);
} else {
SetLastError(ERROR_SUCCESS);
}
return file_handle;
}
bool ShouldBypass(LPCWSTR file_name) {
// If the shell functions are not present, forward the call to kernel32.
if (!PopulateShellFunctions())
return false;
// Forward all UNC filepaths to kernel32.
if (g_path_is_unc_func(file_name))
return false;
wchar_t local_appdata_path[MAX_PATH];
// Get the %LOCALAPPDATA% Path and append the location of our UserData
// directory to it.
HRESULT appdata_result = g_get_folder_func(
NULL, CSIDL_LOCAL_APPDATA, NULL, 0, local_appdata_path);
// If getting the %LOCALAPPDATA% path or appending to it failed, then forward
// the call to kernel32.
if (!SUCCEEDED(appdata_result) ||
!g_path_append_func(local_appdata_path, kAppDataDirName) ||
!g_path_append_func(local_appdata_path, kUserDataDirName)) {
return false;
}
// Check if we are trying to access something in the UserData dir. If so,
// then redirect the call to bypass kernel32.
return !!g_path_is_prefix_func(local_appdata_path, file_name);
}
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_ELF_CREATE_FILE_CHROME_CREATE_FILE_H_
#define CHROME_ELF_CREATE_FILE_CHROME_CREATE_FILE_H_
#include <windows.h>
#include "chrome_elf/chrome_elf_types.h"
// A CreateFileW replacement that will call NTCreateFile directly when the
// criteria defined in ShouldBypass() are satisfied for |lp_file_name|.
extern "C" HANDLE WINAPI CreateFileWRedirect(
LPCWSTR file_name,
DWORD desired_access,
DWORD share_mode,
LPSECURITY_ATTRIBUTES security_attributes,
DWORD creation_disposition,
DWORD flags_and_attributes,
HANDLE template_file);
// Partial reimplementation of kernel32!CreateFile (very partial: only handles
// reading and writing to files in the User Data directory).
HANDLE CreateFileNTDLL(
LPCWSTR file_name,
DWORD desired_access,
DWORD share_mode,
LPSECURITY_ATTRIBUTES security_attributes,
DWORD creation_disposition,
DWORD flags_and_attributes,
HANDLE template_file);
// Determines whether or not we should use our version of CreateFile, or the
// system version (only uses ours if we're writing to the user data directory).
bool ShouldBypass(LPCWSTR file_name);
#endif // CHROME_ELF_CREATE_FILE_CHROME_CREATE_FILE_H_
This diff is collapsed.
...@@ -25,7 +25,6 @@ typedef LONG NTSTATUS; ...@@ -25,7 +25,6 @@ typedef LONG NTSTATUS;
#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L) #define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L) #define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS)0xC0000034L) #define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS)0xC0000034L)
#define STATUS_OBJECT_NAME_COLLISION ((NTSTATUS)0xC0000035L)
#define STATUS_PROCEDURE_NOT_FOUND ((NTSTATUS)0xC000007AL) #define STATUS_PROCEDURE_NOT_FOUND ((NTSTATUS)0xC000007AL)
#define STATUS_INVALID_IMAGE_FORMAT ((NTSTATUS)0xC000007BL) #define STATUS_INVALID_IMAGE_FORMAT ((NTSTATUS)0xC000007BL)
#define STATUS_NO_TOKEN ((NTSTATUS)0xC000007CL) #define STATUS_NO_TOKEN ((NTSTATUS)0xC000007CL)
...@@ -126,15 +125,6 @@ typedef struct _IO_STATUS_BLOCK { ...@@ -126,15 +125,6 @@ typedef struct _IO_STATUS_BLOCK {
#define FILE_OPEN_NO_RECALL 0x00400000 #define FILE_OPEN_NO_RECALL 0x00400000
#define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000 #define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000
// Create/open result values. These are the disposition values returned on the
// io status information.
#define FILE_SUPERSEDED 0x00000000
#define FILE_OPENED 0x00000001
#define FILE_CREATED 0x00000002
#define FILE_OVERWRITTEN 0x00000003
#define FILE_EXISTS 0x00000004
#define FILE_DOES_NOT_EXIST 0x00000005
typedef NTSTATUS (WINAPI *NtCreateFileFunction)( typedef NTSTATUS (WINAPI *NtCreateFileFunction)(
OUT PHANDLE FileHandle, OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess, IN ACCESS_MASK DesiredAccess,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment