Check if database is modified when making cache 53/274853/3
authorIlho Kim <ilho159.kim@samsung.com>
Tue, 10 May 2022 11:46:35 +0000 (20:46 +0900)
committerIlho Kim <ilho159.kim@samsung.com>
Wed, 11 May 2022 03:30:15 +0000 (12:30 +0900)
If there is a writer tring access db directly,
there is a possibility that the database will change while creating the cache
so check the change time of the database before and after making the cache
and detect the modification of the database
if so fails the cache creation task

Change-Id: Ib606db06e424b5dfca2414592938a10f43ab4240
Signed-off-by: Ilho Kim <ilho159.kim@samsung.com>
src/server/database/db_handle_provider.cc
src/server/database/remove_cache_db_handler.cc
src/server/runner.cc

index 013c8e9..bd3d6e0 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <fcntl.h>
 #include <glib.h>
+#include <sys/stat.h>
 #include <sys/types.h>
 
 #include <tzplatform_config.h>
@@ -58,6 +59,24 @@ uid_t ConvertUID(uid_t uid) {
     return uid;
 }
 
+bool GetModifiedTime(const char* dbpath, timespec* t) {
+  if (dbpath == nullptr || t == nullptr) {
+    LOG(ERROR) << "Invalid argument";
+    return false;
+  }
+
+  struct stat attr;
+  if (stat(dbpath, &attr)) {
+    LOG(ERROR) << "Fail to get status from file "
+        << dbpath << " errno : " << errno;
+    return false;
+  }
+
+  *t = attr.st_mtim;
+
+  return true;
+}
+
 static const std::string global_parser_memdb_path =
     "file:parserdb?mode=memory&cache=shared";
 
@@ -271,12 +290,8 @@ void DBHandleProvider::UnsetMemoryMode(pid_t pid) {
   is_user_memdb_set_ = false;
   is_global_memdb_set_ = false;
 
-  auto lock = CacheFlag::GetWriterLock();
-  CacheFlag::SetStatus(CacheFlag::Status::PREPARING);
+  TrimCache();
 
-  pkg_map_.clear();
-  app_map_.clear();
-  CacheFlag::SetStatus(CacheFlag::Status::UNPREPARED);
   LOG(DEBUG) << "Set Memory mode : File";
 }
 
@@ -327,15 +342,20 @@ int DBHandleProvider::UpdateCache(sqlite3* db, pid_t pid, uid_t uid, bool write,
     return PMINFO_R_ERROR;
   }
 
-  auto tmp_filter = reinterpret_cast<pkgmgrinfo_filter_x*>(
-      calloc(1, sizeof(pkgmgrinfo_filter_x)));
-  if (tmp_filter == nullptr) {
-    LOG(ERROR) << "Out of memory";
-    g_hash_table_destroy(list);
-    return PMINFO_R_ERROR;
+  const char* dbpath = sqlite3_db_filename(db, "main");
+  bool is_inmemory_db = false;
+  if (dbpath == nullptr || strlen(dbpath) == 0) {
+    LOG(INFO) << "database is inmemory db";
+    is_inmemory_db = true;
   }
 
-  int ret = pkginfo_internal_filter_get_list(db, tmp_filter, uid_,
+  timespec start_time = { 0, };
+  timespec end_time = { 0, };
+  if (!is_inmemory_db && !GetModifiedTime(dbpath, &start_time))
+    return PMINFO_R_ERROR;
+
+  pkgmgrinfo_filter_x tmp_filter = { 0, };
+  int ret = pkginfo_internal_filter_get_list(db, &tmp_filter, uid_,
                                              locale.c_str(), list);
   if (ret == PMINFO_R_OK) {
     GHashTableIter iter;
@@ -349,22 +369,44 @@ int DBHandleProvider::UpdateCache(sqlite3* db, pid_t pid, uid_t uid, bool write,
   }
 
   g_hash_table_destroy(list);
-  if (ret == PMINFO_R_ERROR) {
-    free(tmp_filter);
+  if (ret == PMINFO_R_ERROR)
     return ret;
+
+  if (!is_inmemory_db && !GetModifiedTime(dbpath, &end_time))
+    return PMINFO_R_ERROR;
+
+  if (start_time.tv_sec != end_time.tv_sec ||
+      start_time.tv_nsec != end_time.tv_nsec) {
+    LOG(ERROR) << "Database(" << dbpath << ") modification was detected";
+    return PMINFO_R_ERROR;
   }
 
   std::vector<std::shared_ptr<application_x>> app_list;
   ret = pkgmgr_server::internal::appinfo_internal_filter_get_list(db,
-      tmp_filter, uid_, uid, locale.c_str(), app_list);
-  free(tmp_filter);
+      &tmp_filter, uid_, uid, locale.c_str(), app_list);
+
+  if (!is_inmemory_db && !GetModifiedTime(dbpath, &end_time))
+    return PMINFO_R_ERROR;
+
+  if (start_time.tv_sec != end_time.tv_sec ||
+      start_time.tv_nsec != end_time.tv_nsec) {
+    LOG(ERROR) << "Database(" << dbpath << ") modification was detected";
+    return PMINFO_R_ERROR;
+  }
+
   if (ret == PMINFO_R_OK) {
     for (auto& app : app_list) {
+      if (pkg_map_.find(app->package) == pkg_map_.end()) {
+        LOG(ERROR) << "Can not find package from pkg_map";
+        return PMINFO_R_ERROR;
+      }
+
       app->privileges = pkg_map_[app->package].front()->privileges;
       std::string appid = app->appid;
       AddApplication(std::move(appid), std::move(app));
     }
   }
+
   released_ = false;
 
   return ret;
index d16a085..3ce37b5 100644 (file)
@@ -28,6 +28,7 @@ int RemoveCacheDBHandler::Execute() {
   std::unique_lock<std::shared_timed_mutex> u(lock_);
 
   database::DBHandleProvider::GetInst(GetUID()).UnsetMemoryMode(GetPID());
+  database::DBHandleProvider::GetInst(GetUID()).TrimCache();
 
   return PMINFO_R_OK;
 }
index b5725d1..b9fab8d 100644 (file)
@@ -70,9 +70,11 @@ Runner::Runner(unsigned int thread_num) {
   pkgmgr_common::SystemLocale::GetInst().RegisterEvent(this);
   thread_pool_->SetLocale(pkgmgr_common::SystemLocale::GetInst().Get());
 
-  QueueRequest(
-      std::make_shared<CreateCacheRequest>(
-          tzplatform_getuid(TZ_SYS_DEFAULT_USER)));
+  if (CacheFlag::SetPreparing()) {
+    QueueRequest(
+        std::make_shared<CreateCacheRequest>(
+            tzplatform_getuid(TZ_SYS_DEFAULT_USER)));
+  }
   LOGI("Start Runner");
 }