blob: f6abcfea58630713f208e2991bde8335c8610bf3 [file] [log] [blame]
// 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 {
int SandboxedClose(sqlite3_file* file) {
return SandboxedVfsFile::FromSqliteFile(*file).Close();
}
int SandboxedRead(sqlite3_file* file,
void* buffer,
int size,
sqlite3_int64 offset) {
return SandboxedVfsFile::FromSqliteFile(*file).Read(buffer, size, offset);
}
int SandboxedWrite(sqlite3_file* file,
const void* buffer,
int size,
sqlite3_int64 offset) {
return SandboxedVfsFile::FromSqliteFile(*file).Write(buffer, size, offset);
}
int SandboxedTruncate(sqlite3_file* file, sqlite3_int64 size) {
return SandboxedVfsFile::FromSqliteFile(*file).Truncate(size);
}
int SandboxedSync(sqlite3_file* file, int flags) {
return SandboxedVfsFile::FromSqliteFile(*file).Sync(flags);
}
int SandboxedFileSize(sqlite3_file* file, sqlite3_int64* result_size) {
return SandboxedVfsFile::FromSqliteFile(*file).FileSize(result_size);
}
int SandboxedLock(sqlite3_file* file, int mode) {
return SandboxedVfsFile::FromSqliteFile(*file).Lock(mode);
}
int SandboxedUnlock(sqlite3_file* file, int mode) {
return SandboxedVfsFile::FromSqliteFile(*file).Unlock(mode);
}
int SandboxedCheckReservedLock(sqlite3_file* file, int* has_reserved_lock) {
return SandboxedVfsFile::FromSqliteFile(*file).CheckReservedLock(
has_reserved_lock);
}
int SandboxedFileControl(sqlite3_file* file, int opcode, void* data) {
return SandboxedVfsFile::FromSqliteFile(*file).FileControl(opcode, data);
}
int SandboxedSectorSize(sqlite3_file* file) {
return SandboxedVfsFile::FromSqliteFile(*file).SectorSize();
}
int SandboxedDeviceCharacteristics(sqlite3_file* file) {
return SandboxedVfsFile::FromSqliteFile(*file).DeviceCharacteristics();
}
int SandboxedShmMap(sqlite3_file* file,
int page_index,
int page_size,
int extend_file_if_needed,
void volatile** result) {
return SandboxedVfsFile::FromSqliteFile(*file).ShmMap(
page_index, page_size, extend_file_if_needed, result);
}
int SandboxedShmLock(sqlite3_file* file, int offset, int size, int flags) {
return SandboxedVfsFile::FromSqliteFile(*file).ShmLock(offset, size, flags);
}
void SandboxedShmBarrier(sqlite3_file* file) {
SandboxedVfsFile::FromSqliteFile(*file).ShmBarrier();
}
int SandboxedShmUnmap(sqlite3_file* file, int also_delete_file) {
return SandboxedVfsFile::FromSqliteFile(*file).ShmUnmap(also_delete_file);
}
int SandboxedFetch(sqlite3_file* file,
sqlite3_int64 offset,
int size,
void** result) {
return SandboxedVfsFile::FromSqliteFile(*file).Fetch(offset, size, result);
}
int SandboxedUnfetch(sqlite3_file* file,
sqlite3_int64 offset,
void* fetch_result) {
return SandboxedVfsFile::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
static constexpr int kSqliteVfsIoApiVersion = 3;
static const 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
void SandboxedVfsFile::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