| // Copyright 2019 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifdef UNSAFE_BUFFERS_BUILD |
| // TODO(crbug.com/351564777): Remove this and convert code to safer constructs. |
| #pragma allow_unsafe_buffers |
| #endif |
| |
| #include"sql/sandboxed_vfs_file.h" |
| |
| #include<atomic> |
| #include<cstddef> |
| #include<cstdint> |
| #include<cstring> |
| #include<type_traits> |
| #include<utility> |
| |
| #include"base/check.h" |
| #include"base/check_op.h" |
| #include"base/files/file.h" |
| #include"base/files/file_path.h" |
| #include"base/notreached.h" |
| #include"build/build_config.h" |
| #include"sql/sandboxed_vfs.h" |
| #include"third_party/sqlite/sqlite3.h" |
| |
| namespace sql{ |
| |
| namespace{ |
| |
| intSandboxedClose(sqlite3_file* file){ |
| returnSandboxedVfsFile::FromSqliteFile(*file).Close(); |
| } |
| intSandboxedRead(sqlite3_file* file, |
| void* buffer, |
| int size, |
| sqlite3_int64 offset){ |
| returnSandboxedVfsFile::FromSqliteFile(*file).Read(buffer, size, offset); |
| } |
| intSandboxedWrite(sqlite3_file* file, |
| constvoid* buffer, |
| int size, |
| sqlite3_int64 offset){ |
| returnSandboxedVfsFile::FromSqliteFile(*file).Write(buffer, size, offset); |
| } |
| intSandboxedTruncate(sqlite3_file* file, sqlite3_int64 size){ |
| returnSandboxedVfsFile::FromSqliteFile(*file).Truncate(size); |
| } |
| intSandboxedSync(sqlite3_file* file,int flags){ |
| returnSandboxedVfsFile::FromSqliteFile(*file).Sync(flags); |
| } |
| intSandboxedFileSize(sqlite3_file* file, sqlite3_int64* result_size){ |
| returnSandboxedVfsFile::FromSqliteFile(*file).FileSize(result_size); |
| } |
| intSandboxedLock(sqlite3_file* file,int mode){ |
| returnSandboxedVfsFile::FromSqliteFile(*file).Lock(mode); |
| } |
| intSandboxedUnlock(sqlite3_file* file,int mode){ |
| returnSandboxedVfsFile::FromSqliteFile(*file).Unlock(mode); |
| } |
| intSandboxedCheckReservedLock(sqlite3_file* file,int* has_reserved_lock){ |
| returnSandboxedVfsFile::FromSqliteFile(*file).CheckReservedLock( |
| has_reserved_lock); |
| } |
| intSandboxedFileControl(sqlite3_file* file,int opcode,void* data){ |
| returnSandboxedVfsFile::FromSqliteFile(*file).FileControl(opcode, data); |
| } |
| intSandboxedSectorSize(sqlite3_file* file){ |
| returnSandboxedVfsFile::FromSqliteFile(*file).SectorSize(); |
| } |
| intSandboxedDeviceCharacteristics(sqlite3_file* file){ |
| returnSandboxedVfsFile::FromSqliteFile(*file).DeviceCharacteristics(); |
| } |
| intSandboxedShmMap(sqlite3_file* file, |
| int page_index, |
| int page_size, |
| int extend_file_if_needed, |
| voidvolatile** result){ |
| returnSandboxedVfsFile::FromSqliteFile(*file).ShmMap( |
| page_index, page_size, extend_file_if_needed, result); |
| } |
| intSandboxedShmLock(sqlite3_file* file,int offset,int size,int flags){ |
| returnSandboxedVfsFile::FromSqliteFile(*file).ShmLock(offset, size, flags); |
| } |
| voidSandboxedShmBarrier(sqlite3_file* file){ |
| SandboxedVfsFile::FromSqliteFile(*file).ShmBarrier(); |
| } |
| intSandboxedShmUnmap(sqlite3_file* file,int also_delete_file){ |
| returnSandboxedVfsFile::FromSqliteFile(*file).ShmUnmap(also_delete_file); |
| } |
| intSandboxedFetch(sqlite3_file* file, |
| sqlite3_int64 offset, |
| int size, |
| void** result){ |
| returnSandboxedVfsFile::FromSqliteFile(*file).Fetch(offset, size, result); |
| } |
| intSandboxedUnfetch(sqlite3_file* file, |
| sqlite3_int64 offset, |
| void* fetch_result){ |
| returnSandboxedVfsFile::FromSqliteFile(*file).Unfetch(offset, fetch_result); |
| } |
| |
| const sqlite3_io_methods*GetSqliteIoMethods(){ |
| // VFS IO API entry points are listed at |
| // https://www.sqlite.org/c3ref/io_methods.html |
| staticconstexprint kSqliteVfsIoApiVersion=3; |
| |
| staticconst sqlite3_io_methods kIoMethods={ |
| kSqliteVfsIoApiVersion, |
| SandboxedClose, |
| SandboxedRead, |
| SandboxedWrite, |
| SandboxedTruncate, |
| SandboxedSync, |
| SandboxedFileSize, |
| SandboxedLock, |
| SandboxedUnlock, |
| SandboxedCheckReservedLock, |
| SandboxedFileControl, |
| SandboxedSectorSize, |
| SandboxedDeviceCharacteristics, |
| SandboxedShmMap, |
| SandboxedShmLock, |
| SandboxedShmBarrier, |
| SandboxedShmUnmap, |
| SandboxedFetch, |
| SandboxedUnfetch, |
| }; |
| |
| return&kIoMethods; |
| } |
| |
| }// namespace |
| |
| SandboxedVfsFile::SandboxedVfsFile()=default; |
| SandboxedVfsFile::~SandboxedVfsFile()=default; |
| |
| // static |
| voidSandboxedVfsFile::BindSandboxedFile(SandboxedVfsFile* vfs_file, |
| sqlite3_file& buffer){ |
| SandboxedVfsFileSqliteBridge& bridge= |
| SandboxedVfsFileSqliteBridge::FromSqliteFile(buffer); |
| bridge.sandboxed_vfs_file= vfs_file; |
| bridge.sqlite_file.pMethods=GetSqliteIoMethods(); |
| } |
| |
| // static |
| SandboxedVfsFile&SandboxedVfsFile::FromSqliteFile(sqlite3_file& sqlite_file){ |
| return*SandboxedVfsFileSqliteBridge::FromSqliteFile(sqlite_file) |
| .sandboxed_vfs_file; |
| } |
| |
| // static |
| SandboxedVfsFileSqliteBridge&SandboxedVfsFileSqliteBridge::FromSqliteFile( |
| sqlite3_file& sqlite_file){ |
| static_assert(std::is_standard_layout<SandboxedVfsFileSqliteBridge>::value, |
| "needed for the reinterpret_cast below"); |
| static_assert(offsetof(SandboxedVfsFileSqliteBridge, sqlite_file)==0, |
| "sqlite_file must be the first member of the struct."); |
| |
| SandboxedVfsFileSqliteBridge& bridge= |
| reinterpret_cast<SandboxedVfsFileSqliteBridge&>(sqlite_file); |
| DCHECK_EQ(&sqlite_file,&bridge.sqlite_file) |
| <<"assumed by the reinterpret_casts in the implementation"; |
| return bridge; |
| } |
| |
| }// namespace sql |