From: Ilho Kim Date: Mon, 21 Dec 2020 08:57:10 +0000 (+0900) Subject: Check pkgmgr database's crashed schema X-Git-Tag: accepted/tizen/6.0/unified/20201228.015305~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0860be10d1d5b329a72a2abce5d6843d0d33a560;p=platform%2Fcore%2Fappfw%2Fpkgmgr-info.git Check pkgmgr database's crashed schema If there is a column edited in the database, the integrity check routine may fail to detect This patch performs an additional check to detect the malformed database using sqlite_master table's sql statement Change-Id: I612e6562506f3e253727c96995d0a89fe4d02a8e Signed-off-by: Ilho Kim --- diff --git a/parser/src/pkgmgr_parser_db_queries.h b/parser/include/pkgmgr_parser_db_queries.h similarity index 86% rename from parser/src/pkgmgr_parser_db_queries.h rename to parser/include/pkgmgr_parser_db_queries.h index d444f4c..fc3e726 100644 --- a/parser/src/pkgmgr_parser_db_queries.h +++ b/parser/include/pkgmgr_parser_db_queries.h @@ -225,7 +225,7 @@ " (SELECT package_app_info.app_splash_screen_display FROM\n" \ " package_app_info, package_app_info_for_uid\n" \ " WHERE package_app_info.app_id=NEW.app_id) AND is_disabled='false';\n" \ - "END;" + "END" #define QUERY_CREATE_TABLE_PACKAGE_APP_SPLASH_SCREEN \ "CREATE TABLE IF NOT EXISTS package_app_splash_screen (\n" \ @@ -284,7 +284,7 @@ "WHEN (NEW.package_count = 0)\n" \ "BEGIN\n" \ " DELETE FROM package_cert_info WHERE package=OLD.package;\n" \ - "END;" + "END" #define QUERY_CREATE_TRIGGER_UPDATE_CERT_INFO2 \ "CREATE TRIGGER IF NOT EXISTS update_cert_info2\n" \ @@ -302,7 +302,7 @@ " OR cert_id = OLD.dist2_root_cert\n" \ " OR cert_id = OLD.dist2_im_cert\n" \ " OR cert_id = OLD.dist2_signer_cert;\n" \ - "END;" + "END" #define QUERY_CREATE_TRIGGER_DELETE_CERT_INFO \ "CREATE TRIGGER IF NOT EXISTS delete_cert_info\n" \ @@ -319,7 +319,7 @@ " OR cert_id = OLD.dist2_root_cert\n" \ " OR cert_id = OLD.dist2_im_cert\n" \ " OR cert_id = OLD.dist2_signer_cert;\n" \ - "END;" + "END" #define QUERY_CREATE_TRIGGER_UPDATE_CERT_INDEX_INFO \ "CREATE TRIGGER IF NOT EXISTS update_cert_index_info\n" \ @@ -328,6 +328,70 @@ " WHERE cert_id = OLD.cert_id) = 0)\n"\ "BEGIN\n" \ " DELETE FROM package_cert_index_info WHERE cert_id = OLD.cert_id;\n" \ - "END;" + "END" + +const char *PARSER_TABLES[] = { + "package_info", + "package_localized_info", + "package_privilege_info", + "package_appdefined_privilege_info", + "package_update_info", + "package_app_info", + "package_app_localized_info", + "package_app_app_control", + "package_app_app_control_privilege", + "package_app_app_category", + "package_app_app_metadata", + "package_app_data_control", + "package_app_data_control_privilege", + "package_app_info_for_uid", + "update_package_appinfo_for_uid", + "package_app_splash_screen", + "package_dependency_info", + "package_plugin_info", + NULL, +}; + +const char *CERT_TABLES[] = { + "package_cert_info", + "package_cert_index_info", + "update_cert_info", + "update_cert_info2", + "delete_cert_info", + "update_cert_index_info", + NULL, +}; + +const char *PARSER_INIT_QUERIES[] = { + QUERY_CREATE_TABLE_PACKAGE_INFO, + QUERY_CREATE_TABLE_PACKAGE_LOCALIZED_INFO, + QUERY_CREATE_TABLE_PACKAGE_PRIVILEGE_INFO, + QUERY_CREATE_TABLE_PACKAGE_APPDEFINED_PRIVILEGE_INFO, + QUERY_CREATE_TABLE_PACKAGE_UPDATE_INFO, + QUERY_CREATE_TABLE_PACKAGE_APP_INFO, + QUERY_CREATE_TABLE_PACKAGE_APP_LOCALIZED_INFO, + QUERY_CREATE_TABLE_PACKAGE_APP_APP_CONTROL, + QUERY_CREATE_TABLE_PACKAGE_APP_APP_CONTROL_PRIVILEGE, + QUERY_CREATE_TABLE_PACKAGE_APP_APP_CATEGORY, + QUERY_CREATE_TABLE_PACKAGE_APP_APP_METADATA, + QUERY_CREATE_TABLE_PACKAGE_APP_DATA_CONTROL, + QUERY_CREATE_TABLE_PACKAGE_APP_DATA_CONTROL_PRIVILEGE, + QUERY_CREATE_TABLE_PACKAGE_APP_INFO_FOR_UID, + QUERY_CREATE_TRIGGER_UPDATE_PACKAGE_APP_INFO_FOR_UID, + QUERY_CREATE_TABLE_PACKAGE_APP_SPLASH_SCREEN, + QUERY_CREATE_TABLE_PACKAGE_DEPENDENCY_INFO, + QUERY_CREATE_TABLE_PACKAGE_PLUGIN_INFO, + NULL, +}; + +const char *CERT_INIT_QUERIES[] = { + QUERY_CREATE_TABLE_PACKAGE_CERT_INFO, + QUERY_CREATE_TABLE_PACKAGE_CERT_INDEX_INFO, + QUERY_CREATE_TRIGGER_UPDATE_CERT_INFO, + QUERY_CREATE_TRIGGER_UPDATE_CERT_INFO2, + QUERY_CREATE_TRIGGER_DELETE_CERT_INFO, + QUERY_CREATE_TRIGGER_UPDATE_CERT_INDEX_INFO, + NULL +}; #endif /* __PKGMGR_PARSER_DB_QUERIES_H__ */ diff --git a/parser/src/pkgmgr_parser_db.c b/parser/src/pkgmgr_parser_db.c index b63af0f..aa6d804 100644 --- a/parser/src/pkgmgr_parser_db.c +++ b/parser/src/pkgmgr_parser_db.c @@ -313,38 +313,6 @@ static int __set_db_permission(const char *path, uid_t uid) return 0; } -static const char *parser_init_queries[] = { - QUERY_CREATE_TABLE_PACKAGE_INFO, - QUERY_CREATE_TABLE_PACKAGE_LOCALIZED_INFO, - QUERY_CREATE_TABLE_PACKAGE_PRIVILEGE_INFO, - QUERY_CREATE_TABLE_PACKAGE_APPDEFINED_PRIVILEGE_INFO, - QUERY_CREATE_TABLE_PACKAGE_UPDATE_INFO, - QUERY_CREATE_TABLE_PACKAGE_APP_INFO, - QUERY_CREATE_TABLE_PACKAGE_APP_LOCALIZED_INFO, - QUERY_CREATE_TABLE_PACKAGE_APP_APP_CONTROL, - QUERY_CREATE_TABLE_PACKAGE_APP_APP_CONTROL_PRIVILEGE, - QUERY_CREATE_TABLE_PACKAGE_APP_APP_CATEGORY, - QUERY_CREATE_TABLE_PACKAGE_APP_APP_METADATA, - QUERY_CREATE_TABLE_PACKAGE_APP_DATA_CONTROL, - QUERY_CREATE_TABLE_PACKAGE_APP_DATA_CONTROL_PRIVILEGE, - QUERY_CREATE_TABLE_PACKAGE_APP_INFO_FOR_UID, - QUERY_CREATE_TRIGGER_UPDATE_PACKAGE_APP_INFO_FOR_UID, - QUERY_CREATE_TABLE_PACKAGE_APP_SPLASH_SCREEN, - QUERY_CREATE_TABLE_PACKAGE_DEPENDENCY_INFO, - QUERY_CREATE_TABLE_PACKAGE_PLUGIN_INFO, - NULL, -}; - -static const char *cert_init_queries[] = { - QUERY_CREATE_TABLE_PACKAGE_CERT_INFO, - QUERY_CREATE_TABLE_PACKAGE_CERT_INDEX_INFO, - QUERY_CREATE_TRIGGER_UPDATE_CERT_INFO, - QUERY_CREATE_TRIGGER_UPDATE_CERT_INFO2, - QUERY_CREATE_TRIGGER_DELETE_CERT_INFO, - QUERY_CREATE_TRIGGER_UPDATE_CERT_INDEX_INFO, - NULL -}; - static int __create_tables(sqlite3 *db, const char **queries) { int ret; @@ -367,9 +335,9 @@ static int __initialize_db(sqlite3 *db, const char *dbpath, uid_t uid) return -1; if (strstr(dbpath, ".pkgmgr_parser.db")) { - queries = parser_init_queries; + queries = PARSER_INIT_QUERIES; } else if (strstr(dbpath, ".pkgmgr_cert.db")) { - queries = cert_init_queries; + queries = CERT_INIT_QUERIES; } else { _LOGE("unexpected dbpath: %s", dbpath); return -1; diff --git a/tool/pkg-db-recovery.c b/tool/pkg-db-recovery.c index c370b43..a64d123 100644 --- a/tool/pkg-db-recovery.c +++ b/tool/pkg-db-recovery.c @@ -39,6 +39,7 @@ #include #include +#include #ifdef LOG_TAG #undef LOG_TAG @@ -356,6 +357,90 @@ static void _get_user_list() closedir(dir); } +static bool __check_db_schema(const char *db_path, + const char **db_tables, const char **init_queries) { + int ret = -1; + int i; + sqlite3_stmt *stmt = NULL; + const char *check_result; + char *schema_in_library, *schema_in_db; + static const char table_schema_query[] = + "SELECT sql from sqlite_master WHERE name=?"; + char buf[BUFSIZE]; + sqlite3 *db; + + ret = sqlite3_open_v2(db_path, &db, + SQLITE_OPEN_READONLY, NULL); + if (ret != SQLITE_OK) { + LOGE("Failed to open db"); + sqlite3_close_v2(db); + return false; + } + + ret = sqlite3_busy_handler(db, __db_busy_handler, NULL); + if (ret != SQLITE_OK) { + LOGE("failed to register busy handler: %s", + sqlite3_errmsg(db)); + sqlite3_close_v2(db); + return ret; + } + for (i = 0; db_tables[i] != NULL; i++) { + ret = sqlite3_prepare_v2(db, table_schema_query, + strlen(table_schema_query), &stmt, NULL); + if (ret != SQLITE_OK) { + LOGE("Failed to check db schema : %s", + sqlite3_errmsg(db)); + goto err; + } + + ret = sqlite3_bind_text(stmt, 1, + db_tables[i],-1, SQLITE_STATIC); + + ret = sqlite3_step(stmt); + if (ret != SQLITE_ROW) { + LOGE("Failed to check db schema :%s", + sqlite3_errmsg(db)); + goto err; + } + + check_result = (const char *)sqlite3_column_text(stmt, 0); + if (!check_result) { + LOGE("Failed to check db schema :%s", + sqlite3_errmsg(db)); + goto err; + } + + schema_in_library = strstr(init_queries[i], db_tables[i]); + if (schema_in_library == NULL) { + LOGE("Failed to get initialization query from library"); + goto err; + } + schema_in_db = strstr(check_result, db_tables[i]); + if (schema_in_db == NULL) { + LOGE("Failed to get initialization query from db"); + goto err; + } + + ret = strcmp(schema_in_library, schema_in_db); + if (ret != 0) { + LOGE("Broken schema detected in table[%s], query[%s]", + db_tables[i], schema_in_db); + goto err; + } + + sqlite3_finalize(stmt); + stmt = NULL; + } + + sqlite3_close(db); + return true; + +err: + sqlite3_finalize(stmt); + sqlite3_close(db); + return false; +} + static void _check_db() { int need_recovery = false; @@ -369,6 +454,14 @@ static void _check_db() } else if (__check_aborted(GLOBAL_USER)) { LOGE("Previous recovery was aborted. restore entire pkgmgr db"); need_recovery = true; + } else if (!__check_db_schema(PKGMGR_PARSER_DB_FILE, + PARSER_TABLES, PARSER_INIT_QUERIES)) { + LOGE("Global parser db schema was broken. restore entire pkgmgr db"); + need_recovery = true; + } else if (!__check_db_schema(PKGMGR_CERT_DB_FILE, + CERT_TABLES, CERT_INIT_QUERIES)) { + LOGE("Cert db schema was broken. restore entire pkgmgr db"); + need_recovery = true; } if (need_recovery) {