sandboxed_vfs.cc 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  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.h"
  5. #include <algorithm>
  6. #include <cstring>
  7. #include <string>
  8. #include <utility>
  9. #include <vector>
  10. #include "base/check_op.h"
  11. #include "base/files/file.h"
  12. #include "base/no_destructor.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_file.h"
  18. #include "third_party/sqlite/sqlite3.h"
  19. namespace sql {
  20. namespace {
  21. // Extracts the SandboxedVfs* stashed in a SQLite VFS structure.
  22. SandboxedVfs& SandboxedVfsFromSqliteVfs(sqlite3_vfs& vfs) {
  23. return *reinterpret_cast<SandboxedVfs*>(vfs.pAppData);
  24. }
  25. int SandboxedVfsOpen(sqlite3_vfs* vfs,
  26. const char* full_path,
  27. sqlite3_file* result_file,
  28. int requested_flags,
  29. int* granted_flags) {
  30. return SandboxedVfsFromSqliteVfs(*vfs).Open(full_path, *result_file,
  31. requested_flags, granted_flags);
  32. }
  33. int SandboxedVfsDelete(sqlite3_vfs* vfs, const char* full_path, int sync_dir) {
  34. return SandboxedVfsFromSqliteVfs(*vfs).Delete(full_path, sync_dir);
  35. }
  36. int SandboxedVfsAccess(sqlite3_vfs* vfs,
  37. const char* full_path,
  38. int flags,
  39. int* result) {
  40. return SandboxedVfsFromSqliteVfs(*vfs).Access(full_path, flags, *result);
  41. }
  42. int SandboxedVfsFullPathname(sqlite3_vfs* vfs,
  43. const char* file_path,
  44. int result_size,
  45. char* result) {
  46. return SandboxedVfsFromSqliteVfs(*vfs).FullPathname(file_path, result_size,
  47. result);
  48. }
  49. int SandboxedVfsRandomness(sqlite3_vfs* vfs, int result_size, char* result) {
  50. return SandboxedVfsFromSqliteVfs(*vfs).Randomness(result_size, result);
  51. }
  52. int SandboxedVfsSleep(sqlite3_vfs* vfs, int microseconds) {
  53. return SandboxedVfsFromSqliteVfs(*vfs).Sleep(microseconds);
  54. }
  55. int SandboxedVfsGetLastError(sqlite3_vfs* vfs,
  56. int message_size,
  57. char* message) {
  58. return SandboxedVfsFromSqliteVfs(*vfs).GetLastError(message_size, message);
  59. }
  60. int SandboxedVfsCurrentTimeInt64(sqlite3_vfs* vfs, sqlite3_int64* result_ms) {
  61. return SandboxedVfsFromSqliteVfs(*vfs).CurrentTimeInt64(result_ms);
  62. }
  63. sqlite3_vfs SqliteVfsFor(SandboxedVfs* sandboxed_vfs, const char* name) {
  64. DCHECK_EQ(sandboxed_vfs, reinterpret_cast<SandboxedVfs*>(
  65. reinterpret_cast<void*>(sandboxed_vfs)))
  66. << "This implementation round-trips SandboxedVfs* via void*";
  67. // VFS API entry points are listed at https://www.sqlite.org/c3ref/vfs.html
  68. static constexpr int kSqliteVfsApiVersion = 3;
  69. // Maximum file path size.
  70. // TODO(pwnall): Obtain this from //base or some other good place.
  71. static constexpr int kSqliteMaxPathSize = 512;
  72. return {
  73. kSqliteVfsApiVersion,
  74. sizeof(SandboxedVfsFileSqliteBridge),
  75. kSqliteMaxPathSize,
  76. /*pNext=*/nullptr,
  77. name,
  78. /*pAppData=*/reinterpret_cast<void*>(sandboxed_vfs),
  79. SandboxedVfsOpen,
  80. SandboxedVfsDelete,
  81. SandboxedVfsAccess,
  82. SandboxedVfsFullPathname,
  83. /*xDlOpen=*/nullptr,
  84. /*xDlError=*/nullptr,
  85. /*xDlSym=*/nullptr,
  86. /*xDlClose=*/nullptr,
  87. SandboxedVfsRandomness,
  88. SandboxedVfsSleep,
  89. /*xCurrentTime=*/nullptr, // Deprecated in API versions 2 and above.
  90. SandboxedVfsGetLastError,
  91. SandboxedVfsCurrentTimeInt64,
  92. /*xSetSystemCall=*/nullptr,
  93. /*xGetSystemCall=*/nullptr,
  94. /*xNextSystemCall=*/nullptr,
  95. };
  96. }
  97. // SQLite measures time according to the Julian calendar.
  98. base::Time SqliteEpoch() {
  99. constexpr const double kMicroSecondsPerDay = 24 * 60 * 60 * 1000;
  100. // The ".5" is intentional -- days in the Julian calendar start at noon.
  101. // The offset is in the SQLite source code (os_unix.c) multiplied by 10.
  102. constexpr const double kUnixEpochAsJulianDay = 2440587.5;
  103. return base::Time::FromJsTime(-kUnixEpochAsJulianDay * kMicroSecondsPerDay);
  104. }
  105. #if DCHECK_IS_ON()
  106. // `full_path_cstr` must be a filename argument passed to the VFS from SQLite.
  107. SandboxedVfsFileType VfsFileTypeFromPath(const char* full_path_cstr) {
  108. base::StringPiece full_path(full_path_cstr);
  109. const char* database_file_cstr = sqlite3_filename_database(full_path_cstr);
  110. base::StringPiece database_file(database_file_cstr);
  111. if (full_path == database_file)
  112. return SandboxedVfsFileType::kDatabase;
  113. const char* journal_file_cstr = sqlite3_filename_journal(full_path_cstr);
  114. base::StringPiece journal_file(journal_file_cstr);
  115. if (full_path == journal_file)
  116. return SandboxedVfsFileType::kJournal;
  117. const char* wal_file_cstr = sqlite3_filename_wal(full_path_cstr);
  118. base::StringPiece wal_file(wal_file_cstr);
  119. if (full_path == wal_file)
  120. return SandboxedVfsFileType::kWal;
  121. NOTREACHED()
  122. << "Argument is not a file name buffer passed from SQLite to a VFS: "
  123. << full_path;
  124. return SandboxedVfsFileType::kDatabase;
  125. }
  126. #endif // DCHECK_IS_ON()
  127. } // namespace
  128. // static
  129. void SandboxedVfs::Register(const char* name,
  130. std::unique_ptr<Delegate> delegate,
  131. bool make_default) {
  132. static base::NoDestructor<std::vector<SandboxedVfs*>>
  133. registered_vfs_instances;
  134. sql::EnsureSqliteInitialized();
  135. registered_vfs_instances->push_back(
  136. new SandboxedVfs(name, std::move(delegate), make_default));
  137. }
  138. int SandboxedVfs::Open(const char* full_path,
  139. sqlite3_file& result_file,
  140. int requested_flags,
  141. int* granted_flags) {
  142. base::FilePath file_path = base::FilePath::FromUTF8Unsafe(full_path);
  143. base::File file = delegate_->OpenFile(file_path, requested_flags);
  144. if (!file.IsValid()) {
  145. // TODO(pwnall): Figure out if we can remove the fallback to read-only.
  146. if (!(requested_flags & SQLITE_OPEN_READWRITE)) {
  147. // The SQLite API requires that pMethods is set to null even if the open
  148. // call returns a failure status.
  149. result_file.pMethods = nullptr;
  150. return SQLITE_CANTOPEN;
  151. }
  152. int new_flags =
  153. (requested_flags & ~SQLITE_OPEN_READWRITE) | SQLITE_OPEN_READONLY;
  154. return Open(full_path, result_file, new_flags, granted_flags);
  155. }
  156. SandboxedVfsFile::Create(std::move(file), std::move(file_path),
  157. #if DCHECK_IS_ON()
  158. VfsFileTypeFromPath(full_path),
  159. #endif // DCHECK_IS_ON()
  160. this, result_file);
  161. if (granted_flags)
  162. *granted_flags = requested_flags;
  163. return SQLITE_OK;
  164. }
  165. int SandboxedVfs::Delete(const char* full_path, int sync_dir) {
  166. DCHECK(full_path);
  167. return delegate_->DeleteFile(base::FilePath::FromUTF8Unsafe(full_path),
  168. sync_dir == 1);
  169. }
  170. int SandboxedVfs::Access(const char* full_path, int flags, int& result) {
  171. DCHECK(full_path);
  172. absl::optional<PathAccessInfo> access =
  173. delegate_->GetPathAccess(base::FilePath::FromUTF8Unsafe(full_path));
  174. if (!access) {
  175. result = 0;
  176. return SQLITE_OK;
  177. }
  178. switch (flags) {
  179. case SQLITE_ACCESS_EXISTS:
  180. result = 1;
  181. break;
  182. case SQLITE_ACCESS_READ:
  183. result = access->can_read ? 1 : 0;
  184. break;
  185. case SQLITE_ACCESS_READWRITE:
  186. result = (access->can_read && access->can_write) ? 1 : 0;
  187. break;
  188. default:
  189. NOTREACHED() << "Unsupported xAccess flags: " << flags;
  190. return SQLITE_ERROR;
  191. }
  192. return SQLITE_OK;
  193. }
  194. int SandboxedVfs::FullPathname(const char* file_path,
  195. int result_size,
  196. char* result) {
  197. DCHECK(file_path);
  198. DCHECK_GT(result_size, 0);
  199. DCHECK(result);
  200. // Renderer processes cannot access files directly, so it doesn't make sense
  201. // to expose full paths here.
  202. size_t file_path_size = std::strlen(file_path) + 1;
  203. if (static_cast<size_t>(result_size) < file_path_size)
  204. return SQLITE_CANTOPEN;
  205. std::memcpy(result, file_path, file_path_size);
  206. return SQLITE_OK;
  207. }
  208. int SandboxedVfs::Randomness(int result_size, char* result) {
  209. DCHECK_GT(result_size, 0);
  210. DCHECK(result);
  211. // TODO(pwnall): Figure out if we need a real implementation.
  212. std::memset(result, 0, result_size);
  213. return result_size;
  214. }
  215. int SandboxedVfs::Sleep(int microseconds) {
  216. DCHECK_GE(microseconds, 0);
  217. base::PlatformThread::Sleep(base::Microseconds(microseconds));
  218. return SQLITE_OK;
  219. }
  220. int SandboxedVfs::GetLastError(int message_size, char* message) const {
  221. DCHECK_GE(message_size, 0);
  222. DCHECK(message_size == 0 || message);
  223. std::string error_string = base::File::ErrorToString(last_error_);
  224. size_t error_string_size = error_string.length() + 1;
  225. size_t copy_length =
  226. std::min(static_cast<size_t>(message_size), error_string_size);
  227. std::memcpy(message, error_string.c_str(), copy_length);
  228. // The return value is zero if the message fits in the buffer, and non-zero if
  229. // it does not fit.
  230. return copy_length != error_string_size;
  231. }
  232. int SandboxedVfs::CurrentTimeInt64(sqlite3_int64* result_ms) {
  233. DCHECK(result_ms);
  234. base::TimeDelta delta = base::Time::Now() - sqlite_epoch_;
  235. *result_ms = delta.InMilliseconds();
  236. return SQLITE_OK;
  237. }
  238. SandboxedVfs::SandboxedVfs(const char* name,
  239. std::unique_ptr<Delegate> delegate,
  240. bool make_default)
  241. : sandboxed_vfs_(SqliteVfsFor(this, name)),
  242. sqlite_epoch_(SqliteEpoch()),
  243. delegate_(std::move(delegate)),
  244. last_error_(base::File::FILE_OK) {
  245. // The register function returns a SQLite status as an int. The status is
  246. // ignored here. If registration fails, we'd want to report the error while
  247. // attempting to open a database. This is exactly what will happen, because
  248. // SQLite won't find the VFS we're asking for.
  249. sqlite3_vfs_register(&sandboxed_vfs_, make_default ? 1 : 0);
  250. }
  251. } // namespace sql