Check pkgmgr database's crashed schema 62/250162/1
authorIlho Kim <ilho159.kim@samsung.com>
Mon, 21 Dec 2020 08:57:10 +0000 (17:57 +0900)
committerIlho Kim <ilho159.kim@samsung.com>
Mon, 21 Dec 2020 08:57:10 +0000 (17:57 +0900)
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 <ilho159.kim@samsung.com>
parser/include/pkgmgr_parser_db_queries.h [moved from parser/src/pkgmgr_parser_db_queries.h with 86% similarity]
parser/src/pkgmgr_parser_db.c
tool/pkg-db-recovery.c

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 (file)
        "    (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" \
        "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" \
        "    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" \
        "    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" \
        "       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__ */
index b63af0f..aa6d804 100644 (file)
@@ -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;
index c370b43..a64d123 100644 (file)
@@ -39,6 +39,7 @@
 #include <tzplatform_config.h>
 
 #include <pkgmgr_parser_db.h>
+#include <pkgmgr_parser_db_queries.h>
 
 #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) {