sandboxed_vfs_file.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef SQL_SANDBOXED_VFS_FILE_H_
  5. #define SQL_SANDBOXED_VFS_FILE_H_
  6. #include "base/files/file.h"
  7. #include "base/files/file_path.h"
  8. #include "base/memory/raw_ptr.h"
  9. #include "base/memory/raw_ptr_exclusion.h"
  10. #include "third_party/sqlite/sqlite3.h"
  11. namespace sql {
  12. // The file types associated with a SQLite database.
  13. enum class SandboxedVfsFileType {
  14. // The main file, which stores the database pages.
  15. kDatabase,
  16. // The transaction rollback journal file. Used when WAL is off.
  17. // This file has the same path as the database, plus the "-journal" suffix.
  18. kJournal,
  19. // The Write-Ahead Log (WAL) file.
  20. // This file has the same path as the database, plus the "-wal" suffix.
  21. kWal,
  22. };
  23. class SandboxedVfs;
  24. // SQLite VFS file implementation that works in a sandboxed process.
  25. //
  26. // An instance is created when SQLite calls into SandboxedVfs::Open(). The
  27. // instance is deleted by a call to SandboxedVfsFile::Close().
  28. //
  29. // The SQLite VFS API includes a complex locking strategy documented in
  30. // https://www.sqlite.org/lockingv3.html
  31. //
  32. // This implementation uses a simplified locking strategy, where we grab an
  33. // exclusive lock when entering any of the modes that prepare for a transition
  34. // to EXCLUSIVE. (These modes are RESERVED and PENDING). This approach is easy
  35. // to implement on top of base::File's locking primitives, at the cost of some
  36. // false contention, which makes us slower under high concurrency.
  37. //
  38. // SQLite's built-in VFSes use the OS support for locking a range of bytes in
  39. // the file, rather locking than the whole file.
  40. class SandboxedVfsFile {
  41. public:
  42. // Creates an instance in the given buffer. Note that `vfs` MUST outlive the
  43. // returned sqlite3_file object.
  44. static void Create(base::File file,
  45. base::FilePath file_path,
  46. #if DCHECK_IS_ON()
  47. SandboxedVfsFileType file_type,
  48. #endif // DCHECK_IS_ON()
  49. SandboxedVfs* vfs,
  50. sqlite3_file& buffer);
  51. // Extracts the instance bridged to the given SQLite VFS file.
  52. static SandboxedVfsFile& FromSqliteFile(sqlite3_file& sqlite_file);
  53. // sqlite3_file implementation.
  54. int Close();
  55. int Read(void* buffer, int size, sqlite3_int64 offset);
  56. int Write(const void* buffer, int size, sqlite3_int64 offset);
  57. int Truncate(sqlite3_int64 size);
  58. int Sync(int flags);
  59. int FileSize(sqlite3_int64* result_size);
  60. int Lock(int mode);
  61. int Unlock(int mode);
  62. int CheckReservedLock(int* has_reserved_lock);
  63. int FileControl(int opcode, void* data);
  64. int SectorSize();
  65. int DeviceCharacteristics();
  66. int ShmMap(int page_index,
  67. int page_size,
  68. int extend_file_if_needed,
  69. void volatile** result);
  70. int ShmLock(int offset, int size, int flags);
  71. void ShmBarrier();
  72. int ShmUnmap(int also_delete_file);
  73. int Fetch(sqlite3_int64 offset, int size, void** result);
  74. int Unfetch(sqlite3_int64 offset, void* fetch_result);
  75. private:
  76. SandboxedVfsFile(base::File file,
  77. base::FilePath file_path,
  78. #if DCHECK_IS_ON()
  79. SandboxedVfsFileType file_type,
  80. #endif // DCHECK_IS_ON()
  81. SandboxedVfs* vfs);
  82. ~SandboxedVfsFile();
  83. // Constructed from a file handle passed from the browser process.
  84. base::File file_;
  85. // One of the SQLite locking mode constants.
  86. int sqlite_lock_mode_;
  87. // The SandboxedVfs that created this instance.
  88. const raw_ptr<SandboxedVfs> vfs_;
  89. #if DCHECK_IS_ON()
  90. // Tracked to check assumptions about SQLite's locking protocol.
  91. const SandboxedVfsFileType file_type_;
  92. #endif // DCHECK_IS_ON()
  93. // Used to identify the file in IPCs to the browser process.
  94. const base::FilePath file_path_;
  95. };
  96. // sqlite3_file "subclass" that bridges to a SandboxedVfsFile instance.
  97. struct SandboxedVfsFileSqliteBridge {
  98. sqlite3_file sqlite_file;
  99. // `sandboxed_vfs_file` is not a raw_ptr<SandboxedVfsFile>, because
  100. // reinterpret_cast of uninitialized memory to raw_ptr can cause ref-counting
  101. // mismatch.
  102. RAW_PTR_EXCLUSION SandboxedVfsFile* sandboxed_vfs_file;
  103. static SandboxedVfsFileSqliteBridge& FromSqliteFile(
  104. sqlite3_file& sqlite_file);
  105. };
  106. } // namespace sql
  107. #endif // SQL_SANDBOXED_VFS_FILE_H_