[go: nahoru, domu]

blob: 5f9ce841bbcd9dd5803ae506fb933763e2488966 [file] [log] [blame]
Avi Drissman69b874f2022-09-15 19:11:141// Copyright 2019 The Chromium Authors
Victor Costan451bb9cf2019-03-16 04:48:072// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ken Rockot7655fcb62020-08-12 19:22:405#ifndef SQL_SANDBOXED_VFS_FILE_H_
6#define SQL_SANDBOXED_VFS_FILE_H_
Victor Costan451bb9cf2019-03-16 04:48:077
8#include "base/files/file.h"
Ken Rockot7655fcb62020-08-12 19:22:409#include "base/files/file_path.h"
Keishi Hattori0e45c022021-11-27 09:25:5210#include "base/memory/raw_ptr.h"
Keishi Hattori488b7602022-05-02 13:09:3111#include "base/memory/raw_ptr_exclusion.h"
Victor Costan451bb9cf2019-03-16 04:48:0712#include "third_party/sqlite/sqlite3.h"
13
Ken Rockot7655fcb62020-08-12 19:22:4014namespace sql {
Victor Costan451bb9cf2019-03-16 04:48:0715
Victor Costan862ec722022-02-07 23:08:5316// The file types associated with a SQLite database.
17enum class SandboxedVfsFileType {
18 // The main file, which stores the database pages.
19 kDatabase,
20 // The transaction rollback journal file. Used when WAL is off.
21 // This file has the same path as the database, plus the "-journal" suffix.
22 kJournal,
23 // The Write-Ahead Log (WAL) file.
24 // This file has the same path as the database, plus the "-wal" suffix.
25 kWal,
26};
27
Victor Costan451bb9cf2019-03-16 04:48:0728class SandboxedVfs;
Victor Costan451bb9cf2019-03-16 04:48:0729
Victor Costan959eab02020-08-17 18:33:5630// SQLite VFS file implementation that works in a sandboxed process.
Victor Costan451bb9cf2019-03-16 04:48:0731//
32// An instance is created when SQLite calls into SandboxedVfs::Open(). The
33// instance is deleted by a call to SandboxedVfsFile::Close().
34//
35// The SQLite VFS API includes a complex locking strategy documented in
36// https://www.sqlite.org/lockingv3.html
37//
38// This implementation uses a simplified locking strategy, where we grab an
39// exclusive lock when entering any of the modes that prepare for a transition
40// to EXCLUSIVE. (These modes are RESERVED and PENDING). This approach is easy
41// to implement on top of base::File's locking primitives, at the cost of some
42// false contention, which makes us slower under high concurrency.
43//
44// SQLite's built-in VFSes use the OS support for locking a range of bytes in
45// the file, rather locking than the whole file.
46class SandboxedVfsFile {
Victor Costan451bb9cf2019-03-16 04:48:0747 public:
Ken Rockot7655fcb62020-08-12 19:22:4048 // Creates an instance in the given buffer. Note that `vfs` MUST outlive the
49 // returned sqlite3_file object.
Victor Costan451bb9cf2019-03-16 04:48:0750 static void Create(base::File file,
Ken Rockot7655fcb62020-08-12 19:22:4051 base::FilePath file_path,
Victor Costan862ec722022-02-07 23:08:5352#if DCHECK_IS_ON()
53 SandboxedVfsFileType file_type,
54#endif // DCHECK_IS_ON()
Victor Costan451bb9cf2019-03-16 04:48:0755 SandboxedVfs* vfs,
Ken Rockot7655fcb62020-08-12 19:22:4056 sqlite3_file& buffer);
Victor Costan451bb9cf2019-03-16 04:48:0757
58 // Extracts the instance bridged to the given SQLite VFS file.
Ken Rockot7655fcb62020-08-12 19:22:4059 static SandboxedVfsFile& FromSqliteFile(sqlite3_file& sqlite_file);
Victor Costan451bb9cf2019-03-16 04:48:0760
61 // sqlite3_file implementation.
62 int Close();
63 int Read(void* buffer, int size, sqlite3_int64 offset);
64 int Write(const void* buffer, int size, sqlite3_int64 offset);
65 int Truncate(sqlite3_int64 size);
66 int Sync(int flags);
67 int FileSize(sqlite3_int64* result_size);
68 int Lock(int mode);
69 int Unlock(int mode);
70 int CheckReservedLock(int* has_reserved_lock);
71 int FileControl(int opcode, void* data);
72 int SectorSize();
73 int DeviceCharacteristics();
74 int ShmMap(int page_index,
75 int page_size,
76 int extend_file_if_needed,
77 void volatile** result);
78 int ShmLock(int offset, int size, int flags);
79 void ShmBarrier();
80 int ShmUnmap(int also_delete_file);
81 int Fetch(sqlite3_int64 offset, int size, void** result);
82 int Unfetch(sqlite3_int64 offset, void* fetch_result);
83
84 private:
Ken Rockot7655fcb62020-08-12 19:22:4085 SandboxedVfsFile(base::File file,
86 base::FilePath file_path,
Victor Costan862ec722022-02-07 23:08:5387#if DCHECK_IS_ON()
88 SandboxedVfsFileType file_type,
89#endif // DCHECK_IS_ON()
Ken Rockot7655fcb62020-08-12 19:22:4090 SandboxedVfs* vfs);
Victor Costan451bb9cf2019-03-16 04:48:0791 ~SandboxedVfsFile();
92
93 // Constructed from a file handle passed from the browser process.
94 base::File file_;
95 // One of the SQLite locking mode constants.
96 int sqlite_lock_mode_;
97 // The SandboxedVfs that created this instance.
Keishi Hattori0e45c022021-11-27 09:25:5298 const raw_ptr<SandboxedVfs> vfs_;
Victor Costan862ec722022-02-07 23:08:5399#if DCHECK_IS_ON()
100 // Tracked to check assumptions about SQLite's locking protocol.
101 const SandboxedVfsFileType file_type_;
102#endif // DCHECK_IS_ON()
Victor Costan451bb9cf2019-03-16 04:48:07103 // Used to identify the file in IPCs to the browser process.
Ken Rockot7655fcb62020-08-12 19:22:40104 const base::FilePath file_path_;
Victor Costan451bb9cf2019-03-16 04:48:07105};
106
107// sqlite3_file "subclass" that bridges to a SandboxedVfsFile instance.
108struct SandboxedVfsFileSqliteBridge {
109 sqlite3_file sqlite_file;
Lukasz Anforowicz877e6222021-11-26 00:03:23110 // `sandboxed_vfs_file` is not a raw_ptr<SandboxedVfsFile>, because
111 // reinterpret_cast of uninitialized memory to raw_ptr can cause ref-counting
112 // mismatch.
Keishi Hattori488b7602022-05-02 13:09:31113 RAW_PTR_EXCLUSION SandboxedVfsFile* sandboxed_vfs_file;
Victor Costan451bb9cf2019-03-16 04:48:07114
Ken Rockot7655fcb62020-08-12 19:22:40115 static SandboxedVfsFileSqliteBridge& FromSqliteFile(
116 sqlite3_file& sqlite_file);
Victor Costan451bb9cf2019-03-16 04:48:07117};
118
Ken Rockot7655fcb62020-08-12 19:22:40119} // namespace sql
Victor Costan451bb9cf2019-03-16 04:48:07120
Ken Rockot7655fcb62020-08-12 19:22:40121#endif // SQL_SANDBOXED_VFS_FILE_H_