chrome_create_file.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome_elf/create_file/chrome_create_file.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <string> 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string16.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome_elf/chrome_elf_constants.h" 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome_elf/chrome_elf_util.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome_elf/ntdll_cache.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "sandbox/win/src/nt_internals.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// From ShlObj.h in the Windows SDK. 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define CSIDL_LOCAL_APPDATA 0x001c 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef BOOL (WINAPI *PathIsUNCFunction)( 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IN LPCWSTR path); 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef BOOL (WINAPI *PathAppendFunction)( 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IN LPWSTR path, 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IN LPCWSTR more); 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef BOOL (WINAPI *PathIsPrefixFunction)( 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IN LPCWSTR prefix, 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IN LPCWSTR path); 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef LPCWSTR (WINAPI *PathFindFileName)( 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IN LPCWSTR path); 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef HRESULT (WINAPI *SHGetFolderPathFunction)( 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IN HWND hwnd_owner, 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IN int folder, 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IN HANDLE token, 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IN DWORD flags, 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OUT LPWSTR path); 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PathIsUNCFunction g_path_is_unc_func; 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PathAppendFunction g_path_append_func; 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PathIsPrefixFunction g_path_is_prefix_func; 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PathFindFileName g_path_find_filename_func; 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SHGetFolderPathFunction g_get_folder_func; 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Record the number of calls we've redirected so far. 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int g_redirect_count = 0; 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Populates the g_*_func pointers to functions which will be used in 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// ShouldBypass(). Chrome_elf cannot have a load-time dependency on shell32 or 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// shlwapi as this would induce a load-time dependency on user32.dll. Instead, 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// the addresses of the functions we need are retrieved the first time this 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// method is called, and cached to avoid subsequent calls to GetProcAddress(). 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// It is assumed that the host process will never unload these functions. 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Returns true if all the functions needed are present. 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool PopulateShellFunctions() { 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Early exit if functions have already been populated. 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (g_path_is_unc_func && g_path_append_func && 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) g_path_is_prefix_func && g_get_folder_func) { 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Get the addresses of the functions we need and store them for future use. 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // These handles are intentionally leaked to ensure that these modules do not 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // get unloaded. 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HMODULE shell32 = ::LoadLibrary(L"shell32.dll"); 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HMODULE shlwapi = ::LoadLibrary(L"shlwapi.dll"); 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!shlwapi || !shell32) 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) g_path_is_unc_func = reinterpret_cast<PathIsUNCFunction>( 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ::GetProcAddress(shlwapi, "PathIsUNCW")); 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) g_path_append_func = reinterpret_cast<PathAppendFunction>( 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ::GetProcAddress(shlwapi, "PathAppendW")); 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) g_path_is_prefix_func = reinterpret_cast<PathIsPrefixFunction>( 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ::GetProcAddress(shlwapi, "PathIsPrefixW")); 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) g_path_find_filename_func = reinterpret_cast<PathFindFileName>( 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ::GetProcAddress(shlwapi, "PathFindFileNameW")); 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) g_get_folder_func = reinterpret_cast<SHGetFolderPathFunction>( 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ::GetProcAddress(shell32, "SHGetFolderPathW")); 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return g_path_is_unc_func && g_path_append_func && g_path_is_prefix_func && 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) g_path_find_filename_func && g_get_folder_func; 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Turn off optimization to make sure these calls don't get inlined. 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#pragma optimize("", off) 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Wrapper method for kernel32!CreateFile, to avoid setting off caller 93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// mitigation detectors. 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)HANDLE CreateFileWImpl(LPCWSTR file_name, 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DWORD desired_access, 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DWORD share_mode, 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LPSECURITY_ATTRIBUTES security_attributes, 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DWORD creation_disposition, 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DWORD flags_and_attributes, 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) HANDLE template_file) { 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return CreateFile(file_name, 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) desired_access, 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) share_mode, 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) security_attributes, 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) creation_disposition, 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) flags_and_attributes, 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) template_file); 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)HANDLE WINAPI CreateFileWRedirect( 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LPCWSTR file_name, 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DWORD desired_access, 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DWORD share_mode, 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LPSECURITY_ATTRIBUTES security_attributes, 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DWORD creation_disposition, 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DWORD flags_and_attributes, 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HANDLE template_file) { 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (ShouldBypass(file_name)) { 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ++g_redirect_count; 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return CreateFileNTDLL(file_name, 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) desired_access, 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) share_mode, 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) security_attributes, 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) creation_disposition, 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flags_and_attributes, 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) template_file); 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return CreateFileWImpl(file_name, 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) desired_access, 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) share_mode, 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) security_attributes, 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) creation_disposition, 134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) flags_and_attributes, 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) template_file); 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#pragma optimize("", on) 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int GetRedirectCount() { 140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return g_redirect_count; 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)HANDLE CreateFileNTDLL( 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LPCWSTR file_name, 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DWORD desired_access, 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DWORD share_mode, 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LPSECURITY_ATTRIBUTES security_attributes, 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DWORD creation_disposition, 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DWORD flags_and_attributes, 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HANDLE template_file) { 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HANDLE file_handle = INVALID_HANDLE_VALUE; 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NTSTATUS result = STATUS_UNSUCCESSFUL; 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IO_STATUS_BLOCK io_status_block = {}; 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ULONG flags = 0; 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Convert from Win32 domain to to NT creation disposition values. 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) switch (creation_disposition) { 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case CREATE_NEW: 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) creation_disposition = FILE_CREATE; 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case CREATE_ALWAYS: 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) creation_disposition = FILE_OVERWRITE_IF; 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case OPEN_EXISTING: 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) creation_disposition = FILE_OPEN; 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case OPEN_ALWAYS: 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) creation_disposition = FILE_OPEN_IF; 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case TRUNCATE_EXISTING: 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) creation_disposition = FILE_OVERWRITE; 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default: 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetLastError(ERROR_INVALID_PARAMETER); 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return INVALID_HANDLE_VALUE; 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Translate the flags that need no validation: 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!(flags_and_attributes & FILE_FLAG_OVERLAPPED)) 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flags |= FILE_SYNCHRONOUS_IO_NONALERT; 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (flags_and_attributes & FILE_FLAG_WRITE_THROUGH) 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flags |= FILE_WRITE_THROUGH; 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (flags_and_attributes & FILE_FLAG_RANDOM_ACCESS) 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flags |= FILE_RANDOM_ACCESS; 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (flags_and_attributes & FILE_FLAG_SEQUENTIAL_SCAN) 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flags |= FILE_SEQUENTIAL_ONLY; 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (flags_and_attributes & FILE_FLAG_DELETE_ON_CLOSE) { 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flags |= FILE_DELETE_ON_CLOSE; 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) desired_access |= DELETE; 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (flags_and_attributes & FILE_FLAG_BACKUP_SEMANTICS) 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flags |= FILE_OPEN_FOR_BACKUP_INTENT; 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flags |= FILE_NON_DIRECTORY_FILE; 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (flags_and_attributes & FILE_FLAG_OPEN_REPARSE_POINT) 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flags |= FILE_OPEN_REPARSE_POINT; 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (flags_and_attributes & FILE_FLAG_OPEN_NO_RECALL) 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flags |= FILE_OPEN_NO_RECALL; 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!g_ntdll_lookup["NtCreateFile"] || 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !g_ntdll_lookup["RtlInitUnicodeString"]) { 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return INVALID_HANDLE_VALUE; 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NtCreateFileFunction create_file = 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reinterpret_cast<NtCreateFileFunction>(g_ntdll_lookup["NtCreateFile"]); 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RtlInitUnicodeStringFunction init_unicode_string = 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reinterpret_cast<RtlInitUnicodeStringFunction>( 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) g_ntdll_lookup["RtlInitUnicodeString"]); 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UNICODE_STRING path_unicode_string; 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Format the path into an NT path. Arguably this should be done with 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // RtlDosPathNameToNtPathName_U, but afaict this is equivalent for 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // local paths. Using this with a UNC path name will almost certainly 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // break in interesting ways. 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 filename_string(L"\\??\\"); 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) filename_string += file_name; 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) init_unicode_string(&path_unicode_string, filename_string.c_str()); 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OBJECT_ATTRIBUTES path_attributes = {}; 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InitializeObjectAttributes(&path_attributes, 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &path_unicode_string, 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OBJ_CASE_INSENSITIVE, 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, // No Root Directory 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL); // No Security Descriptor 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Set desired_access, and flags_and_attributes to match those 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // set by kernel32!CreateFile. 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) desired_access |= 0x100080; 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flags_and_attributes &= 0x2FFA7; 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result = create_file(&file_handle, 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) desired_access, 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &path_attributes, 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &io_status_block, 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 0, // Allocation size 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flags_and_attributes, 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) share_mode, 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) creation_disposition, 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flags, 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 0); 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (result != STATUS_SUCCESS) { 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (result == STATUS_OBJECT_NAME_COLLISION && 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) creation_disposition == FILE_CREATE) { 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetLastError(ERROR_FILE_EXISTS); 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return INVALID_HANDLE_VALUE; 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (creation_disposition == FILE_OPEN_IF) { 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetLastError(io_status_block.Information == FILE_OPENED ? 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ERROR_ALREADY_EXISTS : ERROR_SUCCESS); 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else if (creation_disposition == FILE_OVERWRITE_IF) { 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetLastError(io_status_block.Information == FILE_OVERWRITTEN ? 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ERROR_ALREADY_EXISTS : ERROR_SUCCESS); 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetLastError(ERROR_SUCCESS); 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return file_handle; 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ShouldBypass(LPCWSTR file_path) { 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Do not redirect in non-browser processes. 278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (IsNonBrowserProcess()) 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If the shell functions are not present, forward the call to kernel32. 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!PopulateShellFunctions()) 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Forward all UNC filepaths to kernel32. 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (g_path_is_unc_func(file_path)) 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) wchar_t local_appdata_path[MAX_PATH]; 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Get the %LOCALAPPDATA% Path and append the location of our UserData 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // directory to it. 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HRESULT appdata_result = g_get_folder_func( 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, CSIDL_LOCAL_APPDATA, NULL, 0, local_appdata_path); 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) wchar_t buffer[MAX_PATH] = {}; 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!GetModuleFileNameW(NULL, buffer, MAX_PATH)) 2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool is_canary = IsCanary(buffer); 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If getting the %LOCALAPPDATA% path or appending to it failed, then forward 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the call to kernel32. 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!SUCCEEDED(appdata_result) || 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !g_path_append_func(local_appdata_path, is_canary ? 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kCanaryAppDataDirName : kAppDataDirName) || 3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !g_path_append_func(local_appdata_path, kUserDataDirName)) { 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LPCWSTR file_name = g_path_find_filename_func(file_path); 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool in_userdata_dir = !!g_path_is_prefix_func(local_appdata_path, file_path); 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool is_settings_file = wcscmp(file_name, kPreferencesFilename) == 0 || 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) wcscmp(file_name, kLocalStateFilename) == 0; 3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Check if we are trying to access the Preferences in the UserData dir. If 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // so, then redirect the call to bypass kernel32. 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return in_userdata_dir && is_settings_file; 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 321