// Copyright 2019 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 SQL_SANDBOXED_VFS_FILE_H_ #define SQL_SANDBOXED_VFS_FILE_H_ #include "base/files/file.h" #include "base/files/file_path.h" #include "third_party/sqlite/sqlite3.h" namespace sql { class SandboxedVfs; // SQLite VFS file implementation that works in a sandboxed process. // // An instance is created when SQLite calls into SandboxedVfs::Open(). The // instance is deleted by a call to SandboxedVfsFile::Close(). // // The SQLite VFS API includes a complex locking strategy documented in // https://www.sqlite.org/lockingv3.html // // This implementation uses a simplified locking strategy, where we grab an // exclusive lock when entering any of the modes that prepare for a transition // to EXCLUSIVE. (These modes are RESERVED and PENDING). This approach is easy // to implement on top of base::File's locking primitives, at the cost of some // false contention, which makes us slower under high concurrency. // // SQLite's built-in VFSes use the OS support for locking a range of bytes in // the file, rather locking than the whole file. class SandboxedVfsFile { public: // Creates an instance in the given buffer. Note that `vfs` MUST outlive the // returned sqlite3_file object. static void Create(base::File file, base::FilePath file_path, SandboxedVfs* vfs, sqlite3_file& buffer); // Extracts the instance bridged to the given SQLite VFS file. static SandboxedVfsFile& FromSqliteFile(sqlite3_file& sqlite_file); // sqlite3_file implementation. int Close(); int Read(void* buffer, int size, sqlite3_int64 offset); int Write(const void* buffer, int size, sqlite3_int64 offset); int Truncate(sqlite3_int64 size); int Sync(int flags); int FileSize(sqlite3_int64* result_size); int Lock(int mode); int Unlock(int mode); int CheckReservedLock(int* has_reserved_lock); int FileControl(int opcode, void* data); int SectorSize(); int DeviceCharacteristics(); int ShmMap(int page_index, int page_size, int extend_file_if_needed, void volatile** result); int ShmLock(int offset, int size, int flags); void ShmBarrier(); int ShmUnmap(int also_delete_file); int Fetch(sqlite3_int64 offset, int size, void** result); int Unfetch(sqlite3_int64 offset, void* fetch_result); private: SandboxedVfsFile(base::File file, base::FilePath file_path, SandboxedVfs* vfs); ~SandboxedVfsFile(); // Constructed from a file handle passed from the browser process. base::File file_; // One of the SQLite locking mode constants. int sqlite_lock_mode_; // The SandboxedVfs that created this instance. SandboxedVfs* const vfs_; // Used to identify the file in IPCs to the browser process. const base::FilePath file_path_; }; // sqlite3_file "subclass" that bridges to a SandboxedVfsFile instance. struct SandboxedVfsFileSqliteBridge { sqlite3_file sqlite_file; SandboxedVfsFile* sandboxed_vfs_file; static SandboxedVfsFileSqliteBridge& FromSqliteFile( sqlite3_file& sqlite_file); }; } // namespace sql #endif // SQL_SANDBOXED_VFS_FILE_H_