From 2ce69708359f7658d2f31298e60645508e5e0eca Mon Sep 17 00:00:00 2001 From: Ilho Kim Date: Tue, 10 May 2022 20:46:35 +0900 Subject: [PATCH] Check if database is modified when making cache 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 --- src/server/database/db_handle_provider.cc | 74 ++++++++++++++++++++------ src/server/database/remove_cache_db_handler.cc | 1 + src/server/runner.cc | 8 +-- 3 files changed, 64 insertions(+), 19 deletions(-) diff --git a/src/server/database/db_handle_provider.cc b/src/server/database/db_handle_provider.cc index 013c8e9..bd3d6e0 100644 --- a/src/server/database/db_handle_provider.cc +++ b/src/server/database/db_handle_provider.cc @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -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( - 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> 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; diff --git a/src/server/database/remove_cache_db_handler.cc b/src/server/database/remove_cache_db_handler.cc index d16a085..3ce37b5 100644 --- a/src/server/database/remove_cache_db_handler.cc +++ b/src/server/database/remove_cache_db_handler.cc @@ -28,6 +28,7 @@ int RemoveCacheDBHandler::Execute() { std::unique_lock u(lock_); database::DBHandleProvider::GetInst(GetUID()).UnsetMemoryMode(GetPID()); + database::DBHandleProvider::GetInst(GetUID()).TrimCache(); return PMINFO_R_OK; } diff --git a/src/server/runner.cc b/src/server/runner.cc index b5725d1..b9fab8d 100644 --- a/src/server/runner.cc +++ b/src/server/runner.cc @@ -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( - tzplatform_getuid(TZ_SYS_DEFAULT_USER))); + if (CacheFlag::SetPreparing()) { + QueueRequest( + std::make_shared( + tzplatform_getuid(TZ_SYS_DEFAULT_USER))); + } LOGI("Start Runner"); } -- 2.7.4