sandboxed_vfs_file.cc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  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. #include "sql/sandboxed_vfs_file.h"
  5. #include <atomic>
  6. #include <cstring>
  7. #include <type_traits>
  8. #include <utility>
  9. #include "base/check_op.h"
  10. #include "base/files/file.h"
  11. #include "base/files/file_path.h"
  12. #include "base/logging.h"
  13. #include "base/notreached.h"
  14. #include "base/threading/platform_thread.h"
  15. #include "build/build_config.h"
  16. #include "sql/initialization.h"
  17. #include "sql/sandboxed_vfs.h"
  18. #include "third_party/sqlite/sqlite3.h"
  19. namespace sql {
  20. namespace {
  21. int SandboxedClose(sqlite3_file* file) {
  22. return SandboxedVfsFile::FromSqliteFile(*file).Close();
  23. }
  24. int SandboxedRead(sqlite3_file* file,
  25. void* buffer,
  26. int size,
  27. sqlite3_int64 offset) {
  28. return SandboxedVfsFile::FromSqliteFile(*file).Read(buffer, size, offset);
  29. }
  30. int SandboxedWrite(sqlite3_file* file,
  31. const void* buffer,
  32. int size,
  33. sqlite3_int64 offset) {
  34. return SandboxedVfsFile::FromSqliteFile(*file).Write(buffer, size, offset);
  35. }
  36. int SandboxedTruncate(sqlite3_file* file, sqlite3_int64 size) {
  37. return SandboxedVfsFile::FromSqliteFile(*file).Truncate(size);
  38. }
  39. int SandboxedSync(sqlite3_file* file, int flags) {
  40. return SandboxedVfsFile::FromSqliteFile(*file).Sync(flags);
  41. }
  42. int SandboxedFileSize(sqlite3_file* file, sqlite3_int64* result_size) {
  43. return SandboxedVfsFile::FromSqliteFile(*file).FileSize(result_size);
  44. }
  45. int SandboxedLock(sqlite3_file* file, int mode) {
  46. return SandboxedVfsFile::FromSqliteFile(*file).Lock(mode);
  47. }
  48. int SandboxedUnlock(sqlite3_file* file, int mode) {
  49. return SandboxedVfsFile::FromSqliteFile(*file).Unlock(mode);
  50. }
  51. int SandboxedCheckReservedLock(sqlite3_file* file, int* has_reserved_lock) {
  52. return SandboxedVfsFile::FromSqliteFile(*file).CheckReservedLock(
  53. has_reserved_lock);
  54. }
  55. int SandboxedFileControl(sqlite3_file* file, int opcode, void* data) {
  56. return SandboxedVfsFile::FromSqliteFile(*file).FileControl(opcode, data);
  57. }
  58. int SandboxedSectorSize(sqlite3_file* file) {
  59. return SandboxedVfsFile::FromSqliteFile(*file).SectorSize();
  60. }
  61. int SandboxedDeviceCharacteristics(sqlite3_file* file) {
  62. return SandboxedVfsFile::FromSqliteFile(*file).DeviceCharacteristics();
  63. }
  64. int SandboxedShmMap(sqlite3_file* file,
  65. int page_index,
  66. int page_size,
  67. int extend_file_if_needed,
  68. void volatile** result) {
  69. return SandboxedVfsFile::FromSqliteFile(*file).ShmMap(
  70. page_index, page_size, extend_file_if_needed, result);
  71. }
  72. int SandboxedShmLock(sqlite3_file* file, int offset, int size, int flags) {
  73. return SandboxedVfsFile::FromSqliteFile(*file).ShmLock(offset, size, flags);
  74. }
  75. void SandboxedShmBarrier(sqlite3_file* file) {
  76. SandboxedVfsFile::FromSqliteFile(*file).ShmBarrier();
  77. }
  78. int SandboxedShmUnmap(sqlite3_file* file, int also_delete_file) {
  79. return SandboxedVfsFile::FromSqliteFile(*file).ShmUnmap(also_delete_file);
  80. }
  81. int SandboxedFetch(sqlite3_file* file,
  82. sqlite3_int64 offset,
  83. int size,
  84. void** result) {
  85. return SandboxedVfsFile::FromSqliteFile(*file).Fetch(offset, size, result);
  86. }
  87. int SandboxedUnfetch(sqlite3_file* file,
  88. sqlite3_int64 offset,
  89. void* fetch_result) {
  90. return SandboxedVfsFile::FromSqliteFile(*file).Unfetch(offset, fetch_result);
  91. }
  92. const sqlite3_io_methods* GetSqliteIoMethods() {
  93. // VFS IO API entry points are listed at
  94. // https://www.sqlite.org/c3ref/io_methods.html
  95. static constexpr int kSqliteVfsIoApiVersion = 3;
  96. static const sqlite3_io_methods kIoMethods = {
  97. kSqliteVfsIoApiVersion,
  98. SandboxedClose,
  99. SandboxedRead,
  100. SandboxedWrite,
  101. SandboxedTruncate,
  102. SandboxedSync,
  103. SandboxedFileSize,
  104. SandboxedLock,
  105. SandboxedUnlock,
  106. SandboxedCheckReservedLock,
  107. SandboxedFileControl,
  108. SandboxedSectorSize,
  109. SandboxedDeviceCharacteristics,
  110. SandboxedShmMap,
  111. SandboxedShmLock,
  112. SandboxedShmBarrier,
  113. SandboxedShmUnmap,
  114. SandboxedFetch,
  115. SandboxedUnfetch,
  116. };
  117. return &kIoMethods;
  118. }
  119. } // namespace
  120. // static
  121. void SandboxedVfsFile::Create(base::File file,
  122. base::FilePath file_path,
  123. #if DCHECK_IS_ON()
  124. SandboxedVfsFileType file_type,
  125. #endif // DCHECK_IS_ON()
  126. SandboxedVfs* vfs,
  127. sqlite3_file& buffer) {
  128. SandboxedVfsFileSqliteBridge& bridge =
  129. SandboxedVfsFileSqliteBridge::FromSqliteFile(buffer);
  130. bridge.sandboxed_vfs_file =
  131. new SandboxedVfsFile(std::move(file), std::move(file_path),
  132. #if DCHECK_IS_ON()
  133. file_type,
  134. #endif // DCHECK_IS_ON()
  135. vfs);
  136. bridge.sqlite_file.pMethods = GetSqliteIoMethods();
  137. }
  138. // static
  139. SandboxedVfsFile& SandboxedVfsFile::FromSqliteFile(sqlite3_file& sqlite_file) {
  140. return *SandboxedVfsFileSqliteBridge::FromSqliteFile(sqlite_file)
  141. .sandboxed_vfs_file;
  142. }
  143. int SandboxedVfsFile::Close() {
  144. file_.Close();
  145. delete this;
  146. return SQLITE_OK;
  147. }
  148. int SandboxedVfsFile::Read(void* buffer, int size, sqlite3_int64 offset) {
  149. DCHECK(buffer);
  150. DCHECK_GE(size, 0);
  151. DCHECK_GE(offset, 0);
  152. #if DCHECK_IS_ON()
  153. // See http://www.sqlite.org/fileformat2.html#database_header
  154. constexpr int kSqliteDatabaseHeaderOffset = 0;
  155. constexpr int kSqliteDatabaseHeaderSize = 100;
  156. // SQLite's locking protocol only acquires locks on the database file. The
  157. // journal and the WAL file are always unlocked. Also, as an optimization,
  158. // SQLite first reads the database header without locking the file.
  159. DCHECK(sqlite_lock_mode_ > SQLITE_LOCK_NONE ||
  160. file_type_ != SandboxedVfsFileType::kDatabase ||
  161. (offset == kSqliteDatabaseHeaderOffset &&
  162. size == kSqliteDatabaseHeaderSize))
  163. << "Read from database file with lock mode " << sqlite_lock_mode_
  164. << "of size" << size << " at offset " << offset;
  165. #endif // DCHECK_IS_ON()
  166. char* data = reinterpret_cast<char*>(buffer);
  167. // If we supported mmap()ed files, we'd check for a memory mapping here,
  168. // and try to fill as much of the request as possible from the mmap()ed
  169. // region.
  170. int bytes_read = file_.Read(offset, data, size);
  171. DCHECK_LE(bytes_read, size);
  172. if (bytes_read == size)
  173. return SQLITE_OK;
  174. if (bytes_read < 0) {
  175. // SQLite first reads the database header without locking the file. On
  176. // Windows, this read will fail if there is an exclusive lock on the file,
  177. // even if the current process owns that lock.
  178. if (sqlite_lock_mode_ == SQLITE_LOCK_NONE) {
  179. // The unlocked read is considered an optimization. SQLite can continue
  180. // even if the read fails, as long as failure is communicated by zeroing
  181. // out the output buffer.
  182. std::memset(data, 0, size);
  183. return SQLITE_OK;
  184. }
  185. vfs_->SetLastError(base::File::GetLastFileError());
  186. return SQLITE_IOERR_READ;
  187. }
  188. // SQLite requires that we fill the unread bytes in the buffer with zeros.
  189. std::memset(data + bytes_read, 0, size - bytes_read);
  190. return SQLITE_IOERR_SHORT_READ;
  191. }
  192. int SandboxedVfsFile::Write(const void* buffer,
  193. int size,
  194. sqlite3_int64 offset) {
  195. DCHECK(buffer);
  196. DCHECK_GE(size, 0);
  197. DCHECK_GE(offset, 0);
  198. #if DCHECK_IS_ON()
  199. // SQLite's locking protocol only acquires locks on the database file. The
  200. // journal and the WAL file are always unlocked.
  201. DCHECK(sqlite_lock_mode_ == SQLITE_LOCK_EXCLUSIVE ||
  202. file_type_ != SandboxedVfsFileType::kDatabase)
  203. << "Write to database file with lock mode " << sqlite_lock_mode_;
  204. #endif // DCHECK_IS_ON()
  205. const char* data = reinterpret_cast<const char*>(buffer);
  206. // If we supported mmap()ed files, we'd check for a memory mapping here,
  207. // and try to fill as much of the request as possible by copying to the
  208. // mmap()ed region.
  209. int bytes_written = file_.Write(offset, data, size);
  210. DCHECK_LE(bytes_written, size);
  211. if (bytes_written >= size)
  212. return SQLITE_OK;
  213. base::File::Error last_error = base::File::GetLastFileError();
  214. vfs_->SetLastError(last_error);
  215. if (last_error == base::File::Error::FILE_ERROR_NO_SPACE)
  216. return SQLITE_FULL;
  217. return SQLITE_IOERR_WRITE;
  218. }
  219. int SandboxedVfsFile::Truncate(sqlite3_int64 size) {
  220. if (file_.SetLength(size))
  221. return SQLITE_OK;
  222. // On macOS < 10.15, the default sandbox blocks ftruncate(), so we have to use
  223. // a sync mojo IPC to ask the browser process to call ftruncate() for us.
  224. //
  225. // TODO(crbug.com/1084565): Figure out if we can allow ftruncate() in renderer
  226. // and utility processes. It would be useful for low-level storage APIs, like
  227. // the upcoming filesystem API.
  228. if (vfs_->delegate()->SetFileLength(file_path_, file_,
  229. static_cast<size_t>(size))) {
  230. return SQLITE_OK;
  231. }
  232. return SQLITE_IOERR_TRUNCATE;
  233. }
  234. int SandboxedVfsFile::Sync(int flags) {
  235. // NOTE: SQLite passes in (SQLITE_SYNC_NORMAL or SQLITE_SYNC_FULL),
  236. // potentially OR-ed with SQLITE_SYNC_DATAONLY. Implementing these could
  237. // lead to better performance.
  238. if (!file_.Flush()) {
  239. vfs_->SetLastError(base::File::GetLastFileError());
  240. return SQLITE_IOERR_FSYNC;
  241. }
  242. // The unix VFS also syncs the file's directory on the first xSync() call.
  243. // Chrome's LevelDB Env implementation does the same for specific files
  244. // (database manifests).
  245. //
  246. // For WebSQL, we would want to sync the directory at file open time, when the
  247. // file is opened for writing.
  248. return SQLITE_OK;
  249. }
  250. int SandboxedVfsFile::FileSize(sqlite3_int64* result_size) {
  251. int64_t length = file_.GetLength();
  252. if (length < 0) {
  253. vfs_->SetLastError(base::File::GetLastFileError());
  254. return SQLITE_IOERR_FSTAT;
  255. }
  256. // SQLite's unix VFS reports 1-byte files as empty. This is documented as a
  257. // workaround for a fairly obscure bug. See unixFileSize() in os_unix.c.
  258. if (length == 1)
  259. length = 0;
  260. *result_size = length;
  261. return SQLITE_OK;
  262. }
  263. namespace {
  264. // True if our simplified implementation uses an exclusive lock for a mode.
  265. bool IsExclusiveLockMode(int sqlite_lock_mode) {
  266. switch (sqlite_lock_mode) {
  267. case SQLITE_LOCK_NONE:
  268. case SQLITE_LOCK_SHARED:
  269. return false;
  270. case SQLITE_LOCK_RESERVED:
  271. case SQLITE_LOCK_PENDING:
  272. case SQLITE_LOCK_EXCLUSIVE:
  273. return true;
  274. }
  275. NOTREACHED() << "Unsupported mode: " << sqlite_lock_mode;
  276. return false;
  277. }
  278. } // namespace
  279. int SandboxedVfsFile::Lock(int mode) {
  280. DCHECK_GT(mode, sqlite_lock_mode_)
  281. << "SQLite asked the VFS to lock the file up to mode " << mode
  282. << " but the file is already locked at mode " << sqlite_lock_mode_;
  283. #if BUILDFLAG(IS_FUCHSIA)
  284. return SQLITE_IOERR_LOCK;
  285. #else
  286. base::File::LockMode file_lock_mode = base::File::LockMode::kExclusive;
  287. switch (mode) {
  288. case SQLITE_LOCK_NONE:
  289. return SQLITE_OK;
  290. case SQLITE_LOCK_SHARED:
  291. if (sqlite_lock_mode_ != SQLITE_LOCK_NONE)
  292. return SQLITE_OK;
  293. file_lock_mode = base::File::LockMode::kShared;
  294. break;
  295. case SQLITE_LOCK_RESERVED:
  296. // A SHARED lock is required before a RESERVED lock is acquired.
  297. DCHECK_EQ(sqlite_lock_mode_, SQLITE_LOCK_SHARED);
  298. file_lock_mode = base::File::LockMode::kExclusive;
  299. break;
  300. case SQLITE_LOCK_PENDING:
  301. NOTREACHED() << "SQLite never directly asks for PENDING locks";
  302. // Should we ever receive PENDING lock requests, the handler for
  303. // EXCLUSIVE lock requests below happens to work perfectly.
  304. [[fallthrough]];
  305. case SQLITE_LOCK_EXCLUSIVE:
  306. // A SHARED lock is required before an EXCLUSIVE lock is acquired.
  307. //
  308. // No higher level is required. In fact, SQLite upgrades the lock directly
  309. // from SHARED to EXCLUSIVE when rolling back a transaction, to avoid
  310. // having other readers queue up in the RESERVED state.
  311. DCHECK_GE(sqlite_lock_mode_, SQLITE_LOCK_SHARED);
  312. if (IsExclusiveLockMode(sqlite_lock_mode_)) {
  313. sqlite_lock_mode_ = mode;
  314. return SQLITE_OK;
  315. }
  316. file_lock_mode = base::File::LockMode::kExclusive;
  317. break;
  318. default:
  319. NOTREACHED() << "Unimplemented xLock() mode: " << mode;
  320. }
  321. DCHECK_EQ(IsExclusiveLockMode(mode),
  322. file_lock_mode == base::File::LockMode::kExclusive)
  323. << "Incorrect file_lock_mode logic for SQLite mode: " << mode;
  324. // On POSIX, it would be possible to upgrade atomically from a shared lock to
  325. // an exclusive lock. This implementation prioritizes the simplicity of no
  326. // platform-specific code over being faster in high contention cases.
  327. if (sqlite_lock_mode_ != SQLITE_LOCK_NONE) {
  328. base::File::Error error = file_.Unlock();
  329. if (error != base::File::FILE_OK) {
  330. vfs_->SetLastError(base::File::GetLastFileError());
  331. return SQLITE_IOERR_LOCK;
  332. }
  333. sqlite_lock_mode_ = SQLITE_LOCK_NONE;
  334. }
  335. base::File::Error error = file_.Lock(file_lock_mode);
  336. if (error != base::File::FILE_OK) {
  337. vfs_->SetLastError(base::File::GetLastFileError());
  338. return SQLITE_IOERR_LOCK;
  339. }
  340. sqlite_lock_mode_ = mode;
  341. return SQLITE_OK;
  342. #endif // BUILDFLAG(IS_FUCHSIA)
  343. }
  344. int SandboxedVfsFile::Unlock(int mode) {
  345. // The 2nd term in the DCHECK predicate is there because SQLite occasionally
  346. // attempts to unlock (to SQLITE_LOCK_NONE) a file that was already unlocked.
  347. // We're not aware of any other case of no-op VFS unlock calls.
  348. DCHECK(mode < sqlite_lock_mode_ ||
  349. (mode == sqlite_lock_mode_ && mode == SQLITE_LOCK_NONE))
  350. << "SQLite asked the VFS to unlock the file down to mode " << mode
  351. << " but the file is already at mode " << sqlite_lock_mode_;
  352. // No-op if we're already unlocked or at the requested mode.
  353. if (sqlite_lock_mode_ == mode || sqlite_lock_mode_ == SQLITE_LOCK_NONE)
  354. return SQLITE_OK;
  355. #if BUILDFLAG(IS_FUCHSIA)
  356. return SQLITE_IOERR_UNLOCK;
  357. #else
  358. // On POSIX, it is possible to downgrade atomically from an exclusive lock to
  359. // a shared lock. SQLite's unix VFS takes advantage of this. This
  360. // implementation prioritizes the simplicity of no platform-specific code over
  361. // being faster in high contention cases.
  362. base::File::Error error = file_.Unlock();
  363. if (error != base::File::FILE_OK) {
  364. vfs_->SetLastError(base::File::GetLastFileError());
  365. return SQLITE_IOERR_UNLOCK;
  366. }
  367. if (mode == SQLITE_LOCK_NONE) {
  368. sqlite_lock_mode_ = mode;
  369. return SQLITE_OK;
  370. }
  371. DCHECK_EQ(mode, SQLITE_LOCK_SHARED);
  372. error = file_.Lock(base::File::LockMode::kShared);
  373. if (error == base::File::FILE_OK) {
  374. sqlite_lock_mode_ = mode;
  375. return SQLITE_OK;
  376. }
  377. // Gave up the exclusive lock, but failed to get a shared lock.
  378. vfs_->SetLastError(base::File::GetLastFileError());
  379. sqlite_lock_mode_ = SQLITE_LOCK_NONE;
  380. return SQLITE_IOERR_UNLOCK;
  381. #endif // BUILDFLAG(IS_FUCHSIA)
  382. }
  383. int SandboxedVfsFile::CheckReservedLock(int* has_reserved_lock) {
  384. if (IsExclusiveLockMode(sqlite_lock_mode_)) {
  385. *has_reserved_lock = 1;
  386. return SQLITE_OK;
  387. }
  388. if (sqlite_lock_mode_ == SQLITE_LOCK_SHARED) {
  389. // Lock modes at or above RESERVED map to exclusive locks in our simplified
  390. // implementation. If this process has a shared lock, no other process can
  391. // have an exclusive lock.
  392. *has_reserved_lock = 0;
  393. return SQLITE_OK;
  394. }
  395. #if BUILDFLAG(IS_FUCHSIA)
  396. return SQLITE_IOERR_CHECKRESERVEDLOCK;
  397. #else
  398. // On POSIX, it's possible to query the existing lock state of a file. The
  399. // SQLite unix VFS takes advantage of this. On Windows, this isn't the case.
  400. // Follow the strategy of the Windows VFS, which checks by trying to get an
  401. // exclusive lock on the file.
  402. base::File::Error error = file_.Lock(base::File::LockMode::kShared);
  403. if (error != base::File::FILE_OK) {
  404. *has_reserved_lock = 1;
  405. return SQLITE_OK;
  406. }
  407. *has_reserved_lock = 0;
  408. if (file_.Unlock() == base::File::FILE_OK)
  409. return SQLITE_OK;
  410. // We acquired a shared lock that we can't get rid of.
  411. sqlite_lock_mode_ = SQLITE_LOCK_SHARED;
  412. return SQLITE_IOERR_CHECKRESERVEDLOCK;
  413. #endif // BUILDFLAG(IS_FUCHSIA)
  414. }
  415. int SandboxedVfsFile::FileControl(int opcode, void* data) {
  416. switch (opcode) {
  417. case SQLITE_FCNTL_MMAP_SIZE:
  418. // Implementing memory-mapping will require handling this correctly.
  419. return SQLITE_NOTFOUND;
  420. default:
  421. return SQLITE_NOTFOUND;
  422. }
  423. }
  424. int SandboxedVfsFile::SectorSize() {
  425. return 0;
  426. }
  427. int SandboxedVfsFile::DeviceCharacteristics() {
  428. // TODO(pwnall): Figure out if we can get away with returning 0 on Windows.
  429. #if BUILDFLAG(IS_WIN)
  430. return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN;
  431. #else
  432. // NOTE: SQLite's unix VFS attempts to detect the underlying filesystem and
  433. // sets some flags based on the result.
  434. return 0;
  435. #endif // BUILDFLAG(IS_WIN)
  436. }
  437. int SandboxedVfsFile::ShmMap(int page_index,
  438. int page_size,
  439. int extend_file_if_needed,
  440. void volatile** result) {
  441. DCHECK_GE(page_index, 0);
  442. DCHECK_GE(page_size, 0);
  443. DCHECK(result);
  444. // https://www.sqlite.org/wal.html#use_of_wal_without_shared_memory states
  445. // that SQLite only attempts to use shared memory "-shm" files for databases
  446. // in WAL mode that may be accessed by multiple processes (are not EXCLUSIVE).
  447. //
  448. // Chrome will not only use WAL mode on EXCLUSIVE databases.
  449. NOTREACHED() << "SQLite should not attempt to use shared memory";
  450. *result = nullptr;
  451. return SQLITE_IOERR;
  452. }
  453. int SandboxedVfsFile::ShmLock(int offset, int size, int flags) {
  454. DCHECK_GE(offset, 0);
  455. DCHECK_GE(size, 0);
  456. // https://www.sqlite.org/wal.html#use_of_wal_without_shared_memory states
  457. // that SQLite only attempts to use shared memory "-shm" files for databases
  458. // in WAL mode that may be accessed by multiple processes (are not EXCLUSIVE).
  459. //
  460. // Chrome will not only use WAL mode on EXCLUSIVE databases.
  461. NOTREACHED() << "SQLite should not attempt to use shared memory";
  462. return SQLITE_IOERR;
  463. }
  464. void SandboxedVfsFile::ShmBarrier() {
  465. // https://www.sqlite.org/wal.html#use_of_wal_without_shared_memory states
  466. // that SQLite only attempts to use shared memory "-shm" files for databases
  467. // in WAL mode that may be accessed by multiple processes (are not EXCLUSIVE).
  468. //
  469. // Chrome will not only use WAL mode on EXCLUSIVE databases.
  470. NOTREACHED() << "SQLite should not attempt to use shared memory";
  471. // All writes to shared memory that have already been issued before this
  472. // function is called must complete before the function returns.
  473. std::atomic_thread_fence(std::memory_order_acq_rel);
  474. }
  475. int SandboxedVfsFile::ShmUnmap(int also_delete_file) {
  476. // https://www.sqlite.org/wal.html#use_of_wal_without_shared_memory states
  477. // that SQLite only attempts to use shared memory "-shm" files for databases
  478. // in WAL mode that may be accessed by multiple processes (are not EXCLUSIVE).
  479. //
  480. // Chrome will not only use WAL mode on EXCLUSIVE databases.
  481. NOTREACHED() << "SQLite should not attempt to use shared memory";
  482. return SQLITE_IOERR;
  483. }
  484. int SandboxedVfsFile::Fetch(sqlite3_int64 offset, int size, void** result) {
  485. DCHECK_GE(offset, 0);
  486. DCHECK_GE(size, 0);
  487. DCHECK(result);
  488. // NOTE: This would be needed for mmap()ed file support.
  489. *result = nullptr;
  490. return SQLITE_IOERR;
  491. }
  492. int SandboxedVfsFile::Unfetch(sqlite3_int64 offset, void* fetch_result) {
  493. DCHECK_GE(offset, 0);
  494. DCHECK(fetch_result);
  495. // NOTE: This would be needed for mmap()ed file support.
  496. return SQLITE_IOERR;
  497. }
  498. SandboxedVfsFile::SandboxedVfsFile(base::File file,
  499. base::FilePath file_path,
  500. #if DCHECK_IS_ON()
  501. SandboxedVfsFileType file_type,
  502. #endif // DCHECK_IS_ON()
  503. SandboxedVfs* vfs)
  504. : file_(std::move(file)),
  505. sqlite_lock_mode_(SQLITE_LOCK_NONE),
  506. vfs_(vfs),
  507. #if DCHECK_IS_ON()
  508. file_type_(file_type),
  509. #endif // DCHECK_IS_ON()
  510. file_path_(std::move(file_path)) {
  511. }
  512. SandboxedVfsFile::~SandboxedVfsFile() = default;
  513. // static
  514. SandboxedVfsFileSqliteBridge& SandboxedVfsFileSqliteBridge::FromSqliteFile(
  515. sqlite3_file& sqlite_file) {
  516. static_assert(std::is_standard_layout<SandboxedVfsFileSqliteBridge>::value,
  517. "needed for the reinterpret_cast below");
  518. static_assert(offsetof(SandboxedVfsFileSqliteBridge, sqlite_file) == 0,
  519. "sqlite_file must be the first member of the struct.");
  520. SandboxedVfsFileSqliteBridge& bridge =
  521. reinterpret_cast<SandboxedVfsFileSqliteBridge&>(sqlite_file);
  522. DCHECK_EQ(&sqlite_file, &bridge.sqlite_file)
  523. << "assumed by the reinterpret_casts in the implementation";
  524. return bridge;
  525. }
  526. } // namespace sql