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